            LIST      p=12F629
            #include  <P12F629.inc>
            __CONFIG  (_MCLRE_OFF & _CP_OFF & _CPD_OFF & _PWRTE_OFF & _WDT_ON & _INTRC_OSC_NOCLKOUT & _BODEN_ON)


            #define   COLD   1      ; лампа холодного света
            #define   HOT    2      ; лампа теплого света
            #define   UP     3      ; увеличение яркости
            #define   DOWN   4      ; уменьшение яркости
            #define   POWER  5      ; вкл\выкл
            #define   MODE   0      ; выбор холодного\теплого света
            
Reg_1       EQU         0x21
Reg_2       EQU         0x22
Reg_3       EQU         0x23          ; в данном регистре храним значение яркости светодиода во время работы
Reg_4       EQU         0x24
Reg_5       EQU         0x25          ; в данном регистре храним значение яркости светодиода после выключения устройства


            org         2100h         ; На стадии "прошивки", записываем в EEPROM-ячейку,
            de          .254          ; с адресом 00h, число 254 (FE) константу определяющую яркость светодиода при первом включении устройства (.1 min - .254 max)

                            ;;;;;;;;;;;;;;;;;;;
                            ; старт программы ;
                            ;;;;;;;;;;;;;;;;;;;
            org         0
            goto        START
                            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                            ; подготовительные операции ;
                            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
START       call        0x3FF	      ; копируем калибровочную константу
            bsf         STATUS,5      ; переход в банк 1
            movwf       OSCCAL	      ; записываем калибровочную константу
            banksel     TRISIO        ; переходим в регистр TRISIO
            movlw       b'00111001'   ; настраиваем GP0-3-4-5 на вход
            movwf       TRISIO	      ; -//-
            banksel     WPU           ; переходим в регистр WPU
            movlw       b'00111001'   ; включаем подтягивающие резисторы
            movwf       WPU           ; -//-
            banksel     OPTION_REG    ; переходим в регистр OPTION_REG
            movlw       b'00001110'   ; включаем предделитель перед WDT 1:16
            movwf       OPTION_REG    ; -//-
            banksel     INTCON        ; переходим в регистр INTCON
            movlw       b'00000000'   ; глобальный запрет прерываний
            movwf       INTCON        ; -//-
            banksel     VRCON         ; переходим в регистр VRCON
            movlw       .0            ; отключаем источник опорного напряжения
            movwf       VRCON         ; -//-
            banksel     IOC           ; переходим в регистр IOCB
            movlw       b'00000000'   ; запрет прерываний по изменению уровня сигнала на входах
            movwf       IOC           ; -//-
            bcf         STATUS,5      ; переход в банк 0

;читаем данные значения яркости светодиода из EEPROM
READ        bsf         STATUS,5      ; переход в банк 1
            movlw       0             ; Считывается содержимое
            movwf       EEADR         ; EEPROM-ячейки с адресом 00h.
            bsf         EECON1,RD     ; Разрешение чтения.
            movf        EEDATA,W      ; Считанный байт записывается в W.
            movwf       Reg_5         ; W -> Reg_5.
            bcf         STATUS,5      ; переход в банк 0
            call        Pause
            call        Pause
            call        Pause

loop        clrwdt                    ; сброс сторожевого таймера
            btfsc       GPIO,POWER    ; если на входе 1, то переход на "loop" (ждем поступления команды на включение)
            goto        loop          ; если 0 то данная команда пропускается
            bsf         GPIO,COLD     ; включаем холодный свет

                            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                            ; Зажигаем светодиод до заданной яркости ;
                            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
            bcf         STATUS,Z      ; сбрасываем флаг Z
            movlw       .1            ; начинаем разжигание светодиода с минимальной яркости
            movwf       Reg_3         ; -//-
            call        pwm
inc         incf        Reg_3         ; увеличиваем на 1 содержимое 3 регистра
            call        pwm

q           btfss       GPIO,UP       ; если на входе 0, то переход в подпрограмму увеличения яркости светодиода
            call        UPS           ; пропускаем если 1
            btfss       GPIO,DOWN     ; если на входе 0, то переход в подпрограмму уменьшения яркости светодиода
            call        DOWNS         ; пропускаем если 1
            movf        Reg_5,W       ; копируем в W содержимое 5 регистра
            xorwf       Reg_3,W       ; проверяем равно ли значение 3 регистра содержимому регистра W
            btfss       STATUS,Z      ; проверяем значение флага Z, если =0 то значение W и Reg_3 не равны и исполняется следующая команда,
            goto        inc           ; если =1 то значение W и Reg_3 равны и следующая команда пропускается
            bcf         STATUS,Z      ; сбрасываем флаг Z
            call        pwm


            btfsc       GPIO,POWER    ; если на входе 1, то переход на "q" => закольцовка
            goto        q             ; пропускаем если поступила команда отключения
                            ;;;;;;;;;;;;;;;;;;;;;;;;;;;
                            ; Гасим светодиод до нуля ;
                            ;;;;;;;;;;;;;;;;;;;;;;;;;;;
dec         decf        Reg_3         ; вычитаем 1 из 3 регистра
            call        pwm
            movlw       .1            ; гасим светодиод до этого значения, т.е. минимальной яркости
            xorwf       Reg_3,W       ; сравниваем значение W и регистра 3
            btfss       STATUS,Z      ; проверяем значение флага Z, если =0 то значение W и Reg_3 не равны и исполняется следующая команда, 
				      ;если =1 то значение W и Reg_3 равны и следующая команда пропускается
            goto        dec           ; -//-
            call        pwm
            call        Pause
            call        Pause
            call        Pause
            call        Pause

