Hi
This is my most recent 16F628A controller code for Silicon Labs Si4703 FM radio chip.
This chip gets itís watch crystal disconnected, and itís clock input (RCLK) taken from the 16F628A via a resistor divider.

I suppose Iíll have to do a schematic after all of this Iíll also post a simpler code, all in PBP from another thread which is easy to understand and modify.
This version is as much as I could cram into the pic in some weeks, is much better to use, and has more functionality, but will be more difficult to follow.

Major features:
Turns the Si4703 FM radio IC into a dual band radio (FM Broadcast band, and VHF amateur band).
Displays accurate frequencies up to two decimal places ie. ď146.30 MHzĒ.
Displays signal strength and volume with a pixel width resolution graphic bar graph and numbers.
Squelch feature for muting radio silence, particularly good for VHF amateur band.
Printed debug error codes to warn of some hardware errors during project construction.
Six buttons supported with 74HC165 parallel shift register, as well as a jumper to set hardware configuration.
A jumper configures hardware for serial output or for a character LCD display, to aid testing during construction.

Code:
'
'****************************************************************
'*                                                              *
'*           FM Radio DDS controller V2 (c) Art 2019            *
'*            Some base code by Darrel Taylor (RIP)             *
'*              For Microchip Pic 16F628A @ 10MHz               *
'*           Tested with Si4703 & version 19 firmware           *
'*                                                              *
'****************************************************************
'
' RB4 = sr load
' RB5 = sr clock
' RB6 = sr data
' RB0 = si reset
' RB1 = si sdio
' RB7 = si clock
' RB3 = freq out
' RB2 = lcd en
' RA0 = lcd d0
' RA1 = lcd d1 or default serial out
' RA2 = lcd d2
' RA3 = lcd d3
' RA4 = lcd rs
' RA5 = reset or spare input
' Shift register input pins are buttons and a jumper
' Shift register jumper sets lcd or serial output
' One spare input on 74HC165 shift register
' Shift register pins should be tied normally high
' Two unused outputs on Si4703 gpio pins
'
' printed lcd debug error code messages:
' ERROR: 1 - i2c communication failure
' ERROR: 2 - Si470x device id incorrect
' ERROR: 3 - 74HC165 shift register error
'
DEFINE OSC 10		'10 MHz oscillator
DEFINE NO_CLRWDT 1	'tell compiler not to insert clrwdt instructions
'
DATA  " DDS HACK RADIOBREK MARTIN 2019 BROADCAST AMATEUR"
DATA  " VHF FMVOLUME:  MHz  FREQ: SIGNAL: ERROR: Si470"
DATA  " DDS Radio V2 -"   ' load credit string to eeprom
DATA  " Brek Martin 2019" ' DDS Radio V2 - Brek Martin 2019
'
E_PIN var portb.2	'lcd enable pin alternative name
'
'Darrel Taylor's register variables with extras and omissions
Si_REGS  VAR WORD[16]
deviceid        VAR Si_REGS[0]        ' Read Only
chipid          VAR Si_REGS[1]        ' Read Only
powercfg        VAR Si_REGS[2]        ' R/W
    DSMUTE      VAR powercfg.15
    DMUTE       VAR powercfg.14
    MONO        VAR powercfg.13
    RDSM        VAR powercfg.11
    SEEK        VAR powercfg.8
    SiDISABLE   VAR powercfg.6
    SiENABLE    VAR powercfg.0
channel         VAR Si_REGS[3]        ' R/W
    TUNE        VAR channel.15
sysconfig1      VAR Si_REGS[4]        ' R/W
    RDSIEN      VAR sysconfig1.15
    STCIEN      VAR sysconfig1.14
    RDS         VAR sysconfig1.12
    DE          VAR sysconfig1.11
    AGCD        VAR sysconfig1.10
sysconfig2      VAR Si_REGS[5]        ' R/W
    SPACEH      VAR sysconfig2.5	  ' channel spacing
    SPACEL      VAR sysconfig2.4      '
sysconfig3      VAR Si_REGS[6]        ' R/W
	VOLEXT		VAR sysconfig3.8
test1           VAR Si_REGS[7]        ' R/W
    XOSCEN      VAR test1.15
    AHIZEN      VAR test1.14
test2           VAR Si_REGS[8]        ' R/W, Reserved
bootconfig      VAR Si_REGS[9]        ' R/W, Reserved
statusrssi      VAR Si_REGS[10]       ' Read Only
    RDSR        VAR statusrssi.15
    STC         VAR statusrssi.14
    SF_BL       VAR statusrssi.13
    AFCRL       VAR statusrssi.12
    RDSS        VAR statusrssi.11
    ST          VAR statusrssi.8
