;***************************************************************************************************
;****                              Firmware pre dvojitý časový spínač                           ****
;****                                      Procesor PIC18F88                                    ****
;****                                                                                           ****
;****                                        c.NIKI 6/2016                                      ****
;****                                            v.1.0                                          ****
;**** Pre správne zobrazenie treba nastaviť kodovanie textu na  1250 (ANSI - Central Europe)    ****
;***************************************************************************************************

 LIST P=16F88,R=DEC
 INCLUDE<p16f88.inc>
 INCLUDE<EEPROM.inc>
 INCLUDE<HD44780.inc>
;***************************************************************************************************
  ORG  h'2007'   ;konfiguračné slovo
  Data h'3F34' 
  data h'0002'   

 cblock  h'32'
 W_TMP           ;Záloha W reg. pri prerušení
 STATUS_TMP      ;Záloha registra STATUS
 FLAGS           ;Moje príznaky využité v programe
 FLAGS1
 BLIK            ;Register pre nastavenie blikania údajov
 HOD1            ;Počítadla času
 MIN1
 SEC1
 HOD2
 MIN2
 SEC2
 COUNT           ;Interné počítadlo sekúnd, register je každú sekundu dekrementovaný
 KEYS            ;Register stavu kláves
 AX0             ;Registre pre matematické výpočty
 AX1
 AX2
 BX0
 CNT             ;vnútorné počítadlo štvrť sekúnd.
 ZAL1            ;Registre pre zálohu času.
 ZAL2
 ZAL3
 ZAL4
 ZAL5
 ZAL6
 VAX0            ;Registre pre výpočty v prerušení.
 VAX1
 VAX2
 CAKAJ1          ;Registre čakacej slučky.
 CAKAJ2 
 endc

 #define      SW1           PORTA,7   ;Ovládanie výstupu SWITCH 1, Log.1 - zapne koncový spínač 1. 
 #define      SW2           PORTA,6   ;ovládanie výstupu SWITCH 2, Log.1 - zapne koncový spínač 2.
 #define      BUZZ          PORTA,4   ;Log.1 - zapne piezo sirénku.
 #define      DOOR          PORTA,3   ;Dverný kontakt osvitky, Log.0 zapne odpočet.
 #define      TM            FLAGS,0   ;TIMING - softwarové zapnutie odpočtu časovača
 #define      W_H           FLAGS,1   ;Wisible/Hide, používa rutina SHOW_BYTE, 0 - zobrazí číslo, 1 - skryje číslo, (určené pre blikanie času)
 #define      T500mS        CNT,1     ;Hodnota sa mení v intervale 500mS,(0-1-0-1),časová základna pre blikanie počas nastavovania času
 #define      INI           FLAGS,3   ;LOG.1 - Indikuje prebiehajúcu inicializáciu
 #define      TIC1          FLAGS,2   ;Time In Counter 1, príznak indikuje že v registroch času 1 čítača je nejaká hodnota.           
 #define      TIC2          FLAGS,6   ;Time In Counter 2, príznak indikuje že v registroch času 2 čítača je nejaká hodnota.            

 ;klávesnica
 #define      KEY1          KEYS,0    ;Krátke stlačenie klavesy 1
 #define      KEY2          KEYS,1    ;Krátke stlačenie klavesy 2
 #define      KEY3          KEYS,2    ;Krátke stlačenie klavesy 3
 #define      KEY4          KEYS,3    ;Krátke stlačenie klavesy 4
 #define      KEY_LONG      KEYS,4    ;Dlhé stlačenie klávesy
 #define      REL           FLAGS,4   ;RELEASE uvolnenie tlačítka

 #define      MOD1          FLAGS,5   ;indikuje MOD1, tj. že sa menu nachádza v móde nastavovania

 ;Blikanie dispeja,nastavením príslušného bitu bude údaj na LCD blikať v 500mS intervale.
 #define      B_H1          BLIK,0    ;HOD1 blikanie hodiny 1 
 #define      B_M1          BLIK,1    ;MIN1 blikanie minuty 1
 #define      B_S1          BLIK,2    ;SEC1 blikanie sekundy 1
 #define      B_H2          BLIK,3    ;HOD2 blikanie hodiny 2
 #define      B_M2          BLIK,4    ;MIN2 blikanie minuty 2
 #define      B_S2          BLIK,5    ;SEC2 blikanie sekundy 2
 
 #define      BP1           FLAGS1,0   ;BEEP 1 indikuje že už sa píplo po ukončení odpočtu, Log.1 - zákaz pípnutia
 #define      BP2           FLAGS1,1   ;BEEP 2 indikuje že už sa píplo po ukončení odpočtu

 
;*********************************************************************************************************** 

               ORG         0H
               GOTO        INIT
               ORG         4H             
           ;PRERUŠENIE          
               ;uloženie obsahu prac. registrov do zálohy
               MOVWF       W_TMP            ;W-do zálohy
               MOVF        STATUS,W         ;STATUS do zálohy
               MOVWF       STATUS_TMP
               BTFSS       PIR1,TMR1IF      ;Test či sa jedná o prerušenie od TMR1
               GOTO        END_INT          ;NIE - odchod z prerusenia.

               ;Prerušenie od TMR1, nové nastavenie časovača na 0,25 Sekundy.
               BCF         PIR1,TMR1IF      ;Vynulujeme príznak prerušenia od TMR1               
               nop                          ;Dodatočné kroky aby bol časový interval presne 500.0000mS
               nop
               noP
               NOP
               MOVLW       133              ;Nastavíme nový čas pre TMR1, 250mSec.           
               MOVWF       TMR1H           
               MOVLW       240
               MOVWF       TMR1L            ;<--- 250 mS interval, v tomto bode.

           ;Časová záklaňa 250mS.
               INCF        CNT,F            ;Každých 250mS inkrementuj interné počítadlo
                             
               ;Testuj či neprebieha inicializácia mikrokontroléra
