;=============================================
; DigiScal.asm
; Digital scale - frequency counter
; Five internal freq.
; LCD display
; Automatic Frequency Control
; Alexander Y. Denisov Tambov 2002
; Выбор шага удержания - 20/40 Гц
;
; 24.03.2002
;=============================================
;
        include <macro.mac>
;
;=============================================
        LIST    p=16F84
       __CONFIG 03FF1H
;=============================================
T1            equ       .200         ; Delay
T2            equ       .163         ; maybe from 1 up to 255   (163)
T3            equ       .195        ; (tuned for 4000 kHz)     (195)
;=============================================
;    System
IndF          equ        00h         ; for FSR
Timer0        equ        01h         ; TMR0
OptionR       equ        01h         ; Option (RP0=1)
PC            equ        02h         ; PC
Status        equ        03h         ; Status
FSR           equ        04h         ; FSR
PortA         equ        05h         ; Port A
TrisA         equ        05h         ; Tris A - RP0=1
PortB         equ        06h         ; Port B
TrisB         equ        06h         ; Tris B - RP0=1
EEData        equ        08h         ; EEPROM Data
EECon1        equ        08h         ; EECON1 - RP0=1
EEAdr         equ        09h         ; EEPROM Address
EECon2        equ        09h         ; EECON2 - RP0=1

IntCon        equ        0Bh         ;
;
;------------------------------------------
;    Users
KeyBuf        equ        0Ch         ; keyboard buffer
KeyWait       equ        0Dh         ; wait for key press
Count         equ        0Eh         ; temporary counter
Count1        equ        0Fh         ; another one
;
LED1          equ       010h         ; display
LED2          equ       011h         ; buffer
LED3          equ       012h         ;
LED4          equ       013h         ;
;
IFptr         equ       014H         ; IF pointer
Mode          equ       015h         ;
Rotate        equ       016h
;
Temp          equ       017h         ; temporary register
Temp1         equ       018h         ; another one
;
Mask          equ       019h         ;

TimerL        equ       01ah         ; Low byte of counter
TimerM        equ       01bh         ; Middle byte of counter
TimerH        equ       01ch         ; High byte of counter

IF_L          equ       01dh         ; Low byte of IF
IF_M          equ       01eh         ; Middle byte of IF
IF_H          equ       01fh         ; High byte of IF
init_c        equ       020h         ; init C charging
;
;=============================================
; Literally
W             equ        0
F             equ        1
;
;=============================================
; Flag bits:
CF            equ        0           ; Carry
DC            equ        1           ; DC
ZF            equ        2           ; Zero
;
RP0           equ        5
;
;=============================================
;
              org        2100h
                                        ;  Default IF
              DE         01CH,03AH,090H ; 18.5000 khz
              DE         011H,08CH,030H ; 11.5000 mhz
              DE         005H,06AH,0B8H ;  3.5500 mhz
              DE         006H,0F1H,058H ;  4.5500 mhz
              DE         008H,077H,0F8H ;  5.5500 mhz
;
;=============================================
;
              org        0
              jmp     Start
;
;=============================================
; Modify mask
MaskMod
              movlw      0aah
              movwf      Mask
              ret
;
;=============================================
; Output display
;=============================================
Display
              movf       LED1,w
              call       Displ
              movf       LED2,w
              call       Displ
              movf       LED3,w
              call       Displ
              movf       LED4,w
              call       Displ
              movf       Mode,w
              iorlw      0a0h
;
;=============================================
;Out byte to display
Displ
              movwf   Rotate
              clrf    Count
              bsf     Count,3
              bcf     Status,0
displ1
              clrf    Status
              rlf     Rotate,f
              btfsc   Status,0
              bsf     PortA,1
              btfss   Status,0
              bcf     PortA,1
;
              bsf     PortA,0
;
              bcf     PortA,0
              decfsz  Count,f
              goto    displ1
;
              ret
;
;=============================================
KeyQuery                           ; keyboard querry
              movf       PortB,w
              andlw      b'00000011'
              addwf      PC,f
              jmp        Fun         ; "Function"
              jmp        plusIF      ; +IF
              jmp        minusIF     ; -IF
              jmp        Go1         ; all again