readchan        VAR Si_REGS[11]       ' Read Only
SI470X_CURRENTVOLUME     VAR BYTE
SI470X_CURRENTBAND       VAR BYTE
SI470X_CURRENTSPACE      VAR BYTE
SI470X_CURRENTFREQUENCY  VAR WORD
SI470X_CURRENTRSSI       VAR BYTE
SI470X_MINFREQUENCY      VAR WORD
SI470X_MAXFREQUENCY      VAR WORD
SI470X_TempB             VAR BYTE
SI470X_TempW             VAR WORD
' application variables
bflags var word		'bit flags
userfreq var word	'user frequency
displayfreq var word'frequency for display
vwork var word		'work variable
sigst var word		'signal strength
sigstb var word		'
psthr var byte		'delay counters and
psfor var byte		'i2c comms buffers
psnin var byte		'
psone var byte		'
pstwo var byte		'
psfiv var byte		'
psate var byte		'
pssix var byte		'tuning down delay timer
pssev var byte		'tuning up delay timer
'alternative names for serial port
delay var psfiv     'set baud rate delay
txbyte var psate    'byte to send
bcount var psnin    'serial counter
'character lcd control
lata var byte		'port latch
arg var byte		'lcd function arguments
nib var byte		'lcd nibble buffer
'shift register control
srbuff var byte		'
srcnt var byte		'
srbyte var byte		'
cnt var byte		'text counter
uservol var byte	'user volume
volchanged var byte	'volume changed
freqchanged var byte'frequency changed
vchan var byte		'vhf channel value
lll var byte		'counter
squelch var byte	'squelch enabled flag
srbit var bit		'shift register control
userband var bit	'current selected band
itwosee var bit		'i2c control
startup var bit		'first cycle flag
rssitype var bit	'signal display type
demobar var bit		'animated bar control
mutebuf var bit		'mute value for squelch
rsflag var bit		'lcd rs flag
buttona var bflags.0'shift register button flags
buttonb var bflags.1'
buttonc var bflags.2'
buttond var bflags.3'
buttone var bflags.4'
buttonf var bflags.5'
hwconfg var bflags.6'hardware configuration flag
srstats var bflags.7'shift register status flag
silinfo var bflags.8'print chip info flag
itceror var bit		'i2c error flag
'serial output pin if enabled by shift register jumper
serpin var porta.1	'set port pin for serial out
'                  
'execution begins
'@ call order_66 ;destroy all jedi
'
userband = 1		'toggled to zero at startup
volchanged = 0		'
freqchanged = 0		'
rssitype = 0		'
demobar = 0			'
squelch = 0			'
mutebuf = 1			'
startup = 1			'set first cycle flag
pssix = 0			'reset tuning delay timers
pssev = 0
'
CMCON = 7			'set ports to digital
trisb = %01000000  	'
trisa = %00100000	'
'
gosub pauseten '10ms
gosub shiftbytein	'read hardware configuration jumper
if hwconfg = 0 then	'for serial enabled jumper configuration
serpin = 1			'set serial pin idle normally high
endif ' hwconfg
'
gosub onesec		'delay
gosub lcdinit		'initialise lcd
gosub pauseten '10ms
gosub setchars		'set bargraph graphics
gosub pauseten '10ms
gosub lcdcls		'clear lcd display
arg = $07 : gosub send_data_byte	'custom antenna symbol
for cnt = 0 to 14
gosub getdata
next cnt
arg = $C0 : gosub send_command_byte	'start of second line
for cnt = 15 to 30
gosub getdata
next cnt
gosub onesec : gosub onesec 		'pause for title display
'
silinfo = 0			'set flag to display chip info
gosub initradio		'initialise to display chip info
silinfo = 1			'disable chip info
arg = $C0 : gosub send_command_byte ' set second lcd line
gosub sixspaces		'print ok message since we got here
pssix = 1			'enable a single serial test message
arg = "O" : gosub send_data_byte : gosub serialarg
arg = "K" : gosub send_data_byte : gosub serialarg
txbyte = $0D : gosub serialout
txbyte = $0A : gosub serialout
pssix = 0 'disable serial until frequency change
gosub sevenspaces	'fill lcd line with spaces
gosub onesec		'delay for info display
'
'
start:
gosub shiftbytein		'read shift register inputs
'
if startup = 1 then		'only executes once at startup
buttone = 1				'change band to fm broadcast
endif					'for first program cycle
'
if buttona = 1 then		'audio volume down
if uservol > 0 then
uservol = uservol - 1
endif
gosub radiosetvol
endif
'
if buttonb = 1 then		'audio volume up
if uservol < 15 then
uservol = uservol + 1
endif
gosub radiosetvol
endif
'
if buttonc = 1 then		'tuned frequency down
if pssix < $1A then
pssix = pssix + 1
endif
if (pssix = $1A) || (pssix = 1) then
volchanged = 0			'kill volume display
if userband = 1 then
if vchan > 0 then		'channel steps for vhf amateur
vchan = vchan - 1
userfreq = userfreq - 1
endif
else
if userfreq > 871 then
userfreq = userfreq - 1
if userband = 0 then	'200 kHz steps for fm broadcast
userfreq = userfreq - 1
endif
endif
endif
gosub radiotune
endif	'pssix
else
pssix = 0				'reset tuning delay timer
endif
'
if buttond = 1 then		'tuned frequency up
if pssev < $1A then
pssev = pssev + 1
endif
if (pssev = $1A) || (pssev = 1) then
volchanged = 0			'kill volume display
if userband = 1 then
if vchan < 28 then		'channel steps for vhf amateur
vchan = vchan + 1
userfreq = userfreq + 1
endif
else
if userfreq < 1076 then
userfreq = userfreq + 1
if userband = 0 then	'200 kHz steps for fm broadcast
userfreq = userfreq + 1
endif
endif
endif
gosub radiotune
endif	'pssev
else
pssev = 0				'reset tuning delay timer
endif
'
if buttone = 1 then		'change reciever band
volchanged = 0			'kill volume display
userband = userband + 1 'increment band
if userband > 1 then
userband = 0
endif
'
arg = $C0 : gosub send_command_byte	'start of second line
if userband = 0 then	'fm broadcast
gosub printvhf
else					'vhf amateur
arg = $20 : gosub send_data_byte
gosub printvhffm
for cnt = 41 to 49
gosub getdata
next cnt
endif
demobar = 1				'progress bar effect
for sigstb = 0 to 95
psone = 10 : gosub pausems	'progress bar speed
gosub drawsig
next sigstb
psone = 254 : gosub pausems '100ms
psone = 254 : gosub pausems '100ms
sigstb = 0
gosub drawsig
demobar = 0
squelch = 0				'disable squelch
gosub initradio			'initialise the radio ic
psone = 10 : gosub pausems '4ms
if userband = 0 then
userfreq = 945			'default broadcast frequency 94.9 MHz
else
userfreq = 1039			'default vhf amateur band frequency 146.9 MHz
endif
gosub radiotune
'
if startup = 1 then		'only executes once at startup
uservol = 0				'reset volume byte
while uservol < 4		'ramp volume up to 4
buttone = 1
gosub radiosetvol
buttone = 0
uservol = uservol + 1
psone = 254 : gosub pausems '100ms
wend
startup = 0
endif
'
gosub radiosetvol
psone = 6 : gosub pausems '2ms
endif
'
if buttonf = 1 then		'signal display type button
volchanged = 0			'kill volume display
squelch = 1				'enable squelch
psone = 254 : gosub pausems '100ms
if rssitype = 0 then	'alternate signal display
rssitype = 1
else
rssitype = 0
endif
psone = 254 : gosub pausems '100ms
psone = 254 : gosub pausems '100ms
endif
'
if srstats = 0 then		'print shift register error
goto printerror			'
endif 'srstats
'
gosub radioread
if volchanged = 0 then	'display bargraph for volume
gosub printinfo
else
volchanged = volchanged - 1
endif
'
if squelch = 1 then		'handle squelch if enabled
if sigstb < 13 then		'hard coded squelch level
mutebuf = 0 'mute
else
mutebuf = 1 'unmute
endif
if DMUTE != mutebuf then
DMUTE = mutebuf
gosub radiowrite
endif
endif
'
goto start
'
'
'
'
shiftbit:			'private shift register routine
psone = 2 : gosub pausems '1ms
if srbit = 0 then
portb.6 = 0
else
portb.6 = 1
endif
psone = 2 : gosub pausems '1ms
portb.5 = 1
return
'
'
sbprivate:			'private shift register routine
gosub pausethree
portb.5 = 0
gosub pausethree
portb.5 = 1
return
'
'
'this is the function called by the user to read 74hc165
shiftbytein:		'read byte from the shift register
portb.5 = 0
gosub pausethree
portb.4 = 1
gosub pausethree
portb.4 = 0
gosub pausethree
portb.4 = 1
gosub pausethree
buttona = portb.6 : gosub sbprivate
buttonb = portb.6 : gosub sbprivate
buttonc = portb.6 : gosub sbprivate
buttond = portb.6 : gosub sbprivate
buttone = portb.6 : gosub sbprivate
buttonf = portb.6 : gosub sbprivate
hwconfg = portb.6 : gosub sbprivate
srstats = portb.6 : gosub sbprivate
psone = 2 : gosub pausems '1ms
portb.5 = 0
psone = 2 : gosub pausems '1ms
@ comf	_bflags ,f	;invert for normally high buttons
portb.4 = 1
return
'
'
initradio:				'initialise function
if userband = 0 then	'fm broadcast
PR2 = %00010010
T2CON = %00000101
CCPR1L = %00001001
CCP1CON = %00011100
else					'vhf amateur
vchan = 20				'set default channel
PR2 = %00110101
T2CON = %00000100
CCPR1L = %00011010
CCP1CON = %00111100
endif
gosub pauseten
portb.1 = 0             'start with SDA LOW
gosub pausethree
portb.0 = 0				'reset the device
gosub pausethree
portb.0 = 1             'release reset
gosub pausethree
trisb.1 = 1             'release SDA
gosub radioread         'read all registers
XOSCEN = 1              'turn on oscillator
gosub radiowrite
gosub onesec			'wait for startup
gosub radioread         'read all registers
'
if userband = 0 then
SPACEH = 0				'set 100 kHz spacing for this version for vhf amateur
SPACEL = 1				'200kHz steps for broadcast implemented in application
else
SPACEH = 0				'reserved this program memory for future 50 kHz spacing
SPACEL = 1				'set vhf to 100 kHz steps also for this program version
endif
DMUTE = silinfo         'mute disable
MONO = 1				'force mono for communications reciever
SiEnable = 1            'powerup enable
gosub radiowrite
psone = 254 : gosub pausems '100ms
psone = 180 : gosub pausems '60ms       
gosub radioread         'read all registers    
'print information about the radio chip to the lcd
if silinfo = 0 then		'executes for first pass only
if Si_REGS(0) != $1242 then	'check device id register
gosub printerror
else
lll = Si_REGS(1) 'save firmware version area
lll.bit7 = 0     '
lll.bit6 = 0     '
Si_REGS(1) = Si_REGS(1) << 6
arg = $80 : gosub send_command_byte
gosub pauseten '10ms
for cnt = 90 to 95	'print Si470
gosub getdata
next cnt
Si_REGS(1) = Si_REGS(1) >> 12
arg = "?"
if Si_REGS(1) = %0001 then 'complete for Si4702
arg = $32
endif
if Si_REGS(1) = %1001 then 'complete for Si4703
arg = $33
endif
gosub send_data_byte
arg = $20 : gosub send_data_byte 'space
gosub send_data_byte 'space
arg = "F" : gosub send_data_byte 'FW:
arg = "W" : gosub send_data_byte '
arg = ":" : gosub send_data_byte '
arg = $20 : gosub send_data_byte 'space
arg = lll / 10
gosub sendnumeral
arg = arg - $30
lll = lll - (arg * 10)
arg = lll
gosub sendnumeral
arg = $20 : gosub send_data_byte
gosub onesec 'delay
endif 'device
endif 'silinfo
return
'
'
radioread:				'read all registers
gosub itcreadctrl
for cnt = 10 to 15
itwosee = 0
gosub icread
itwosee = 1
gosub icread        
next cnt
for cnt = 0 to 8
itwosee = 0
gosub icread
itwosee = 1
gosub icread  
next cnt
itwosee = 0
cnt = 9
gosub icread
'
asm
 CALL itcend       
 BTFSC STATUS, 0   
 GOTO _SiError      
 MOVWF _arg 