INTJ0          BTFSC       INI
               GOTO        INTJ3            ;Ak práve prebieha init, odchod na koniec obsluhy prerušenia.
                          
               ;Každých 250mS zobraz obsah registrov času
               MOVLW       8                ;Nastav kurzor na 1 riadok, 8 znak. 
               MOVWF       LCD_COL
               MOVLW       1
               MOVWF       LCD_ROW
               CALL        LCD_SET_POS      ;Vykonaj nastavenie.
               BTFSC       T500mS           ;Každú druhú polsekundu prednastavíme skrytie znaku.
               BSF         W_H              ;(Wisible/Hide) W_H v Log.1 = skryj znaky   
               BTFSS       B_H1             ;(Blik Hodiny 1) Ak nebolo povolené blikanie následujúceho znaku tak zhoď blikanie.
               BCF         W_H
               MOVF        HOD1,W           ;Zobraz obsah HOD1 (2 dekadicke cislice), ak je W_H = 0 číslo sa zobrazí, ak je W_H = 1 zobrazí sa prázdny znak.
               CALL        SHOW_BYTE
               CALL        LCD_CUR_INC      ;Posun kurzora cez dvojbodku.
               BTFSC       T500mS           ;Každú druhú polsekundu prednastavíme skrytie znaku.
               BSF         W_H              ;W_H v Log.1 = skryj znaky
               BTFSS       B_M1             ;Ak nebolo povolené blikanie následujúceho znaku tak zhoď blikanie.
               BCF         W_H
               MOVF        MIN1,W           ;Zobraz obsah MIN1
               CALL        SHOW_BYTE
               CALL        LCD_CUR_INC      ;Posun kurzora cez dvojbodku.
               BTFSC       T500mS           ;Každú druhú polsekundu prednastavíme skrytie znaku.
               BSF         W_H              ;W_H v Log.1 = skryj znaky.
               BTFSS       B_S1             ;Ak nebolo povolené blikanie následujúceho znaku tak zhoď blikanie.
               BCF         W_H
               MOVF        SEC1,W           ;Zobraz obsah SEC1
               CALL        SHOW_BYTE
               MOVLW       2                ;Nastav kurzor na 2 riadok.
               MOVWF       LCD_ROW     
               CALL        LCD_SET_POS
               BTFSC       T500mS           ;Každú druhú polsekundu prednastavíme skrytie znaku.
               BSF         W_H              ;W_H v Log.1 = skryj znaky.
               BTFSS       B_H2             ;Ak nebolo povolené blikanie následujúceho znaku tak zhoď blikanie.
               BCF         W_H
               MOVF        HOD2,W           ;Zobraz obsah HOD2
               CALL        SHOW_BYTE
               CALL        LCD_CUR_INC      ;Posun kurzora cez dvojbodku.
               BTFSC       T500mS           ;Každú druhú polsekundu prednastavíme skrytie znaku.
               BSF         W_H              ;W_H v Log.1 = skryj znaky.
               BTFSS       B_M2             ;Ak nebolo povolené blikanie následujúceho znaku tak zhoď blikanie
               BCF         W_H
               MOVF        MIN2,W           ;Zobraz obsah MIN2
               CALL        SHOW_BYTE
               CALL        LCD_CUR_INC      ;Posun kurzora cez dvojbodku.
               BTFSC       T500mS           ;Každú druhú polsekundu prednastavíme skrytie znaku.
               BSF         W_H              ;W_H v Log.1 = skryj znaky
               BTFSS       B_S2             ;Ak nebolo povolené blikanie následujúceho znaku tak zhoď blikanie.
               BCF         W_H
               MOVF        SEC2,W           ;Zobraz obsah SEC2
               CALL        SHOW_BYTE

              ;Testovanie či je v čítači prvého času nastavený nejaký čas, ak nie vypni SW1.
               BCF         TIC1
               CLRW
               ADDWF       HOD1,W           ;Sčítame všetky časy
               ADDWF       MIN1,W 
               ADDWF       SEC1,W
               SKPZ                         ;Ak je súčet 0, ponecháme TIC1 v nule.
               BSF         TIC1             ;Ak je súčet väčší ako 0 nastavíme TIC1
               BNZ         INTJ0a
               BCF         SW1              ;Ak je čas 0, vypni koncový spínač 1.
               BTFSS       BP1              ;Ak je povolené pípnutie BP1=0 tak pípni.
               CALL        BEEP2            ;Dlho pípni.
               BSF         BP1              ;Práve sa píplo, indikuj že pípnutie prebehlo.
               
               ;Testovanie či je v čítači druhého času nastavený nejaký čas, ak nie vypni SW2.
INTJ0a         BCF         TIC2             ;popis ako pri TIC1.
               CLRW
               ADDWF       HOD2,W
               ADDWF       MIN2,W
               ADDWF       SEC2,W
               SKPZ 
               BSF         TIC2
               BNZ         INTJ0b
               BCF         SW2              ;Vypni koncový spínač 2.
               BTFSS       BP2
               CALL        BEEP2            ;Ak vypršal čas odpočtu dlho pípni.
               BSF         BP2       

               ;Zhodenie príznaku časovača TM ak oba čítače skončili odpočet.
INTJ0b         MOVLW       B'01000100' 
               ANDWF       FLAGS,W
               SKPNZ
               BCF         TM

          ;časová záklaňa 1sec.
             ;V každom štvrtom prechode (4*250mS = 1Sec.) zníž počítadlo sekúnd.