;записываем в EEPROM значение яркости светодиода, которое будет храниться после отключения устройства
WRITE       bsf         STATUS,5      ; переход в банк 1
            movlw       0             ; Выбор адреса той EEPROM-ячейки, в которую
            movwf       EEADR         ; будет произведена запись. В данном случае, это ячейка с адресом 00h, но можно назначить и другой адрес.
            movf        Reg_5,W       ; Копирование данных, из регистра Reg_5,
            movwf       EEDATA        ; в регистр EEDATA (то, что в нём "лежит", в дальнейшем будет записано в выбранную EEPROM-ячейку).
            bsf         EECON1,WREN   ; "Глобальное" разрешение записи.
            movlw       55h           ; Обязательная последователь команд
            movwf       EECON2        ; -//-
            movlw       0AAh          ; -//-
            movwf       EECON2        ; -//-
            bsf         EECON1,WR     ; "Запуск в работу" аппаратной процедуры записи.
;Пояснение: по окончании записи, бит WR аппаратно сбрасывается в 0 (блокировка "запуска в работу" аппаратной процедуры записи).
            btfsc       EECON1,WR     ; Запись завершена или нет?
            goto        $-1           ; Если не завершена, то проверка производится снова.
                                      ; Если завершена, то выход из "плавающей" задержки.
            bcf         EECON1,WREN   ; "Глобальный" запрет записи.
            bcf         STATUS,5      ; переход в банк 0
            goto        loop

                            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                            ; Подпрограмма увеличения яркости светодиода если нажата кнопка UP ;
                            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
UPS         bcf         STATUS,Z      ; сбрасываем флаг Z
            movlw       .254          ; константа максимальной яркости светодиода, копируем в регистр W
            xorwf       Reg_5,W       ; сверяем содержание регистров W и Reg_5
            btfss       STATUS,Z      ; результат 1, если содержимое регистров равно -> пропускаем следующую команду
            incf        Reg_5         ; увеличиваем на 1 содержимое 5 регистра, если содержание регистров W и Reg_5 не равно
            bcf         STATUS,Z      ; сбрасываем флаг Z
            return                    ; возвращаемcя по стеку обратно
                            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                            ; Подпрограмма уменьшения яркости светодиода если нажата кнопка DOWN ;
                            ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DOWNS       bcf         STATUS,Z      ; сбрасываем флаг Z
            movlw       .2            ; константа минимальной яркости светодиода, копируем в регистр W
            xorwf       Reg_5,W       ; сверяем содержание регистров W и Reg_5
            btfss       STATUS,Z      ; результат 1, если содержимое регистров равно -> пропускаем следующую команду
            decf        Reg_5         ; уменьшаем на 1 содержимое 5 регистра, если содержание регистров W и Reg_5 не равно
            bcf         STATUS,Z      ; сбрасываем флаг Z
            movf        Reg_5,W       ; копируем в W содержимое 5 регистра
            xorwf       Reg_3,W       ; проверяем равно ли значение 3 регистра содержимому регистра W
            btfss       STATUS,Z      ; результат 1, если содержимое регистров равно -> пропускаем следующую команду
            decf        Reg_3         ; уменьшаем на 1 содержимое 3 регистра, если содержание регистров W и Reg_5 не равно
            bcf         STATUS,Z      ; сбрасываем флаг Z
            return                    ; возвращаемcя по стеку обратно
                            ;;;;;;;;;;;;;;;;;;;;;
                            ; Подпрограмма ШИМа ;
                            ;;;;;;;;;;;;;;;;;;;;;
pwm         movlw       .3            ; константа определяющая время нарастания(гашения) яркости светодиода(чем больше, тем продолжительней инерционность)
            movwf       Reg_4         ; копируем константу в 4 регистр
wr          clrwdt                    ; сброс сторожевого таймера
            movf        Reg_3,W       ; копируем в W содержимое 3 регистра
            movwf       Reg_2         ; копируем содержимое регистра W в 2 регистр
            movwf       Reg_1         ; копируем содержимое регистра W в 1 регистр
            comf        Reg_1,F       ; инвертируем содержимое 1 регистра
wrr         decfsz      Reg_1,F       ; вычитаем 1 из 1 регистра, если результат не = 0, то исполняется следующая команда
            goto        wrr           ; если результат = 0, то данная команда пропускается и программа исполняется далее
            bsf         GPIO,COLD     ; зажигаем холодный светодиод
wrrr        decfsz      Reg_2,F       ; вычитаем 1 из 2 регистра, если результат не = 0, то исполняется следующая команда
            goto        wrrr          ; если результат = 0, то данная команда пропускается и программа исполняется далее
            bcf         GPIO,COLD     ; гасим светодиод
next5       decfsz      Reg_4,F       ; вычитаем 1 из 4 регистра, если результат не = 0, то исполняется следующая команда
            goto        wr            ; если результат = 0, то данная команда пропускается и программа исполняется далее
            return                    ; возвращаемcя по стеку обратно :-)

;delay = 150'000 machine cycles
Pause       movlw       .140
            movwf       Reg_1
            movlw       .195
            movwf       Reg_2
wr1         decfsz      Reg_1,F
            goto        wr1
            clrwdt
            decfsz      Reg_2,F
            goto        wr1
            return

            end