endasm
Si_REGS(9) = Si_REGS(9) + arg
SI470X_CURRENTVOLUME = sysconfig2 & $0F
SI470X_CURRENTRSSI   = statusrssi & $FF
SI470X_CURRENTSPACE  = (sysconfig2 >> 4) & %11
SI470X_CURRENTBAND   = (sysconfig2 >> 6) & %11
SI470X_CURRENTFREQUENCY = (readchan & $1FF)
SI470X_CURRENTFREQUENCY = SI470X_CURRENTFREQUENCY + 875 ; 87.5Ů108 MHz (USA, Europe)
SI470X_MINFREQUENCY = 875
SI470X_MAXFREQUENCY = 1081
return
'
icread:
@ CALL itcbyte      
@ BTFSC STATUS, 0   
@ GOTO _SiError   
@ MOVWF _arg
if itwosee = 0 then
Si_REGS(cnt) = arg
Si_REGS(cnt) = Si_REGS(cnt) << 8
else
Si_REGS(cnt) = Si_REGS(cnt) + arg
endif
return
'
radiowrite:				'write all writeable registers
itceror = 0				'reset comms error flag
asm                   
 MOVLW 0x2                              
 MOVWF _psfiv                                     
 MOVLW 0x80                             
 MOVWF _psate                         
 MOVLW 0x20                             
 CALL itcrd                
 BTFSC STATUS, 0                           
 GOTO _SiError                       