INTJ3         MOVLW         B'00000011'     ;Zmažeme všetky bity okrem 0 a 1 
              ANDWF         CNT,F
              SKPZ                          ;ak je register v nule ubehla sekunda
              GOTO          END_INT         ;ak ubehlo menej ako 1 sekunda, odchod.
              
              DECF          COUNT,F         ;<--- 1 Sekundový interval
              BTFSC         MOD1            ;zabezpečenie aby nedošlo k náhodnému spusteniu čítača pri nastavovaní času.
              GOTO          END_INT         ;
             
              ;Test či je spustený odpočet časovača 1, na odpočet sa ide ak sú zatvorené dvierka alebo ak je spustený odpočet tlačítkom.
              BTFSS         DOOR            ;Pokračuj na časovač iba ak je Log.0 dvierka zatvorené.
              GOTO          INTJ1           ;Log.0 dvierka zatvorené, choď na odpočet prvého časovača. 
              BTFSS         TM              ;Dvierka sú otvorené, testuj či je zapnutý odpočet tlačítkom.
              GOTO          INTJ5           ;NIE- odchod.
             
              ;odpočet času prvého časovača
INTJ1         BTFSS         TIC1            ;Odpočet prebehne iba ak je v čítačoch nejaký čas, TIC1=1
              GOTO          INTJ2           ;inak odchod.
              BSF           SW1             ;V časovači je nejaký čas, zapni koncový spínač 1.
              MOVLW         1              
              SUBWF         SEC1,F          ;čas -1 sekunda, nepoužívame decf pretože neovplyvňuje príznaky!
              SKPNC                         ;Skok ak je výsledok záporný  
              GOTO          INTJ2           ;výsledok je kladný, čítač sekúnd nepodtiekol,choď na druhý časovač.
              MOVLW         59              ;Ošetrenie podtečenia času. Ak je čas < 0 potom vlož 59. 
              MOVWF         SEC1
              MOVLW         1
              SUBWF         MIN1,F
              SKPNC 
              GOTO          INTJ2
              MOVLW         59
              MOVWF         MIN1
              DECF          HOD1,F
              
              ;odpočet času druhého časovača
INTJ2         BTFSS         TIC2
              GOTO          END_INT
              BSF           SW2             ;V časovači je nejaký čas,zapni koncový spínač 2
              MOVLW         1              
              SUBWF         SEC2,F          ;Čas -1 sekunda
              SKPNC                         ;Skok ak je výsledok záporný  
              GOTO          END_INT         ;výsledok je kladný, čítač sekúnd nepodtiekol,choď na koniec obsluhy.
              MOVLW         59
              MOVWF         SEC2
              MOVLW         1
              SUBWF         MIN2,F
              SKPNC 
              GOTO          END_INT
              MOVLW         59
              MOVWF         MIN2
              DECF          HOD2,F
              GOTO          END_INT

INTJ5         BCF           SW1
              BCF           SW2
              
              ;Koniec obsluhy prerušenia a obnova pracovných registrov.
END_INT       MOVF          STATUS_TMP,W
              MOVWF         STATUS            ;Obnova statusu
              MOVF          W_TMP,W           ;Obnova W
              RETFIE
;***************************************************************************************************************************            
  
INIT          CLRWDT
              BANKSEL       OSCCON            ;výber tretej stranky pamäti
              MOVLW         B'01100000'       ;oscilátor interný,4Mhz
              MOVWF         OSCCON     
              CLRF          OSCTUNE
              MOVLW         B'00101111'       ;bit4, 6 a 7 ako výstupy
              MOVWF         TRISA
              MOVLW         B'11000000'       ;bit0-3,6,7 ako vstupy; bit4,5 ako výstupy
              MOVWF         TRISB
              BSF           PIE1, TMR1IE      ;povoľ prerušenie od TMR1
              BANKSEL       TMR1H             ;stránka 0
              MOVLW         11                ;prednastav TMR1 na pretečenie po 1 Sec.
              MOVWF         TMR1H             
              MOVLW         222
              MOVWF         TMR1L 
              BANKSEL       ANSEL             ;výber druhej banky 
              CLRF          ANSEL             ;portA ako digitálne I/O
              BANKSEL       PORTA             ;banka 0  
              BCF           INTCON,GIE
              CLRF          FLAGS
              BSF           INI     
              MOVLW         B'00010000'       ;vypni BUZZ
              MOVWF         PORTA
              CLRF          PORTB
              BSF           RS                ;nastav LCD na príjem povelu
              MOVLW         B'00110001'       ;zapni časovač TMR1, preddelič na 1:8
              MOVWF         T1CON  
              CLRF          HOD1
              CLRF          MIN1
              CLRF          SEC1
              CLRF          HOD2
              CLRF          MIN2
              CLRF          SEC2
              CLRF          BLIK
              BSF           INTCON,GIE        ;povoľ prerušenia
              BSF           INTCON,PEIE
              CALL          LCD_INIT          ;inicializuj displej
              CALL          LCD_NATIONAL      ;natiahni do LCD národnú znakovú sadu.

              ;zobraz intro 1 riadok
              MOVLW         1                 ;kurzor na riadok 1, stĺpec 1
              MOVWF         LCD_ROW
              MOVWF         LCD_COL
              CALL          LCD_SET_POS
              MOVLW         40H              ;INTRO1, počiatočná adresa textu intra v EEPROM 
              MOVWF         EE_ADR
              CALL          LCD_WR_STR
              ;zobraz intro 2 riadok 
              MOVLW         2                ;kurzor na riadok 2, stĺpec 2
              MOVWF         LCD_ROW
              MOVWF         LCD_COL
              CALL          LCD_SET_POS
              MOVLW         51H              ;INTRO2, počiatočná adresa textu intra v EEPROM 
              MOVWF         EE_ADR
              CALL          LCD_WR_STR 
              ;pockaj 2 sekundy
              MOVLW         2
              MOVWF         COUNT
SJ1           CLRWDT
              MOVF          COUNT,F
              BNZ           SJ1
              ;pipni
              CALL          BEEP1
              ;zmaz displej
              CALL          LCD_CLR
              CALL          SHOW_MENU1
              BCF           INI              ;Koniec inicializácie

       ;HLAVNA SLUCKA PROGRAMU
