Adding a RTC: DS3231¶
- Date:
 2017-08-19
Intro¶
the clock provides these counters
second (0 .. 59)
minute (0 .. 59)
hour (0 .. 23)
24h / am/pm flags
day of week (1 .. 7)
day of month (1 .. 28,29,30,31)
month (1 .. 12)
century rollover flag
year % 100 (0 .. 99)
some of them are merged into one byte!
the counters are in bcd notation
The 7 bit address is
$68the clock also provides the reading of its thermometer
This clock also provides alarms, which are not yet used.
Code Details¶
There should not be any surprises in the code below. The i2c transfers
use AmForths builtin capabilities, Bytes are read or written, masking
of unneccessary bits and conversion from and to bcd (binary coded
decimal) is used. Since year #100 /mod is a complete counter (and
not some bit bolted into some unused place elsewhere), the functions in
this module are a little simpler than in the case of the PCF8583
clock.
$68 constant i2c_addr_rtc
#include i2c_rtc_ds3231.fs
The included file provides these functions:
rtc.get ( -- sec min hour wday day month year )— read the RTC counters
rtc.dot ( sec min hour wday day month year -- )— print the counters found on the stack
rtc.show ( --)— get and print the RTC counters
rtc.set ( year month day wday hour min sec -- )— set the RTC counters
rtc.t.show ( -- )— get and print the temperature (degrees Celsius)
They are sufficient to read and write the RTCs counters. In order to
copy the RTC counters to the clock counters of the controller or vice
versa, two more words are needed in the main program. Note that
the counters day and month of the controller are used with an
offset of 1 (month 0 .. 11, day 0 .. 30).
: hwclock>clock ( -- )
  rtc.get  \ -- sec min hour wday day month year
     year  !
  1- month !
  1- day   !
  ( wday ) drop
     hour  !
     min   !
     sec   !
  year @   month @ 1+  tu.upd.limits
;
: clock>hwclock ( -- )
  year @   month @ 1+  day @ 1+
  1 \ fixme: sunday ":-)
  hour @   min   @     sec @
  ( Y m d wday H M S ) rtc.set
;
The day-of-week counter is ignored at this stage.
The Code (DS3231)¶
 1\ 2017-05-20 ew
 2\
 3\ access to DS3231 RTC --- this is by no means complete!
 4\
 5\ Written in 2017 by Erich Wälde <erich.waelde@forth-ev.de>
 6\
 7\ To the extent possible under law, the author(s) have dedicated
 8\ all copyright and related and neighboring rights to this software
 9\ to the public domain worldwide. This software is distributed
10\ without any warranty.
11\
12\ You should have received a copy of the CC0 Public Domain
13\ Dedication along with this software. If not, see
14\ <http://creativecommons.org/publicdomain/zero/1.0/>.
15\
16\ needs:
17\     #2000 constant Century
18\
19\ words:
20\     rtc.get ( -- sec min hour wday day month year )
21\     rtc.dot ( sec min hour wday day month year -- )
22\     rtc.show ( --)
23\     rtc.set ( year month day wday hour min sec -- )
24\     rtc.t.show ( -- )
25
26
27: rtc.get ( -- sec min hour wday day month year )
28  #7 0 1 i2c_addr_rtc  i2c.m!n@
29  bcd>dec Century + >r
30  bcd>dec >r
31  bcd>dec >r
32  >r
33  bcd>dec >r
34  bcd>dec >r
35  bcd>dec
36  r> r>  r>  r> r> r>
37;
38: rtc.dot ( sec min hour wday day month year -- )
39  #4 u0.r [char] - emit \ year
40  #2 u0.r [char] - emit \ month / 7bit century rollover!
41  #2 u0.r [char] _ emit \ day-of-month
42  >r
43  #2 u0.r [char] : emit \ hour / flags?
44  #2 u0.r [char] : emit \ minute
45  #2 u0.r               \ second
46  r> space .            \ day-of-week
47;
48: rtc.show ( -- )  rtc.get rtc.dot ;
49
50: rtc.set ( year month day wday hour min sec -- )
51  dec>bcd >r            \ second
52  dec>bcd >r            \ minute
53  dec>bcd >r            \ hour (24h format)
54  $07 and >r            \ wday: 1:So 2:Mo .. 7:Sa
55  dec>bcd >r            \ day
56  dec>bcd >r            \ month; century flag ignored
57  #100 mod dec>bcd      \ year % 100
58  r> r> r>  r> r> r>
59  0 #8 i2c_addr_rtc i2c.n!
60;
61
62: rtc.t.show ( -- )
63  2 $11 1 i2c_addr_rtc i2c.m!n@
64  swap >< +  #6 rshift ( T/[0.25 C] )
65  #4 /mod #3 .r [char] . emit 25 * .
66;