;Program: Teploměr
  LIST P = 16F84,  R = DEC
  #INCLUDE <P16F84.INC>
;---------------------------------------------------------------
 __CONFIG   _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC
;***************************************************************
RAM     EQU     H'0C'
;---------------------------------------------------------------
RAM     EQU     H'0C'
RBF     EQU     RAM
RBF1    EQU     RAM+1
NUM     EQU     RAM+2
NUM1    EQU     RAM+3
TMP     EQU     RAM+4
TM1     EQU     RAM+5
TM2     EQU     RAM+6
JEDN    EQU     RAM+7
DES     EQU     RAM+8

b_A1    EQU     RAM+9
b_A2    EQU     RAM+10
b_A3    EQU     RAM+11
b_A4    EQU     RAM+12
b_B1    EQU     RAM+13
b_B2    EQU     RAM+14
b_B3    EQU     RAM+15
b_C1    EQU     RAM+16
b_C2    EQU     RAM+17
b_C3    EQU     RAM+18
b_C4    EQU     RAM+19
b_X1    EQU     RAM+20
b_X2    EQU     RAM+21
b_X3    EQU     RAM+22

T_H     EQU     RAM+23
T_L     EQU     RAM+24
T_H1    EQU     RAM+25
T_H2    EQU     RAM+26
T_L1    EQU     RAM+27
T_L2    EQU     RAM+28
T_HL1   EQU     RAM+29
T_HL2   EQU     RAM+30

#define Q       PORTB,0
#define RS      PORTB,1  
#define RW      PORTB,2
#define E       PORTB,3
#define BF      RBF,3
#define A4      PORTA,4
;xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
        ORG     0
        GOTO    START
;***************************************************************
;PODPROGRAMY
;***************************************************************
INILCD  CALL    t15mS           ;doba 15 milisekund
        BCF     RS
        BCF     RW
        CALL    A_OUT           ;port A výstup
        BSF     E
        MOVLW   B'00000011'
        MOVWF   PORTA
        BCF     E
        CALL    t4mS            ;doba 4 milisekund
        BSF     E
        MOVLW   B'00000011'
        MOVWF   PORTA
        BCF     E
        CALL    t100uS          ;doba 100 mikrosekund
        BSF     E
        MOVLW   B'00000011'
        MOVWF   PORTA
        BCF     E
        CALL    t100uS          ;doba 100 mikrosekund
        MOVLW   B'00101000'
        CALL    WRPRI           ;4.bitová komunikace a dva řádky
        MOVLW   B'00001000'
        CALL    WRPRI           ;displej OFF
        MOVLW   B'00001100'
        CALL    WRPRI           ;displej ON, kurzor OFF, blikání OFF
        MOVLW   B'00000110'
        CALL    WRPRI           ;inkrementace, normální operace
        MOVLW   1
        CALL    WRPRI           ;reset displeje
        RETURN
;-------------------------------------------------------------------------------
WRDATA  BSF     RS              ;nastavení bitu RS pro zápis dat
        GOTO    $+2
WRPRI   BCF     RS              ;nastavení bitů RS a RW pro zápis příkazu
        BCF     RW
        MOVWF   TMP             ;číslo příkazu nebo data do registru TMP
        CALL    A_OUT           ;portA jako výstup
        SWAPF   TMP,W           ;horní 4 bity do registru W
        BSF     E
        MOVWF   PORTA           ;zápis 4 horních bitů do displeje
        BCF     E
        MOVFW   TMP             ;obsah registru TMP do registru W
        BSF     E
        MOVWF   PORTA           ;zápis dolních 4 bitů do displeje
        BCF     E
        CALL    T_BF            ;testování bitu BF
        RETURN
;-------------------------------------------------------------------------------    
RDDATA  CALL    WRPRI           ;nastavení čtené adresy
        CALL    A_IN            ;port A vstup              
        BSF     RS
        BSF     RW
        BSF     E
        MOVFW   PORTA
        MOVWF   NUM             ;jedna půlka dat do registru NUM
        SWAPF   NUM,F
        BCF     E
        MOVLW   B'11110000'
        ANDWF   NUM,F           ;úprava registru NUM
        BSF     E
        MOVFW   PORTA
        MOVWF   NUM1
        BCF     E
        MOVLW   B'00001111'
        ANDWF   NUM1,W
        IORWF   NUM,F           ;druhá půlka dat do registru NUM
        CALL    T_BF            ;čeká konec operace
        RETURN