endasm
'
for cnt = 2 to 6
itwosee = 0
gosub icwrite
itwosee = 1
gosub icwrite
next cnt
itwosee = 0
cnt = 7
gosub icwrite
arg = Si_REGS(7)             
@ MOVF _arg, W                           
@ CALL itcre                            
@ BTFSC STATUS, 0                           
@ GOTO _SiError
return
'
'
icwrite:
if itwosee = 0 then
arg = Si_REGS(cnt) >> 8
else
arg = Si_REGS(cnt) 
endif
@ MOVF _arg, W                           
@ CALL itcrd           
@ BTFSC STATUS, 0                           
@ GOTO _SiError       
return
'
'
SiError:				'i2c comms error
itceror = 1				'set comms error flag
goto printerror			'will return from here
'
'
'i2c read and write chunk of code that gets inserted by PBP
'little if any optimisation here, but it's disassembled in
'order to optimise the calls that PBP normally makes to it.
asm
itcend:                              
 BSF _psone, 0x5                          
 BTFSS _psone, 0x5  
itcbyte:                      
 BCF _psone, 0x5                          
 BTFSC _psone, 0x3                        
 GOTO oxb                               
 BSF _psone, 0x3                          
 CALL fortyfour                       
 BTFSC STATUS, 0                           
 GOTO thirtytwo    
