\ READ R2000 RTC \ 48 BITS = 6, 8 BIT COUNTERS \ b47..b40|b39..b32|b31..b24|b23..b16|b15..b8|b7..b0 bit # \ 7 | 6 | 5 | 4 | 3 | 2 addr \ 5R |4R |3R |2R |1R |0R Reg name \ 1/32768 x 256 x 128 = 1SEC (B15) \ 48 BITS = TICKS SINCE JAN 1, 1980 (TUESDAY) \ 86,400 SEC/DAY \ TIME IN B15..B31 INCLUSIVE (17 bits) \ B31 IS 2^17 = 131072, SO THERE ARE 44,672 COUNTS INTO THE NEXT DAY... \ 65536 DAYS / 365 = 179 YEARS \ 1980 is leap year. every 4 (80,84,88,92,96,00,04...) has extra day 2/29 \ 1/31,2/28,3/31,4/30,5/31,6/30,7/31,8/31,9/30,10/31,11/30,12/31 \ 10/28/2001 : 31+28+31+30+31+30+31+31+30+28 + 21*365 + 6 \ = 301+7665+6 = 7972 \ read # days div by 365 = year + 1980 \ remainder is date. fix leap year residue. year div 4 + 1 (zero based) \ subtract from date remainder. then subtract # days in month using index to \ array. \ 345678901234567890123456789012345678901234567890123456789012345678901234567890 \ 1 2 3 4 5 6 7 8 \ copies of time registers: VARIABLE R5 VARIABLE R4 VARIABLE R3 VARIABLE R2 VARIABLE R1 VARIABLE R0 DECIMAL \ array for figuring out month from # days (24hr intervals) \ jan = 000..030 31 days \ feb = 031..058 28 days special case for leap years \ mar = 059..089 31 days \ apr = 090..119 30 days \ may = 120..150 31 days \ jun = 151..180 30 days \ jul = 181..211 31 days \ aug = 212..242 31 days \ sep = 243..272 30 days \ oct = 273..303 31 days \ nov = 304..333 30 days \ dec = 334..364 31 days \ need to add one day for each leap year... \ 1980,1984,1988,1992,1996,2000,2004,... CREATE DIY ( Days in Year by month ) 0 , 031 , 059 , 090 , 120 , 151 , 181 , 212 , 243 , 273 , 304 , 334 , 365 , \ nul, jan , feb , mar , apr , may , jun , jul , aug , sep , oct , nov , dec , VARIABLE 24HFMT 0 24HFMT ! \ INITIALLY 12HR FMT \ double word add : D+ ( d d -- d ) >R SWAP >R UM+ R> + R> + ; \ DOT_TIME_REG (rabbit time registers) : .TR 0 2 P! 2 P@ 3 P@ 4 P@ 5 P@ 6 P@ 7 P@ . . . . . . ; \ DOT_R_REG (copy of time registers) : .RR R2 @ R3 @ R4 @ R5 @ . . . . ; \ reads rabbit time registers & saves in copy of time registers : RTR 0 2 P! 2 P@ 3 P@ 4 P@ 5 P@ 6 P@ 7 P@ \ read them as quickly as possible R5 ! R4 ! R3 ! R2 ! R1 ! R0 ! ; \ then save them \ puts time into double word format : DTIME ( -- tlw thw ) R3 @ 256 * R2 @ + R5 @ 256 * R4 @ + ; \ double word time -> seconds days : TIMEDATE DTIME 43200 UM/MOD ( -- r=time q=days ) ; : TIMEBYTES RTR TIMEDATE DROP ( time -- ) R1 @ ( get 17th bit of time ) SWAP DUP UM+ ( shift L. 17 bit result ) ( R1 timeL timeH -- ) ROT 128 AND IF 1 ELSE 0 THEN ( lsb ) ( timeL timeH 0,1 -- ) ROT UM+ ( timeH timeL+lsbL timeL+lsbH -- ) ROT + ( add high carries ) 60 UM/MOD ( div 60 = seconds minutes ) 0 60 UM/MOD ( div 60 = minutes hours ) ( -- s m h ) ; : TIMEFMT ( s m h -- ) 24HFMT @ IF ( div 24 = hours day ) 0 24 UM/MOD ( s m h q -- ) ELSE ( div 12 ) 0 12 UM/MOD ( 12 hr format ) ( s m h q -- ) THEN ROT ROT ( s q m h ) CR <# # # #> TYPE ." :" \ HR <# # # #> TYPE ." :" \ MIN SWAP <# # # #> TYPE \ SEC 24HFMT @ IF DROP ELSE ( a -- ) IF ." PM" ELSE ." AM" THEN THEN ; : TIME TIMEBYTES TIMEFMT ; : <= 2DUP = ROT ROT < OR ; \ define [month]D(ays) words that return # days in YEAR for month from DIY array \ i.e. more than 31 days means we aren't in january any more \ mmmD ( -- #days ) : JAND DIY 2 + @ ; : FEBD DIY 4 + @ ; : MARD DIY 6 + @ ; : APRD DIY 8 + @ ; : MAYD DIY 10 + @ ; : JUND DIY 12 + @ ; : JULD DIY 14 + @ ; : AUGD DIY 16 + @ ; : SEPD DIY 18 + @ ; : OCTD DIY 20 + @ ; : NOVD DIY 22 + @ ; : DECD DIY 24 + @ ; \ figure out month from # days... \ ( #days -- day-in-month ) : MONTH DUP JAND <= IF ." JAN " EXIT THEN DUP FEBD <= IF ." FEB " JAND - EXIT THEN DUP MARD <= IF ." MAR " FEBD - EXIT THEN DUP APRD <= IF ." APR " MARD - EXIT THEN DUP MAYD <= IF ." MAY " APRD - EXIT THEN DUP JUND <= IF ." JUN " MAYD - EXIT THEN DUP JULD <= IF ." JUL " JUND - EXIT THEN DUP AUGD <= IF ." AUG " JULD - EXIT THEN DUP SEPD <= IF ." SEP " AUGD - EXIT THEN DUP OCTD <= IF ." OCT " SEPD - EXIT THEN DUP NOVD <= IF ." NOV " OCTD - EXIT THEN DUP DECD <= IF ." DEC " NOVD - EXIT THEN ; : NLY ( days -- t/f #leapyears ) 0 365 UM/MOD ( days years ) SWAP DROP 0 4 UM/MOD ( rem #ly -- ) 1 + \ include 1980 as leap year SWAP 0 = IF -1 ELSE 0 THEN SWAP ( -- t/f #leapyears ) ; : nDAYS RTR TIMEDATE SWAP DROP ( -- days ) ; : fDATE ( days -- ) DUP NLY ( days t/f #leapyear -- ) ROT SWAP - ( t/f adjdays -- ) \ date has problems at the end of the year because \ of leap year adjust... \ so drop extra days from leap years to correctly figure out year 0 365 UM/MOD ( t/f ndays years ) 1980 + ( t/f ndays year -- ) SWAP ( t/f year ndays -- ) \ now include extra day if THIS YEAR is a leap year \ AND past feb 28 ROT IF ( past 2/28? ) DUP 59 SWAP < IF 1 + THEN THEN 1 + \ days is zero based! ( -- year ndays ) ; : DATE nDAYS fDATE MONTH <# # # #> TYPE ." , " <# # # # # #> TYPE CR ; : SETTIME ( nn dd yyyy hh mm ss -- r5 r4 r3 r2 r1 ) \ DOSET actually sets the time! \ probably want to set decimal mode before invoking! \ SETTIME **ONLY** 24 hour format \ ss + (mm*60) + (hh*3600) + \ ((yy-1980)*365 + (yy-1980)/4 + (nn*"nnD") + dd)*86400 \ add ss last. do all constants (60,3600,86400) as 1/2 value (2sec sum) \ this allows the sum to be done as a double >R >R >R \ SAVE TIME on return stack 1980 - DUP 365 * SWAP 4 / + \ # DAYS FROM YEARS & LEAPS + \ add in days this month SWAP 1 - DUP + ( 2x ) DIY + @ + \ total days 43200 UM* ( dsL dsH -- ) R> R> R> \ restore time from return stack ROT ROT SWAP ( ss mm hh -- ) 3600 UM* ( ss mm dhl dhh -- ) ROT 60 * ( ss dhL dhH mm60 -- ) ROT UM+ ( add to low ) ( ss dhH dhL+mm60L dhL+mm60H -- ) ROT + ( add high words ) ( ss low high -- ) SWAP ROT UM+ ROT + ( add high words ) 2 UM/MOD ( r q -- ) ( rem is lsb -> 1R ) \ still have date # secs on stack too... ( dsL dsH r q -- ) SWAP >R 0 D+ \ save rem. add q to date # sec SWAP 0 256 UM/MOD ( split LOW word into 2 bytes ) SWAP ( low byte 1st ) >R >R 0 256 UM/MOD ( split HIGH word into 2 bytes ) SWAP ( low byte 1st ) R> R> R> ; HEX : DOSET ( r5 r4 r3 r2 r1 -- ) \ do register increment sequentially \ faster if sort and mask bits together. maybe later. 40 1 P! C0 1 P! IF 7F FOR 42 1 P! NEXT ( 1R ) THEN ( set lsb ) 1 - FOR 44 1 P! NEXT ( 2R ) 1 - FOR 48 1 P! NEXT ( 3R ) 1 - FOR 50 1 P! NEXT ( 4R ) 1 - FOR 60 1 P! NEXT ( 5R ) 0 1 P! ; : 1SEC ( -- t/f ) 0 2 P! 3 P@ 80 AND ; : BLINK BEGIN 1SEC IF 80 70 P! ELSE 0 70 P! THEN ?KEY UNTIL ; DECIMAL : BCDTIME ( ss mm hh -- bs bm bh ) DUP 13 SWAP < IF 12 - THEN \ always 12hr fmt for pclk display \ decimal -> BCD 0 10 UM/MOD 16 * + ROT 0 10 UM/MOD 16 * + ROT 0 10 UM/MOD 16 * + ROT ; 2E HAND EMIT