;
; *******************************************************************************
; * LCD test program V7 *
; * Version 0.01 *
; * March 2021 *
; * Author: T Mowles VK5TM *
; *******************************************************************************
;
;
; Target Controller - PIC16F628A
; __________
; SPARE-------RA2 |1 18| RA1----ENCODER A
; SPARE-------RA3 |2 17| RA0----ENCODER B
; SPARE-------RA4 |3 16| RA7----SPARE
; SPARE-------RA5 |4 15| RA6----SPARE
; Ground------Vss |5 14| VDD----+5 V
; LCD D4------RB0 |6 13| RB7----SPARE
; LCD D5------RB1 |7 12| RB6----LCD_rs (LCD Pin 4)
; LCD D6------RB2 |8 11| RB5----LCD_rw (LCD Pin 5)
; LCD D7------RB3 |9 10| RB4----LCD_e (LCD Pin 6)
; ----------
;
; *******************************************************************************
; * Device type and options. *
; *******************************************************************************
;
processor 16F628A
radix dec
errorlevel -302 ; Skip out of bank nuisance messages
;
; *******************************************************************************
; * Configuration fuse information for 16F628A: *
; *******************************************************************************
;
include <P16F628A.INC>
__config _CP_OFF&_LVP_OFF&_BODEN_OFF&_MCLRE_OFF&_PWRTE_ON&_WDT_OFF& _INTOSC_OSC_NOCLKOUT
;
; *******************************************************************************
; Info for power-up display
MCODE_REV_0 equ 'V' ;
MCODE_REV_1 equ '0' ;
MCODE_REV_2 equ '.' ;
MCODE_REV_3 equ '0' ;
MCODE_REV_4 equ '1' ;
MCODE_REV_5 equ ' ' ;
MCODE_REV_6 equ ' ' ;
MCODE_REV_7 equ ' ' ;
;
; *******************************************************************************
; * General equates *
; *******************************************************************************
;
; default 0 & 1 contains the default startup frequency as a 16 bit integer.
; control 0 & 1 contains the control word data as a 16 bit integer.
;
;default_1 equ 0x21 ; Most significant byte
;default_0 equ 0xFC ; Least significant byte (87MHz)
default_1 equ 0x2A ; Most significant byte
default_0 equ 0x30 ; Least significant byte (108MHz)
control_1 equ b'11000101' ; Control_1 data 11000101 (MSB)
control_0 equ b'11110101' ; Control_0 data 11110101 (LSB)
ORG 0x2100
;
; startup frequency bytes must be next 4 bytes of EEPROM
DATA default_1 ; startup -> MSB
DATA default_0 ; startup -> LSB
;
; *******************************************************************************
; * Assign names to IO pins *
; *******************************************************************************
;
; B register bits:
;
CLK equ 0x02 ; SAA1057 write clock
DAT equ 0x03 ; SAA1057 serial data input
LCD_busy equ 0x03 ; LCD busy bit
LCD_e equ 0x04 ; 0=disable, 1=enable
LCD_rw equ 0x05 ; 0=write, 1=read
LCD_rs equ 0x06 ; 0=instruction, 1=data
DLEN equ 0x07 ; SAA1057 Data load control pin - high to load data
;
; *******************************************************************************
; * Allocate variables in general purpose register space *
; *******************************************************************************
;
CBLOCK 0x20 ; Start Data Block
LCD_char ; Character being sent to the LCD
timer1 ; Used in delay routines
CounterA ; "
CounterB ; "
CounterC ; "
CounterD ; "
CounterE ; "
count ; loop counter (gets reused)
rs_value ; The LCD rs line flag value
NumH
NumL
hcomp
lcomp
TenK
Thou
Hund
Tens
Ones
byte2send
bit_count
previous
temp
clicks
freqHigh
freqLow
W_TEMP
STATUS_TEMP
ENDC ; End of Data Block
CBLOCK 0x70
freq_1 ; Use bank common locations - saves bank switching when
freq_0 ; saving/retreiving to/from EEPROM
ENDC ; End of Data Block
; *******************************************************************************
; * The 16F628 resets to 0x00 *
; * The Interrupt vector is at 0x04 *
; *******************************************************************************
;
ORG 0x0000
goto start ;
ORG 0x0004 ;
GOTO ISR
;
enc_table
addwf PCL,f ;index into table
dt 0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0
;
; *******************************************************************************
; * Purpose: *
; * This is the start of the program *
; * *
; *******************************************************************************
;
start
clrf PORTA
clrf PORTB
movlw 0x07 ; Code to turn off the analog comparators
movwf CMCON ; Turn off comparators
banksel TRISA ; Switch to bank 1
movlw 0xFF ; Tristate PORTA (all Inputs)
movwf TRISA ;
clrf TRISB ; Set port B to all outputs
banksel PORTB ; Switch back to bank 0
clrf PORTB
movlw control_1 ; send start sequence or control word to SAA1057
movwf freq_1
movlw control_0
movwf freq_0
call send_word ; Send it to the SAA1057
call send_word ; twice to initialise chip
read_EEocs ; Get the power on frequency
banksel EEADR ; Switch to bank 1
clrf EEADR ; Reset the EEPROM read address
call read_EEPROM ; Read EEPROM
movf EEDATA,w ; Get the first default freq byte
movwf freq_1 ; Save it
call read_EEPROM ; Read EEPROM
movf EEDATA,w ; Get the next freq byte
movwf freq_0 ; Save it
banksel PORTB ; Switch back to bank 0
;////////////////////////////////////////////////////////////////////////////////
MOVFW freq_0
MOVWF freqLow
MOVFW freq_1
MOVWF freqHigh
;////////////////////////////////////////////////////////////////////////////////
;
call bin2BCD ; Convert it to BCD
call init_LCD ; Initialize the LCD
call display_version
call show_freq ; Display the frequency on the LCD
call wait_250
movfw PORTA
movwf previous
;////////////////////////////////////////////////////////////////////////////////
initTmr2
;using internal 4MHz clock = 1MHz instruction time
;prescaler = 4 = clocked at 250kHz
;PR2 = 249 will clock around every 250 cycles
;postscaler = 5 = clock every 250*4*5 = 5000 cycles = 5mS interrupt
MOVLW B'00100101'
MOVWF T2CON
BSF STATUS,RP0
MOVLW 249
MOVWF PR2
BSF PIE1,TMR2IE
BCF STATUS,RP0
BSF STATUS,PEIE
BSF STATUS,GIE
; RETURN
;////////////////////////////////////////////////////////////////////////////////
;
main
;////////////////////////////////////////////////////////////////////////////////
GETfreq
BCF STATUS,GIE
MOVFW freqLow
MOVWF freq_0
MOVFW freqHigh
MOVWF freq_1
; BSF STATUS,GIE
; RETURN
;////////////////////////////////////////////////////////////////////////////////
;
; Based on the knob direction, either increment or decrement the frequency,
; update the LCD and SAA1057.
;
;down
; clrf clicks
; call dec_freq ;
; goto update ; Update LCD
;up
; clrf clicks
; call inc_freq ;
update
call bin2BCD ; Convert the frequency to BCD
call show_freq ; Display the frequency on the LCD
; call send_word ; Send the control word to the chip
BSF STATUS,GIE
goto main ; Continue main loop
;////////////////////////////////////////////////////////////////////////////////
;note W_TEMP and STATUS_TEMP need to be in the common area (above 0x70)
ISR
MOVWF W_TEMP ; SAVE OFF CURRENT W REGISTER CONTENTS
MOVF STATUS,W ; MOVE STATUS REGISTER INTO W REGISTER
MOVWF STATUS_TEMP ; SAVE OFF CONTENTS OF STATUS REGISTER
BCF STATUS,RP0
BCF PIR1,TMR2IF
RLF previous,F
RLF previous,W
ANDLW 0X0C ;KEEP ONLY BITS 2 & 3
BTFSS PORTA,0 ;MOVE ENCODER BITS
IORLW 1 ;TO BITS 0 & 1
BTFSS PORTA,1
IORLW 2
MOVWF previous ;KEEP FOR NEXT TIME
CALL enc_table
ADDWF clicks,F
MOVLW 4
XORWF clicks,W
BTFSS STATUS,Z
GOTO CHECK_DOWN
CLRF clicks
MOVLW high 10800 ;test if frequency has reached 108MHz
XORWF freqHigh,W
BTFSS STATUS,Z
GOTO DOINC ;high bytes don't match so do increment
MOVLW low 10800
XORWF freqLow,W
BTFSC STATUS,Z ;low bytes don't match so do increment
GOTO EXIT ;if it has, exit
DOINC
INCF freqHigh,F ;if not then increment it
INCFSZ freqLow,F
DECF freqHigh,F
GOTO EXIT
CHECK_DOWN
MOVLW 0XFC ;-4
XORWF clicks,W
BTFSC STATUS,Z
GOTO EXIT
CLRF clicks
MOVLW high 8700
XORWF freqHigh,W
BTFSC STATUS,Z
GOTO DODEC
MOVLW low 8700
XORWF freqLow,W
BTFSS STATUS,Z
GOTO EXIT
DODEC
MOVF freqLow,F
SKPNZ
DECF freqHigh,F
DECF freqLow,F
; GOTO EXIT
; RESTORE CONTEXT BEFORE RETURNING FROM INTERRUPT
EXIT
MOVF STATUS_TEMP,W ; RETRIEVE COPY OF STATUS REGISTER
MOVWF STATUS ; RESTORE PRE-ISR STATUS REGISTER CONTENTS
SWAPF W_TEMP,F
SWAPF W_TEMP,W ; RESTORE PRE-ISR W REGISTER CONTENTS
RETFIE ; RETURN FROM INTERRUPT
;////////////////////////////////////////////////////////////////////////////////
;;
;; *******************************************************************************
;; * Purpose: *
;; * Increment frequency 16 bit inc/dec From Scott Dattalo *
;; * *
;; *******************************************************************************
;;
;inc_freq
; incf freq_1,f
; incfsz freq_0,f
; decf freq_1,f
;
; MOVLW low 10800 ; Initialize a 16 bit value
; MOVWF lcomp
; MOVLW high 10800
; MOVWF hcomp
; call COMP ; Test if frequency is above 108MHz
;
; addlw 0x00 ; Test if 'w'is 0 or 1
; btfsc STATUS,Z ; The Z or Zero bit is set to "1" when the result
; return ; of an arithmetic or logical operation is zero
;
; MOVLW low 10800 ; Initialize a 16 bit value
; MOVWF freq_0
; MOVLW high 10800
; MOVWF freq_1
; return
;;
;;
;; *******************************************************************************
;; * Purpose: *
;; * Decrement the freq, checking that it does not go below lowest freq *
;; * *
;; *******************************************************************************
;;
;dec_freq
; movf freq_0,f
; skpnz
; decf freq_1,f
; decf freq_0,f
;
; MOVLW low 8700 ; Initialize a 16 bit value
; MOVWF lcomp
; MOVLW high 8700
; MOVWF hcomp
; call COMP ; Test if frequency is below 87MHz
;
; addlw 0x00 ; Test if 'w'is 0 or 1
; btfss STATUS,Z ; The Z or Zero bit is set to "1" when the result
; return ; of an arithmetic or logical operation is zero
;
; MOVLW low 8700 ; Initialize a 16 bit value
; MOVWF freq_0
; MOVLW high 8700
; MOVWF freq_1
; return
;;
;; *******************************************************************************
;; * Purpose: *
;; * Check if freq exceeds upper or lower limit *
;; * *
;; * A not too optimised 16 bit compare routine for 16bit absolute values, *
;; * ie 0 -> 65536. Antonio L Benci (PIClist) *
;; * Compare WORD to COMP (a word value). *
;; * If WORD = COMP return with 00 *
;; * If WORD > COMP return with 01 *
;; * If WORD < COMP return with 00 *
;; *******************************************************************************
;;
;COMP
; movfw hcomp ; get high byte of comp value
; subwf freq_1,w ; subtract values
; btfsc STATUS,Z ; first check if result is 0
; goto COMPL ; if zero compare low bytes
; btfsc STATUS,C ; else test carry bit
; retlw 0x01 ; if WORD > COMP, return with 01h
; retlw 0x00 ; if WORD < COMP, return with 00h
;
;COMPL
; movfw lcomp ; get low byte of comp value
; subwf freq_0,w ; subtract values
; btfsc STATUS,Z ; first check if result is 0
; retlw 0x00 ; if result is 0, return with 00
; btfsc STATUS,C ; if c set then WORD > COMP
; retlw 0x01 ; if WORD > COMP, return with 01h
; retlw 0x00 ; if WORD < COMP, return with 00h
;;
;
; *******************************************************************************
; * Purpose: *
; * This routine sends data to the SAA1057 using serial data transfer mode *
; * *
; * To send data:- *
; * Set Clock low *
; * *
; * Set DLEN high *
; * *
; * Set Data low *
; * *
; * Send clock bit ->high->low *
; * *
; * 1 Get Data bit from file *
; * *
; * Send clock bit ->high->low *
; * *
; * Repeat from 1 for remaining bits *
; * *
; * Set DLEN low *
; * *
; * Send clock bit ->high->low *
; * *
; * End of sequence *
; * *
; *******************************************************************************
;
send_word
bcf PORTB,CLK ; Set clock low
NOP
bsf PORTB,DLEN ; Set data load high
NOP
bcf PORTB,DAT ; Set Data low
NOP
bsf PORTB,CLK ; Toggle write clock
NOP
bcf PORTB,CLK ;
movlw freq_1 ; Point FSR at most Significant Byte
movwf FSR ;
next_byte
movf INDF,w ;
movwf byte2send ;
movlw 0x08 ; Set counter to 8
movwf bit_count ;
next_bit
rlf byte2send,f ; Test if next bit is 1 or 0
btfss STATUS,C ; Was it zero?
goto send0 ; Yes, send zero
bsf PORTB,DAT ; No, send one
goto break ;
send0
bcf PORTB,DAT ; Send zero
NOP
break
bsf PORTB,CLK ; Toggle write clock
NOP
bcf PORTB,CLK ;
decfsz bit_count,f ; Has the whole byte been sent?
goto next_bit ; No, keep going
incf FSR,f ; Start the next byte unless finished
movlw freq_0+1 ; Next byte (past the end)
subwf FSR,w ;
btfss STATUS,C ;
goto next_byte ;
bcf PORTB,DLEN ; Send load signal to the SAA1057
NOP
bsf PORTB,CLK ; Toggle write clock
NOP
bcf PORTB,CLK ;
clrf PORTB ;
return
;
; *******************************************************************************
; * Purpose: *
; * This subroutine converts a 16 bit binary number to decimal in *
; * TenK, Thou, Hund, Tens, Ones *
; * Written by John Payson. *
; *******************************************************************************
;
bin2BCD ; Takes number in freq_1:freq_0 returns decimal in TenK:Thou:Hund:Tens:Ones
movfw freq_1
movwf NumH
movfw freq_0
movwf NumL
swapf NumH,w
IORLW 0xF0
movwf Thou
addwf Thou,f
addlw 0xE2
movwf Hund
addlw 0x32
movwf Ones
movf NumH,w
andlw 0x0F
addwf Hund,f
addwf Hund,f
addwf Ones,f
addlw 0xE9
movwf Tens
addwf Tens,f
addwf Tens,f
swapf NumL,w
andlw 0x0F
addwf Tens,f
addwf Ones,f
rlf Tens,f
rlf Ones,f
comf Ones,f
rlf Ones,f
movf NumL,w
andlw 0x0F
addwf Ones,f
rlf Thou,f
movlw 0x07
movwf TenK
; At this point, the original number is equal to TenK*10000+Thou*1000+Hund*100+Tens*10+Ones
; if those entities are regarded as two's compliment binary.
; To be precise, all of them are negative except TenK.
; Now the number needs to be normalized, but this can all be done with simple byte arithmetic.
movlw 0x0A ; Ten
Lb1:
addwf Ones,f
decf Tens,f
btfss STATUS,C
goto Lb1
Lb2:
addwf Tens,f
decf Hund,f
btfss STATUS,C
goto Lb2
Lb3:
addwf Hund,f
decf Thou,f
btfss STATUS,C
goto Lb3
Lb4:
addwf Thou,f
decf TenK,f
btfss STATUS,C
goto Lb4
return
;
; *******************************************************************************
; * Purpose: *
; * Display the frequency on the LCD. *
; * *
; *******************************************************************************
;
show_freq
movlw 0xC5 ; Point the LCD to digit location
call cmnd2LCD ; Send digit location to LCD
movfw TenK
addlw 0x00 ; Test if 'w'is 0 or 1
btfss STATUS,Z ; The Z or Zero bit is set to "1" when the result
goto not_zero ; of an arithmetic or logical operation is zero
movlw ' ' ; TenK = 0, insert space
call data2LCD ; Send byte in W to LCD
goto show_thou
not_zero
call process ; TenK is not 0, insert number
show_thou
movfw Thou
call process ;
movfw Hund
call process ;
movlw '.' ; insert seperator
call data2LCD ; Send byte in W to LCD
movfw Tens
call process ;
movfw Ones
call process ;
return
process
addlw 0x30
call data2LCD
return
;
; *******************************************************************************
; * Purpose: *
; * Power on initialization of Liquid Crystal Display *
; * The LCD controller chip must be equivalent to an Hitachi 44780 *
; * *
; *******************************************************************************
;
init_LCD
movlw 100
call wait ; Wait for LCD to power up (100mS)
; Put 4-bit command in RB3..RB0
; PIC's RB3..RB0 lines connect to LCD's DB7..DB4 (pins 14-11)
movlw 0x03 ; LCD init instruction (First)
movwf PORTB ; Send to LCD via RB3..RB0
bsf PORTB,LCD_e ; Set the LCD E line high,
nop
bcf PORTB,LCD_e ; and then Clear E
call wait_100us
movlw 0x03 ; LCD init instruction (Second)
movwf PORTB ; Send to LCD via RB3..RB0
bsf PORTB,LCD_e ; Set E high,
nop
bcf PORTB,LCD_e ; and then Clear E
call wait_100us
movlw 0x03 ; LCD init instruction (Third)
movwf PORTB ; Send to LCD via RB3..RB0
bsf PORTB,LCD_e ; Set E high,
nop
bcf PORTB,LCD_e ; and then Clear E
call wait_100us ; wait a while,
movlw 0x02 ; 4-bit mode instruction
movwf PORTB ; Send to LCD via RB3..RB0
bsf PORTB,LCD_e ; Set E high,
nop
bcf PORTB,LCD_e ; and then Clear E
call wait_100us ; wait a while,
movlw 0x28 ; 1/16 duty cycle, 5x8 matrix
call cmnd2LCD ; Send command in w to LCD
call wait_100us
; movlw 0x08 ; Display off, cursor and blink off
; movlw 0x0C ; Display on, cursor and blink off
movlw 0x0E ; Display on, cursor on and blink off
; movlw 0x0F ; Display on, cursor and blink on
call cmnd2LCD ; Send command to LCD
call wait_100us
movlw 0x01 ; Clear and reset cursor
call cmnd2LCD ; Send command in w to LCD
movlw 2
call wait ; wait a while,
movlw 0x06 ; Set cursor to move right, no shift
call cmnd2LCD ; Send command in w to LCD
return ;
;
; *******************************************************************************
; * Purpose: *
; * Send Command or Data byte to the LCD *
; * Entry point cmnd2LCD: Send a Command to the LCD *
; * Entry Point data2LCD: Send a Data byte to the LCD *
; * *
; *******************************************************************************
;
cmnd2LCD ; ****** Entry point ******
clrf rs_value ; Remember to clear RS (clear rs_value)
goto write2LCD ; Go to common code
data2LCD ; ****** Entry point ********
bsf rs_value,0 ; Remember to set RS (set bit 0 of rs_value)
write2LCD
movwf LCD_char ; Save byte to write to LCD
; call busy_check ; Check to see if LCD is ready for new data
call wait_100us
MOVLW 2 ;
MOVWF count ; SET UP LOOP COUNTER
write_again
SWAPF LCD_char,F ; SWAP MS & LS NIBBLES
MOVF LCD_char,W
ANDLW 15 ; MAKE TOP 4 BITS OF W 0
MOVWF PORTB ; SEND MS NIBBLE
bcf PORTB,LCD_rs ; Guess RS should be clear - command mode
btfsc rs_value,0 ; Should RS be clear? (is bit 0 == 0?)
bsf PORTB,LCD_rs ; No, set RS - data mode
NOP
BSF PORTB,LCD_e ; SET E HIGH
NOP
BCF PORTB,LCD_e ; SET E LOW
DECFSZ count,F
GOTO write_again ; GO BACK AND SEND LS NIBBLE
clrf PORTB
return
;
; *******************************************************************************
; * Purpose: *
; * Check if LCD is done with the last operation. *
; * This subroutine polls the LCD busy flag to determine if previous *
; * operations are completed. *
; * *
; *******************************************************************************
;
;busy_check
; clrf PORTB ; Clear all outputs on PORTB
; banksel TRISB ; Switch to bank for Tris operation
; movlw b'00001000' ; Set RB3 input, others outputs
; movwf TRISB ;
;
; banksel PORTB
; bcf PORTB,LCD_rs ; Set up LCD for Read Busy Flag (RS = 0)
; nop
; bsf PORTB,LCD_rw ; Set up LCD for Read (RW = 1)
; nop ;
; bsf PORTB,LCD_e ; Set E high
; nop
; bcf PORTB,LCD_e ; Drop E again
;
;LCD_is_busy
; call wait_100us ;
; bsf PORTB,LCD_e ; Set E high
; nop
; bcf PORTB,LCD_e ; Drop E again
;
; btfss PORTB,LCD_busy ; Is Busy Flag (RB3) clear?
; goto not_busy ; Yes - exit
; nop ; No
; nop ; Wait a while
;
; bsf PORTB,LCD_e ; Pulse E high (dummy read of lower nibble),
; nop ; wait,
; bcf PORTB,LCD_e ; and drop E again
;
; goto LCD_is_busy ; If not, it is busy so jump back
;
;not_busy
; banksel TRISB ; Switch to bank 1 for Tristate operation
; clrf TRISB ; All pins (RB7..RB0) are back to outputs
; banksel PORTB ; Switch to bank 0
; clrf PORTB ; Clear all of Port B (inputs and outputs)
; return
;
; ****************************************************************************P
; * P
; * Purpose: Display version and other info on LCD for 2 seconds P
; * upon power-up P
; * P
; * Input: MCODE_REV_0 through MCODE_REV_4 set up P
; * P
; * Output: LCD displays debug info P
; * P
; ****************************************************************************P
;
display_version
movlw 0x80 ; Point LCD at digit 1
call cmnd2LCD ;
movlw 'S' ; digit 1
call data2LCD ;
movlw 'A' ; digit 2
call data2LCD ;
movlw 'A' ; digit 3
call data2LCD ;
movlw '1' ; digit 4
call data2LCD ;
movlw '0' ; digit 5
call data2LCD ;
movlw '5' ; digit 6
call data2LCD ;
movlw '7' ; digit 7
call data2LCD ;
movlw ' ' ; digit 8
call data2LCD ;
movlw MCODE_REV_0 ; Get mcode rev byte
call data2LCD ; and display it (digit 9)
movlw MCODE_REV_1 ; Get mcode rev byte
call data2LCD ; and display it (digit 10)
movlw MCODE_REV_2 ; Get mcode rev byte
call data2LCD ; and display it (digit 11)
movlw MCODE_REV_3 ; Get mcode rev byte
call data2LCD ; and display it (digit 12)
movlw MCODE_REV_4 ; Get mcode rev byte
call data2LCD ; and display it (digit 13)
movlw MCODE_REV_5 ; Get mcode rev byte
call data2LCD ; and display it (digit 14)
movlw MCODE_REV_6 ; Get mcode rev byte
call data2LCD ; and display it (digit 15)
movlw MCODE_REV_7 ; Get mcode rev byte
call data2LCD ; and display it (digit 16)
nop
LINE2
movlw 0xC0 ; Point LCD at digit 1 of second line
call cmnd2LCD ;
movlw 'F' ; digit 1
call data2LCD ;
movlw 'R' ; digit 2
call data2LCD ;
movlw 'E' ; digit 3
call data2LCD ;
movlw 'Q' ; digit 4
call data2LCD ;
movlw ':' ; digit 5
call data2LCD ;
movlw ' ' ; digit 6 0xC5
call data2LCD ;
movlw ' ' ; digit 7
call data2LCD ;
movlw ' ' ; digit 8
call data2LCD ;
movlw ' ' ; digit 9
call data2LCD ;
movlw ' ' ; digit 10
call data2LCD ;
movlw ' ' ; digit 11
call data2LCD ;
movlw 'M' ; digit 12
call data2LCD ;
movlw 'H' ; digit 13
call data2LCD ;
movlw 'z' ; digit 14
call data2LCD ;
movlw ' ' ; digit 15
call data2LCD ;
movlw ' ' ; digit 16
call data2LCD ;
return
;
; *****************************************************************************
; * *
; * Purpose: Read a byte of EEPROM data at address EEADR into EEDATA. *
; * *
; * Input: The address EEADR. *
; * *
; * Output: The value in EEDATA. *
; * *
; * NOTE: All in BANK 1 *
; *****************************************************************************
;
read_EEPROM
bsf EECON1,RD ; Request the read
movf EEDATA,W ; Get the data
incf EEADR,f ; Increment the read address
return ; Return to the caller
;
; *******************************************************************************
; * *
; * Purpose: Delay routines *
; * *
; *******************************************************************************
;
wait_a_sec ;PIC Time Delay = 0.99999900 s with Osc = 4000000 Hz
movlw D'6'
movwf CounterC
movlw D'19'
movwf CounterB
movlw D'172'
movwf CounterA
loop
decfsz CounterA,f
goto loop
decfsz CounterB,f
goto loop
decfsz CounterC,f
goto loop
return
wait_250
movlw 250
wait
movwf timer1 ; Set up counter
call wait_1ms ; Go to wait loops
decfsz timer1,f
goto $-2
return
wait_1ms ;PIC Time Delay = 0.00099800 s with Osc = 4MHz
movlw D'2'
movwf CounterD
movlw D'74'
movwf CounterE
loop1
decfsz CounterE,f
goto loop1
decfsz CounterD,f
goto loop1
return
wait_100us ;PIC Time Delay = 0.00009800 s with Osc = 4MHz
movlw D'31'
movwf CounterA
loop2
decfsz CounterA,1
goto loop2
return
;
; *****************************************************************************
;
END
;////////////////////////////////////////////////////////////////////////////////
GETfreq
BCF STATUS,GIE
MOVFW freqLow
MOVWF freq_0
MOVFW freqHigh
MOVWF freq_1
; BSF STATUS,GIE
; RETURN
;////////////////////////////////////////////////////////////////////////////////
MOVFW freqLow
MOVLW 0X30
MOVWF freq_0
MOVFW freqHigh
MOVLW 0X2A
MOVWF freq_1
ISR MOVWF W_TEMP ; SAVE OFF CURRENT W REGISTER CONTENTS
MOVF STATUS,W ; MOVE STATUS REGISTER INTO W REGISTER
MOVWF STATUS_TEMP ; SAVE OFF CONTENTS OF STATUS REGISTER
BCF STATUS,RP0
BCF PIR1,TMR2IF
RLF previous,F
RLF previous,W
ANDLW 0X0C ;KEEP ONLY BITS 2 & 3
BTFSS PORTA,0 ;MOVE ENCODER BITS
IORLW 1 ;TO BITS 0 & 1
BTFSS PORTA,1
IORLW 2
MOVWF previous ;KEEP FOR NEXT TIME
CALL ENC_TABLE
ADDWF clicks,F
MOVLW 4
XORWF clicks,W
BTFSS STATUS,Z
GOTO CHECK_DOWN
CLRF clicks ;added this line
INCF freqHigh,F ;if not then increment it
INCFSZ freqLow,F
DECF freqHigh,F
GOTO EXIT
CHECK_DOWN
MOVLW 0XFC ;-4
XORWF clicks,W
BTFSC STATUS,Z
GOTO EXIT
CLRF clicks ;added this line
MOVF freqLow,F
SKPNZ
DECF freqHigh,F
DECF freqLow,F
GOTO EXIT
; RESTORE CONTEXT BEFORE RETURNING FROM INTERRUPT
EXIT MOVF STATUS_TEMP,W ; RETRIEVE COPY OF STATUS REGISTER
MOVWF STATUS ; RESTORE PRE-ISR STATUS REGISTER CONTENTS
SWAPF W_TEMP,F
SWAPF W_TEMP,W ; RESTORE PRE-ISR W REGISTER CONTENTS
RETFIE ; RETURN FROM INTERRUPT
BSF STATUS,PEIE
BSF STATUS,GIE
;
; *******************************************************************************
; * LCD test program V7 *
; * Version 0.01 *
; * March 2021 *
; * Author: T Mowles VK5TM *
; *******************************************************************************
;
;
; Target Controller - PIC16F628A
; __________
; SPARE-------RA2 |1 18| RA1----ENCODER A
; SPARE-------RA3 |2 17| RA0----ENCODER B
; SPARE-------RA4 |3 16| RA7----SPARE
; SPARE-------RA5 |4 15| RA6----SPARE
; Ground------Vss |5 14| VDD----+5 V
; LCD D4------RB0 |6 13| RB7----SPARE
; LCD D5------RB1 |7 12| RB6----LCD_rs (LCD Pin 4)
; LCD D6------RB2 |8 11| RB5----LCD_rw (LCD Pin 5)
; LCD D7------RB3 |9 10| RB4----LCD_e (LCD Pin 6)
; ----------
;
; *******************************************************************************
; * Device type and options. *
; *******************************************************************************
;
processor 16F628A
radix dec
errorlevel -302 ; Skip out of bank nuisance messages
;
; *******************************************************************************
; * Configuration fuse information for 16F628A: *
; *******************************************************************************
;
include <P16F628A.INC>
__config _CP_OFF&_LVP_OFF&_BODEN_OFF&_MCLRE_OFF&_PWRTE_ON&_WDT_OFF& _INTOSC_OSC_NOCLKOUT
;
; *******************************************************************************
; Info for power-up display
MCODE_REV_0 equ 'V' ;
MCODE_REV_1 equ '0' ;
MCODE_REV_2 equ '.' ;
MCODE_REV_3 equ '0' ;
MCODE_REV_4 equ '1' ;
MCODE_REV_5 equ ' ' ;
MCODE_REV_6 equ ' ' ;
MCODE_REV_7 equ ' ' ;
;
; *******************************************************************************
; * General equates *
; *******************************************************************************
;
; default 0 & 1 contains the default startup frequency as a 16 bit integer.
; control 0 & 1 contains the control word data as a 16 bit integer.
;
;default_1 equ 0x21 ; Most significant byte
;default_0 equ 0xFC ; Least significant byte (87MHz)
;default_1 equ 0x2A ; Most significant byte
;default_0 equ 0x30 ; Least significant byte (108MHz)
default_1 equ 0x27 ; Most significant byte
default_0 equ 0x10 ; Least significant byte (100MHz)
control_1 equ b'11000101' ; Control_1 data 11000101 (MSB)
control_0 equ b'11110101' ; Control_0 data 11110101 (LSB)
ORG 0x2100
;
; startup frequency bytes must be next 4 bytes of EEPROM
DATA default_1 ; startup -> MSB
DATA default_0 ; startup -> LSB
;
; *******************************************************************************
; * Assign names to IO pins *
; *******************************************************************************
;
; B register bits:
;
CLK equ 0x02 ; SAA1057 write clock
DAT equ 0x03 ; SAA1057 serial data input
LCD_busy equ 0x03 ; LCD busy bit
LCD_e equ 0x04 ; 0=disable, 1=enable
LCD_rw equ 0x05 ; 0=write, 1=read
LCD_rs equ 0x06 ; 0=instruction, 1=data
DLEN equ 0x07 ; SAA1057 Data load control pin - high to load data
;
; *******************************************************************************
; * Allocate variables in general purpose register space *
; *******************************************************************************
;
CBLOCK 0x20 ; Start Data Block
LCD_char ; Character being sent to the LCD
timer1 ; Used in delay routines
CounterA ; "
CounterB ; "
CounterC ; "
CounterD ; "
CounterE ; "
count ; loop counter (gets reused)
rs_value ; The LCD rs line flag value
NumH
NumL
hcomp
lcomp
TenK
Thou
Hund
Tens
Ones
byte2send
bit_count
previous
temp
clicks
freqHigh
freqLow
ENDC ; End of Data Block
CBLOCK 0x70
freq_1 ; Use bank common locations - saves bank switching when
freq_0 ; saving/retreiving to/from EEPROM
W_TEMP
STATUS_TEMP
ENDC ; End of Data Block
; *******************************************************************************
; * The 16F628 resets to 0x00 *
; * The Interrupt vector is at 0x04 *
; *******************************************************************************
;
ORG 0x0000
goto start ;
ORG 0x0004 ;
GOTO ISR
;
ENC_TABLE
addwf PCL,f ;index into table
dt 0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0
;
; *******************************************************************************
; * Purpose: *
; * This is the start of the program *
; * *
; *******************************************************************************
;
start
clrf PORTA
clrf PORTB
movlw 0x07 ; Code to turn off the analog comparators
movwf CMCON ; Turn off comparators
banksel TRISA ; Switch to bank 1
movlw 0xFF ; Tristate PORTA (all Inputs)
movwf TRISA ;
clrf TRISB ; Set port B to all outputs
banksel PORTB ; Switch back to bank 0
clrf PORTB
movlw control_1 ; send start sequence or control word to SAA1057
movwf freq_1
movlw control_0
movwf freq_0
call send_word ; Send it to the SAA1057
call send_word ; twice to initialise chip
read_EEocs ; Get the power on frequency
banksel EEADR ; Switch to bank 1
clrf EEADR ; Reset the EEPROM read address
call read_EEPROM ; Read EEPROM
movf EEDATA,w ; Get the first default freq byte
movwf freq_1 ; Save it
call read_EEPROM ; Read EEPROM
movf EEDATA,w ; Get the next freq byte
movwf freq_0 ; Save it
banksel PORTB ; Switch back to bank 0
;////////////////////////////////////////////////////////////////////////////////
MOVFW freq_0
MOVWF freqLow
MOVFW freq_1
MOVWF freqHigh
;////////////////////////////////////////////////////////////////////////////////
;
call bin2BCD ; Convert it to BCD
call init_LCD ; Initialize the LCD
call display_version
call show_freq ; Display the frequency on the LCD
call wait_250
movfw PORTA
movwf previous
;////////////////////////////////////////////////////////////////////////////////
initTmr2
;using internal 4MHz clock = 1MHz instruction time
;prescaler = 4 = clocked at 250kHz
;PR2 = 249 will clock around every 250 cycles
;postscaler = 5 = clock every 250*4*5 = 5000 cycles = 5mS interrupt
MOVLW B'00100101'
MOVWF T2CON
BSF STATUS,RP0
MOVLW 249
MOVWF PR2
BSF PIE1,TMR2IE
BCF STATUS,RP0
BSF INTCON,PEIE
BSF INTCON,GIE
; RETURN
;////////////////////////////////////////////////////////////////////////////////
;
main
;////////////////////////////////////////////////////////////////////////////////
GETfreq
BCF INTCON,GIE
MOVFW freqLow
MOVWF freq_0
MOVFW freqHigh
MOVWF freq_1
BSF INTCON,GIE
; RETURN
;////////////////////////////////////////////////////////////////////////////////
;
; Based on the knob direction, either increment or decrement the frequency,
; update the LCD and SAA1057.
;
;down
; clrf clicks
; call dec_freq ;
; goto update ; Update LCD
;up
; clrf clicks
; call inc_freq ;
update
call bin2BCD ; Convert the frequency to BCD
call show_freq ; Display the frequency on the LCD
; call send_word ; Send the control word to the chip
; BSF STATUS,GIE
goto main ; Continue main loop
;////////////////////////////////////////////////////////////////////////////////
;note W_TEMP and STATUS_TEMP need to be in the common area (above 0x70)
ISR
MOVWF W_TEMP ; SAVE OFF CURRENT W REGISTER CONTENTS
MOVF STATUS,W ; MOVE STATUS REGISTER INTO W REGISTER
MOVWF STATUS_TEMP ; SAVE OFF CONTENTS OF STATUS REGISTER
BCF STATUS,RP0
BCF PIR1,TMR2IF
RLF previous,F
RLF previous,W
ANDLW 0X0C ;KEEP ONLY BITS 2 & 3
BTFSS PORTA,0 ;MOVE ENCODER BITS
IORLW 1 ;TO BITS 0 & 1
BTFSS PORTA,1
IORLW 2
MOVWF previous ;KEEP FOR NEXT TIME
CALL ENC_TABLE
ADDWF clicks,F
MOVLW 4
XORWF clicks,W
BTFSS STATUS,Z
GOTO CHECK_DOWN
CLRF clicks ;added this line
INCF freqHigh,F ;if not then increment it
INCFSZ freqLow,F
DECF freqHigh,F
GOTO EXIT
CHECK_DOWN
MOVLW 0XFC ;-4
XORWF clicks,W
BTFSS STATUS,Z
GOTO EXIT
CLRF clicks ;added this line
MOVF freqLow,F
SKPNZ
DECF freqHigh,F
DECF freqLow,F
GOTO EXIT
; RESTORE CONTEXT BEFORE RETURNING FROM INTERRUPT
EXIT
MOVF STATUS_TEMP,W ; RETRIEVE COPY OF STATUS REGISTER
MOVWF STATUS ; RESTORE PRE-ISR STATUS REGISTER CONTENTS
SWAPF W_TEMP,F
SWAPF W_TEMP,W ; RESTORE PRE-ISR W REGISTER CONTENTS
RETFIE ; RETURN FROM INTERRUPT
;////////////////////////////////////////////////////////////////////////////////
;
; *******************************************************************************
; * Purpose: *
; * This routine sends data to the SAA1057 using serial data transfer mode *
; * *
; * To send data:- *
; * Set Clock low *
; * *
; * Set DLEN high *
; * *
; * Set Data low *
; * *
; * Send clock bit ->high->low *
; * *
; * 1 Get Data bit from file *
; * *
; * Send clock bit ->high->low *
; * *
; * Repeat from 1 for remaining bits *
; * *
; * Set DLEN low *
; * *
; * Send clock bit ->high->low *
; * *
; * End of sequence *
; * *
; *******************************************************************************
;
send_word
bcf PORTB,CLK ; Set clock low
NOP
bsf PORTB,DLEN ; Set data load high
NOP
bcf PORTB,DAT ; Set Data low
NOP
bsf PORTB,CLK ; Toggle write clock
NOP
bcf PORTB,CLK ;
movlw freq_1 ; Point FSR at most Significant Byte
movwf FSR ;
next_byte
movf INDF,w ;
movwf byte2send ;
movlw 0x08 ; Set counter to 8
movwf bit_count ;
next_bit
rlf byte2send,f ; Test if next bit is 1 or 0
btfss STATUS,C ; Was it zero?
goto send0 ; Yes, send zero
bsf PORTB,DAT ; No, send one
goto break ;
send0
bcf PORTB,DAT ; Send zero
NOP
break
bsf PORTB,CLK ; Toggle write clock
NOP
bcf PORTB,CLK ;
decfsz bit_count,f ; Has the whole byte been sent?
goto next_bit ; No, keep going
incf FSR,f ; Start the next byte unless finished
movlw freq_0+1 ; Next byte (past the end)
subwf FSR,w ;
btfss STATUS,C ;
goto next_byte ;
bcf PORTB,DLEN ; Send load signal to the SAA1057
NOP
bsf PORTB,CLK ; Toggle write clock
NOP
bcf PORTB,CLK ;
clrf PORTB ;
return
;
; *******************************************************************************
; * Purpose: *
; * This subroutine converts a 16 bit binary number to decimal in *
; * TenK, Thou, Hund, Tens, Ones *
; * Written by John Payson. *
; *******************************************************************************
;
bin2BCD ; Takes number in freq_1:freq_0 returns decimal in TenK:Thou:Hund:Tens:Ones
movfw freq_1
movwf NumH
movfw freq_0
movwf NumL
swapf NumH,w
IORLW 0xF0
movwf Thou
addwf Thou,f
addlw 0xE2
movwf Hund
addlw 0x32
movwf Ones
movf NumH,w
andlw 0x0F
addwf Hund,f
addwf Hund,f
addwf Ones,f
addlw 0xE9
movwf Tens
addwf Tens,f
addwf Tens,f
swapf NumL,w
andlw 0x0F
addwf Tens,f
addwf Ones,f
rlf Tens,f
rlf Ones,f
comf Ones,f
rlf Ones,f
movf NumL,w
andlw 0x0F
addwf Ones,f
rlf Thou,f
movlw 0x07
movwf TenK
; At this point, the original number is equal to TenK*10000+Thou*1000+Hund*100+Tens*10+Ones
; if those entities are regarded as two's compliment binary.
; To be precise, all of them are negative except TenK.
; Now the number needs to be normalized, but this can all be done with simple byte arithmetic.
movlw 0x0A ; Ten
Lb1:
addwf Ones,f
decf Tens,f
btfss STATUS,C
goto Lb1
Lb2:
addwf Tens,f
decf Hund,f
btfss STATUS,C
goto Lb2
Lb3:
addwf Hund,f
decf Thou,f
btfss STATUS,C
goto Lb3
Lb4:
addwf Thou,f
decf TenK,f
btfss STATUS,C
goto Lb4
return
;
; *******************************************************************************
; * Purpose: *
; * Display the frequency on the LCD. *
; * *
; *******************************************************************************
;
show_freq
movlw 0xC5 ; Point the LCD to digit location
call cmnd2LCD ; Send digit location to LCD
movfw TenK
addlw 0x00 ; Test if 'w'is 0 or 1
btfss STATUS,Z ; The Z or Zero bit is set to "1" when the result
goto not_zero ; of an arithmetic or logical operation is zero
movlw ' ' ; TenK = 0, insert space
call data2LCD ; Send byte in W to LCD
goto show_thou
not_zero
call process ; TenK is not 0, insert number
show_thou
movfw Thou
call process ;
movfw Hund
call process ;
movlw '.' ; insert seperator
call data2LCD ; Send byte in W to LCD
movfw Tens
call process ;
movfw Ones
call process ;
return
process
addlw 0x30
call data2LCD
return
;
; *******************************************************************************
; * Purpose: *
; * Power on initialization of Liquid Crystal Display *
; * The LCD controller chip must be equivalent to an Hitachi 44780 *
; * *
; *******************************************************************************
;
init_LCD
movlw 100
call wait ; Wait for LCD to power up (100mS)
; Put 4-bit command in RB3..RB0
; PIC's RB3..RB0 lines connect to LCD's DB7..DB4 (pins 14-11)
movlw 0x03 ; LCD init instruction (First)
movwf PORTB ; Send to LCD via RB3..RB0
bsf PORTB,LCD_e ; Set the LCD E line high,
nop
bcf PORTB,LCD_e ; and then Clear E
call wait_100us
movlw 0x03 ; LCD init instruction (Second)
movwf PORTB ; Send to LCD via RB3..RB0
bsf PORTB,LCD_e ; Set E high,
nop
bcf PORTB,LCD_e ; and then Clear E
call wait_100us
movlw 0x03 ; LCD init instruction (Third)
movwf PORTB ; Send to LCD via RB3..RB0
bsf PORTB,LCD_e ; Set E high,
nop
bcf PORTB,LCD_e ; and then Clear E
call wait_100us ; wait a while,
movlw 0x02 ; 4-bit mode instruction
movwf PORTB ; Send to LCD via RB3..RB0
bsf PORTB,LCD_e ; Set E high,
nop
bcf PORTB,LCD_e ; and then Clear E
call wait_100us ; wait a while,
movlw 0x28 ; 1/16 duty cycle, 5x8 matrix
call cmnd2LCD ; Send command in w to LCD
call wait_100us
; movlw 0x08 ; Display off, cursor and blink off
; movlw 0x0C ; Display on, cursor and blink off
movlw 0x0E ; Display on, cursor on and blink off
; movlw 0x0F ; Display on, cursor and blink on
call cmnd2LCD ; Send command to LCD
call wait_100us
movlw 0x01 ; Clear and reset cursor
call cmnd2LCD ; Send command in w to LCD
movlw 2
call wait ; wait a while,
movlw 0x06 ; Set cursor to move right, no shift
call cmnd2LCD ; Send command in w to LCD
return ;
;
; *******************************************************************************
; * Purpose: *
; * Send Command or Data byte to the LCD *
; * Entry point cmnd2LCD: Send a Command to the LCD *
; * Entry Point data2LCD: Send a Data byte to the LCD *
; * *
; *******************************************************************************
;
cmnd2LCD ; ****** Entry point ******
clrf rs_value ; Remember to clear RS (clear rs_value)
goto write2LCD ; Go to common code
data2LCD ; ****** Entry point ********
bsf rs_value,0 ; Remember to set RS (set bit 0 of rs_value)
write2LCD
movwf LCD_char ; Save byte to write to LCD
; call busy_check ; Check to see if LCD is ready for new data
call wait_100us
MOVLW 2 ;
MOVWF count ; SET UP LOOP COUNTER
write_again
SWAPF LCD_char,F ; SWAP MS & LS NIBBLES
MOVF LCD_char,W
ANDLW 15 ; MAKE TOP 4 BITS OF W 0
MOVWF PORTB ; SEND MS NIBBLE
bcf PORTB,LCD_rs ; Guess RS should be clear - command mode
btfsc rs_value,0 ; Should RS be clear? (is bit 0 == 0?)
bsf PORTB,LCD_rs ; No, set RS - data mode
NOP
BSF PORTB,LCD_e ; SET E HIGH
NOP
BCF PORTB,LCD_e ; SET E LOW
DECFSZ count,F
GOTO write_again ; GO BACK AND SEND LS NIBBLE
clrf PORTB
return
;
; *******************************************************************************
; * Purpose: *
; * Check if LCD is done with the last operation. *
; * This subroutine polls the LCD busy flag to determine if previous *
; * operations are completed. *
; * *
; *******************************************************************************
;
;busy_check
; clrf PORTB ; Clear all outputs on PORTB
; banksel TRISB ; Switch to bank for Tris operation
; movlw b'00001000' ; Set RB3 input, others outputs
; movwf TRISB ;
;
; banksel PORTB
; bcf PORTB,LCD_rs ; Set up LCD for Read Busy Flag (RS = 0)
; nop
; bsf PORTB,LCD_rw ; Set up LCD for Read (RW = 1)
; nop ;
; bsf PORTB,LCD_e ; Set E high
; nop
; bcf PORTB,LCD_e ; Drop E again
;
;LCD_is_busy
; call wait_100us ;
; bsf PORTB,LCD_e ; Set E high
; nop
; bcf PORTB,LCD_e ; Drop E again
;
; btfss PORTB,LCD_busy ; Is Busy Flag (RB3) clear?
; goto not_busy ; Yes - exit
; nop ; No
; nop ; Wait a while
;
; bsf PORTB,LCD_e ; Pulse E high (dummy read of lower nibble),
; nop ; wait,
; bcf PORTB,LCD_e ; and drop E again
;
; goto LCD_is_busy ; If not, it is busy so jump back
;
;not_busy
; banksel TRISB ; Switch to bank 1 for Tristate operation
; clrf TRISB ; All pins (RB7..RB0) are back to outputs
; banksel PORTB ; Switch to bank 0
; clrf PORTB ; Clear all of Port B (inputs and outputs)
; return
;
; ****************************************************************************P
; * P
; * Purpose: Display version and other info on LCD for 2 seconds P
; * upon power-up P
; * P
; * Input: MCODE_REV_0 through MCODE_REV_4 set up P
; * P
; * Output: LCD displays debug info P
; * P
; ****************************************************************************P
;
display_version
movlw 0x80 ; Point LCD at digit 1
call cmnd2LCD ;
movlw 'S' ; digit 1
call data2LCD ;
movlw 'A' ; digit 2
call data2LCD ;
movlw 'A' ; digit 3
call data2LCD ;
movlw '1' ; digit 4
call data2LCD ;
movlw '0' ; digit 5
call data2LCD ;
movlw '5' ; digit 6
call data2LCD ;
movlw '7' ; digit 7
call data2LCD ;
movlw ' ' ; digit 8
call data2LCD ;
movlw MCODE_REV_0 ; Get mcode rev byte
call data2LCD ; and display it (digit 9)
movlw MCODE_REV_1 ; Get mcode rev byte
call data2LCD ; and display it (digit 10)
movlw MCODE_REV_2 ; Get mcode rev byte
call data2LCD ; and display it (digit 11)
movlw MCODE_REV_3 ; Get mcode rev byte
call data2LCD ; and display it (digit 12)
movlw MCODE_REV_4 ; Get mcode rev byte
call data2LCD ; and display it (digit 13)
movlw MCODE_REV_5 ; Get mcode rev byte
call data2LCD ; and display it (digit 14)
movlw MCODE_REV_6 ; Get mcode rev byte
call data2LCD ; and display it (digit 15)
movlw MCODE_REV_7 ; Get mcode rev byte
call data2LCD ; and display it (digit 16)
nop
LINE2
movlw 0xC0 ; Point LCD at digit 1 of second line
call cmnd2LCD ;
movlw 'F' ; digit 1
call data2LCD ;
movlw 'R' ; digit 2
call data2LCD ;
movlw 'E' ; digit 3
call data2LCD ;
movlw 'Q' ; digit 4
call data2LCD ;
movlw ':' ; digit 5
call data2LCD ;
movlw ' ' ; digit 6 0xC5
call data2LCD ;
movlw ' ' ; digit 7
call data2LCD ;
movlw ' ' ; digit 8
call data2LCD ;
movlw ' ' ; digit 9
call data2LCD ;
movlw ' ' ; digit 10
call data2LCD ;
movlw ' ' ; digit 11
call data2LCD ;
movlw 'M' ; digit 12
call data2LCD ;
movlw 'H' ; digit 13
call data2LCD ;
movlw 'z' ; digit 14
call data2LCD ;
movlw ' ' ; digit 15
call data2LCD ;
movlw ' ' ; digit 16
call data2LCD ;
return
;
; *****************************************************************************
; * *
; * Purpose: Read a byte of EEPROM data at address EEADR into EEDATA. *
; * *
; * Input: The address EEADR. *
; * *
; * Output: The value in EEDATA. *
; * *
; * NOTE: All in BANK 1 *
; *****************************************************************************
;
read_EEPROM
bsf EECON1,RD ; Request the read
movf EEDATA,W ; Get the data
incf EEADR,f ; Increment the read address
return ; Return to the caller
;
; *******************************************************************************
; * *
; * Purpose: Delay routines *
; * *
; *******************************************************************************
;
wait_a_sec ;PIC Time Delay = 0.99999900 s with Osc = 4000000 Hz
movlw D'6'
movwf CounterC
movlw D'19'
movwf CounterB
movlw D'172'
movwf CounterA
loop
decfsz CounterA,f
goto loop
decfsz CounterB,f
goto loop
decfsz CounterC,f
goto loop
return
wait_250
movlw 250
wait
movwf timer1 ; Set up counter
call wait_1ms ; Go to wait loops
decfsz timer1,f
goto $-2
return
wait_1ms ;PIC Time Delay = 0.00099800 s with Osc = 4MHz
movlw D'2'
movwf CounterD
movlw D'74'
movwf CounterE
loop1
decfsz CounterE,f
goto loop1
decfsz CounterD,f
goto loop1
return
wait_100us ;PIC Time Delay = 0.00009800 s with Osc = 4MHz
movlw D'31'
movwf CounterA
loop2
decfsz CounterA,1
goto loop2
return
;
; *****************************************************************************
;
END
;using internal 4MHz clock = 1MHz instruction time
;prescaler = 4 = clocked at 250kHz
;PR2 = 249 will clock around every 250 cycles
;postscaler = 5 = clock every 250*4*5 = 5000 cycles = 5mS interrupt
MOVLW B'00100101'
MOVWF T2CON
BSF STATUS,RP0
MOVLW 249
MOVWF PR2
BSF PIE1,TMR2IE
BCF STATUS,RP0
BSF INTCON,PEIE
BSF INTCON,GIE
main
BCF INTCON,GIE
MOVFW freqLow
MOVWF freq_0
MOVFW freqHigh
MOVWF freq_1
BSF INTCON,GIE
call bin2BCD ; Convert the frequency to BCD
call show_freq ; Display the frequency on the LCD
goto main ; Continue main loop
initTmr2
;using internal 4MHz clock = 1MHz instruction time
;prescaler = 4 = clocked at 250kHz
;PR2 = 249 will clock around every 250 cycles
;postscaler = 5 = clock every 250*4*5 = 5000 cycles = 5mS interrupt
MOVLW B'00100001' ;<-----------------
MOVWF T2CON
BSF STATUS,RP0
MOVLW 249
MOVWF PR2
BSF PIE1,TMR2IE
BCF STATUS,RP0
BSF INTCON,PEIE
BSF INTCON,GIE
BSF T2CON,TMR2ON ;<------------------
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?