MAIN          CLRWDT
              CALL         INKEY             ;Zosnímaj stav tlačítok a dekóduj klávesy.
              BTFSC        KEY_LONG          ;test či bolo dlhé stlačenie klávesy
              GOTO         MJ14              ;ano, pokračuj obsluhu dlhého stlačenia

       ;základné menu, krátke stlačenie tlačítka. 
              ;KEY1, START/STOP
              BTFSS        KEY1              ;Test či bolo stlačené tlačítko KEY1
              GOTO         MJ11              ;nie, pokračuj v zisťovaní aké tlačítko bolo stlačené.
              MOVLW        B'00000001'       ;ano, zapneme/vypneme oba časovače. (BTG  TM )
              XORWF        FLAGS,F
              BTFSS        TM                ;Test či je zapnuté časovanie (odpočet)
              GOTO         MJ10              ;nie, odchod
              BTFSC        TIC1              ;Test či je v časovači 1 nejaký čas
              BSF          SW1               ;áno, okamžite zopni výstup 1
              BTFSC        TIC2              ;Test či je v časovači 2 nejaký čas
              BSF          SW2               ;áno, okamžite zopni výstup 2 
              CLRF         CNT               ;Vynuluj poč. sekúnd aby sekunda začala od nuly.
              BTFSC        TIC1              ;Test či je v časovači 1 nejaký čas
              BCF          BP1               ;áno, povoľ pípnutie po dokončení odpočtu 1
              BTFSC        TIC2              ;Test či je v časovači 2 nejaký čas
              BCF          BP2               ;áno, povoľ pípnutie po dokončení odpočtu 2
              GOTO         MJ11
MJ10          BCF          SW1               ;Časovanie zakázané, okamžite odpoj výstupy.
              BCF          SW2
              BSF          BP1               ;a zakáž pípnutie.
              BSF          BP2
              GOTO         MAIN
              ;KEY2, CLR UP              
MJ11          BTFSS        KEY2              ;test či bolo stlačené tlačítko KEY2
              GOTO         MJ12              ;nie, pokračuj v zisťovaní aké tlačítko bolo stlačené.
              CLRF         HOD1              ;ano, vynuluj počítadlo 1.
              CLRF         MIN1
              CLRF         SEC1
              GOTO         MAIN
              ;KEY3, CLR DOWN
MJ12          BTFSS        KEY3              ;test či bolo stlačené tlačítko KEY3
              GOTO         MJ13              ;nie, pokračuj v zisťovaní aké tlačítko bolo stlačené.
              CLRF         HOD2              ;ano, vynuluj počítadlo 2.
              CLRF         MIN2
              CLRF         SEC2   
              GOTO         MAIN                         
              ;KEY4, PRESSET 2 Minuty
MJ13          BTFSC        SW1               ;testuj či nebeží odpočet.
              GOTO         MAIN              ;ak áno, nebude sa dať prednastavovať
              BTFSC        SW2
              GOTO         MAIN
              BTFSS        KEY4              ;test či bolo stlačené tlačítko KEY4
              GOTO         MAIN              ;nie, pokračuj v zisťovaní aké tlačítko bolo stlačené.
              MOVLW        2                 ;prednastavíme čas 2 minúty do oboch časovačov
              MOVWF        MIN1
              MOVWF        MIN2
              CLRF         HOD1
              CLRF         HOD2
              CLRF         SEC1
              CLRF         SEC2
              BCF          TM                ;vypneme odpočet ak bol predtým zapnutý.
              GOTO         MAIN
         
              ;KEY1 + KEY_LONG, základné menu, ošetrenie dlhého stlačenia tlačítka
MJ14          BTFSC        TM                ;Test či beží odpočet, ak áno nepovolíme vykonanie dlhého stlačenia
              GOTO         MAIN
              BTFSS        KEY1              ;test či sa jednalo o dlhé stlačenie klávesy KEY1.
              GOTO         MJ15              ;nie, pokračuj v zisťovaní o aká klávesa bola stlačená.
              CALL         TIME_TO_ZAL       ;aktuálne nastavený čas ulož do zálohy.
              ;Prechod do módu 1, nastavovanie času.
              BSF          MOD1              ;indikujeme že je program v móde1 (v nastavovaní času)
              MOVLW        1
              MOVWF        BLIK
              GOTO         MJ20              ;pokračuj na menu 2 
                         ;KEY2 + KEY_LONG  vyvolanie menu 3 save
MJ15          BTFSS        KEY2              ;test či sa jednalo o dlhé stlačenie klávesy KEY4
              GOTO         MJ16              ;Nie, odchod zo ziťovania kláves.
              MOVLW        0                 ;Prednastav ukazateľ na prvé miesto pre uloženie SAVE.
              MOVWF        AX2
              ;Zobraz menu 3,preset, menu 3 je spoločné pre save i load 
              MOVLW        1                 ;Nastav riadok 1, stlpec 1
              MOVWF        LCD_COL
              MOVWF        LCD_ROW
              CALL         LCD_SET_POS
              MOVLW        MEM1              ;adresa 1 riadku textu
              CALL         LCD_WR_STR        ;prenes text na LCD
              INCF         LCD_ROW,F         ;posun na druhý riadok
              CALL         LCD_SET_POS
              MOVLW        MEM2              ;adresa druhého riadku
              CALL         LCD_WR_STR        ;text na LCD
              GOTO         MJ40              ;pokračuj obsluhu 4
              
              ;KEY4 + KEY_LONG vyvolanie menu 3, preset