;-------------------------------------------------------------------------------
T_BF    BCF     RS              ;podprogram testuje konec operace (bit BF)
        BSF     RW
        CALL    A_IN            ;portA vstup (po ukončení zase výstup)
        BSF     E
        MOVFW   PORTA
        MOVWF   RBF
        BCF     E
        NOP
        BSF     E
        MOVFW   PORTA
        MOVWF   RBF1
        BCF     E
        BTFSC   BF              ;je bit BF=0 ? (0 = konec operace)
        GOTO    $-10            ;ne - testuj znova
;-------------------------------------------------------------------------------
A_OUT   MOVLW   B'11110000'     ;pin A0/A3 výstup, pin A4 vstup
        GOTO    $+2
A_IN    MOVLW   B'11111111'     ;pin A0/A7 vstup
        BSF     STATUS,RP0      ;banka 1
        MOVWF   TRISA           ;nastavení portu A
        BCF     STATUS,RP0      ;banka 0
        RETURN
;*******************************************************************************
t15mS   MOVLW   246             ;doba 15 milisekund
        GOTO    $+2
t4mS    MOVLW   66              ;doba 4 milisekund
        MOVWF   TM1
        MOVLW   19
        MOVWF   TM2
        DECFSZ  TM2,F
        GOTO    $-1
        DECFSZ  TM1,F
        GOTO    $-5
        RETURN
;-------------------------------------------------------------------------------
t100uS  MOVLW   33              ;doba 100 mikrosekund
        MOVWF   TM1
        DECFSZ  TM1,F
        GOTO    $-1
        RETURN
;-------------------------------------------------------------------------------
t500mS  CLRF    TM2     ;doba 500 milisekund
        CLRF    TM1
        NOP
        DECFSZ  TM1,F
        GOTO    $-2
        NOP
        DECFSZ  TM1,F
        GOTO    $-2
        DECFSZ  TM2,F
        GOTO    $-7
        RETURN        
;*******************************************************************************
PREVOD  MOVLW   48
        MOVWF   DES             ;registr DES=48
        MOVWF   JEDN            ;registr JEDN=48
        MOVLW   10
        SUBWF   NUM,W           ;W=NUM-10
        BTFSS   STATUS,C        ;došlo k podtečení?
        GOTO    $+4             ;ano,proveď skok
        MOVWF   NUM             ;obsah W do NUM
        INCF    DES,F           ;registr DES + 1
        GOTO    $-6             ;odečítej znova
        MOVFW   NUM
        ADDWF   JEDN,F          ;zbytek přičíst do registru JEDN
        RETURN
;*******************************************************************************
SOUCET  CALL    NUL_C           ;provede součet (b_A1/3 + b_B1/3 = b_C1/4)
SCET    MOVFW   b_A1
        ADDWF   b_B1,W
        BTFSC   STATUS,C
        INCF    b_C2,F
        MOVWF   b_C1
        MOVFW   b_A2
        ADDWF   b_B2,W
        BTFSC   STATUS,C
        INCF    b_C3,F
        ADDWF   b_C2,F
        BTFSC   STATUS,C
        INCF    b_C3,F
        MOVFW   b_A3
        ADDWF   b_B3,W
        BTFSC   STATUS,C
        INCF    b_C4,F
        ADDWF   b_C3,F
        BTFSC   STATUS,C
        INCF    b_C4,F
        MOVFW   b_A4
        ADDWF   b_C4,F
        RETURN
;*******************************************************************************
ROZDIL  CALL    D_DOPL          ;provede rozdíl (b_A1/3 - b_B1/3 = b_C1/3)
        CALL    SOUCET
        RETURN
;-------------------------------------------------------------------------------
D_DOPL  COMF    b_B1,F
        COMF    b_B2,F
        COMF    b_B3,F
        INCF    b_B1,F
        BTFSC   STATUS,Z
        INCF    b_B2,F
        BTFSC   STATUS,Z
        INCF    b_B3,F
        RETURN
;*******************************************************************************
SOUCIN  CALL    NUL_C           ;provede součin (b_A1/2 . b_B1/2 = b_C1/4)
        MOVF    b_B1,F
        BTFSC   STATUS,Z
        MOVF    b_B2,F
        BTFSC   STATUS,Z
        RETURN
        CALL    AdoX
        CALL    NUL_A
SCIN    MOVLW   1
        SUBWF   b_X1,F
        BTFSC   STATUS,C
        GOTO    $+4
        SUBWF   b_X2,F
        BTFSS   STATUS,C
        RETURN
        CALL    SOUCET
        CALL    CdoA
        GOTO    SCIN