;
Fun
              incf       KeyWait,f
              btfss      KeyWait,3
              jmp        Go

              clrf       KeyWait
Function
              movf       PortB,w
              andlw      b'00000011'
              addwf      PC,f
              jmp        Function    ; wait keyOFF
              nop
              nop
              nop
              movf       TimerL,w
              movwf      IF_L
              movf       TimerM,w
              movwf      IF_M
              movf       TimerH,w
              movwf      IF_H
              call       Bin2LCD
              rrf        IFptr,w ; bank
              movwf      Mode    ;
              rrf        Mode,f  ; memory
              andlw      0fh     ; number
              incf       Mode,f  ;
              incf       Mode,f  ;
              call       Display
;
;=============================================
;
FunOff
              movf       PortB,w
              andlw      b'00000011'
              addwf      PC,f
              jmp        Fun1
              jmp        FunOff      ; not pressed
              jmp        FunOff      ; not pressed
              jmp        FunOff      ; not pressed
Fun1
              incf       KeyWait,f
              btfss      KeyWait,3
              jmp        FunOff      ; not pressed
              jmp        WrtMem      ; write to EEPROM
;
;=============================================
; from bin to LCD
;=============================================
;
Bin2LCD
              bcf        Status,0    ; clear the carry bit
              movlw      .24
              movwf      Count
              clrf       LED1
              clrf       LED2
              clrf       LED3
              clrf       LED4
loop16
              rlf        TimerL,f
              rlf        TimerM,f
              rlf        TimerH,f
              rlf        LED4,f
              rlf        LED3,f
              rlf        LED2,f
              rlf        LED1,f
;
              decfsz     Count,f
              jmp        adjDEC
;
              clrf       Mask   ; adust for LCD
l1
              movf       LED1,w
              andlw      0f0h
              cnz        MaskMod
l11
              movf       LED1,w
              andlw      0fh
              jz         l111
              call       MaskMod
              jmp        l2
l111
              movf       Mask,w
              andlw      0fh
              iorwf      LED1,f
l2
              movf       LED2,w
              andlw      0f0h
              jz         l22
              call       MaskMod
              jmp        l222
l22
              movf       Mask,w
              andlw      0f0h
              iorwf      LED2,f
l222
              movf       LED2,w
              andlw      0fh
              jz         l2222
              call       MaskMod
              jmp        l3
l2222
              movf       Mask,w
              andlw      0fh
              iorwf      LED2,f
l3
              movf       LED3,w
              andlw      0f0h
              jz         l33
              call       MaskMod
              jmp        l333
l33
              movf       Mask,w
              andlw      0f0h
              iorwf      LED3,f
l333
              movf       LED3,w
              andlw      0fh
              jz         l3333
              call       MaskMod
              jmp        l4
l3333
              movf       Mask,w
              andlw      0fh
              iorwf      LED3,f
l4
              movf       LED4,w
              andlw      0f0h
              jz         l44
              call       MaskMod
              jmp        l444
l44
              movf       Mask,w
              andlw      0f0h
              iorwf      LED4,f
l444
              movf       LED4,w
              andlw      0fh
              rnz
              movf       Mask,w
              andlw      0fh
              iorwf      LED4,f
;
              ret
;
adjDEC
              movlw      LED4
              movwf      FSR
              call       adjBCD
;
              movlw      LED3
              movwf      FSR
              call       adjBCD
;
              movlw      LED2
              movwf      FSR
              call       adjBCD
;
              movlw      LED1
              movwf      FSR
              call       adjBCD
;
              jmp        loop16
;
adjBCD
              movlw      3
              addwf      0,W
              movwf      Count1
              btfsc      Count1,3
              movwf      0
              movlw      30
              addwf      0,W
              movwf      Count1
              btfsc      Count1,7
              movwf      0
;
              ret