MJ16          BTFSS        KEY4              ;test či sa jednalo o dlhé stlačenie klávesy KEY4
              GOTO         MAIN              ;Nie, odchod zo ziťovania kláves.
              CALL         TIME_TO_ZAL       ;Áno, ulož aktuálny čas do zálohy.
              CLRF         AX2               ;Prednastav ukazateľ na prvý preset (0).
              ;Zobraz menu 3
              MOVLW        1                 ;Nastav riadok 1, stlpec 1
              MOVWF        LCD_COL
              MOVWF        LCD_ROW
              CALL         LCD_SET_POS
              MOVLW        MEM1              ;adresa 1 riadku textu
              CALL         LCD_WR_STR        ;prenes text na LCD
              INCF         LCD_ROW,F         ;posun na druhý riadok
              CALL         LCD_SET_POS
              MOVLW        MEM2              ;adresa druhého riadku
              CALL         LCD_WR_STR        ;text na LCD
              MOVLW        0   
              CALL         LOAD_PRESET
              GOTO         MJ30              ;pokračuj obsluhu menu 3

        ;Menu 2,nastavovanie času
MJ20          CLRWDT
              CALL         INKEY            ;získaj stav tlačítok
              BTFSC        KEY_LONG         ;test či šlo o dlhé stlačenie
              GOTO         MJ25             ;ÁNO, pokračuj na ošetrenie dlhého stlačenia.

               ;Tlačítko KEY1 posúva ukazateľ výberu času.
              BTFSS      KEY1             ;test či bolo stlačené KEY1
              GOTO       MJ22             ;nie, pokračuj na iné tlačítko
              BCF        STATUS,C         ;áno, posuň blikanie na ďalšiu číslicu
              RLF        BLIK,F           ;posun ukazateľa blikania na ďalšiu čislicu.
              ;uzavretie výberovej slučky
              MOVLW      64               ;ak bol vybraný register SEC2 bude nasledovať výber HOD1
              SUBWF      BLIK,W           ;uzavretie slučky výberu.
              MOVLW      1
              SKPNZ
              MOVWF      BLIK
              GOTO       MJ20              

              ;tlačítko KEY2 zvyšuje obsah čítača.           
MJ22          BTFSS      KEY2             ;test či bola stlačená klávesa KEY2
              GOTO       MJ23             ;nie, pokračuj na ďalšiu klávesu.
              BTFSS      B_H1             ;testuj či bliká HOD1
              GOTO       $+4              ;nie, pokračuj na ďalšiu číslicu 
              INCF       HOD1,W           ;áno, zvyš obsah o 1 
              CALL       TEST60           ;testuj pretečenie času, ak je > 59 uprav na 0
              MOVWF      HOD1             ;vlož do registra.
              BTFSS      B_M1             ;rovnaký algoritmus platí aj pre MIN1,SEC1,HOD2,MIN2,SEC2...
              GOTO       $+4
              INCF       MIN1,W
              CALL       TEST60
              MOVWF      MIN1
              BTFSS      B_S1
              GOTO       $+4
              INCF       SEC1,W
              CALL       TEST60
              MOVWF      SEC1
              BTFSS      B_H2
              GOTO       $+4
              INCF       HOD2,W
              CALL       TEST60
              MOVWF      HOD2
              BTFSS      B_M2
              GOTO       $+4
              INCF       MIN2,W
              CALL       TEST60
              MOVWF      MIN2
              BTFSS      B_S2
              GOTO       $+4
              INCF       SEC2,W
              CALL       TEST60
              MOVWF      SEC2
              CLRF       CNT                ;Pozdrží blikanie znaku (rozsvieti znak nasilu)
              BSF        INTCON,TMR1IF      ;okamžite zobrazí číslo na LCD.
              GOTO       MJ20

              ;tlačítko KEY3 znižuje obsah čítača. 
MJ23          BTFSS      KEY3               ;test či bola stlačená klávesa KEY3
              GOTO       MJ24               ;nie, pokračuj na ďalšiu klávesu.
              BTFSS      B_H1               ;testuj či bliká HOD1
              GOTO       $+4                ;nie, pokračuj na ďalšiu číslicu
              DECF       HOD1,W             ;áno, zníž obsah o 1
              CALL       TEST00             ;testuj pretečenie času, ak je < 0 uprav na 59
              MOVWF      HOD1               ;vlož do registra.
              BTFSS      B_M1               ;rovnaký algoritmus platí aj pre MIN1,SEC1,HOD2,MIN2,SEC2...
              GOTO       $+4
              DECF       MIN1,W
              CALL       TEST00
              MOVWF      MIN1
              BTFSS      B_S1
              GOTO       $+4
              DECF       SEC1,W
              CALL       TEST00
              MOVWF      SEC1
              BTFSS      B_H2
              GOTO       $+4
              DECF       HOD2,W
              CALL       TEST00
              MOVWF      HOD2
              BTFSS      B_M2
              GOTO       $+4
              DECF       MIN2,W
              CALL       TEST00
              MOVWF      MIN2
              BTFSS      B_S2
              GOTO       $+4
              DECF       SEC2,W
              CALL       TEST00
              MOVWF      SEC2
              CLRF       CNT                ;Pozdrží blikanie znaku
              BSF        INTCON,TMR1IF      ;okamžite zobraz číslo na LCD
              GOTO       MJ20

               ;pripočítaj k nast. času 30 sekúnd.
MJ24          BTFSS      KEY4               ;test či bola stlačená klávesa KEY4    
              GOTO       MJ20               ;nie, odchod.
              MOVLW      30
              BTFSC      B_H1
              ADDWF      HOD1,W
              BTFSC      B_M1
              ADDWF      MIN1,W
              BTFSC      B_S1
              ADDWF      SEC1,W
              BTFSC      B_H2
              ADDWF      HOD2,W
              BTFSC      B_M2
              ADDWF      MIN2,W
              BTFSC      B_S2
              ADDWF      SEC2,W
              MOVWF      AX0
              MOVLW      60
              SUBWF      AX0,W               
              SKPC
              ADDLW      60
              BTFSC      B_H1
              MOVWF      HOD1
              BTFSC      B_M1
              MOVWF      MIN1
              BTFSC      B_S1
              MOVWF      SEC1
              BTFSC      B_H2
              MOVWF      HOD2
              BTFSC      B_M2
              MOVWF      MIN2
              BTFSC      B_S2
              MOVWF      SEC2
              GOTO       MJ20

         ;menu 2, ošetrenie dlhého stlačenia tlačítka 
               ;KEY1 + KEY_LONG              