;*******************************************************************************
PODIL   CALL    NUL_C           ;provede dělení (b_A1/3 : b_B1/3 =b_C1/3)
        CALL    NUL_X
        MOVF    b_B1,F
        BTFSC   STATUS,Z
        MOVF    b_B2,F
        BTFSC   STATUS,Z
        MOVF    b_B3,F
        BTFSC   STATUS,Z
        GOTO    CHYBA
        MOVF    b_A1,F
        BTFSC   STATUS,Z
        MOVF    b_A2,F
        BTFSC   STATUS,Z
        MOVF    b_A3,F
        BTFSC   STATUS,Z
        MOVF    b_A4,F
        BTFSC   STATUS,Z
        RETURN
        CALL    D_DOPL
PODL    CALL    SOUCET
        MOVF    b_C4,F
        BTFSC   STATUS,Z
        GOTO    XdoC
        INCF    b_X1,F
        BTFSC   STATUS,Z
        INCF    b_X2,F
        BTFSC   STATUS,Z
        INCF    b_X3,F
        CALL    CdoA
        CLRF    b_A4
        GOTO    PODL
;*******************************************************************************
NUL_A   CLRF    b_A1            ;vynuluje operand b_A1/4
        CLRF    b_A2
        CLRF    b_A3
        CLRF    b_A4
        RETURN
;-------------------------------------------------------------------------------
NUL_C   CLRF    b_C1            ;vynuluje registry výsledku b_C1/4
        CLRF    b_C2
        CLRF    b_C3
        CLRF    b_C4
        RETURN
;-------------------------------------------------------------------------------
NUL_X   CLRF    b_X1            ;vynuluje pomocné registry b_X1/3
        CLRF    b_X2
        CLRF    b_X3
        RETURN
;*******************************************************************************
AdoX    MOVFW   b_A1            ;kopírování registrů b_A1/2 do b_X1/2
        MOVWF   b_X1
        MOVFW   b_A2
        MOVWF   b_X2
        RETURN
;-------------------------------------------------------------------------------
CdoA    MOVFW   b_C1            ;kopírování registrů b_C1/4 do b_A1/4
        MOVWF   b_A1
        MOVFW   b_C2
        MOVWF   b_A2
        MOVFW   b_C3
        MOVWF   b_A3
        MOVFW   b_C4
        MOVWF   b_A4
        RETURN
;-------------------------------------------------------------------------------
XdoC    MOVFW   b_X1            ;kopírování registrů b_X1/3 do b_C1/3
        MOVWF   b_C1
        MOVFW   b_X2
        MOVWF   b_C2
        MOVFW   b_X3
        MOVWF   b_C3
        RETURN    
;-------------------------------------------------------------------------------
CHYBA   MOVLW   42
        CALL    WRDATA
        GOTO    $-0             ;bylo děleno nulou
;*******************************************************************************
NUL_ABC CALL    NUL_A
        CALL    NUL_C
NUL_B   CLRF    b_B1
        CLRF    b_B2
        CLRF    b_B3
        RETURN
          
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
;PROGRAM
;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
START   BSF     STATUS,RP0      ;banka 1     
        MOVLW   B'11110001'
        MOVWF   TRISB           ;nastavení portu B (pouze pro displej)
        MOVLW   B'11000000'
        MOVWF   OPTION_REG      ;načítání TMR0 z vnitřních hodin v poměru 1:2
        BCF     STATUS,RP0      ;banka 0

        CALL    INILCD          ;inicializace displeje
        
ZAS     MOVLW   100
        MOVWF   TM1             ;registr TM1 = 100
        
        CLRF    T_H1            ;vynulování potřebných registrů
        CLRF    T_H2
        CLRF    T_L1
        CLRF    T_L2
        
        CALL    NUL_ABC         ;vynulování matematických registrů

SEM     BTFSC   A4              ;je signál v dolní fázi?
        GOTO    $-1             ;ne,tak testuj znovu
        BTFSS   A4              ;je signál v horní fázi?
        GOTO    $-1             ;ne,tak testuj znovu

        CLRF    TMR0            ;zde začíná horní fáze impulsu a vynulujeme načítací registr
        BTFSC   A4              ;je horní fáze u konce?
        GOTO    $-1             ;ne,tak načítej a testuj znovu
        MOVFW   TMR0            ;ano,tak ulož obsah načítání do registru T_H
        MOVWF   T_H

        BTFSS   A4              ;je signál v horní fázi?
        GOTO    $-1             ;ne,tak testuj znovu
        BTFSC   A4              ;je signál v dolní fázi?
        GOTO    $-1             ;ne,tak testuj znovu

        CLRF    TMR0            ;zde začíná dolní fáze impulsu a vymulujeme načítací registr
        BTFSS   A4              ;je dolní fáze u konce?
        GOTO    $-1             ;ne,tak načítej a testuj znovu
        MOVFW   TMR0            ;ano,tak ulož obsah načítání do registru T_L
        MOVWF   T_L