;
;=============================================
;Program start here ( cold start )
;
Start
              movlw      .30         ; init C
              movwf      init_c      ; (charging)

              bsf        Status,RP0

              movlw      b'00010100' ; RA0,RA1,RA3 outputs
              movwf      TrisA       ; RA2,RA4 input

              movlw      b'11110011' ; RB0,RB1,RB4,RB5,RB6,RB7 inputs
              movwf      TrisB       ; RB2,RB3 outputs

              clrwdt                 ;
              movlw      b'00100111' ; Prescaler -> Timer0,
              movwf      OptionR     ; 1:256, rising edge
              bcf        Status,RP0  ;

              clrf       Mode        ; Display
              clrf       LED1
              clrf       LED2
              clrf       LED3
              clrf       LED4

              clrf       TimerL      ; counter bytes
              clrf       TimerM
              clrf       TimerH

;=============================================
; Hot start
;
Go
              clrf       Mode
              clrf       IFptr
              movf       PortB,w
              andlw      b'10000000'
              jz         Go11         ; 0 to IF pointer
              incf       IFptr,f
              incf       IFptr,f
              incf       IFptr,f
              movf       PortB,w
              andlw      b'01000000'
              jz         Go11         ; 3 to IF pointer
              incf       IFptr,f
              incf       IFptr,f
              incf       IFptr,f
              movf       PortB,w
              andlw      b'00100000'
              jz         Go11         ; 6 to IF pointer
              incf       IFptr,f
              incf       IFptr,f
              incf       IFptr,f
              movf       PortB,w
              andlw      b'00010000'
              jz         Go11         ; 9 to IF pointer
              incf       IFptr,f
              incf       IFptr,f
              incf       IFptr,f
Go11                                 ; 12 to IF pointer
              bcf        EECon1,2    ; recording disable
              movf       IFptr,w
              movwf      EEAdr
              bsf        Status,RP0
              bsf        EECon1,0
              bcf        Status,RP0  ;
              movf       EEData,w
              movwf      IF_H

              incf       IFptr,w
              movwf      EEAdr
              bsf        Status,RP0
              bsf        EECon1,0
              bcf        Status,RP0  ;
              movf       EEData,w
              movwf      IF_M

              incf       IFptr,w
              movwf      EEAdr
              incf       EEAdr,f
              bsf        Status,RP0
              bsf        EECon1,0
              bcf        Status,RP0  ;
              movf       EEData,w
              movwf      IF_L

              call       Bin2LCD
              call       Display

              movf       init_c,f
              jz         afc_on
              decf       init_c,f
              bsf        PortB,3
              jmp        afc
afc_on
              bcf        PortB,3
afc
;
;=============================================
; Prepare for measuring
;=============================================
;
              clrf       IntCon      ; clear carry
              clrf       TimerH      ; clear hight timer byte
              clrf       Timer0      ; clear timer
;
              movlw      T2
              movwf      Temp1
;
;=============================================
;*********************************************
; Start measuring,   RA3 set input
;*********************************************
;=============================================
;
;
              bsf        Status,RP0
              movlw      b'00011100' ; RA0,RA1 output,RA2,RA3,RA4 input
              movwf      TrisA       ; RA4 input
              bcf        Status,RP0  ;
;
;=============================================
; Check TMR0 overflow
;=============================================
;
Measure
              btfss      IntCon,2
              jmp        DoNothing
              incf       TimerH,F
              bcf        IntCon,2
              jmp        O_K
DoNothing     nop
              nop
              nop
;
;=============================================
; The first timing loop
;=============================================
O_K
              movlw      T1
              movwf      Temp
Pause
              decfsz     Temp,F
              jmp        Pause

;
;=============================================
; The second timing loop
;=============================================

              decfsz     Temp1,F
              jmp        Measure

;=============================================
; Stop measuring
;=============================================
Nx
              ;last delay
              movlw      T3
              movwf      Temp
Last_Pause
              decfsz     Temp,F
              jmp        Last_Pause
;
              clrw
              movwf      PortA       ; RA0..RA3 = 0

              bsf        Status,RP0
              movlw      b'00010100'
              movwf      TrisA       ; RA4 input
              bcf        Status,RP0  ;
              nop
              nop
;=============================================
;*********************************************
; Last check TMR0 overflow
;*********************************************
;=============================================
              btfss      IntCon,2
              jmp        Analyse
              bcf        IntCon,2
              incf       TimerH,F
