'( ################################################################################ project: NIXIECLOCK - Clock with russian "NIXIE" tubes -------------------------------------------------------------------------------- name : NIXIEClock.bas copyright : (c) Chris Hirt, OE3HBW, JN87AQ, Austria, 2015 purpose : Nixie Clock Controller with RTC and DCF77 micro : ATmega644P programmer : homebrew (STK200/STK300 emulation) compiler : MCS BASCOM-AVR 2.0.7.8 - 001 flash : 4% code build : 0.11 @ 16012016 (16. Jan. 2016) status : test -------------------------------------------------------------------------------- ########################### HARDWARE ########################################### uC ATmega644P 40 PDIP PIN 1 PB0 PORTB.0 CLK595 2 PB1 PORTB.1 SDI595 3 PB2 PORTB.2 DCF77_Data 4 PB3 PORTB.3 DCF77_PON 5 PB4 PORTB.4 STB595 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 15 PD1 PORTD.1 16 PD2 PORTD.2 17 PD3 PORTD.3 18 PD4 PORTD.4 19 PD5 PORTD.5 20 PD6 PORTD.6 21 PD7 PORTD.7 RTC INT 22 PC0 SCL I2C Bus RTC 23 PC1 SDA I2C Bus RTC 24 PC2 PORTC.2 25 PC3 PORTC.3 26 PC4 PORTC.4 27 PC5 PORTC.5 28 PC6 PORTC.6 29 PC7 PORTC.7 30 AVCC Filter -> VCC +/- 0.3V 31 AGDN AGND - GND 32 AREF -> 100n - AGND 33 PA7 PORTA.7 34 PA6 PORTA.6 35 PA5 PORTA.5 36 PA4 PORTA.4 37 PA3 PORTA.3 38 PA2 PORTA.2 39 PA1 PORTA.1 40 PA0 PORTA.0 ADC0 RTC RV-3029-C2 DCF77 Modul ################################################################################ ') '$PROG &HFF,&HD7,&HD9,&HFC 'Take care! Fuse Bits !!! $regfile = "m644Pdef.dat" 'ATmega644P $crystal = 18432000 '18.4320 MHz 'stack and framesize not optimized! $hwstack = 128 $framesize = 128 $swstack = 128 'By default BASCOM will use software routines when you use I2C statements but 'to force BASCOM to use the TWI, you need to insert the following statement: $Lib "I2C_TWI.lbx" '----- Config PORTs ------------------------------------------------------------ DDRA = &b0000_0000 'PortA = Input (ADC) PortA = &b1111_1110 'Pullup unused ADC Pins 1-7 CLK595 Alias Portb.0 '74HC595 Clock Config CLK595 = Output SDI595 Alias Portb.1 '74HC595 First Input Config SDI595 = Output STB595 Alias Portb.4 '74HC595 Latch/Strobe Config STB595 = Output DDRB.2 = 0 : PortB.2 = 0 'DCF77_Data - Input - No pull-up! DCF77_data Alias PinB.2 DCF77_PON Alias PORTB.3 Config DCF77_PON = Output 'DCF77_PON - Output DDRD.7 = 0 : PORTD.7 = 0 'RV3029 INT - Input - No pull-up! RV3029_INT Alias PinD.7 '----- Config ADC -------------------------------------------------------------- Config ADC = Single , Prescaler = Auto , Reference = Avcc '---- Config DCF77 ------------------------------------------------------------- Config Dcf77 = PinB.2 , Timer = 1 , Inverted = 1 , Check = 1 , Update = 0 , _ Timer1sec = 1 'Config Dcf77 = PinB.2 , Timer = 1 , Inverted = 0 , Check = 2 , Update = 2 , _ ' Updatetime = 1 , Timer1sec = 0 , Switchpower = 0 , Debug = 1 Config Date = Dmy , Separator = . '----- Config I2C -------------------------------------------------------------- Config Sda = PortC.1 'Configures a port pin for use as serial data SDA Config Scl = PortC.0 'Configures a port pin for use as serial clock SCL Config Twi = 400000 'TWI = I2C clock speed is 400 kHz I2cinit 'Initializes the SCL and SDA pins '( RV-3029-C2: The I2C communcation starts with a START condition and terminate with STOP condition. Repeated START does not allow. Therefore a STOP has to be released before the next START condition. There is no limit of data bytes between the START and STOP condition. Each byte is followed by an acknowledege cycle ACK. The addressing is always carried out with the first byte transmitted after the START condition. The next byte contains the Page & Register Address and the followed byte contains the data the Master sends to the RV-3029. Within the same memory page the Register address is automatically incremented. ') '----------------------- Declarations ------------------------------------------ Const Shift_delay = 50 'shift delay in microseconds Declare Sub SendData() Declare Sub ClearRegs() Declare Sub DisplayError() Declare Sub RV3029_Status() Declare Sub RV3029_EEControl() Declare Sub RV3029_SysReset() Declare Sub RV3029_RegInit() Declare Sub RV3029_GetWatch() Declare Sub RV3029_SetWatch() Declare Sub RV3029_Temperat() Dim ByteAr(3) As Byte 'shift register output buffer Dim Tmpbyte As Byte Dim i As Byte Dim RV3029_PON As Byte Dim RV3029_EEbusy As Byte Dim TimeDate(7) As Byte Dim Temperat As Byte Dim sec_old As Byte Dim wADC As Word '####################### Main ################################################## '----- Initialize ----- Set DCF77_PON 'DCF77 PON High --> OFF Waitms 200 Reset DCF77_PON 'DCF77 PON Low - DCF77 Modul Power ON Enable Interrupts Call RV3029_Status() If RV3029_PON = &h20 Then 'PON is set 'Micro Chrystal recommended to make a software System Reset after Power-Up! Call RV3029_SysReset() End If Call RV3029_RegInit() '------------------------------------------------------ 'Call RV3029_EEControl() 'Write EEPROM -- Only Once! '------------------------------------------------------ Reset CLK595 Reset SDI595 Call ClearRegs() Set STB595 'latch the shift reg to outputs Waitms 10 Reset STB595 sec_old = 0 wADC = 0 Start ADC '----- Main Loop ----- Do wADC = GetADC(0) Select Case wADC Case 0 To 400: Call RV3029_Temperat() ByteAr(1) = &b1111_1111 ByteAr(2) = temperat 'RV3029 chip temperature ByteAr(3) = &b1111_1111 Call Senddata() Wait 3 Case 600 To 700: ByteAr(1) = TimeDate(4) 'RTC RV3029 day ByteAr(2) = TimeDate(6) 'RTC RV3029 month ByteAr(3) = TimeDate(7) 'RTC RV3029 year Call SendData() 'send to Nixie display'Datum anzeigen Wait 3 End Select If DCF_Status.7 = 1 Then Call RV3029_SetWatch() Waitms 10 Reset DCF_Status.7 End If Call RV3029_GetWatch() If sec_old <> TimeDate(1) Then sec_old = TimeDate(1) ByteAr(1) = TimeDate(1) 'RTC RV3029 seconds ByteAr(2) = TimeDate(2) 'RTC RV3029 minutes ByteAr(3) = TimeDate(3) 'RTC RV3029 hours Call SendData() 'send to Nixie display End If If RV3029_INT = 0 Then 'RTC RV3029 Error Call RV3029_SysReset() 'reset RV3029 Call RV3029_RegInit() 'set register Waitms 100 If RV3029_INT = 0 Then 'Error again Call DisplayError() 'only manually operated Reset of uC End If End If Loop End '######################## Subs ################################################# '---- RV-3029-C2 ---- Sub RV3029_Status() 'Read Power On status I2cstart 'START condition I2cwbyte &hAC 'RV-3029 address in Write mode I2cwbyte &h03 'Control_Status register I2cstop 'STOP condition I2cstart 'START condition I2cwbyte &hAD 'RV-3029 address in Read mode I2crbyte RV3029_PON , Nack 'read PON flag I2cstop 'STOP condition RV3029_PON = RV3029_PON And &b0010_0000 'Power On mask End Sub Sub RV3029_SysReset() 'Trigger a System Reset I2cstart 'START condition I2cwbyte &hAC 'RV-3029 address in Write mode I2cwbyte &h04 'Control_Reset register I2cwbyte &b0001_0000 'set SysR I2cstop 'STOP condition Waitms 10 End Sub Sub RV3029_RegInit() I2cstart 'START condition I2cwbyte &hAC 'RV-3029 address in Write mode I2cwbyte &h00 'Control_1 register I2cwbyte &b1001_1001 'set Control_1 register I2cwbyte &b0001_1000 'set Control_INT register (SRIE and V2IE) I2cwbyte &b0000_0000 'set Control_INT Flag register I2cwbyte &b0000_0000 'set Control_Status register I2cwbyte &b0000_0000 'set Control_Reset register I2cstop 'STOP condition End Sub Sub RV3029_EEControl() 'SetEEPROM Control register 'set EERE = 0 --> disable EEPROM refresh I2cstart 'START condition I2cwbyte &hAC 'RV-3029 address in Write mode I2cwbyte &h00 'Control_1 register I2cwbyte &b0000_0000 'EERE set 0 I2cstop 'STOP condition RV3029_EEbusy = 1 For i = 1 to 100 'test max 1sec for EEbusy = 0 I2cstart 'START condition I2cwbyte &hAC 'RV-3029 address in Write mode I2cwbyte &h03 'Control_Status register I2cstop 'STOP condition I2cstart 'START condition I2cwbyte &hAD 'RV-3029 address in Read mode I2crbyte RV3029_EEbusy , Nack 'read EEbusy I2cstop 'STOP condition RV3029_EEbusy = RV3029_EEbusy And &b1000_0000 'mask out If RV3029_EEbusy = 0 Then Exit For Waitms 10 Next i 'EEbusy = 0, now write EEPROM I2cstart 'START condition I2cwbyte &hAC 'RV-3029 address in Write mode I2cwbyte &h30 'EEPROM Control register I2cwbyte &b0010_1111 'Set trickle charger and other bits I2cstop 'STOP condition Waitms 10 'wait for internal EEPROM write 'set EERE = 1 --> enable EEPROM refresh I2cstart 'START condition I2cwbyte &hAC 'RV-3029 address in Write mode I2cwbyte &h00 'Control_1 register I2cwbyte &b0000_1000 'EERE set 1 I2cstop 'STOP condition End Sub Sub RV3029_GetWatch() I2cstart 'START condition I2cwbyte &hAC 'RV-3029 address in Write mode I2cwbyte &h08 'Clock page - Seconds register I2cstop 'STOP condition I2cstart 'START condition I2cwbyte &hAD 'RV-3029 address in Read mode For i = 1 to 6 I2crbyte TimeDate(i) , Ack 'read clock page Next i I2crbyte TimeDate(i) , Nack 'read clock page I2cstop End Sub Sub RV3029_SetWatch() 'set Watch page with start values TimeDate(1) = MakeBCD(_sec) TimeDate(2) = MakeBCD(_min) TimeDate(3) = MakeBCD(_hour) TimeDate(4) = MakeBCD(_day) TimeDate(5) = MakeBCD(_weekday) TimeDate(6) = MakeBCD(_month) TimeDate(7) = MakeBCD(_year) I2cstart 'START condition I2cwbyte &hAC 'RV-3029 address in Write mode I2cwbyte &h08 'Clockpage - Seconds For i = 1 to 7 I2cwbyte TimeDate(i) 'Write clock page Next i I2cstop 'STOP condition End Sub Sub RV3029_Temperat() temperat = 0 I2cstart 'START condition I2cwbyte &hAC 'RV-3029 address in Write mode I2cwbyte &h20 'Temperature page I2cstop 'STOP condition I2cstart 'START condition I2cwbyte &hAD 'RV-3029 address in Read mode I2crbyte temperat , Nack 'read temperature page I2cstop temperat = temperat - 60 temperat = MakeBCD(temperat) End Sub '---- U74HC595 ---- Sub SendData() Reset CLK595 For i = 3 To 1 Step -1 'send byte array to shift regs Reset CLK595 Tmpbyte = ByteAr(i) Shiftout SDI595 , CLK595 , Tmpbyte , 1 , 8 , Shift_delay Next I Set STB595 'latch the shift reg to outputs Waitms 1 Reset STB595 End Sub Sub ClearRegs() 'clear shift reg to all 0's Reset CLK595 Tmpbyte = 0 For i = 1 To 3 Reset CLK595 Shiftout SDI595 , CLK595 , Tmpbyte , 1 , 8 , Shift_delay Next i End Sub Sub DisplayError() '55:55:55 Do ByteAr(1) = &b0101_0101 ByteAr(2) = &b0101_0101 ByteAr(3) = &b0101_0101 Call SendData() Wait 2 ByteAr(1) = &b1111_1111 ByteAr(2) = &b1111_1111 ByteAr(3) = &b1111_1111 Call SendData() Wait 1 Loop 'until manually Reset End Sub '############################ End Of File ######################################