MJ25          BTFSS      KEY1               ;OK, použij nastvenie času
              GOTO       MJ26
              BCF        MOD1
              CLRF       BLIK               ;zruš blikanie číslic.
              GOTO       MAIN
              ;KEY4 + KEY_LONG
MJ26          BTFSS      KEY4               ;ESC, odchod bez použitia nastavenia času.
              GOTO       MJ20
              BCF        MOD1               ;zruš mód 1
              CLRF       BLIK               ;zruš blikanie číslic.
              CALL       TIME_FROM_ZAL      ;obnov pôvodný stav čítačov
              GOTO       MAIN

         ;menu 3, ošetrenie krátkeho stlačenia kláves 
MJ30          CLRWDT     
              CALL       INKEY
              ;KEY1, OK odchod z menu3 na menu1
              BTFSS      KEY1
              GOTO       MJ31               ;ak sa nejednalo o klavesu KEY1 pokračuj na testovanie ďalšej klávesy.
              CALL       SHOW_MENU1         ;zobraz menu1 
              GOTO       MAIN               ;odchod z menu3
 
              ;KEY2, + pohyb v menu
MJ31          BTFSS      KEY2
              GOTO       MJ32
              INCF       AX2,F
              MOVF       AX2,W
              SUBLW      10
              SKPNZ
              CLRF       AX2
              MOVF       AX2,W
              CALL       LOAD_PRESET
              GOTO       MJ30

              ;KEY3, - pohyb v menu
MJ32          BTFSS      KEY3
              GOTO       MJ33
              MOVLW      1  
              SUBWF      AX2,F
              MOVLW      9
              SKPC
              MOVWF      AX2
              MOVF       AX2,W
              CALL       LOAD_PRESET               
              GOTO       MJ30

              ;KEY4, ESC odchod z menu bez nastavenia času
MJ33          BTFSS      KEY4
              GOTO       MJ30               ;ak sa nejednalo o klavesu KEY4 odchod.
              CALL       TIME_FROM_ZAL      ;inak obnov čas zo zálohy
              CALL       SHOW_MENU1         ;zobraz menu1
              GOTO       MAIN               ;odchod z menu 3 



 ;menu 4, ošetrenie krátkeho stlačenia kláves 
MJ40          CLRWDT     
              CALL       INKEY
              ;KEY1, OK odchod z menu3 na menu1
              BTFSS      KEY1
              GOTO       MJ41               ;ak sa nejednalo o klavesu KEY1 pokračuj na testovanie ďalšej klávesy.
              CALL       SHOW_MENU1         ;zobraz menu1 
              MOVF       AX2,W
              CALL       SAVE_PRESET
              GOTO       MAIN               ;odchod z menu3
 
              ;KEY2, + pohyb v menu
MJ41          BTFSS      KEY2
              GOTO       MJ42
              INCF       AX2,F
              MOVF       AX2,W
              SUBLW      10
              SKPNZ
              CLRF       AX2
              MOVLW      1           
              MOVWF      LCD_ROW
              MOVLW      5
              MOVWF      LCD_COL
              CALL       LCD_SET_POS        ;nastav kuzor na riadok 1, stĺpec 5
              MOVLW      30h                ;prednastav bázu čísiel v tabulke znakov
              ADDWF      AX2,W              ;k báze pripočítaj číslo miesta v eeprom (presetu)
              CALL       LCD_WR_CHAR        ;na LCD zobraz číslo presetu
              GOTO       MJ40

              ;KEY3, - pohyb v menu
MJ42          BTFSS      KEY3
              GOTO       MJ43
              MOVLW      1  
              SUBWF      AX2,F
              MOVLW      9
              SKPC
              MOVWF      AX2
              MOVLW      1           
              MOVWF      LCD_ROW
              MOVLW      5
              MOVWF      LCD_COL 
              CALL       LCD_SET_POS        ;nastav kuzor na riadok 1, stĺpec 5
              MOVLW      30h                ;prednastav bázu čísiel v tabulke znakov
              ADDWF      AX2,W              ;k báze pripočítaj číslo miesta v eeprom (presetu)
              CALL       LCD_WR_CHAR        ;na LCD zobraz číslo presetu               
              GOTO       MJ40

              ;KEY4, ESC odchod z menu bez nastavenia času
MJ43          BTFSS      KEY4
              GOTO       MJ40               ;ak sa nejednalo o klavesu KEY4 odchod.
              CALL       SHOW_MENU1         ;zobraz menu1
              GOTO       MAIN               ;odchod z menu 3 
            
;*****************************************************************************************
;zistí či pretiekol čítač času cez 59 a ak áno, vráti vo W nulu.
TEST60        MOVWF      AX0
              MOVLW      60
              SUBWF      AX0,W
              MOVLW      0
              SKPZ
              MOVF       AX0,W
              RETURN

;zistí či podtiekol čítač času pod 0 a ak áno, vráti vo W 59
TEST00        MOVWF      AX0
              MOVLW      255
              SUBWF      AX0,W
              MOVLW      59
              SKPZ
              MOVF       AX0,W
              RETURN
               
;Snímanie klávesnice, podľa stavu tlačítiek nastaví bity v reg. KEYS.
INKEY         CLRF        KEYS    
              MOVF        PORTA,W         ;Stav tlačítok do W
              ANDLW       B'00000111'     ;vynuluj vsetky bity okrem 3-0 (klavesnica)
              MOVWF       BX0             ;stav tlacitok do zalohy
              SUBLW       7               ;testuj ci je zmacknute nejake tlacitko
              BNZ         INKJ0           ;ak nieje stlacene ziadne tak odchod z rutiny
              BCF         REL             ;tlacitka su uvolnene tak zhodime RELEASE
              RETURN
                       