;=============================================
; Prescaler analyse
;=============================================
Analyse
              movf       Timer0,W    ; middle byte of counter
              movwf      TimerM      ; TMR0 -> TimerM

              clrf       TimerL
CountIt
              incf       TimerL,F
              bsf        PortA,3     ; _| false impulz
              nop
              bcf        PortA,3     ;    |_
              nop
              movf       Timer0,W    ; actual Timer0 -> W
              bcf        Status,ZF
              subwf      TimerM,W
              btfsc      Status,ZF
              jmp        CountIt
              incf       TimerL,F
              comf       TimerL,F
              incf       TimerL,F
              incf       TimerL,F         ; low byte of counter

              jb         PortA,2,step40

              jb         TimerL,1,set_20  ; AFC function 20 Hz
              bcf        PortB,2          ;
              jmp        KeyQuery         ;
set_20
              bsf        PortB,2          ;
              jmp        KeyQuery

step40
              jb         TimerL,2,set_40  ; AFC function 40 Hz
              bcf        PortB,2          ;
              jmp        KeyQuery         ;
set_40
              bsf        PortB,2          ;
              jmp        KeyQuery
minusIF
              comf       IF_L,f
              incf       IF_L,f
              btfsc      Status,ZF
              decf       IF_M,f
              comf       IF_M,f
              btfsc      Status,ZF
              decf       IF_H,f
              comf       IF_H,f
;
              movf       IF_L,w
              addwf      TimerL,f
              jnc        min11
              incf       TimerM,f
              jnz        min11
              incf       TimerH,f
min11
              movf       IF_M,w
              addwf      TimerM,f
              btfsc      Status,CF
              incf       TimerH,f
              movf       IF_H,w
              addwf      TimerH,f
              btfsc      Status,CF   ; negative?
              jmp        Go1         ; no
              btfsc      Status,CF   ; zero?
              jmp        Go1         ; no
              comf       TimerL,f    ; transformation
              incf       TimerL,f    ;
              btfsc      Status,ZF   ;
              decf       TimerM,f    ;
              comf       TimerM,f    ; negative
              btfsc      Status,ZF   ;
              decf       TimerH,f    ;
              comf       TimerH,f    ; result
Go1
              movlw      0
              movwf      KeyWait     ; reset keywait
              jmp        Go
plusIF
              movf       IF_L,w
              addwf      TimerL,f
              jnc        plus1
              incf       TimerM,f
              jnz        plus1
              incf       TimerH,f
plus1
              movf       IF_M,w
              addwf      TimerM,f
              jnc        plus11
              incf       TimerH,f
plus11
              movf       IF_H,w
              addwf      TimerH,f
              jmp        Go1
;
WrtMem        ;      write to EEPROM

              movlw      0
              movwf      IntCon      ; interrupt disable
              movf       IFptr,w
              movwf      EEAdr
              movf       IF_H,w
              movwf      EEData
              bsf        Status,RP0
              bsf        EECon1,2    ; recording enable
              movlw      055h
              movwf      EECon2
              movlw      0AAh
              movwf      EECon2
              bsf        EECon1,1
wr1
              btfss      EECon1,4
              jmp        wr1
              bcf        EECon1,4
              bcf        Status,RP0

              incf       IFptr,w
              movwf      EEAdr
              movf       IF_M,w
              movwf      EEData
              bsf        Status,RP0
              bsf        EECon1,2    ; recording enable
              movlw      055h
              movwf      EECon2
              movlw      0AAh
              movwf      EECon2
              bsf        EECon1,1
wr2
              btfss      EECon1,4
              jmp        wr2
              bcf        EECon1,4
              bcf        Status,RP0

              incf       IFptr,w
              movwf      EEAdr
              incf       EEAdr,f
              movf       IF_L,w
              movwf      EEData
              bsf        Status,RP0
              bsf        EECon1,2    ; recording enable
              movlw      055h
              movwf      EECon2
              movlw      0AAh
              movwf      EECon2
              bsf        EECon1,1
wr3
              btfss      EECon1,4
              jmp        wr3
              bcf        EECon1,4
              bcf        Status,RP0
;
              jmp        Go1
;
;=============================================
            end
