; MW transmitter based on an Si5351A PLL and PIC16F628 with LCD for frequency and wavelength
; UP and DN buttons, EEPROM for current frequency (index). There are 122 frequencies from 522 to 1602 kHz.
; Frequency step is 9 kHz (Europe/Asia).
; v0.0 210923 Start project, copy-paste from various previous projects
; v0.1 210924 Removed WDT, fixed data to Si5351A
; v0.2 210925 Buttons, FRINDX
; v0.3 210925 PLL Frequency lookup
; v0.4 210925 Frequency calculation and display
; v0.5 210925 Wavelength display
; v0.6 210925 EEPROM storing of frequency setting
; v1.0 210926 Release
LIST P=16F628A, F=INHX8M
#include <p16f628a.inc>
__CONFIG _INTRC_OSC_NOCLKOUT & _WDT_OFF & _LVP_OFF & _CP_OFF
ERRORLEVEL -302 ; remove message about using proper bank
; Equates
RESET_V EQU 0x00 ; Address of RESET Vector
; Registers
FLAGS EQU 0x20 ; Various flags
LCDByte EQU 0x22 ; Byte to send to LCD
TEMP1 EQU 0x23 ; Temp register
TEMP2 EQU 0x24 ; Temp register
d1 EQU 0x25 ; Delay register
d2 EQU 0x26 ; Delay register
I2CBUF EQU 0x27 ; Used for I2C data
I2CCNT EQU 0x28 ; Used for I2C bitbanger
FRINDX EQU 0x29 ; Frequency Index
SCANCTR EQU 0x2A ; Scan speed counter
EEBUF EQU 0x2B ; Used for writing a byte to EEPROM
R26 EQU 0x2C ; Register 26
R27 EQU 0x2D ; Register 27
R29 EQU 0x2E ; Register 29
R30 EQU 0x2F ; Register 30
R32 EQU 0x32 ; Register 32
R33 EQU 0x33 ; Register 33
R44 EQU 0x44 ; Register 44
R45 EQU 0x45 ; Register 45
FREQ9 EQU 0x34 ; FRINDX+0x3A (58)
FREQLO EQU 0x35 ; Actual frequency low byte
FREQHI EQU 0x36 ; Actual frequency high byte
FREQ0 EQU 0x37 ; units BCD value for frequency display
FREQ1 EQU 0x38 ; tens BCD value for frequency display
FREQ2 EQU 0x39 ; hundreds BCD value for frequency display
FREQ3 EQU 0x3A ; thousands BCD value for frequency display
WAVELO EQU 0x3B ; Wavelength units and tens (meters)
WAVEHI EQU 0x3C ; Wavelength hundreds (meters)
; Defines
#define SCL PORTB,0 ; I2C Clock
#define SDA PORTB,1 ; I2C Data
#DEFINE LCD_EN PORTB,2
#DEFINE LCD_RS PORTB,3
#DEFINE LCD_D4 PORTB,4
#DEFINE LCD_D5 PORTB,5
#DEFINE LCD_D6 PORTB,6
#DEFINE LCD_D7 PORTB,7
#DEFINE UP PORTA,3 ; Up button (active LOW)
#DEFINE DN PORTA,4 ; Down button (active LOW)
#define NAK FLAGS,1 ; Not Acknowledge after I2C byte
#define SYSINIT FLAGS,2 ; Clear when system init of Si5351A has completed
;Macros
BANK1: MACRO
BSF STATUS,RP0
ENDM
BANK0: MACRO
BCF STATUS,RP0
ENDM
ORG 0
GOTO START
ORG 4
; Interrupts
; Timer0 Interrupt Handler
BCF INTCON,TMR0IF ; Clear TMR0 interrupt (every 58 ms)
BTFSS DN ; DN pressed?
GOTO WriteDN ; Yes
BTFSS UP ; UP pressed?
GOTO WriteUP ; Yes
RETFIE
WriteDN
CALL LONGDLY ; Extra delay to catch short keypress
MOVLW 0x0A
MOVWF SCANCTR ; Preload Scan Speed Counter
DNScanFast
INCF SCANCTR,F ; Ensure scan test passes
DNScanSlow
DECF FRINDX,F
MOVLW 0x79 ; Test for invalid index (>0x78)
SUBWF FRINDX,W
BTFSS STATUS,C ; Invalid value?
GOTO $+3 ; No
MOVLW 0x78 ; Handle rollover
MOVWF FRINDX
MOVFW FRINDX ; Get correct value for display
CALL LOADPLL
CALL FREQDISPLAY
BTFSC DN ; DN still pressed?
GOTO BTNExit ; Yes
DNCont
DECFSZ SCANCTR,F ; Scan speed fast?
GOTO $+2 ; No
GOTO DNScanFast
DNSlow ; Slow scan speed in case of Autoscan to provide time for correct STOP operation
CALL LONGDLY
CALL LONGDLY
GOTO DNScanSlow
WriteUP
CALL LONGDLY ; Extra delay to catch short keypress
MOVLW 0x0A
MOVWF SCANCTR ; Preload Scan Speed Counter
UPScanFast
INCF SCANCTR,F ; Ensure scan zero test passes
UPScanSlow
INCF FRINDX,F
MOVLW 0x79 ; Test for index rollover
SUBWF FRINDX,W
BTFSC STATUS,C ; Invalid value?
CLRF FRINDX ; Yes
MOVFW FRINDX ; No
CALL LOADPLL
CALL FREQDISPLAY
BTFSC UP ; UP pressed again?
GOTO BTNExit ; Yes
UPCont
DECFSZ SCANCTR,F ; Scan speed fast?
GOTO $+2 ; No
GOTO UPScanFast
UPSlow ; Slow scan speed in case of Autoscan to provide time for correct STOP operation
CALL LONGDLY
CALL LONGDLY
GOTO UPScanSlow
BTNExit
CALL LONGDLY
MOVFW FRINDX ; Get current index to store in EEPROM
MOVWF EEBUF
CLRW ; Point to EEPROM Address 0x00
CALL EEPROMWRITE ; Save index
CLRF TMR0
BCF INTCON,TMR0IF ; Clear TMR0 interrupt just in case (extra debounce delay)
RETFIE
; End interrupts
; Subroutines (I2C)
I2CSTART
BCF SDA
CALL I2CDELAY
BCF SCL
CALL I2CDELAY
RETURN
I2CBYTE ; Sends byte in W
MOVWF I2CBUF
MOVLW 0x08
MOVWF I2CCNT
NEXTBIT
BCF STATUS,C ; Clear carry
RLF I2CBUF,F ; Rotate MSB into carry
BTFSC STATUS,C ; Carry clear?
BSF SDA ; No, set SDA
BTFSS STATUS,C ; Carry set?
BCF SDA ; No, clear SDA
CALL I2CDELAY
BSF SCL ; Send clock
CALL I2CDELAY
BCF SCL ; Done clock
DECFSZ I2CCNT,F
GOTO NEXTBIT
; ACK handler
BSF STATUS,RP0 ; Select Bank 1
BSF TRISB,1 ; Set SDA as input to float SDA line
BCF STATUS,RP0 ; Select Bank 0
BSF NAK
CALL I2CDELAY
BSF SCL ; Solicit ACK
CLRF I2CCNT
TESTACK
BTFSC SDA ; SDA pulled low?
GOTO CONTACK ; No, continue testing for ACK until timeout (~20 ms)
BCF NAK ; Clear NAK
GOTO EXITACK ; Exit loop
CONTACK
DECFSZ I2CCNT,F
GOTO TESTACK
EXITACK
BSF STATUS,RP0 ; Select Bank 1
BCF TRISB,1 ; Set SDA as output
BCF STATUS,RP0 ; Select Bank 0
BTFSC NAK ; NAK handler
GOTO START ; Timeout, no ACK, force reset
BCF SCL
CALL I2CDELAY
RETURN
I2CSTOP
BCF SDA
CALL I2CDELAY
BSF SCL
CALL I2CDELAY
BSF SDA
RETURN
I2CDELAY
NOP ; 8 us delay
NOP
NOP
NOP
RETURN
LOADPLL
MOVLW high R2627 ; PCLATH to first entry of table
MOVWF PCLATH
BCF STATUS,C
RLF FRINDX,W ; Multiply FRINDX by 2
CALL R2627
MOVWF R26
BSF STATUS,C
RLF FRINDX,W ; Multiply FRINDX by 2 and add 1
CALL R2627
MOVWF R27
MOVLW high R2930 ; PCLATH to first entry of table
MOVWF PCLATH
BCF STATUS,C
RLF FRINDX,W ; Multiply FRINDX by 2
CALL R2930
MOVWF R29
BSF STATUS,C
RLF FRINDX,W ; Multiply FRINDX by 2 and add 1
CALL R2930
MOVWF R30
MOVLW high R3233 ; PCLATH to first entry of table
MOVWF PCLATH
BCF STATUS,C
RLF FRINDX,W ; Multiply FRINDX by 2
CALL R3233
MOVWF R32
BSF STATUS,C
RLF FRINDX,W ; Multiply FRINDX by 2 and add 1
CALL R3233
MOVWF R33
MOVLW high R4445 ; PCLATH to first entry of table
MOVWF PCLATH
BCF STATUS,C
RLF FRINDX,W ; Multiply FRINDX by 2
CALL R4445
MOVWF R44
BSF STATUS,C
RLF FRINDX,W ; Multiply FRINDX by 2 and add 1
CALL R4445
MOVWF R45
MOVLW high wave ; PCLATH to first entry of table
MOVWF PCLATH
BCF STATUS,C
RLF FRINDX,W ; Multiply FRINDX by 2
CALL wave
MOVWF WAVEHI
BSF STATUS,C
RLF FRINDX,W ; Multiply FRINDX by 2 and add 1
CALL wave
MOVWF WAVELO
CALL I2CSTART
MOVLW 0xC0 ; Address
CALL I2CBYTE
MOVLW 0x1A ; Register 26
CALL I2CBYTE
MOVFW R26 ; Get Register 26 data
CALL I2CBYTE
MOVFW R27 ; Get Register 27 data
CALL I2CBYTE
CLRW ; Register 28 data is zero
CALL I2CBYTE
MOVFW R29 ; Get Register 29 data
CALL I2CBYTE
MOVFW R30 ; Get Register 30 data
CALL I2CBYTE
CLRW ; Register 31 data is zero
CALL I2CBYTE
MOVFW R32 ; Get Register 32 data
CALL I2CBYTE
MOVFW R33 ; Get Register 33 data
CALL I2CBYTE
CALL I2CSTOP
CALL I2CSTART
MOVLW 0xC0 ; Address
CALL I2CBYTE
MOVLW 0x2C ; Register 44
CALL I2CBYTE
MOVFW R44 ; Get Register 44 data
CALL I2CBYTE
MOVFW R45 ; Get Register 45 data
CALL I2CBYTE
CALL I2CSTOP
CALL I2CSTART
MOVLW 0xC0 ; Address
CALL I2CBYTE
MOVLW 0xB1 ; Register 177
CALL I2CBYTE
MOVLW 0x20 ; Register 177 data (Reset PLLA)
CALL I2CBYTE
CALL I2CSTOP
RETURN
; Subroutines (EEPROM)
EEPROMREAD
; W contains address to read, at return contains read data
BANK1 ; Select Bank 1
MOVWF EEADR ; Data Memory Address to read from W
BSF EECON1, RD ; EE Read
MOVFW EEDATA ; W = EEDATA
BANK0 ; Select Bank 0
RETURN
EEPROMWRITE
; W contains address to write, data is in EEBUF
BANK1 ; Select Bank 1
BSF EECON1, WREN ; Enable write
BANKSEL EEADR ; Select Bank of EEADR
MOVWF EEADR ; Data Memory Address to write
BANKSEL EEBUF
MOVFW EEBUF ; Data to write from buffer
BANKSEL EEDATA
MOVWF EEDATA ; Data Memory Value to write
BANKSEL EECON2 ; Select Bank of EECON2
MOVLW 0x55
MOVWF EECON2 ; Write 55h
MOVLW 0xAA
MOVWF EECON2 ; Write AAh
BSF EECON1, WR ; Set WR bit to begin write
BCF EECON1, WREN ; Disable writes
BANK0 ; Select BANK0
RETURN
; Subroutines (LCD)
LCDPOS ; makes WREG the current LCD position
BCF LCD_RS
MOVWF LCDByte ; Valid values 0x80-0x8F, 0xC0-0xCF
CALL LCDBYTE
BSF LCD_RS
CALL LONGDLY ; Needed for the LCD to process the command
RETURN
LCDCLR ; clears the entire display
BCF LCD_RS ; Instruction mode
MOVLW 0x01
MOVWF LCDByte
CALL LCDBYTE
BSF LCD_RS ; Character mode
CALL LONGDLY ; Clearing the LCD takes ages, so a larger delay is needed
RETURN
LCDBYTE
; sends the byte in WREG to the LCD in 4bit fashion. Set LCD_RS as appropriate (0: instruction, 1: character)
MOVWF LCDByte
BCF LCD_D7 ; Clear data bits
BCF LCD_D6
BCF LCD_D5
BCF LCD_D4
BTFSC LCDByte,7 ; Load high nibble
BSF LCD_D7
BTFSC LCDByte,6
BSF LCD_D6
BTFSC LCDByte,5
BSF LCD_D5
BTFSC LCDByte,4
BSF LCD_D4
BSF LCD_EN ; Strobe EN
NOP
BCF LCD_EN
BCF LCD_D7 ; Clear data bits
BCF LCD_D6
BCF LCD_D5
BCF LCD_D4
BTFSC LCDByte,3 ; Load low nibble
BSF LCD_D7
BTFSC LCDByte,2
BSF LCD_D6
BTFSC LCDByte,1
BSF LCD_D5
BTFSC LCDByte,0
BSF LCD_D4
BSF LCD_EN ; Strobe EN
NOP
BCF LCD_EN
CALL SHORTDLY ; blocks until most instructions are done
RETURN
SHORTDLY
; around 221us, 217 cycles
MOVLW 0x48
MOVWF d1
SHORTDLY_0
DECFSZ d1,F
GOTO SHORTDLY_0 ;4 cycles (including call)
RETURN
LONGDLY
; 92ms delay, 92153 cycles
MOVLW 0xFE
MOVWF d1
MOVLW 0x48
MOVWF d2
LONGDLY_0
DECFSZ d1,F
GOTO $+2
DECFSZ d2,F
GOTO LONGDLY_0 ;3 cycles
NOP
NOP ;4 cycles (including call)
RETURN
; Frequency handler
FREQDISPLAY ; Decodes index to frequency and wavelength display
MOVLW 0x80
CALL LCDPOS ; Set display leftmost corner top line
MOVFW FRINDX
ADDLW 0x3A
MOVWF FREQ9 ; Add offset to get freq/9
CLRF FREQHI ; Multiply by 8
BCF STATUS,C
RLF FREQ9,F
RLF FREQHI,F
BCF STATUS,C
RLF FREQ9,F
RLF FREQHI,F
BCF STATUS,C
RLF FREQ9,F
RLF FREQHI,F
ADDWF FREQ9,W ; Add once to get multiply by 9
MOVWF FREQLO
BTFSC STATUS,C ; Carry from addition?
INCF FREQHI,F ; Yes
; Convert frequency to BCD 4 digits
; See http://www.piclist.com/techref/microchip/math/radix/b2bu-10b4d-eag.htm
movf FREQHI,w
iorlw 0xF0 ;w=H2-16
movwf FREQ1 ;S1=H2-16
addwf FREQ1,f ;S1=H2*2-32
addwf FREQ1,f ;S1=H2*3-48
movwf FREQ2 ;S2=H2-16
addlw -D'5' ;w=H2-21
addwf FREQ2,f ;S2=H2*2-37 Done!
addlw D'41' ;w=H2+20
movwf FREQ0 ;S0=H2+20
swapf FREQLO,w
iorlw 0xF0 ;w=H1-16
addwf FREQ1,f ;S1=H2*3+H1-64
addwf FREQ0,f ;S0=H2+H1+4, C=1
rlf FREQ0,f ;S0=(H2+H1)*2+9, C=0
comf FREQ0,f ;S0=-(H2+H1)*2-10
rlf FREQ0,f ;S0=-(H2+H1)*4-20
movf FREQLO,w
andlw 0x0F ;w=H0
addwf FREQ0,f ;S0=H0-(H2+H1)*4-20 Done!
rlf FREQ1,f ;C=0, S1=H2*6+H1*2-128 Done!
movlw D'5'
movwf FREQ3
movlw D'10'
mod0t
addwf FREQ0,f ;D(X)=D(X)mod10
decf FREQ1,f ;D(X+1)=D(X+1)+D(X)div10
skpc
goto mod0t
mod1t
addwf FREQ1,f
decf FREQ2,f
skpc
goto mod1t
mod2t
addwf FREQ2,f
decf FREQ3,f
skpc
goto mod2t
MOVLW 0x30
ADDWF FREQ0,F ; Add 0x30 to get ASCII value for number
ADDWF FREQ1,F
ADDWF FREQ2,F
ADDWF FREQ3,F
SUBWF FREQ3,W ; Test for leading zero
BTFSS STATUS,Z
GOTO $+3
MOVLW 0x20
MOVWF FREQ3
MOVLW 0x80 ; Leftmost position upper line
CALL LCDPOS
MOVFW FREQ3
CALL LCDBYTE
MOVFW FREQ2
CALL LCDBYTE
MOVFW FREQ1
CALL LCDBYTE
MOVFW FREQ0
CALL LCDBYTE
MOVLW 0x20 ; space
CALL LCDBYTE
MOVLW 0x6B ; k
CALL LCDBYTE
MOVLW 0x48 ; H
CALL LCDBYTE
MOVLW 0x7A ; z
CALL LCDBYTE
MOVLW 0xC0 ; Leftmost position lower line
CALL LCDPOS
MOVFW WAVEHI
ADDLW 0x30
CALL LCDBYTE
MOVFW WAVELO
MOVWF TEMP2
RRF TEMP2,F
RRF TEMP2,F
RRF TEMP2,F
RRF TEMP2,W
ANDLW 0x0F ; Convert to ASCII
ADDLW 0x30
CALL LCDBYTE
MOVFW WAVELO
ANDLW 0x0F ; Convert to ASCII
ADDLW 0x30
CALL LCDBYTE
MOVLW 0x20 ; space
CALL LCDBYTE
MOVLW 0x6D ; m
CALL LCDBYTE
MOVLW 0x65 ; e
CALL LCDBYTE
MOVLW 0x74 ; t
CALL LCDBYTE
MOVLW 0x65 ; e
CALL LCDBYTE
MOVLW 0x72 ; r
CALL LCDBYTE
RETURN
START
; Init stuff
CLRF STATUS ; Do initialization, select Bank 0
CLRF INTCON ; Clear int-flags, disable interrupts
MOVLW 0x07 ; Disable comparators
MOVWF CMCON
BANK1
MOVLW B'11111001'
MOVWF TRISA ; RA7-3 Inputs, RA2,1 Outputs, AN0 Input
CLRF TRISB ; RB7-0 Outputs
MOVLW B'00000110' ; Timer0, prescaler 1:128
MOVWF OPTION_REG
BANK0
CLRF PORTB ; Make all PORT B outputs low
CLRF FLAGS
BSF SCL
BSF SDA
; Init LCD
CALL LONGDLY ; Set LCD to 4-bit mode
MOVLW B'00110011' ; 2x 8bit resets
CALL LCDBYTE
CALL SHORTDLY
MOVLW B'00110011' ; 2x 8bit resets
CALL LCDBYTE
CALL SHORTDLY
MOVLW B'00110010' ; 8bit reset then 4bit reset
CALL LCDBYTE
CALL SHORTDLY
MOVLW B'00101100' ; Function Set - 4bit, 2 lines
CALL LCDBYTE
CALL SHORTDLY
MOVLW B'00000110' ; Set entry mode (move cursor to right after each write)
CALL LCDBYTE
CALL SHORTDLY
MOVLW B'00001100' ; turn display on and cursor off
CALL LCDBYTE
CALL SHORTDLY
MOVLW B'00000001' ; Display Clear
CALL LCDBYTE
CALL LONGDLY ; Should wait for BUSY flag to clear but we cannot read it...
MOVLW B'00000010' ; Cursor Home
CALL LCDBYTE
CALL LONGDLY
; Done init LCD
; Show banner
MOVLW 0x80 ; 1st position top line
CALL LCDPOS
MOVLW 0x4D ; M
CALL LCDBYTE
MOVLW 0x57 ; W
CALL LCDBYTE
MOVLW 0x20 ; space
CALL LCDBYTE
MOVLW 0x50 ; P
CALL LCDBYTE
MOVLW 0x4C ; L
CALL LCDBYTE
MOVLW 0x4C ; L
CALL LCDBYTE
MOVLW 0x20 ; space
CALL LCDBYTE
MOVLW 0x4D ; M
CALL LCDBYTE
MOVLW 0x6F ; o
CALL LCDBYTE
MOVLW 0x64 ; d
CALL LCDBYTE
MOVLW 0x75 ; u
CALL LCDBYTE
MOVLW 0x6C ; l
CALL LCDBYTE
MOVLW 0x61 ; a
CALL LCDBYTE
MOVLW 0x74 ; t
CALL LCDBYTE
MOVLW 0x6F ; o
CALL LCDBYTE
MOVLW 0x72 ; r
CALL LCDBYTE
MOVLW 0xC0 ; 1st postition bottom line
CALL LCDPOS
MOVLW 0x53 ; S
CALL LCDBYTE
MOVLW 0x69 ; i
CALL LCDBYTE
MOVLW 0x35 ; 5
CALL LCDBYTE
MOVLW 0x33 ; 3
CALL LCDBYTE
MOVLW 0x35 ; 5
CALL LCDBYTE
MOVLW 0x31 ; 1
CALL LCDBYTE
MOVLW 0x20 ; space
CALL LCDBYTE
MOVLW 0x43 ; C
CALL LCDBYTE
MOVLW 0x6C ; l
CALL LCDBYTE
MOVLW 0x6F ; o
CALL LCDBYTE
MOVLW 0x63 ; c
CALL LCDBYTE
MOVLW 0x6B ; k
CALL LCDBYTE
MOVLW 0x20 ; space
CALL LCDBYTE
MOVLW 0x47 ; G
CALL LCDBYTE
MOVLW 0x65 ; e
CALL LCDBYTE
MOVLW 0x6E ; n
CALL LCDBYTE
; Restore index from EEPROM
CLRW
CALL EEPROMREAD
BANK0
MOVWF FRINDX ; Restored Frequency Index
; Init Si5351A
CALL I2CSTART
MOVLW 0xC0 ; Address
CALL I2CBYTE
CLRW ; Prepare register 0 for reading
CALL I2CBYTE
CALL I2CSTOP
Readsysinit
CALL I2CSTART
MOVLW 0xC1 ; Read address
CALL I2CBYTE
CLRF I2CCNT ; Used for ACK timeout
BANK1 ; Select Bank 1
BSF TRISB,1 ; Set SDA as input to float SDA line
BANK0 ; Select Bank 0
CALL I2CDELAY
BSF SCL ; Read SYS_INIT bit
CALL I2CDELAY
BTFSS SDA
BCF SYSINIT
BCF SCL
MOVLW 0x07
MOVWF I2CCNT
DUMMYREAD
CALL I2CDELAY
BSF SCL
CALL I2CDELAY
BCF SCL
DECFSZ I2CCNT,F
GOTO DUMMYREAD
BANK1 ; Select Bank 1
BCF TRISB,1 ; Set SDA as output to assert SDA line
BANK0 ; Select Bank 0
BCF SDA ; Present NAK
CALL I2CDELAY
BSF SCL
CALL I2CDELAY
BCF SCL
CALL I2CSTOP
BTFSC SYSINIT ; System init done?
GOTO Readsysinit ; No
; Start configure
CALL I2CSTART
MOVLW 0xC0 ; Address
CALL I2CBYTE
MOVLW 0x03 ; Register 3
CALL I2CBYTE
MOVLW 0xFF ; Register 3 data (Output Enable Control)
CALL I2CBYTE
CALL I2CSTOP
CALL I2CSTART
MOVLW 0xC0 ; Address
CALL I2CBYTE
MOVLW 0x09 ; Register 9
CALL I2CBYTE
MOVLW 0xFF ; Register 9 data (OEB Pin Enable Control Mask)
CALL I2CBYTE
CALL I2CSTOP
CALL I2CSTART
MOVLW 0xC0 ; Address
CALL I2CBYTE
MOVLW 0x10 ; Register 16
CALL I2CBYTE
MOVLW 0x4F ; Register 16 data
CALL I2CBYTE
MOVLW 0x80 ; Register 17 data
CALL I2CBYTE
MOVLW 0x80 ; Register 18 data
CALL I2CBYTE
MOVLW 0x80 ; Register 19 data
CALL I2CBYTE
MOVLW 0x80 ; Register 20 data
CALL I2CBYTE
MOVLW 0x80 ; Register 21 data
CALL I2CBYTE
MOVLW 0x80 ; Register 22 data
CALL I2CBYTE
MOVLW 0x80 ; Register 23 data
CALL I2CBYTE
CLRW ; Register 24 data (CLK3–0 Disable State)
CALL I2CBYTE
CLRW ; Register 25 data (CLK7–4 Disable State)
CALL I2CBYTE
CALL I2CSTOP
CALL I2CSTART
MOVLW 0xC0 ; Address
CALL I2CBYTE
MOVLW 0x3B ; Register 43
CALL I2CBYTE
MOVLW 0x01 ; Register 43 data (always 1)
CALL I2CBYTE
CALL I2CSTOP
CALL LOADPLL
CALL I2CSTART
MOVLW 0xC0 ; Address
CALL I2CBYTE
MOVLW 0xB7 ; Register 183
CALL I2CBYTE
MOVLW 0x92 ; 8 pF load capacitance for XTAL used on Adafruit board and mandatory bit pattern
CALL I2CBYTE
CALL I2CSTOP
CALL I2CSTART
MOVLW 0xC0 ; Address
CALL I2CBYTE
MOVLW 0x03 ; Register 3
CALL I2CBYTE
MOVLW 0xFE ; Register 3 data: enable OSC0
CALL I2CBYTE
CALL I2CSTOP
; Done init Si5351A
MOVLW 0x10 ; Show banner for about one second
MOVWF TEMP1
CALL LONGDLY
DECFSZ TEMP1,F
GOTO $-2
CALL LCDCLR ; Clear display
CALL LONGDLY
CALL FREQDISPLAY
MOVLW B'10100000' ; Enable global (GIE), Timer0 (T0IE) interrupts
MOVWF INTCON
GOTO $ ; Loop forever
ORG 0x300 ; Wavelength table
wave
ADDWF PCL,F
dt 0x05,0x74,0x05,0x65,0x05,0x56,0x05,0x46
dt 0x05,0x37,0x05,0x28,0x05,0x20,0x05,0x12
dt 0x05,0x04,0x04,0x97,0x04,0x89,0x04,0x82
dt 0x04,0x75,0x04,0x69,0x04,0x62,0x04,0x56
dt 0x04,0x50,0x04,0x44,0x04,0x38,0x04,0x32
dt 0x04,0x27,0x04,0x21,0x04,0x16,0x04,0x11
dt 0x04,0x06,0x04,0x01,0x03,0x96,0x03,0x91
dt 0x03,0x87,0x03,0x82,0x03,0x78,0x03,0x74
dt 0x03,0x70,0x03,0x66,0x03,0x62,0x03,0x58
dt 0x03,0x54,0x03,0x50,0x03,0x46,0x03,0x43
dt 0x03,0x39,0x03,0x36,0x03,0x33,0x03,0x29
dt 0x03,0x26,0x03,0x23,0x03,0x20,0x03,0x17
dt 0x03,0x14,0x03,0x11,0x03,0x08,0x03,0x05
dt 0x03,0x02,0x03,0x00,0x02,0x97,0x02,0x94
dt 0x02,0x92,0x02,0x89,0x02,0x87,0x02,0x84
dt 0x02,0x82,0x02,0x79,0x02,0x77,0x02,0x75
dt 0x02,0x73,0x02,0x70,0x02,0x68,0x02,0x66
dt 0x02,0x64,0x02,0x62,0x02,0x60,0x02,0x58
dt 0x02,0x56,0x02,0x54,0x02,0x52,0x02,0x50
dt 0x02,0x48,0x02,0x46,0x02,0x44,0x02,0x43
dt 0x02,0x41,0x02,0x39,0x02,0x37,0x02,0x36
dt 0x02,0x34,0x02,0x32,0x02,0x31,0x02,0x29
dt 0x02,0x28,0x02,0x26,0x02,0x25,0x02,0x23
dt 0x02,0x22,0x02,0x20,0x02,0x19,0x02,0x17
dt 0x02,0x16,0x02,0x14,0x02,0x13,0x02,0x12
dt 0x02,0x10,0x02,0x09,0x02,0x08,0x02,0x06
dt 0x02,0x05,0x02,0x04,0x02,0x03,0x02,0x01
dt 0x02,0x00,0x01,0x99,0x01,0x98,0x01,0x97
dt 0x01,0x95,0x01,0x94,0x01,0x93,0x01,0x92
dt 0x01,0x91,0x01,0x90,0x01,0x89,0x01,0x88
dt 0x01,0x87
ORG 0x400 ; Registers 26,27
R2627
ADDWF PCL,F
dt 0x18,0x6A,0x30,0xD4,0x00,0x01,0x30,0xD4
dt 0x18,0x6A,0x18,0x6A,0x0C,0x35,0x04,0xE2
dt 0x18,0x6A,0x02,0x71,0x0C,0x35,0x30,0xD4
dt 0x02,0x71,0x0C,0x35,0x02,0x71,0x0C,0x35
dt 0x00,0xFA,0x00,0x01,0x0C,0x35,0x0C,0x35
dt 0x0C,0x35,0x30,0xD4,0x00,0x01,0x02,0x71
dt 0x0C,0x35,0x0C,0x35,0x0C,0x35,0x09,0xC4
dt 0x0C,0x35,0x30,0xD4,0x0C,0x35,0x30,0xD4
dt 0x02,0x71,0x30,0xD4,0x0C,0x35,0x18,0x6A
dt 0x18,0x6A,0x09,0xC4,0x02,0x71,0x30,0xD4
dt 0x0C,0x35,0x30,0xD4,0x00,0x01,0x09,0xC4
dt 0x18,0x6A,0x18,0x6A,0x0C,0x35,0x00,0xFA
dt 0x0C,0x35,0x30,0xD4,0x02,0x71,0x0C,0x35
dt 0x04,0xE2,0x00,0xFA,0x0C,0x35,0x30,0xD4
dt 0x18,0x6A,0x09,0xC4,0x02,0x71,0x0C,0x35
dt 0x18,0x6A,0x30,0xD4,0x02,0x71,0x18,0x6A
dt 0x18,0x6A,0x0C,0x35,0x0C,0x35,0x00,0x01
dt 0x0C,0x35,0x18,0x6A,0x0C,0x35,0x30,0xD4
dt 0x04,0xE2,0x30,0xD4,0x02,0x71,0x0C,0x35
dt 0x02,0x71,0x02,0x71,0x0C,0x35,0x0C,0x35
dt 0x0C,0x35,0x02,0x71,0x02,0x71,0x0C,0x35
dt 0x0C,0x35,0x0C,0x35,0x02,0x71,0x02,0x71
dt 0x18,0x6A,0x09,0xC4,0x0C,0x35,0x30,0xD4
dt 0x00,0x01,0x18,0x6A,0x0C,0x35,0x18,0x6A
dt 0x18,0x6A,0x02,0x71,0x00,0x19,0x30,0xD4
dt 0x18,0x6A,0x09,0xC4,0x02,0x71,0x18,0x6A
dt 0x02,0x71,0x30,0xD4,0x0C,0x35,0x02,0x71
dt 0x0C,0x35,0x30,0xD4,0x0C,0x35,0x30,0xD4
dt 0x00,0x7D,0x0C,0x35,0x0C,0x35,0x01,0xF4
dt 0x0C,0x35,0x00,0xFA,0x0C,0x35,0x02,0x71
dt 0x0C,0x35
ORG 0x500 ; Registers 29,30
R2930
ADDWF PCL,F
dt 0x0C,0x02,0x0B,0xFF,0x0B,0x80,0x0B,0xFD
dt 0x0B,0xFE,0x0C,0x04,0x0B,0xFC,0x0B,0xFE
dt 0x0B,0xFE,0x0B,0xFD,0x0B,0xFA,0x0B,0xFC
dt 0x0C,0x02,0x0C,0x01,0x0B,0xFF,0x0B,0xFB
dt 0x0B,0xFC,0x0B,0x80,0x0B,0xFB,0x0B,0xF8
dt 0x0B,0xFB,0x0B,0xF6,0x10,0x00,0x0B,0xFF
dt 0x0B,0xFE,0x0B,0xFB,0x0B,0xF8,0x0B,0xFB
dt 0x0B,0xFE,0x0C,0x00,0x0C,0x00,0x0C,0x00
dt 0x0B,0xFF,0x0B,0xFD,0x0B,0xFA,0x0B,0xFE
dt 0x0B,0xF9,0x0B,0xFC,0x0B,0xFF,0x0C,0x00
dt 0x0C,0x0A,0x0C,0x01,0x0B,0x80,0x0B,0xFF
dt 0x0B,0xFD,0x0C,0x04,0x0C,0x00,0x0B,0xFC
dt 0x0B,0xF7,0x0B,0xFB,0x0B,0xFF,0x0B,0xF8
dt 0x0B,0xFA,0x0B,0xFC,0x0B,0xF3,0x0B,0xF4
dt 0x0B,0xFE,0x0B,0xF3,0x0B,0xFD,0x0B,0xFB
dt 0x0B,0xF9,0x0C,0x02,0x0B,0xFF,0x0C,0x06
dt 0x0C,0x02,0x0B,0xFE,0x0B,0xF8,0x0B,0x80
dt 0x0B,0xF8,0x0B,0xFD,0x0C,0x02,0x0B,0xFA
dt 0x0B,0xFE,0x0C,0x01,0x0C,0x04,0x0B,0xFB
dt 0x0B,0xFD,0x0B,0xFF,0x0C,0x0D,0x0C,0x01
dt 0x0C,0x02,0x0C,0x02,0x0C,0x02,0x0C,0x02
dt 0x0C,0x01,0x0C,0x00,0x0B,0xFF,0x0B,0xFD
dt 0x0C,0x08,0x0C,0x06,0x0C,0x03,0x0C,0x00
dt 0x0B,0x80,0x0C,0x06,0x0C,0x02,0x0B,0xFD
dt 0x0C,0x06,0x0C,0x0F,0x0C,0x0A,0x0C,0x12
dt 0x0C,0x0C,0x0C,0x06,0x0C,0x0D,0x0C,0x06
dt 0x0B,0xFF,0x0C,0x06,0x0B,0xFE,0x0C,0x04
dt 0x0B,0xFB,0x0C,0x02,0x0C,0x08,0x0C,0x0D
dt 0x0C,0x13,0x0C,0x09,0x0B,0xFE,0x0C,0x03
dt 0x0C,0x08,0x0B,0xFC,0x0C,0x00,0x0C,0x04
dt 0x0B,0xF8
ORG 0x600 ; Registers 32,33
R3233
ADDWF PCL,F
dt 0x10,0xAC,0x0D,0x54,0x00,0x00,0x02,0xFC
dt 0x0F,0x54,0x03,0xD8,0x02,0xD4,0x01,0x44
dt 0x0F,0x54,0x00,0xD3,0x04,0xBE,0x06,0xD0
dt 0x02,0x1E,0x09,0xB4,0x00,0x71,0x01,0x89
dt 0x00,0x68,0x00,0x00,0x01,0x89,0x06,0xA8
dt 0x0A,0x89,0x26,0xC8,0x00,0x00,0x00,0x71
dt 0x00,0xEA,0x0A,0x89,0x06,0xA8,0x09,0x54
dt 0x05,0x6A,0x00,0x80,0x08,0x00,0x12,0x80
dt 0x00,0x71,0x02,0xFC,0x00,0x3E,0x0F,0x54
dt 0x14,0x66,0x08,0x90,0x00,0x71,0x24,0x80
dt 0x07,0x6E,0x20,0xAC,0x00,0x00,0x06,0x44
dt 0x0C,0xBE,0x03,0xD8,0x08,0x00,0x00,0x68
dt 0x05,0x5D,0x1C,0xA4,0x00,0x71,0x02,0x28
dt 0x02,0xCC,0x00,0x68,0x04,0xB1,0x01,0x70
dt 0x0F,0x54,0x06,0x74,0x00,0xD3,0x0A,0x89
dt 0x14,0x66,0x0A,0xD8,0x00,0x71,0x12,0x04
dt 0x10,0xAC,0x00,0xEA,0x0B,0x28,0x00,0x00
dt 0x06,0xA8,0x0C,0xBE,0x01,0x96,0x17,0x78
dt 0x01,0x44,0x20,0xAC,0x01,0xBC,0x01,0x89
dt 0x00,0xD3,0x00,0x71,0x02,0x4F,0x09,0x4B
dt 0x06,0x16,0x02,0x1E,0x02,0x1E,0x06,0x16
dt 0x09,0x4B,0x08,0x00,0x00,0x71,0x00,0xD3
dt 0x0E,0x30,0x00,0xE8,0x02,0xE1,0x00,0x80
dt 0x00,0x00,0x09,0x04,0x01,0x96,0x0C,0xBE
dt 0x12,0x04,0x01,0xE1,0x00,0x06,0x27,0x98
dt 0x0F,0x88,0x00,0xE8,0x02,0x43,0x12,0x04
dt 0x00,0x71,0x0D,0x88,0x00,0xEA,0x01,0xBC
dt 0x0A,0x89,0x01,0xD8,0x00,0x58,0x28,0xBD
dt 0x00,0x39,0x01,0xA3,0x05,0x6A,0x00,0xA4
dt 0x00,0x58,0x00,0x68,0x08,0x00,0x01,0xBC
dt 0x02,0x28
ORG 0x700 ; Registers 44.45
R4445
ADDWF PCL,F
dt 0x02,0x9D,0x02,0x91,0x02,0x6F,0x02,0x7B
dt 0x02,0x71,0x02,0x68,0x02,0x5D,0x02,0x54
dt 0x02,0x4B,0x02,0x42,0x02,0x39,0x02,0x31
dt 0x02,0x2A,0x02,0x22,0x02,0x1A,0x02,0x12
dt 0x02,0x0B,0x01,0xF2,0x01,0xFD,0x01,0xF6
dt 0x01,0xF0,0x01,0xE9,0x02,0x6F,0x01,0xDE
dt 0x01,0xD8,0x01,0xD2,0x01,0xCC,0x01,0xC7
dt 0x01,0xC2,0x01,0xBD,0x01,0xB8,0x01,0xB3
dt 0x01,0xAE,0x01,0xA9,0x01,0xA4,0x01,0xA0
dt 0x01,0x9B,0x01,0x97,0x01,0x93,0x01,0x8F
dt 0x01,0x8C,0x01,0x87,0x01,0x75,0x01,0x7F
dt 0x01,0x7B,0x01,0x78,0x01,0x74,0x01,0x70
dt 0x01,0x6C,0x01,0x69,0x01,0x66,0x01,0x62
dt 0x01,0x5F,0x01,0x5C,0x01,0x58,0x01,0x55
dt 0x01,0x53,0x01,0x4F,0x01,0x4D,0x01,0x4A
dt 0x01,0x47,0x01,0x45,0x01,0x42,0x01,0x40
dt 0x01,0x3D,0x01,0X3A,0x01,0x37,0x01,0x2A
dt 0x01,0x32,0x01,0x30,0x01,0x2E,0x01,0x2B
dt 0x01,0x29,0x01,0x27,0x01,0x25,0x01,0x22
dt 0x01,0x20,0x01,0x1E,0x01,0x1D,0x01,0x1A
dt 0x01,0x18,0x01,0x16,0x01,0x14,0x01,0x12
dt 0x01,0x10,0x01,0x0E,0x01,0x0C,0x01,0x0A
dt 0x01,0x09,0x01,0x07,0x01,0x05,0x01,0x03
dt 0x00,0xF8,0x01,0x00,0x00,0xFE,0x00,0xFC
dt 0x00,0xFB,0x00,0xFA,0x00,0xF8,0x00,0xF7
dt 0x00,0xF5,0x00,0xF3,0x00,0xF2,0x00,0xF0
dt 0x00,0xEE,0x00,0xED,0x00,0xEB,0x00,0xEA
dt 0x00,0xE8,0x00,0xE7,0x00,0xE6,0x00,0xE5
dt 0x00,0xE4,0x00,0xE2,0x00,0xE0,0x00,0xDF
dt 0x00,0xDE,0x00,0xDC,0x00,0xDB,0x00,0xDA
dt 0x00,0xD8
ORG 0x2100 ; EEPROM Data
DE 0x35 ; FRINDX (999 kHz)
END