\ 2006-07-25 EW adv2_i2c_rtc.fs

\ pcf8583:
\ addr
\ 0x00    control register 3: mask_flag
\ 0x01    sec/100.bcd
\ 0x02    sec.bcd
\ 0x03    min.bcd
\ 0x04    7: 0=24h clock, 6: am/pm flag
\         5-0: hour.bcd
\ 0x05    7-6: year%4 5-0: day.bcd
\ 0x06    7-5: weekdays unless maskbit,
\         4-0: month.bcd
\ eeprom:
\ 0x10,0x11 full year, not BCD

: bcd>dec ( n.bcd -- n.dec )
  $ff and
  dup 
  4 rshift 10 * \ extract high nibble as 10s
  swap
  $0f and       \ extract low  nibble as 1s
  +             \ add
;
: dec>bcd ( n.dec -- n.bcd )
  &100 mod      \ 99 is largest for 8 bit bcd
  &10 /mod
  4 lshift
  +
  $ff and       \ truncate to 8 bit
;
: get.rtc
  $01                   \ start address
  1 i2c_addr_rtc NB>i2c \ send > rtc
  6 i2c_addr_rtc NB<i2c \ read 6 Bytes
  $10                   \ YEAR's address
  1 i2c_addr_rtc NB>i2c \ send > rtc
  2 i2c_addr_rtc NB<i2c \ read 2 Bytes
  8 lshift +            \ convert to YYYY
;
\ convert human readable numbers to expected
\ BCD numbers and compounds
: format.rtc
  \ year month day hour min sec sec/100
  \ --
  \ year weekday|month.bcd year%4|day.bcd
  \ hour.bcd min.bcd sec.bcd sec/100.bcd
  dec>bcd >R \ sec/100.bcd
  dec>bcd >R \ sec.bcd
  dec>bcd >R \ min.bcd
  dec>bcd >R \ hour.bcd
             \ year%4<<6 | hour.bcd
  dec>bcd 2 pick $03 and 6 lshift + >R 
  dec>bcd    \ month.bcd
  R> R> R> R> R> 
;
: set.rtc ( year ... sec/100.bcd -- )
  format.rtc
  $80 $00               \ stop rtc
  8 i2c_addr_rtc NB>i2c \ send all args
                        \ start rtc
  $08 $00 2 i2c_addr_rtc NB>i2c 
  
  \ year is still on stack
  dup $00ff and         \ low byte
  swap
  8 rshift $00ff and    \ high byte
  swap                  \ low byte first
  $10                   \ start addr
  3 i2c_addr_rtc NB>i2c \ send > rtc
;
: clock-init ( -- )
  get.rtc
  year !
  bcd>dec month !
  bcd>dec day !
  bcd>dec hour !
  bcd>dec min !
  bcd>dec sec !
  drop \ bcd>dec 10 * msec !
;