INKJ0         BTFSC       REL
              RETURN                      ;bolo dlhe stlacenie,a su drzane tlacitka preto odchod
              CALL        CAKAJ15         ;su stlacene nejake tlackitka, pockaj 15mS kvoli odskokom.
              MOVF        PORTA,W         ;stav tlacitok do W  
              ANDLW       B'00000111'     ;vynuluj vsetky bity okrem 3-0 (klavesnica
              SUBWF       BX0,W           ;porovnaj aktualny stav tlacitok zo zalohou.
              SKPZ                        ;ak je stav rovnaky pokracuj dalej na obsluhu
              RETURN                      ;stav tlacitok je iny, chyba,odchod z rutiny.
              CALL        BEEP1           ;bolo kratke stlacenie,pipni
              ;testovanie dlzky stlacenia tlacitka
              MOVLW       2               ;Prednastav interval casovaca na 2 Sekundy.
              MOVWF       COUNT
INKJ1         MOVF        PORTA,W         ;snimaj stav tlacitok
              ANDLW       B'00000111'     
              SUBLW       7               ;test ci boli vsetky tlacitka uvolnene
              BZ          INKJ2           ;niesu uvolnene, cakaj do uvolnenia tlacitok alebo do vyprsania casu (COUNT)
              TSTF        COUNT           ;test či vypršal čas 1 sekunda
              BZ          INKJ3           ;ano, čas vypršal, jedná sa o dlhé stlačnie.
              CLRWDT                      ;nie, čas ešte nevypršal, čakáme na uvolnenie tlačítka.
              GOTO         INKJ1            
              ;dlhe stlačenie
INKJ3         BSF          REL            ;nastav príznak že je tlačítko stále držané.
              CALL         BEEP2          ;dlhé pípnutie
              BSF          KEY_LONG       ;nastav príznak že šlo o dlhé stlačenie
                    
         ;Dlhé + krátke stlačenie, zisťovanie ktoré tlačítko bolo stlačené.    
INKJ2         MOVLW        6                ;tlacitko 1
              SUBWF        BX0,W 
              BNZ          $+3
              BSF          KEY1
              RETURN 
              MOVLW        5                ;tlacitko 2
              SUBWF        BX0,W
              BNZ          $+3
              BSF          KEY2
              RETURN
              MOVLW        3                ;tlacitko 3
              SUBWF        BX0,W
              BNZ          $+3
              BSF          KEY3
              RETURN
              MOVLW        4                ;tlacitko 4
              SUBWF        BX0,W
              SKPNZ
              BSF          KEY4
              RETURN       ;odchod tlačítko nezodpovedá žiadnemu z testovaných (tu môže pokračovať testovanie ďalších tlačítok)

 
;Zobrazí základné menu na displej
SHOW_MENU1    MOVLW        1                ;kurzor na riadok 1, stĺpec 1
              MOVWF        LCD_ROW
              MOVWF        LCD_COL
              CALL         LCD_SET_POS 
              MOVLW        LN1              ;LN1, počiatočná adresa textu prveho casovaca v EEPROM 
              MOVWF        EE_ADR
              CALL         LCD_WR_STR
              ;zobraz casovace 2 riadok 
              MOVLW        2                ;kurzor na riadok 2, stĺpec 1
              MOVWF        LCD_ROW          
              MOVLW        1
              MOVWF        LCD_COL
              CALL         LCD_SET_POS
              MOVLW        LN2              ;LN2,počiatočná adresa textu intra v EEPROM 
              MOVWF        EE_ADR
              CALL         LCD_WR_STR 
              RETURN
       
;Zobrazi preset podla cisla na LCD a natiahne časy do registrov času, číslo pameťového miesta vo W, 0..9
LOAD_PRESET   MOVWF        BX0              ;číslo miesta do zálohy
              MOVLW        1           
              MOVWF        LCD_ROW
              MOVLW        5
              MOVWF        LCD_COL
              CALL         LCD_SET_POS      ;nastav kuzor na riadok 1, stĺpec 5
              MOVLW        30h              ;prednastav bázu čísiel v tabulke znakov
              ADDWF        BX0,W            ;k báze pripočítaj číslo miesta v eeprom (presetu)
              CALL         LCD_WR_CHAR      ;na LCD zobraz číslo presetu
              MOVLW        H'A0'            ;počiatočná adresa v EEPROM kde začínajú presety
LPJ0          TSTF         BX0              ;testuj číslo umiestnenia v EEPROM
              BZ           LPJ1             ;číslo je 0, odchod na preset 0
              DECF         BX0,F            ;číslo je väčšie ako 0, adresu zvýš o počet miest * 6
              ADDLW        6
              GOTO         LPJ0             ;návrat na testovanie čísla umiestnenia v EEPROM
LPJ1          MOVWF        EE_ADR           ;adresa presetu v EEPROM
              CALL         RD_EEPROM        ;nčítaj časy z daného presetu v EEPROM
              MOVWF        HOD1
              CALL         RD_EEPROM
              MOVWF        MIN1
              CALL         RD_EEPROM
              MOVWF        SEC1
              CALL         RD_EEPROM
              MOVWF        HOD2
              CALL         RD_EEPROM
              MOVWF        MIN2
              CALL         RD_EEPROM
              MOVWF        SEC2
              RETURN

;Uloží preset podla cisla do EEPROM na číslo pameťového miesta ktoré je vo W, 0..9
SAVE_PRESET   MOVWF        BX0              ;číslo miesta do zálohy
              MOVLW        H'A0'            ;počiatočná adresa v EEPROM kde začínajú presety
SPJ0          TSTF         BX0              ;testuj číslo umiestnenia v EEPROM
              BZ           SPJ1             ;číslo je 0, odchod na preset 0
              DECF         BX0,F            ;číslo je väčšie ako 0, adresu zvýš o počet miest * 6
              ADDLW        6
              GOTO         SPJ0             ;návrat na testovanie čísla umiestnenia    
SPJ1          MOVWF        EE_ADR           ;adresa presetu v EEPROM
              MOVF         HOD1,W
              CALL         WR_EEPROM        ;ulož čas do daného presetu v EEPROM
              MOVF         MIN1,W
              CALL         WR_EEPROM
              MOVF         SEC1,W
              CALL         WR_EEPROM
              MOVF         HOD2,W
              CALL         WR_EEPROM
              MOVF         MIN2,W
              CALL         WR_EEPROM
              MOVF         SEC2,W
              CALL         WR_EEPROM
              RETURN

;Prenesie stav casovych registrov do zalohy.  
TIME_TO_ZAL   MOVF         HOD1,W
              MOVWF        ZAL1
              MOVF         MIN1,W
              MOVWF        ZAL2
              MOVF         SEC1,W
              MOVWF        ZAL3             
              MOVF         HOD2,W
              MOVWF        ZAL4
              MOVF         MIN2,W
              MOVWF        ZAL5
              MOVF         SEC2,W
              MOVWF        ZAL6
              RETURN                        

;Prenesie zo zalohy cas do pracovnych regisrov.  
TIME_FROM_ZAL MOVF         ZAL1,W
              MOVWF        HOD1
              MOVF         ZAL2,W
              MOVWF        MIN1
              MOVF         ZAL3,W
              MOVWF        SEC1            
              MOVF         ZAL4,W
              MOVWF        HOD2
              MOVF         ZAL5,W
              MOVWF        MIN2
              MOVF         ZAL6,W
              MOVWF        SEC2
              RETURN          

;zobrazi na LCD obsah W registra (1 byte) ako dve dekadicke cislice.
SHOW_BYTE     BTFSS        W_H            ;test WISIBLE/HIDE bitu,0-zobraz cislo, 1-zobraz prazdne miesto
              GOTO         $+5            ;choď na volanie HEXtoDEC
              MOVLW        h'CE'          ;znak medzera do W CEh+30h=FEh (FEh je znak medzera) 
              MOVWF        VAX1
              MOVWF        VAX0
              BTFSS        W_H
              CALL         HEXtoDEC
              MOVF         VAX1,W
              ADDLW        30H
              CALL         LCD_WR_CHAR
              MOVF         VAX0,W
              ADDLW        30H
              CALL         LCD_WR_CHAR
              BCF          W_H
              RETURN

;Kratko pipne
BEEP1         BCF          BUZZ              ;zapni bzučák
              MOVLW        40 ;20            ;čakaj 150mS 
              MOVWF        CAKAJ1
              MOVWF        CAKAJ2
              CALL         DELAY
              BSF          BUZZ              ;vypni bzučák
              RETURN

;Dlhe pipnutie 1 sekundu
BEEP2         BCF          BUZZ
              MOVLW        200               ;100
              MOVWF        CAKAJ1
              MOVWF        CAKAJ2
              CALL         DELAY
              BSF          BUZZ
              RETURN 

;čakacia slučka 15 mSec.
CAKAJ15       MOVLW        115               ;200      
              MOVWF        CAKAJ1
              MOVLW        20                ;10 pre 2 Mhz
              MOVWF        CAKAJ2
              GOTO         DELAY
            
;Jadro čakacej slučky
DELAY         CLRWDT
              DECFSZ       CAKAJ1,F
              GOTO         $-1
              DECFSZ       CAKAJ2,F
              GOTO         $-4
              RETURN  
     
;prevod hex cisla na desiatkovu sustavu
;HEX cislo vo W a vysledok bude v VAX2-0
HEXtoDEC      CLRF        VAX2  ;STOVKY
              CLRF        VAX1  ;DESIATKY
              MOVWF       VAX0  ;JEDNOTKY
              MOVLW       100
              SUBWF       VAX0,F
              SKPC    
              GOTO        $+3
              INCF        VAX2,F
              GOTO        $-5
              ADDWF       VAX0,F
              MOVLW       10
              SUBWF       VAX0,F
              SKPC
              GOTO        $+3
              INCF        VAX1,F
              GOTO        $-5
              ADDWF       VAX0,F
              RETURN

 ;**************************************************************************************** 
 ;data pre EEPROM
 ORG H'2140'
INTRO1   de 44h,75h,61h,6Ch,20h,74h,69h,6Dh,65h,72h,20h,76h,2Eh,31h,2Eh,30h,255 ;Dual timer v.1.0
INTRO2   de 63h,2Eh,4Eh,69h,6Bh,69h,20h,30h,36h,2Fh,32h,30h,31h,36h,255         ;c.Niki 06/2016
LN1      de 01h,61h,73h,20h,06h,3Ah,20h,30h,30h,3Ah,30h,30h,3Ah,30h,30h,255     ;čas ^: 00:00:00
LN2      de 01h,61h,73h,20h,07h,3Ah,20h,30h,30h,3Ah,30h,30h,3Ah,30h,30h,255     ;čas ˇ: 00:00:00
MEM1     de 4Dh,45h,4Dh,20h,30h,3Ah,255                                         ;MEM 0:  
MEM2     de 20h,20h,20h,20h,20h,20h,255

 ORG H'21A0'
         DE 0,0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2     ;Pamäťové miesta pre ukladanie času
         DE 3,3,3,3,3,3,4,4,4,4,4,4,5,5,5,5,5,5     ;každé miesto tvorí 6 hexa čísiel pre 6 časov
         DE 6,6,6,6,6,6,7,7,7,7,7,7,8,8,8,8,8,8     ;HOD1,MIN1,SEC1,HOD2,MIN2,SEC2
         DE 9,9,9,9,9,9                             
 END        