The Revolution Education folks have done a nice job of building the microcontroller interface library into their boot loader to make the PICAXE. The I2C communications provide an example. This is the core of the code needed to pull time from a DS1307 clock chip via I2C and put it on a display at a configurable position.
The clock has 57 bytes of battery backed SRAM. The first 8 are clock data and the remaining 57 bytes are RAM (08h – 3Fh) which are used here for display configuration data starting at byte 10.
First up is to define the positions and raw clock data as variables in the register bank:
; LCD display positions else don't display if out of range Symbol tpos = b6 ; hh:mm Symbol spos = b7 ; :ss Symbol apos = b8 ; am pm Symbol zpos = b9 ; UTC, PST, etc Symbol dpos = b10 ; mo/da/yr Symbol mpos = b11 ; Jan, Feb ... or mo/ Symbol wpos = b12 ; MON Symbol tz = b13 ; time zone (-UTC offset) index to Table_TZ ; w7 b:14:b15 reserved ; clock raw data Symbol sc = b16 ; data read to these registers is compared to Symbol mn = b17 ; a scratchpad copy from previous clock read Symbol hr = b18 ; this allows selective display updating and Symbol wd = b19 ; clock data reading based on what changes Symbol da = b20 Symbol mo = b21 Symbol yr = b22
Next is to define pointers to the scratchpad where the previous data read is stored. This allows comparing the current clock data to what has been displayed in order to determine what needs updating.
; scratchpad 1024 bytes -- ptr, @ptr or get/put Symbol clock_data = 31 ; seconds, bit 7 = 0 to enable oscillator Symbol clock_data_min = 32 Symbol clock_data_hr = 33 ; bit 6 = AM/PM, bit 5 is ten hour Symbol clock_data_dow = 34 ; day of week low 3 bits Symbol clock_data_dom = 35 ; bits 6,7 = 0 Symbol clock_data_mo = 36 ; bits 5,6,7=0 Symbol clock_data_yr = 37 ; -2000 Symbol clock_data_control = 38 ; %00010000 enable output at 1Hz
In order to be able to display month, day, and time zone abbreviations, tables are set up with indices to the start of each table.
; =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= ; TABLE 0-255 (program space) compiler written program space read only ; data. See readtable, tablecopy Symbol Table_ID = 0 Symbol Table_DOW = 20 ; indices to table data Symbol Table_months = 42 Symbol Table_TZ = 80 TABLE Table_ID, ("DS1307 Test by K1CD") TABLE Table_DOW, ("SUNMONTUEWEDTHUFRISAT") TABLE Table_months, ("JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC") TABLE Table_TZ, ("U123AECMP")
In the clock data registers, byte 0 (seconds) bit 7 is clock halt bit. This must be 0 for the clock to run. Byte 2 (hour) bit 6 set for 12 hour mode where bit 5 set for p.m. Bit 6 low uses bit 5 for hours 20-23. To initialize the I2C communications, the microcontroller needs to know that the PICAXE controls the bus, the clock clock address (from its spec sheet), the fact that the clock uses a 100 KHz I2c link with 8 MHz PICAXE, and that clock memory is byte addressed. Other initialization tasks include clearing the scratchpad data to assure a fresh clock data read and clearing the display.
init_clock: hi2csetup i2cmaster, %11010000, i2cslow_8, i2cbyte ; pull clock options from clock static RAM hi2cin 10, (tpos, spos, apos, zpos, dpos, mpos, wpos, tz) ; fall through to reset clock and refresh with new clock read reset_clock_display: For i = clock_data to clock_data_yr put i, $FF ; fill buffer to assure all data read, Next i ; formatted, and put in display buffer Gosub LCD_Reset ; clear display ; fall through to read_clock to read and display the current clock data
Read time and date and format for display. The first 8 bytes in clock are BCD time values with hour having am.pm flag. The routine uses b0 and the defined registers. Clock display data updated to LCD position as indicated. The BCD clock data with a few flags thrown in (e.g. hours) needs a great deal of care if using a time value in tests or calculations. For values <10, BCD and binary are the same but >9 means the high order nibble is another digit (like in hexadecimal notation).
Note that the calls to the LCD set position and display characters are omitted in this code to emphasise the clock data processing.
read_clock: ; Seconds hi2cin 0,(sc) get clock_data, b0 If b0 = sc Then Return ; no time change, leave as is EndIf put clock_data, sc ; update time buffer If spos < $FF Then BCDtoASCII sc, i, j ; seconds (CH assumed not set) b0 = spos ; [[ position LCD to b0 and then display i and j ]] Sertxd("sec @",#b0,"=",i,j,cr,lf) EndIf
This pattern of reads, comparison to scratchpad values, scratchpad updating, and display if position is valid is repeated for the other clock values. For Hours, it is necessary to parse out the 12 or 24 hour mode bit and the am/pm bit.
; Hours hi2cin 2,(hr) get clock_data_hr, b0 If b0 = hr Then Return EndIf put clock_data_hr, hr b0 = hr ; easier to check bits If bit6 = 1 Then ; 12 hour mode morning = bit5 ; mainly used for DST testing If bit5 = 1 Then i = "p" bit5 = 0 Else i = "a" EndIf bit6 = 0 ; clear bit for BCD conversion hr = b0 ; am/pm bits cleaned saved ; If apos < $FF Then ; print am or pm ; EndIf ; Else ; 24 hour mode ; If hr < 12 Then ; morning = 0 ; Else ; morning = 1 ; EndIf EndIf
The morning flag is used for daylight savings time checks. Calculating day of week and checking for daylight savings time adjustments are on the agenda. As the magic DST hour is this weekend, it is a good time to check the tests for whether the clock should be adjusted. As always, there are complications to consider. One of them is that the VCC lead to my LCD display broke, and something else got messed up so I had to spend time figuring out how to fix those problems so I could run tests to get the major bugs fixed.
For this sample, though, go through the code and look for the I2C communications commands hi2csetup, hi2cin, and hi2cout. Look at how the BCD routines built into the PICAXE are used. Here, they are mainly to get display values but in some places, binary values are needed for calculation.
Don’t worry, the whole thing will get posted to the TCL software library before long.
Post a Comment