oxb:                         
 MOVLW 0x8                              
 MOVWF _psfor          
oxd:                   
 CALL fiftynine                    
 RLF _psthr, F                            
 DECFSZ _psfor, F                         
 GOTO oxd                           
 BTFSS _psone, 0x5                        
 CALL threedee                           
 CALL sixtythree              
 CALL fivef                            
 BTFSC _psone, 0x5                        
 CALL thirtytwo                        
 CALL thirtyseven                           
 MOVF _psthr, W                           
 BCF STATUS, 0                             
 GOTO _beforeprogstart
itcre:                            
 BSF _psone, 0x5                          
 BTFSS _psone, 0x5   
itcrd:                    
 BCF _psone, 0x5                     
 BTFSC _psone, 0x2                        
 GOTO twentyfive                 
 ANDLW 0xfe                             
 MOVWF _pstwo                             
 BSF _psone, 0x2                          
 BCF STATUS, 0                             
 GOTO _beforeprogstart           
twentyfive:          
 BTFSC _psone, 0x4                        
 GOTO twodee                        
 MOVWF _psnin                             
 BSF _psone, 0x4                          
 CALL fortyfour                             
 BTFSC STATUS, 0                           
 GOTO thirtytwo                 
 MOVF _psnin, W                       
twodee:    
 CALL fourcee                            
 BTFSC STATUS, 0                           
 GOTO thirtytwo                           
 BTFSS _psone, 0x5                        
 GOTO _beforeprogstart     
thirtytwo:              
 CALL threedee                        
 CALL sixtythree                      
 BCF _psone, 0x2                          
 BCF _psone, 0x4                          
 BCF _psone, 0x3   
thirtyseven:                       
 MOVLW 0x6
 MOVWF 0x4                              
 MOVF _psfiv, W                           
 BSF 0x4, 0x7                           
 IORWF 0, F                             
 GOTO fortythree
threedee:                         
 MOVLW 0x6               
 MOVWF FSR                              
 COMF _psfiv, W   
forty:                        
 ANDWF 0, F                             
 BSF FSR, 0x7                           
 ANDWF 0, F               
