'20040913 cp 'remote frequency setting for the Teletron TE704A 'shortwave receiver ' $regfile = "M8def.dat" $crystal = 6144000 'I2C lines Config Sda = Portc.4 Config Scl = Portc.5 Config I2cdelay = 10 'LCD Config Lcd = 16 * 2 Config Lcdpin = Pin , Db4 = Portb.0 , Db5 = Portb.1 , Db6 = Portb.2 , Db7 = Portb.3 , E = Portb.4 , Rs = Portb.5 'Led Config Pind.7 = Output Led Alias Portd.7 Config Pind.3 = Output Beeper Alias Pind.3 'Int from PCF8574 to Int0 pin Config Pind.2 = Input Config Int0 = Falling Declare Sub Sendfreq Declare Sub Flashled Declare Sub Checkfreq Declare Sub Freqtostring 'PCF8574A read and write address 'NOTE the difference with PCF8574P ! Const Keybwr = &H78 Const Keybrd = &H79 'i2c i/o expander write addresses Const Bw01 = &H70 Const Bw02 = &H72 Const Bw03 = &H74 Const Bw04 = &H76 'Mask for reading columns and rows state Const Columnsmask = &B11110000 Const Rowsmask = &B00001111 'Keyboard debounce time Const Debouncetime = 150 'We want to input not more than 9 frequency characters Const Keystringlength = 9 'Frequency string is seven characters without decimal point Const Freqstringlength = Keystringlength - 2 'Led flash time (msec) Const Wtime = 100 'Frequency step up/down (in 10 Hz) Const Freqstep = 1 'Maximum frequency (in 10Hz units) Const Freqmax = 2999999 'Minimum frequency (in 10Hz units) Const Freqmin = 1 Dim Pcf8574ainput As Byte Dim Keycoderow As Byte Dim Keycodecol As Byte Dim Keycode As Byte Dim Keychar As String * 1 Dim Keystring As String * Keystringlength Dim Keycharpos As Byte Dim Decpos As Byte Dim Strlen As Byte Dim Stradplen As Byte Dim Strbdp As String * 2 'string before decimal point Dim Stradp As String * 5 'string after decimal point Dim Strtmp As String * 5 Dim Flagup As Bit Dim Flagdown As Bit Dim Flagmenu As Bit Dim Flagmenuenter As Bit Dim Flagclear As Bit Dim Flagenter As Bit Dim Flagscandown As Bit Dim Flagscanup As Bit Dim Freqok As Bit Dim Frequency As Long Dim Oldfrequency As Long Dim Freqstr As String * 8 Dim Freqstrptr As Byte Dim Freqbyteval As Byte Dim Freqbyte As Byte Dim Freqchar As String * 1 Dim Freq1 As Byte Dim Freq2 As Byte Dim Freq3 As Byte Dim Freq4 As Byte Reset Flagup Reset Flagdown Reset Flagmenu Reset Flagmenuenter Reset Flagclear Reset Flagscandown Reset Flagscanup Reset Freqok On Int0 Pcfint 'Set PCF8574A to input, masked pins high (pull-up) I2cstart I2cwbyte Keybwr I2cwbyte Columnsmask I2cstop Enable Interrupts Enable Int0 Cls Sound Beeper , 1000 , 500 Keystring = Space(keystringlength) Keycharpos = 1 Frequency = 1000000 Call Freqtostring Set Flagenter Do If Flagenter = 1 Then Reset Flagenter Call Checkfreq Frequency = Val(keystring) If Frequency > Freqmax Then Freqok = 0 If Frequency < Freqmin Then Freqok = 0 If Freqok = 1 Then Freqok = 0 Call Freqtostring Cls Lcd "F: " ; Keystring ; " MHz" Lowerline Lcd "" Call Sendfreq Oldfrequency = Frequency Keystring = Space(keystringlength) Keycharpos = 1 Else Cls Lcd "Input error" Wait 2 Cls Lcd "Max frequency" Lowerline Lcd "is:29.99999(MHz)" Wait 3 Cls Lcd "Min frequency" Lowerline Lcd "is:00.00001(MHz)" Wait 3 Frequency = Oldfrequency Call Freqtostring Set Flagenter End If Elseif Flagclear = 1 Then Reset Flagclear Call Freqtostring Cls Lcd "F: " ; Keystring ; " MHz" Lowerline Lcd "" Call Sendfreq Keystring = Space(keystringlength) Keycharpos = 1 Elseif Flagup = 1 Then Reset Flagup If Frequency < Freqmax Then Frequency = Frequency + Freqstep Call Freqtostring Set Flagenter Elseif Flagdown = 1 Then Reset Flagdown If Frequency > Freqmin Then Frequency = Frequency - Freqstep Call Freqtostring Set Flagenter Elseif Flagmenu = 1 Then Cls Lcd "A=scn up, B=down" Keystring = Space(keystringlength) Keycharpos = 1 'stay here until A or B chosen While Flagmenuenter = 0 Flashled Waitms 250 Wend Flagmenuenter = 0 Else Call Flashled If Flagscandown = 1 Then If Frequency > Freqmin Then Frequency = Frequency - Freqstep Call Freqtostring Flagenter = 1 Else Reset Flagscandown End If Elseif Flagscanup = 1 Then If Frequency < Freqmax Then Frequency = Frequency + Freqstep Call Freqtostring Flagenter = 1 Else Reset Flagscanup End If End If End If Loop 'PCF8574 interrupt routine Pcfint: 'read the input pins I2cstart I2cwbyte Keybrd I2crbyte Keycodecol , Nack I2cstop 'shift upper nibble to lower nibble Shift Keycodecol , Right , 4 'switch column and row input/output state I2cstart I2cwbyte Keybwr I2cwbyte Rowsmask I2cstop 'read the input pins I2cstart I2cwbyte Keybrd I2crbyte Keycoderow , Nack I2cstop 'Cls 'Lcd Bin(keycodecol) ; Bin(keycodecol) 'switch column and row input/output state back I2cstart I2cwbyte Keybwr I2cwbyte Columnsmask I2cstop Select Case Keycoderow Case 7 : Keycode = 0 Case 11 : Keycode = 4 Case 13 : Keycode = 8 Case 14 : Keycode = 12 Case Else : Keycode = 99 End Select 'make final keycode from portb pins read Select Case Keycodecol Case 7 : Keycode = Keycode + 0 Case 11 : Keycode = Keycode + 1 Case 13 : Keycode = Keycode + 2 Case 14 : Keycode = Keycode + 3 Case Else : Keycode = Keycode + 99 End Select 'illegal keycode from bounce effects If Keycode > 15 Then Keycode = 16 'Cls 'Lcd Keycoderow ; " " ; Keycodecol ; " " ; Keycode Keychar = Lookupstr(keycode , Keycodes) If Keychar <> "?" Then Sound Beeper , 100 , 500 If Flagscandown = 1 Then Reset Flagscandown Set Flagclear Goto Returnlabel End If If Flagscanup = 1 Then Reset Flagscanup Set Flagclear Goto Returnlabel End If If Keycharpos = 1 Then If Keychar = "A" Then If Flagmenu = 1 Then Reset Flagmenu Set Flagscanup Set Flagmenuenter Else Set Flagup End If Goto Returnlabel Elseif Keychar = "B" Then If Flagmenu = 1 Then Reset Flagmenu Set Flagscandown Set Flagmenuenter Else Set Flagdown End If Goto Returnlabel Elseif Keychar = "C" Then Set Flagmenu Goto Returnlabel End If End If If Keychar = "R" Then Set Flagclear Goto Returnlabel Elseif Keychar = "E" Then Set Flagenter Goto Returnlabel Elseif Keychar = "A" Then nop Goto Returnlabel Elseif Keychar = "B" Then nop Goto Returnlabel Elseif Keychar = "C" Then nop Goto Returnlabel End If If Keychar = "D" Then Keychar = "." Lcd Keychar Mid(keystring , Keycharpos , 1) = Keychar If Keycharpos = Keystringlength Then Set Flagenter Else Keycharpos = Keycharpos + 1 End If End If Returnlabel: Waitms Debouncetime Gifr = 64 Return Sub Sendfreq 'Convert frequency variable in long to 'four bytes each containing two bcd four-bit frequency bits, 'resulting in 24-bits of frequency data that are sent 'to four 8-bit i2c i/o expanders Freqstr = Strbdp + Stradp Freqstr = Format(freqstr , "0000000") 'Lowerline 'Lcd Freqstr ; " " Freqchar = Mid(freqstr , 1 , 1) Freq4 = Val(freqchar) 'Lcd Freq4 ; " " Freqchar = Mid(freqstr , 2 , 1) Freqbyte = Val(freqchar) Freq3 = Freqbyte Shift Freq3 , Left , 4 Freqchar = Mid(freqstr , 3 , 1) Freqbyte = Val(freqchar) Freq3 = Freq3 + Freqbyte 'Lcd Freq3 ; " " Freqchar = Mid(freqstr , 4 , 1) Freqbyte = Val(freqchar) Freq2 = Freqbyte Shift Freq2 , Left , 4 Freqchar = Mid(freqstr , 5 , 1) Freqbyte = Val(freqchar) Freq2 = Freq2 + Freqbyte 'Lcd Freq2 ; " " Freqchar = Mid(freqstr , 6 , 1) Freqbyte = Val(freqchar) Freq1 = Freqbyte Shift Freq1 , Left , 4 Freqchar = Mid(freqstr , 7 , 1) Freqbyte = Val(freqchar) Freq1 = Freq1 + Freqbyte 'Lcd Freq1 Freq4 = Not Freq4 Freq3 = Not Freq3 Freq2 = Not Freq2 Freq1 = Not Freq1 I2cstart I2cwbyte Bw04 I2cwbyte Freq4 I2cstop I2cstart I2cwbyte Bw03 I2cwbyte Freq3 I2cstop I2cstart I2cwbyte Bw02 I2cwbyte Freq2 I2cstop I2cstart I2cwbyte Bw01 I2cwbyte Freq1 I2cstop End Sub Sub Flashled Set Led Waitms Wtime Reset Led Waitms Wtime End Sub Sub Checkfreq Strbdp = "0" Stradp = "" Strtmp = "00000" Freqok = 0 Keystring = Rtrim(keystring) Strlen = Len(keystring) If Strlen = 0 Then 'empty string Goto Exitcheckfreq End If 'does the string have a decimal point? Decpos = Instr(keystring , ".") If Decpos = 0 Then 'there is no decimal point in the string Strlen = Len(keystring) 'not more than two characters in string? If Strlen > 2 Then 'error more than two characters Goto Exitcheckfreq Else 'no error, this is the string before decimal point Strbdp = Keystring Stradp = Strtmp Freqok = 1 End If Else 'there is a decimal point in the string If Strlen = 1 Then 'only the one decimal point... Goto Exitcheckfreq End If 'not more than two characters before decimal point? If Decpos > 3 Then 'error more than two characters Goto Exitcheckfreq Else If Decpos = 1 Then 'only string after decimal point Stradplen = Strlen - 1 Stradp = Mid(keystring , 2 , Stradplen) Mid(strtmp , 1 , Stradplen) = Stradp Stradp = Strtmp Freqok = 1 Else 'no error, this is the string before decimal point Stradplen = Strlen - Decpos Decpos = Decpos - 1 If Stradplen > 5 Then Stradplen = 5 Strbdp = Mid(keystring , 1 , Decpos) 'and this is the string after decimal point If Stradplen > 0 Then Decpos = Decpos + 2 Stradp = Mid(keystring , Decpos , Stradplen) Mid(strtmp , 1 , Stradplen) = Stradp Stradp = Strtmp Else Stradp = Strtmp End If 'and there should not be another decimal point here... Decpos = Instr(stradp , ".") If Decpos <> 0 Then Goto Exitcheckfreq Freqok = 1 End If End If End If 'Lcd " " ; Strbdp ; "." ; Stradp Keystring = Strbdp + Stradp 'Cls 'Lcd Keystring 'Wait 1 Exitcheckfreq: End Sub Sub Freqtostring Keystring = Str(frequency) Keystring = Format(keystring , "00.00000") 'Cls 'Lcd Keystring 'Wait 1 End Sub End Keycodes: Data "1" , "2" , "3" , "A" , "4" , "5" , "6" , "B" , Data "7" , "8" , "9" , "C" , "R" , "0" , "E" , "D" , "?"