;-------------------------------------------------------------------------------
        CALL    NUL_ABC
        MOVFW   T_H1
        MOVWF   b_A1
        MOVFW   T_H2
        MOVWF   b_A2
        MOVFW   T_H
        MOVWF   b_B1
        CALL    SOUCET          ;dvojregistr T_Hx = T_Hx + T_H
        MOVFW   b_C1
        MOVWF   T_H1
        MOVFW   b_C2
        MOVWF   T_H2
;-------------------------------------------------------------------------------
        CALL    NUL_ABC
        MOVFW   T_L1
        MOVWF   b_A1
        MOVFW   T_L2
        MOVWF   b_A2
        MOVFW   T_L
        MOVWF   b_B1
        CALL    SOUCET          ;dvojregistr T_Lx = T_Lx + T_L
        MOVFW   b_C1
        MOVWF   T_L1
        MOVFW   b_C2
        MOVWF   T_L2

        DECFSZ  TM1,F
        GOTO    SEM
;-------------------------------------------------------------------------------
        CALL    NUL_ABC
        MOVFW   T_H1
        MOVWF   b_A1
        MOVFW   T_H2
        MOVWF   b_A2
        CALL    NUL_B
        MOVLW   100
        MOVWF   b_B1
        CALL    PODIL           ;registr T_H = T_Hx : 100
        MOVFW   b_C1
        MOVWF   T_H
;-------------------------------------------------------------------------------
        CALL    NUL_ABC
        MOVFW   T_L1
        MOVWF   b_A1
        MOVFW   T_L2
        MOVWF   b_A2
        CALL    NUL_B
        MOVLW   100
        MOVWF   b_B1
        CALL    PODIL           ;registr T_L = T_Lx : 100
        MOVFW   b_C1
        MOVWF   T_L
;-------------------------------------------------------------------------------
        CALL    NUL_ABC
        MOVFW   T_L
        MOVWF   b_A1
        MOVFW   T_H
        MOVWF   b_B1
        CALL    SOUCET          ;dvojregistr T_HLx = T_H + T_L
        MOVFW   b_C1
        MOVWF   T_HL1
        MOVFW   b_C2
        MOVWF   T_HL2

;-------------------------------------------------------------------------------
        CALL    NUL_ABC
        MOVLW   211
        MOVWF   b_A1
        MOVFW   T_H
        MOVWF   b_B1
        CALL    SOUCIN          ;211 x T_H = výsledek
        CALL    CdoA
        MOVFW   T_HL1
        MOVWF   b_B1
        MOVFW   T_HL2
        MOVWF   b_B2
        CALL    PODIL           ;výsledek : T_HLx = druhý výsledek
  
        CALL    CdoA
        CALL    NUL_B
        MOVLW   68
        MOVWF   b_B1
        CALL    ROZDIL          ;druhý výsledek - 68 = b_Cx
;-------------------------------------------------------------------------------
        MOVLW   128
        CALL    WRPRI           ;nastavení DDRAM (adresy disple)
        MOVF    b_C4,F
        BTFSS   STATUS,Z        ;je registr b_C4 = 1?
        GOTO    PLUS            ;ano,výsledek je kladný a jdi na návěští PLUS
MINUS   MOVLW   45              ;ne,výsledek je záporný 
        CALL    WRDATA          ;vytiskni "-"
        DECF    b_C1,F
        COMF    b_C1,F          ;upravme výsledné záporné číslo na kladné
        GOTO    TAM             ;jdi na návěští TAM
        
PLUS    MOVLW   43
        CALL    WRDATA          ;vytiskni "+"

TAM     MOVFW   b_C1
        MOVWF   NUM
        CALL    PREVOD          ;provedeme převod výsledku na dekadické číslo
        
        MOVFW   DES
        CALL    WRDATA          ;vytiskneme desítky
        MOVFW   JEDN
        CALL    WRDATA          ;vytiskneme jednotky

        CALL    t500mS
        CALL    t500mS          ;čekací smyčky 2 x 0,5 sekundy
        
        GOTO    ZAS             ;jdi na návěští ZAS (vše zase dokola)

        END                