fortythree:              
 GOTO _beforeprogstart    
fortyfour:
 CALL thirtyseven                           
 CALL sixtythree                     
 CALL _progstartfeight                           
 CALL threedee                          
 CALL fivef                            
 MOVF _pstwo, W                           
 BTFSC _psone, 0x3                        
 IORLW 0x1        
fourcee:                      
 MOVWF _psthr                             
 MOVLW 0x8                              
 MOVWF _psfor      
fourf:                      
 RLF _psthr, F                            
 BTFSC STATUS, 0                           
 CALL thirtyseven                          
 BTFSS STATUS, 0                           
 CALL threedee                     
 CALL sixtythree                 
 CALL fivef                            
 DECFSZ _psfor, F                         
 GOTO fourf                      
 CALL thirtyseven
fiftynine:                       
 CALL sixtythree                            
 MOVLW 0x6                  
 MOVWF FSR                              
 MOVF _psfiv, W                           
 ANDWF 0, W                             
 ADDLW 0xff          
fivef:       
 MOVLW 0x6               
 MOVWF FSR                              
 COMF _psate, W                           
 GOTO forty            
sixtythree:             
 MOVLW 0x6                    
 MOVWF FSR    
sixtyfive:                          
 MOVF _psate, W                           
 BSF FSR, 0x7                           
 IORWF 0, F                             
 BCF FSR, 0x7                           
 ANDWF 0, W                             
 BTFSC STATUS, 0x2                         
 GOTO sixtyfive                             
 GOTO fortythree                     
