'( ################################################################################ project: Tuner - Retro Receiver -------------------------------------------------------------------------------- name : LC72136N_Test25.bas copyright : (c) Chris Hirt, OE3HBW, Austria-JN87AQ, 2018 purpose : Controller for Tuner with PLL LC72136N: Test micro : ATmega644P programmer : homebrew (STK200/STK300 emulation) compiler : MCS BASCOM-AVR 2.0.7.9 - 001 flash : 12% code build : V0.25 @ 23112018 (23. Nov. 2018) status : passed -------------------------------------------------------------------------------- ########################### HARDWARE ########################################### uC ATmega644P 40 PDIP PIN 1 PB0 PORTB.0 CL_CCB 2 PB1 PORTB.1 DI_CCB 3 PB2 PORTB.2 INT2 / ext I2C INT 4 PB3 PORTB.3 DO_CCB 5 PB4 PORTB.4 CE_CCB 6 PB5 MOSI ISP MOSI 7 PB6 MISO ISP MISO 8 PB7 SCK ISP SCK 9 /RESET ISP RST + HWR 10 VCC +5V 11 GND 0V 12 XTAL2 Quartz 18.3420 MHz 13 XTAL1 Quartz 18.3420 MHz 14 PD0 PORTD.0 SW1 15 PD1 PORTD.1 SW2 16 PD2 PORTD.2 INT0/SW INT 17 PD3 PORTD.3 Rotary Encoder A 18 PD4 PORTD.4 SW3 19 PD5 PORTD.5 SW4 20 PD6 PORTD.6 SW5 21 PD7 PORTD.7 Rotary Encoder B 22 PC0 SCL SCL I2C Bus 23 PC1 SDA SDA I2C Bus 24 PC2 PORTC.2 GLCD RST 25 PC3 PORTC.3 GLCD CS2 26 PC4 PORTC.4 GLCD CS1 27 PC5 PORTC.5 GLCD E 28 PC6 PORTC.6 GLCD RW 29 PC7 PORTC.7 GLCD DI 30 AVCC VCC 31 AGDN GND 32 AREF NC 33 PA7 PORTA.7 GLCD D7 34 PA6 PORTA.6 GLCD D6 35 PA5 PORTA.5 GLCD D5 36 PA4 PORTA.4 GLCD D4 37 PA3 PORTA.3 GLCD D3 38 PA2 PORTA.2 GLCD D2 39 PA1 PORTA.1 GLCD D1 40 PA0 PORTA.0 GLCD D0 '----------------------------- Rotary Encoder "ddm427" A GND B 15 pulse / 360° CCW CW A B A B 1 1 1 1 1 0 0 1 0 0 0 0 0 1 1 0 1 1 1 1 '----------------------------- LC72136N PIN 02 BOF/ 03 CE --> PB4 04 DI --> PB1 05 CL --> PB0 06 DO --> PB3 07 BO1/ 08 BO2/ 09 BO3/ 10 BO4/ 11 IO1/ 13 IO2/ 14 BO5/ 17 VDD 21 GND ################################################################################ ') '$PROG &HFF,&HD7,&HD9,&HFC 'Take care - Fuse Bits !!! $regfile = "m644def.dat" 'ATmega644-20PU $crystal = 18342000 '18.4320 MHz 'stack and frame size not optimized! $hwstack = 200 $framesize = 400 $swstack = 300 $lib "glcdKS108.lbx" 'include GLCD Lib '----- Config GLCD ------------------------------------------------------------- Config GraphLCD = 128 * 64sed , Dataport = PortA , Controlport = PortC , _ Cd = 7 , Rd = 6 , Ce = 3 , Ce2 = 4 , Enable = 5 , Reset = 2 '----- Config Keypad ----------------------------------------------------------- DDRD = &b0000_0000 PORTD = &b0111_0111 Config Int0 = Falling On Int0 Isr_keypad 'Interrupt-Routine Externer Int0 --> PD2 '----- Config Rotary Encoder --------------------------------------------------- DDRD.3 = 0 'PD.3 as Input PortD.3 = 1 'and PullUp enabled for Rotary Encoder A DDRD.7 = 0 'PD.7 as Input PortD.7 = 1 'and PullUp enabled for Rotary Encoder B Config Timer0 = Timer , Prescale = 256 On Timer0 Isr_Timer0 '----- Config CCB -------------------------------------------------------------- Config PortB.0 = Output 'Output and no pull-up CL_CCB Alias PortB.0 'CCB CL Config PortB.1 = Output 'Output and no pull-up DI_CCB Alias PortB.1 'CCB DI Config PortB.3 = Input 'Input PortB.3 = 1 'and pull-up DO_CCB Alias PinB.3 'CCB DO Config PortB.4 = Output 'Output and no pull-up CE_CCB Alias PortB.4 'CCB CE '----- Declarations ------------------------------------------------------------ 'CBB chip addresses Const IN1adr = &h82 'Control data input 1 address Const IN2adr = &h92 'Control data input 2 address Const OUTadr = &hA2 'Serial data output address 'FM BC Band Const FMstart = 87500000 'Start frequency = 87.5 MHz Const FMend = 108000000 'End frequency = 108 MHz 'IF filter values and IF counter gate time Const IFF = 10702500 'IF filter middle frequency Const IFW = 320 'IF deviation range +/- 10 kHz Const IFC = 342480 'IF counter value for 10.7025 MHz at GT = 32ms! 'Reference frequency Const RefFreq = 25000 'reference frequency = 25kHz = 25000 Hz 'scan parameters Const SCstep = 50000 'scan step width = 50 kHz Dim IN1 As DWord '4 Byte - 3 Byte are used for IN1 Dim IN2 As DWord '4 Byte - 3 Byte are used for IN2 Dim DOUT As DWord '4 Byte - 3 Byte are used for OUT Dim FMfreq As DWord 'FM frequency in Hz Dim mfc As DWord 'measured IF counter value Dim UL As Byte 'PLL locking state Dim ifok As Byte 'IF measurement state Dim tok As Byte 'tuning state Dim i As Byte Dim j As Byte Dim u As DWord Dim v As DWord Dim a As Byte Dim sw As Byte Dim KeyCode As Byte Dim REstate As Byte Dim REold As Byte Dim REnew As Byte Dim REstep As Integer Dim rs As Long Declare Sub TestDisplay() Declare Sub TestDisplay1() Declare Sub TestDisplay2() Declare Sub CCBinit() Declare Sub LC72136Ninit() Declare Sub SetFrequency(ByVal pd As DWord) Declare Sub SendData(ByVal Addr As Byte , ByVal SData As DWord) Declare Sub ReceiveData(ByVal Addr As Byte) Declare Function CheckUL() As Byte Declare Function CheckIF() As Byte Declare Sub ManualTuning() Declare Sub ScanFM() '----- FM Frequencies at JN87AQ --------------------------------------------- 'FMfreq = 88.2 MHz == BC Ö3 'FMfreq = 90.3 MHz == BC Ö1 'FMfreq = 92.4 MHz == BC FM4 'FMfreq = 95.8 MHz == BC Ö2 NÖ 'FMfreq = 102.9 MHz == BC Kronehit '------------------------------------------------------------------------------- '####################### Main ################################################## Enable Interrupts Enable Int0 Enable Timer0 Glcdcmd &h3E , 1 : Glcdcmd &h3E , 2 'display off Waitms 100 'wait 50ms Glcdcmd &h3F , 1 : Glcdcmd &h3F , 2 'display on Setfont Font8x8 'load font 8x8 Cls 'clear display Showpic 32 , 0 , Intropic 'Intro Testbild anzeigen Wait 2 a = 0 'Action code for nothing sw = 0 'switch number for nothing Keycode = &h73 'KeyCode for nothing REstate = 0 'Rotary Encoder state for nothing REstep = 0 'no RE step UL = 0 'unlocked PLL state tok = 0 'tuning not completed FMfreq = FMstart 'start with 87.5 MHz Call TestDisplay() 'display 128 x 64 Call CCBinit() 'data bus initialization Call LC72136Ninit() 'initialize PLL Waitms 10 'wait for secure lock '----- Main Loop --------------------------------------------------------------- Do Do 'monitor user action If KeyCode <> &h73 Then a = 1 'wait until key pressed If REstate <> 0 Then a = 1 'wait until RE is moved Loop Until a <> 0 If KeyCode <> &h73 Then Select Case KeyCode Case &h72 : sw = 1 'S1 Band --> Start test 1 (manual) Case &h71 : sw = 2 'S2 Mode --> Start test 2 (scan) Case &h63 : sw = 3 'S3 Left - currently without function Case &h53 : sw = 4 'S4 Right - currently without function Case &h33 : sw = 5 'S5 Quit - currently without function End Select End If Disable Timer0 If REstate > 0 Then 'rotary encoder is turned If REstate = 1 Then REstep = REstep - 1 'Down If REstate = 2 Then REstep = REstep + 1 'Up End If Enable Timer0 If sw = 1 Then 'test condition is true Call ManualTuning() 'tuning with RE Call TestDisplay1() 'show actual values End If If sw = 2 Then Call ScanFM() 'scan through BC band Call TestDisplay2() End If KeyCode = &h73 REstep = 0 REstate = 0 a = 0 Loop End 'of program '######################## Subs ################################################# Sub TestDisplay() 'displayed information for test only Cls Box(0 , 0) -(127 , 63) , 1 Lcdat 1 , 1 , " " , 1 Lcdat 2 , 1 , " Tuner Test " , 1 End Sub Sub TestDisplay1() 'displayed information for test only Cls Box(0 , 0) -(127 , 63) , 1 Lcdat 1 , 1 , " " , 1 Lcdat 2 , 1 , " Tuner Test " , 1 Lcdat 4 , 4 , "Freq: " , 0 Lcdat 4 , 50 , FMfreq , 0 'FM frequency in Hz Lcdat 6 , 4 , "UL: " , 0 Lcdat 6 , 50 , UL , 0 End Sub Sub TestDisplay2() 'displayed information for test only Cls Box(0 , 0) -(127 , 63) , 1 Lcdat 1 , 1 , " " , 1 Lcdat 2 , 1 , " Tuner Test " , 1 Lcdat 4 , 20 , FMfreq , 0 'actual frequency in Hz Lcdat 6 , 20 , UL , 0 'PLL lock/unlock LCdat 7 , 20 , tok, 0 'IF in permitted range End Sub Sub CCBinit() 'init CCB only for safety's sake Reset CL_CCB 'CL low = normal low mode Reset DI_CCB Set CE_CCB Waitus 20 Reset CE_CCB Waitus 20 End Sub Sub SetFrequency(ByVal pd As DWord) 'input = RF Frequency in Hz pd = pd + IFF 'plus IF in Hz pd = pd \ RefFreq 'integer division (!) by reference frequency shift pd , Right , 1 'div by 2 --> FM prescaler For i = 15 To 0 Step -1 'pd --> IN1 LSB first j = 23 - i IN1.j = pd.i 'IN1 register bit 8 - bit 23 Next i End Sub 'output = prog divider in IN1 register Sub LC72136Ninit() 'set all register bits IN1 = 0 IN2 = 0 DOUT = 0 Call SetFrequency(FMfreq) 'set test-frequency --> IN1.8 - IN1.23 '----------------------------------------- 'IN1.8-IN1.23 P0-P23 programmable divider IN1.7 = 0 'SNS: for FM not used IN1.6 = 1 'DVS: FMIN 10 - 160 MHz and BOF = low IN1.5 = 0 'CTE: counter reset IN1.4 = 1 'XS: normal Xtal osc mode IN1.3 = 1 'R0: Ref Freq = 25 kHz IN1.2 = 1 'R1: Ref Freq = 25 kHz IN1.1 = 0 'R2: Ref Freq = 25 kHz IN1.0 = 0 'R3: Ref Freq = 25 kHz '----------------------------------------- IN2.23 = 0 'IOC1: input mode for IO1 pin IN2.22 = 0 'IOC2: input mode for IO2 pin IN2.21 = 0 'IO1: open IN2.20 = 0 'IO2: open IN2.19 = 1 'BO1: low - open drain pin IN2.18 = 1 'BO2: low - open drain pin IN2.17 = 1 'BO3: low - open drain pin IN2.16 = 1 'BO4: low - open drain pin IN2.15 = 1 'BO5: low - open drain pin IN2.14 = 1 'DOC0: control DO pin --> DO pin low when unlock state IN2.13 = 0 'DOC1: control DO pin --> DO pin low when unlock state IN2.12 = 0 'DOC2: control DO pin --> DO pin low when unlock state IN2.11 = 1 'UL0: phase error detection --> output directly IN2.10 = 0 'UL1: phase error detection --> output directly IN2.9 = 1 'DZ0: dead zone mode --> DZB IN2.8 = 0 'DZ1: dead zone mode --> DZB IN2.7 = 0 'GT0: counter measurement time 32 ms IN2.6 = 1 'GT1: counter measurement time 32 ms IN2.5 = 0 'TBC: clock time base output --> no IN2.4 = 0 'DLC: charge pump control --> normal operation IN2.3 = 1 'IFS: input sensitivity --> normal operation 'IN2.0-IN2.2 TEST data '----------------------------------------- Call SendData(IN1adr , IN1) 'write IN1 register to LC72136N over CCB Waitus 20 Call SendData(IN2adr , IN2) 'write IN2 register to LC72136N over CCB End Sub Sub SendData(ByVal Addr As Byte , ByVal SData As DWord) 'uC --> PLL Swap Addr 'nibble swap of register INx address For i = 0 To 7 'write address - LSB first If Addr.i = 1 Then Set DI_CCB Else Reset DI_CCB End If Waitus 20 Set CL_CCB Waitus 10 Reset CL_CCB Next i Set CE_CCB For i = 23 To 0 Step -1 'write INx - MSB 24 bit first If SData.i = 1 Then Set DI_CCB Else Reset DI_CCB End If Waitus 20 Set CL_CCB Waitus 10 Reset CL_CCB Next i Waitus 20 Reset CE_CCB Reset DI_CCB End Sub Sub ReceiveData(ByVal Addr As Byte) 'PLL --> uC Swap Addr 'nibble swap of register OUT address For i = 0 To 7 'write address - LSB first If Addr.i = 1 Then Set DI_CCB Else Reset DI_CCB End If Waitus 20 Set CL_CCB Waitus 10 Reset CL_CCB Next i Set CE_CCB For i = 23 To 0 step -1 'read in DO (PinB.3) MSB first in DOUT Set CL_CCB Waitus 10 DOUT.i = DO_CCB Reset CL_CCB Waitus 10 Next i Waitus 20 Reset CE_CCB Reset DI_CCB End Sub Function CheckUL() As Byte 'check lock-bit (20) from DOUT If DOUT.20 = 0 Then CheckUL = 0 'unlocked Else CheckUL = 1 'locked or stop mode End If End Function Function CheckIF() As Byte 'check IF measurement value ifok = 0 mfc = DOUT AND &h000FFFFF 'bit 0 to bit 19 u = IFC + IFW 'upper IF range v = IFC - IFW 'lower IF range If mfc <= u Then ifok = 1 'upper limit If mfc >= v Then ifok = ifok + 1 'lower limit If ifok = 2 Then CheckIF = 1 'IF in permitted range Else CheckIF = 0 'IF value failed End If End Function Sub ManualTuning() 'tune a new frequency and check locking rs = REstep 'rotary encoder state rs = rs * 50000 'change 50 kHz FMfreq = FMfreq + rs 'rotary encoder --> INCR/DECR FMfreq If FMfreq > FMend Then FMfreq = FMstart 'fold actual freq FMend to FMstart If FMfreq < FMstart Then FMfreq = FMend 'fold actual freq FStart to FMend Call SetFrequency(FMfreq) 'actual FM frequency Call SendData(IN1adr , IN1) 'write IN1 --> changing N Waitms 50 'wait 2x ref-freq periode Call ReceiveData(OUTadr) 'then discard first dataset For i = 0 To 20 'reads output several times Waitms 1 Call ReceiveData(OUTadr) UL = CheckUL() 'check UL bit in DOUT If UL = 1 Then Exit For Next i End Sub Sub ScanFM() 'scan FM band and stop run with step width 10 kHz 'at a strong radio station frequency Do tok = 0 FMfreq = FMfreq + SCstep 'scan step width If FMfreq > FMend Then FMfreq = FMstart 'fold if necessary to FMstart Call SetFrequency(FMfreq) 'actual FM frequency Reset IN1.5 'CTE = 0 --> reset IF counter Call SendData(IN1adr , IN1) 'write IN1 --> changing N + CTE Waitus 20 Set IN1.5 'CTE = 1 --> start IF counter Call SendData(IN1adr , IN1) 'write IN1 --> changing CTE Waitms 50 'wait 2x ref-freq periode Call ReceiveData(OUTadr) 'then discard first dataset For i = 0 To 20 'reads output several times Waitms 1 Call ReceiveData(OUTadr) UL = CheckUL() 'check UL bit in DOUT If UL = 1 Then Exit For 'PLL locked Next i tok = CheckIF() 'check whether IF in permitted range Reset IN1.5 'CTE = 0 --> reset IF counter Call SendData(IN1adr , IN1) 'write IN1 --> changing CTE Waitms 1 Loop until tok = 1 'strong BC station reached End Sub '---------------------- Interrupt service requests ----------------------------- Isr_keypad: KeyCode = PinD And &b0111_0011 'read PortD and mask Return 'ISR - rotary encoder - code after an idea from Tom Baer, 2008 Isr_Timer0: Timer0 = 64 'Timer preset REnew.0 = PIND.3 REnew.1 = PIND.7 If REnew <> reold Then 'rotary encoder is turned If REnew = &b0000_0000 AND REold = &b0000_0001 Then REstate = 2 If REnew = &b0000_0000 AND REold = &b0000_0010 Then REstate = 1 If REnew = &b0000_0011 AND REold = &b0000_0010 Then REstate = 2 If REnew = &b0000_0011 AND REold = &b0000_0001 Then REstate = 1 REold = REnew End If Return '----- GLCD Data --------------------------------------------------------------- Intropic: $bgf "Tuner.bgf" $include "font8x8.font" '############################ End Of File ######################################