endasm
beforeprogstart:
@ BCF STATUS, 0x7                           
@ BCF STATUS, 0x6                           
@ BCF STATUS, 0x5
@ clrwdt
progstartfeight:
return
'
'
radiotune:				'tune radio to selected frequency
freqchanged = 15		'start band changed timer
SI470X_TempW = userfreq
SI470X_FREQ    VAR SI470X_TempW
Khz            VAR SI470X_TempB
FREQ2CHANNEL:
gosub radioread         'read all registers
Khz = 10
Channel = (Channel & $FE00) | (((SI470X_FREQ * 10) - (SI470X_MINFREQUENCY * 10)) / Khz)
TUNE = 1
gosub radiowrite
WAIT4STC:
while !STC
gosub radiostat
wend
TUNE = 0
SEEK = 0
goto radiowrite
'
'
radiostat:
gosub itcreadctrl
cnt = 10
itwosee = 0
gosub icread
itwosee = 1
gosub icread   
cnt = 11
itwosee = 0
gosub icread
@ CALL itcend        
@ BTFSC STATUS, 0   
@ GOTO _SiError        
@ MOVWF _arg
Si_REGS(11) = Si_REGS(11) + arg
return
'
'
radiosetvol:
if buttone = 0 then
gosub drawvol
endif
SI470X_CURRENTVOLUME = uservol 'intermediate var could be optimised out
VOLEXT = 0
sysconfig2 = (sysconfig2 & $fff0) | (SI470X_CURRENTVOLUME & $0F)
if SI470X_CURRENTVOLUME = 0 then
VOLEXT = 1
sysconfig2 = (sysconfig2 & $fff0) | (8 & $0F)
endif
goto radiowrite
'
'
printinfo:
if userband = 0 then		'fm broadcast
displayfreq = userfreq + 4	'apply offset for broadcast band
else						'vhf amateur
'do sexy maths for accurate centre frequency display
vwork = vchan
vwork = vwork * 1429
displayfreq = 1440
displayfreq = displayfreq + (vwork DIG 4 * 10)
displayfreq = displayfreq + vwork DIG 3
'
if freqchanged = 0 then
if vwork dig 2 > 4 then		'round up first decimal place
displayfreq = displayfreq + 1
endif
endif
'
endif
'
if rssitype = 0 then		'signal strength display type
sigstb = SI470X_CURRENTRSSI	'copy to word buffer
gosub drawsig				'graphic bar graph
else						'or numeric
arg = $80 : gosub send_command_byte
for cnt = 76 to 83
gosub getdata
next cnt
arg = SI470X_CURRENTRSSI dig 1 : gosub sendnumeral
arg = SI470X_CURRENTRSSI dig 0 : gosub sendnumeral
gosub sixspaces
endif
arg = $C0 : gosub send_command_byte
for cnt = 70 to 75
gosub getdata
next cnt
'
if displayfreq > 999 then
arg = displayfreq dig 3 : gosub sendnumeral : gosub serialarg	'
else
txbyte = $20 : gosub serialout 'transmit leading space
endif
arg = displayfreq dig 2 : gosub sendnumeral : gosub serialarg	'
arg = displayfreq dig 1 : gosub sendnumeral : gosub serialarg	'
arg = "." : gosub send_data_byte : gosub serialarg	'
arg = displayfreq dig 0 : gosub sendnumeral : gosub serialarg	'
'
if freqchanged > 0 then	'temporarily display true centre frequency
if userband = 1 then	'extra decimal place for vhf amateur band
arg = vwork dig 2 : gosub sendnumeral : gosub serialarg	'
endif
freqchanged = freqchanged - 1
endif
'
for cnt = 64 to 69
gosub getdata : gosub serialarg
next cnt
txbyte = $0D : gosub serialout	'send new line and return characters
txbyte = $0A
goto serialout	'will return from here
'
'
'sets up character lcd custom character buffers
'could be stored at the end of on chip eeprom
setchars:			'custom characters for graphic bargraphs
for lll = $40 to $47
arg = lll+$00 : gosub send_command_byte
arg = %000000 : gosub send_data_byte
arg = lll+$08 : gosub send_command_byte
arg = %010000 : gosub send_data_byte
arg = lll+$10 : gosub send_command_byte
arg = %011000 : gosub send_data_byte
arg = lll+$18 : gosub send_command_byte
arg = %011100 : gosub send_data_byte
arg = lll+$20 : gosub send_command_byte
arg = %011110 : gosub send_data_byte
arg = lll+$28 : gosub send_command_byte
arg = %011111 : gosub send_data_byte
arg = lll+$30 : gosub send_command_byte
arg = %011111 : gosub send_data_byte
next lll
lll = $38 + $40		'and custom intro screen antenna symbol
arg = lll+$00 : gosub send_command_byte
arg = %000000 : gosub send_data_byte
arg = lll+$01 : gosub send_command_byte
arg = %011111 : gosub send_data_byte
arg = lll+$02 : gosub send_command_byte
arg = %010001 : gosub send_data_byte
arg = lll+$03 : gosub send_command_byte
arg = %001010 : gosub send_data_byte
arg = lll+$04 : gosub send_command_byte
arg = %000100 : gosub send_data_byte
arg = lll+$05 : gosub send_command_byte
arg = %000100 : gosub send_data_byte
arg = lll+$06 : gosub send_command_byte
arg = %000100 : gosub send_data_byte
arg = lll+$07 : gosub send_command_byte
arg = %000000
goto send_data_byte
'
'
'draw graphic signal strength
drawsig:
sigst = sigstb
if demobar = 0 then
sigst = sigst + sigst + sigst	'scale for display
endif
if sigst > 95 then				'apply display limit
sigst = 95
endif
lll = 16
arg = $80 : gosub send_command_byte		'go to first lcd line
while sigst > 5
arg = $06 : gosub send_data_byte		'print solid bar
lll = lll - 1
sigst = sigst - 6
wend
arg = sigst : gosub send_data_byte		'print the last partial bar
lll = lll - 1
while lll > 0
arg = $00 : gosub send_data_byte		'
lll = lll - 1
wend
return
'
'
'draw graphic and printed volume level
drawvol:
arg = $C0 : gosub send_command_byte
for cnt = 56 to 63
gosub getdata
next cnt
arg = uservol DIG 1 : gosub sendnumeral
arg = uservol DIG 0 : gosub sendnumeral
gosub sevenspaces
demobar = 1
sigstb = uservol + 1
sigstb = sigstb * 6
gosub drawsig
demobar = 0
volchanged = 20
psone = 254 : gosub pausems '100ms
psone = 254
goto pausems '100ms
'
'
'print hard coded string to lcd
printvhf:
gosub printvhffm
for cnt = 31 to 40
gosub getdata
next cnt
return
'
'
'print hard coded string to lcd
printvhffm:
for cnt = 50 to 55
gosub getdata
next cnt
return
'
'
'print a number of spaces to lcd
sevenspaces:
arg = $20 : gosub send_data_byte
sixspaces:
for cnt = 0 to 6	'six spaces
arg = $20 : gosub send_data_byte
next cnt
return
'
'
'HD44780 character lcd functions for PBP - Brek Martin 2019
lcdinit:	'module initialisation sequence for 4 bit interface
if hwconfg = 0 then ' disable lcd for serial configuration
return
endif ' hwconfg
gosub lcdinthand
gosub pauseten '10ms
gosub lcdinthand
gosub pauseten '10ms
gosub lcdinthand
gosub pauseten '10ms
nib = $02 : gosub send_nibble	'set 4 bit mode
gosub pauseten '10ms
arg = %00101000 : gosub send_command_byte 'N=0 : 2 lines F=0 : 5x7 font
gosub pauseten '10ms
arg = %00001000 : gosub send_command_byte 'display: display off, cursor off, blink off
gosub pauseten '10ms
arg = %00000001 : gosub send_command_byte 'clear display
gosub pauseten '10ms
arg = %00000110 : gosub send_command_byte 'set entry mode
gosub pauseten '10ms
arg = %00001100 : gosub send_command_byte 'display: display on
goto pauseten '10ms
'
'
lcdinthand:
nib = $03
send_nibble:
if hwconfg = 0 then ' disable lcd for serial configuration
return
endif ' hwconfg
E_PIN = 1
lata = nib & $0F
lata.4 = rsflag
porta = lata
gosub tennops
E_PIN = 0
tennops:
@ nop
@ nop
@ nop
@ nop
@ nop
@ clrwdt
@ nop
@ nop
@ nop
@ nop
return
'
'
sendnumeral:
arg = arg + $30	'convert numeral to ascii
goto send_data_byte
getdata:
read cnt,arg	'read data from on chip eeprom
goto send_data_byte
send_command_byte:
rsflag = 0
goto send_byte
send_data_byte:
rsflag = 1
send_byte:
nib = arg >> 4 : gosub send_nibble
nib = arg & $F
goto send_nibble
'
'
'delay routine based on those by Mark Crosbie
'all delays have been tweaked for application
'and are not accurate for real time keeping
'psone wass ms delay time approx for 4 MHz
pausethree:
psone = 8 : goto pausems
pauseten:
psone = 25
pausems:
@ movlw	50
@ movwf	_pstwo
delaytwo:
@ nop
@ nop
@ clrwdt
@ nop
@ nop
@ nop
@ decfsz	_pstwo,	f
@ goto _delaytwo
@ decfsz	_psone,	f
@ goto _pausems
return
'
'
'delay routine based on those by Mark Crosbie
'all delays have been tweaked for application
'and are not accurate for real time keeping
'psfor was sec delay time approx for 10 MHz
onesec:	'approx one second delay
psfor = 1
pauses:	'or an arbitrary number of seconds
for lata = 0 to psfor
for psthr = 0 to 9
psone = 249 : gosub pausems '100ms
next psthr
next lata
return
'
'
itcreadctrl:		'optimised i2c calls
itceror = 0			'reset comms error flag
asm
 MOVLW 0x2         ;i2c read 
 MOVWF _psfiv        
 MOVLW 0x80        
 MOVWF _psate     
 MOVLW 0x20        ;send control byte
 CALL itcrd        
 BTFSC STATUS, 0   
 GOTO _SiError      
endasm
return
'
'
'print an error code to character lcd
printerror:
gosub lcdcls		'clear lcd display
for cnt = 83 to 90	'print error
gosub getdata
next cnt
arg = $32
if itceror = 1 then
arg = $31
endif
if srstats = 0 then
arg = $33
endif
gosub send_data_byte
psfor = 9
goto pauses '9s
'
'
'clear the lcd display
lcdcls:
arg = $01 : gosub send_command_byte
goto pauseten '10ms
'
'
'PBP software serial out 8N1 - Brek Martin 2016.
'this is smaller than the PBP debugout command
serialarg:
txbyte = arg
serialout:
if hwconfg = 1 then ' disable serial for lcd configuration
return
endif ' hwconfg
if pssix != 1 then	'allow changed data only
if pssev != 1 then
if (pssev != $1A) && (pssix != $1A) then
return
endif
endif
endif
asm 
 movlw 8
 movwf _bcount 
 bcf     _serpin
 call pausedelay
sendbyte:
 btfss  _txbyte ,0
 goto snd0
 bsf   _serpin
 goto sndd
snd0:
 bcf   _serpin
sndd:
 rrf _txbyte ,F
 call pausedelay
 decfsz _bcount ,F
 goto sendbyte
 bsf _serpin
pausedelay:
 movlw 84		;constant for 9600 baud @ 10 MHz
 movwf _delay 
zpausedelay:
 decfsz _delay  ,F
 goto zpausedelay
 return
endasm
'
'