fl { PropForth 5.5 2021/05/06 22:25:24 Aging calibration by 1PPS on GPS -------rtc module--------------------------------------- DS3231&eeprom ----------- P28 ------|SCL Vcc |----------------3V3 P29 ------|SDA | + - P2--------|SQW VBAT|----battery---- GND | h68 GND|----GND ----------- ------------ P28 ------|SCL Vcc |-----3V3 P29 ------|SDA WP |-----GND |h57 A0/A1/A2|NC ------------ -------GPS--------------------------------------- ----------- 3V3 | GYSFDMAXB | | | 5V|-------5V 10kohm | GND|-------GND | | RXD|-------------------PN----P1 | TXD|-------P0[RXD] | 1PPS|-------P2 ----------- } : GPS ; \ =========================================================================== \ Constants \ =========================================================================== \ serial for PropForth<-->GPS 0 wconstant Rx 1 wconstant Tx d2400 constant baudrate \ 9600/4 2 wconstant 1pps 3 wconstant SQW 1 1pps lshift constant m1pps 1 SQW lshift constant mSQW \ ----special register----- h1F8 wconstant ctra h1F9 wconstant ctrb h1FA wconstant frqa h1FB wconstant frqb h1FC wconstant phsa h1FD wconstant phsb \ -----rtc&eeprom----- hD0 wconstant DS3231 \ Slave addres h68 for DS3231 hAE wconstant eeprom \ Slave addres h57 for 24C32 \ ---DS3231------ hF wconstant status h10 constant Aging hE wconstant control \ ----Switch------ \ P5 + \ P6 - d4000000 constant 50msec 5 wconstant sw 3 sw lshift constant msw \ =========================================================================== \ Variables \ =========================================================================== wvariable inchar variable lastDebounceTime wvariable swState \ current input-data wvariable lastswState \ last input-data wvariable debounce variable ticks \ =========================================================================== \ DS3231 \ =========================================================================== : err_msg ." I2C error" ; \ If error, print message \ ( n1 -- ) n1:t/f : err? if err_msg cr then ; \ Start i2c-commnication \ This also can use SMBus device. \ ( -- ) lockdict create _eestart forthentry $C_a_lxasm w, h122 h113 1- tuck - h9 lshift or here W@ alignl h10 lshift or l, z1[ixnW l, z1[ixnX l, z2WyP[U l, z20iPak l, z3ryPW0 l, z1bixnW l, z2WyP[V l, z20iPak l, z3ryPW0 l, z1bixnX l, z1SV01X l, zl0 l, zCW l, zW0000 l, zG0000 l, freedict \ Re-defined RepeatedStart \ ( -- ) : Sr _eestart ; \ Stop i2c-commnication \ ( -- ) : _eestop _scli \ Release scl _sdai \ Release sda ; \ _eewrite ( c1 -- t/f ) write c1 to the eeprom, true if there was an error \ Received acknowledge from i2c-device during scl is high \ scl/sda use pull-up resistor at hi \ clock:400kHz lockdict create _eewrite forthentry $C_a_lxasm w, h12C h113 1- tuck - h9 lshift or here W@ alignl h10 lshift or l, z2WyPW8 l, z1YVPQ0 l, z1rixnd l, z1Sy\C] l, z1[ixne l, z1Sy\C] l, z1bixne l, zfyPO1 l, z3[yP[K l, z1[ixnd l, z1Sy\C] l, z1[ixne l, z1Sy\C] l, z1YF\Nl l, z1viPR6 l, z1bixne l, z1Sy\C] l, z1bixnd l, z1SV01X l, z2WyPc7 l, z20iPik l, z3ryPb0 l, z1SV000 l, zW0000 l, zG0000 l, freedict \ _eeread ( t/f -- c1 ) flag should be true is this is the last read \ scl/sda use pull-up resistor at hi \ clock:400kHz lockdict create _eeread forthentry $C_a_lxasm w, h12D h113 1- tuck - h9 lshift or here W@ alignl h10 lshift or l, z2WiPZB l, z2WyPO0 l, z1[ixne l, z2WyPj8 l, z1Sy\Ka l, z1[ixnf l, z1Sy\Ka l, z1XF\Vl l, znyPO1 l, z1bixnf l, z3[yPnN l, z26VPW0 l, z1rixne l, z1Sy\Ka l, z1[ixnf l, z1Sy\Ka l, z1bixnf l, z1bixne l, z1Sy\Ka l, z1SV01X l, z2WyPc9 l, z20iPik l, z3ryPb0 l, z1SV000 l, zW0000 l, zG0000 l, freedict \ Write data to register in i2c_device \ ( n1 n2 n3 -- ) n1:data n2:register n3:slave_address : i2c_wr \ Start I2C _eestart \ Write slave address[wr], then receive Acknowledge-bit(ACK:Lo NACK:Hi) _eewrite \ ( n1 n2 t/f ) \ Write register swap _eewrite or \ ( n1 t/f ) \ Write data swap _eewrite or \ ( t/f ) \ Stop I2C _eestop err? \ ( -- ) ; \ Write series data to register in i2c_device \ ( n1..nn n2 n3 n4 -- ) n1..nn:data n2:number n3:register n4:slave_address : i2c_wr_multi \ Start I2C _eestart \ Write slave address[wr], then receive Acknowledge-bit(ACK:Lo NACK:Hi) _eewrite \ ( n1..nn n2 n3 t/f ) \ Write register swap _eewrite or \ ( n1..nn n2 t/f ) swap \ ( n1..nn t/f n2 ) \ Read n2 byte dup 1 > if \ ( n1..nn t/f n2 ) 0 do \ ( n1..nn t/f ) swap _eewrite or \ ( n1.. nn t/f ) loop else \ ( n1 t/f n2 ) drop swap _eewrite or \ ( t/f ) then \ Stop I2C _eestop err? \ ( -- ) ; \ Read data from register in i2c_device \ ( n1 n2 -- n3 ) n1:register n2:slave_address n3:data : i2c_rd \ Start I2C _eestart \ Write slave address[wr], then receive Acknowledge-bit(ACK:Lo NACK:Hi) tuck _eewrite \ ( n2 n1 t/f ) \ Write register swap _eewrite or \ ( n2 t/f ) swap \ ( t/f n2 ) \ Start read_process Sr \ Write slave address[rd], then receive Acknowledge-bit(ACK:Lo NACK:Hi) 1 or _eewrite or \ ( t/f ) \ Read 1byte ,then set sda to Hi(NACK:master->slave) -1 _eeread \ Stop I2C _eestop swap \ (n3 t/f ) err? \ ( n3 ) ; \ bcd> ( n1 -- n2 ) convert bcd byte n1 to hex byte n2 : bcd> dup hF and swap hF0 and 1 rshift dup 2 rshift + + ; \ >bcd ( n1 -- n2 ) convert hex byte n1 to bcd byte n2 : >bcd d10 u/mod 4 lshift + ; \ Get current time \ Read/Convert current time from DS3231 \ ( -- n1 n2 n3 n4 n5 n6 n7 ) \ n1 - second (00 - 59) \ n2 - minute (00 - 59) \ n3 - hour (00 - 23) \ n4 - day of week (Mon:1 Tue:2 Wed:3 Thur:4 Fri:5 Sat:6 San:7) \ n5 - date (01 - 31) \ n6 - month (01 - 12) \ n7 - year (00 - 99) : rdTime 7 0 do 0 i + DS3231 i2c_rd bcd> loop ; \ Set current-time to DS3231 (24Hour mode) \ Set second to 0 \ ( n1 n2 n3 n4 n5 n6 -- ) \ n1 - year (00 - 99) \ n2 - month (01 - 12) \ n3 - date (01 - 31) \ n4 - day-of-week (Mon:1 Tue:2 Wed:3 Thur:4 Fri:5 Sat:6 San:7) \ n5 - hour (00 - 23) \ n6 - minute (00 - 59) : setTime1 >bcd >r \ minute >bcd >r \ hour >r \ day-of-week >bcd >r \ day >bcd >r \ month >bcd \ year r> r> r> r> r> 0 7 0 DS3231 i2c_wr_multi ; \ ================================================================== \ Switch \ ================================================================== \ Set initial \ ( -- ) : init_sw \ Set initial values 3 swState W! 0 lastDebounceTime L! 3 lastswState W! \ Switch state when no pushing switch 0 debounce W! ; \ Read sw-status +(2),-(1),not pushed(3) \ ( -- ) : swScan init_sw begin \ Read current sw and check if pushed or released msw ina COG@ and sw rshift \ 2bit-data(P5,P6) dup lastswState W@ <> if \ If sw is under debouncong debounce W@ 0= if cnt COG@ lastDebounceTime L! 1 debounce W! then else 0 debounce W! then debounce W@ if cnt COG@ lastDebounceTime L@ - 50msec > if \ Update current swState and lastswState dup swState W! lastswState W! \ Break loop \ 1 else drop \ Continue loop \ 0 then else drop \ Break loop \ 1 then 0 until ; \ =========================================================================== \ Main \ =========================================================================== \ Start up serial-communication \ This need to execute when staring serial-communication at first \ ( -- ) : initSerial c" Tx Rx baudrate serial" 4 cogx \ Start serial on cog4 d100 delms inchar 4 cogio 2+ W! \ Set output of cog4 inchar h100 inchar W! \ Clear inchar 1 4 sersetflags ; \ Stop Serial communication \ This need to execute when finishing serial-communication at last \ ( -- ) : stopSerial 0 4 cogio 2+ W! 4 cogreset ; \ Transmit data[1byte] \ ( n1 -- ) n1:transmitting byte : Transmit begin 4 cogio W@ h100 and until \ Wait until input for serial-cog is under ready-state 4 cogio W! \ Write data to cog4's input ; \ Receive data and save them in free area \ ( n1 -- n2 ) n1:repeat number n2:last addres+1 of free area : Receive here W@ swap 0 do begin inchar W@ h100 and 0= until \ Wait until output for serial-cog is under ready-state inchar W@ over C! \ Save output-data of cog4 to free area h100 inchar W! \ Clear inchar1 1+ \ Increment free space address loop ; \ Print character from GPS : test initSerial begin begin inchar W@ h100 and 0= until \ Wait until output for serial-cog is under ready-state inchar W@ emit \ print output-data of cog4 to free area h100 inchar W! \ Clear inchar1 fkey? swap drop until stopSerial ; \ Measure 1PPS of GPS \ ( -- ) : test1 h30000000 1pps or ctra COG! \ NEG detector 1 frqa COG! h20000000 1pps or ctrb COG! \ POS detector 1 frqb COG! 0 m1pps waitpeq \ Wait for pulse-pin go to lo 0 phsb COG! m1pps m1pps waitpeq \ Wait for pulse-pin go to hi begin 0 phsa COG! 0 m1pps waitpeq \ Wait for pulse-pin go to lo phsb COG@ dup . space 0 phsb COG! m1pps m1pps waitpeq \ Wait for pulse-pin go to hi phsa COG@ dup . space + . cr fkey? swap drop until ; \ Measure[average of 20 times] 1PPS of GPS \ ( -- ) : test2 h30000000 1pps or ctra COG! \ NEG detector 1 frqa COG! h20000000 1pps or ctrb COG! \ POS detector 1 frqb COG! 0 m1pps waitpeq \ Wait for pulse-pin go to lo 0 phsb COG! m1pps m1pps waitpeq \ Wait for pulse-pin go to hi begin 0 d20 0 do 0 phsa COG! 0 m1pps waitpeq \ Wait for pulse-pin go to lo phsb COG@ dup . space 0 phsb COG! m1pps m1pps waitpeq \ Wait for pulse-pin go to hi phsa COG@ dup . cr + + loop d20 / . cr fkey? swap drop until ; \ measure SQW(1Hz) of DS3231 \ ( -- ) : test3 h30000000 SQW or ctra COG! \ NEG detector 1 frqa COG! h20000000 SQW or ctrb COG! \ POS detector 1 frqb COG! begin status DS3231 i2c_rd 4 and 0= until h20 control DS3231 i2c_wr \ Set conv-bit=1,RS1=RS2=0,INTC=0 0 mSQW waitpeq \ Wait for pulse-pin go to lo 0 phsb COG! mSQW mSQW waitpeq \ Wait for pulse-pin go to hi begin \ Measure pulse width phsa COG@ dup . space 0 phsa COG! 0 mSQW waitpeq \ Wait for pulse-pin go to lo phsb COG@ dup . space + . space 0 phsb COG! mSQW mSQW waitpeq \ Wait for pulse-pin go to hi Aging DS3231 i2c_rd . cr \ Get Aging register fkey? swap drop until ; \ \ ( -- ) : test4 c" swScan" 0 cogx h30000000 SQW or ctra COG! \ NEG detector 1 frqa COG! h20000000 SQW or ctrb COG! \ POS detector 1 frqb COG! 0 mSQW waitpeq \ Wait for pulse-pin go to lo 0 phsb COG! mSQW mSQW waitpeq \ Wait for pulse-pin go to hi begin swState W@ dup . cr 2 over = if \ increment AGE Aging DS3231 i2c_rd 1+ Aging DS3231 i2c_wr begin status DS3231 i2c_rd 4 and 0= until h20 control DS3231 i2c_wr else 1 over = if \ decrement AGE Aging DS3231 i2c_rd 1- Aging DS3231 i2c_wr begin status DS3231 i2c_rd 4 and 0= until h20 control DS3231 i2c_wr thens drop phsa COG@ dup . space 0 phsa COG! 0 mSQW waitpeq \ Wait for pulse-pin go to lo phsb COG@ dup . space + . space 0 phsb COG! mSQW mSQW waitpeq \ Wait for pulse-pin go to hi Aging DS3231 i2c_rd . cr \ Get Aging register fkey? swap drop until 0 cogreset ; \ Measure[average of 20 times] 1PPS of GPS \ ( -- ) : 1PPSticks h30000000 1pps or ctra COG! \ NEG detector 1 frqa COG! h20000000 1pps or ctrb COG! \ POS detector 1 frqb COG! 0 m1pps waitpeq \ Wait for pulse-pin go to lo 0 phsb COG! m1pps m1pps waitpeq \ Wait for pulse-pin go to hi begin 0 d20 0 do 0 phsa COG! 0 m1pps waitpeq \ Wait for pulse-pin go to lo phsb COG@ 0 phsb COG! m1pps m1pps waitpeq \ Wait for pulse-pin go to hi phsa COG@ + + loop d20 / ticks L! fkey? swap drop until ; \ Display ticks of 1PPS and 1Hz on characterLCD \ ( -- ) : calibration lcd_init lcd_clr c" swScan" 0 cogx c" 1PPSticks" 1 cogx h30000000 SQW or ctra COG! \ NEG detector 1 frqa COG! h20000000 SQW or ctrb COG! \ POS detector 1 frqb COG! 0 mSQW waitpeq \ Wait for pulse-pin go to lo 0 phsb COG! mSQW mSQW waitpeq \ Wait for pulse-pin go to hi begin swState W@ 2 over = if \ increment AGE Aging DS3231 i2c_rd 1+ Aging DS3231 i2c_wr begin status DS3231 i2c_rd 4 and 0= until h20 control DS3231 i2c_wr else 1 over = if \ decrement AGE Aging DS3231 i2c_rd 1- Aging DS3231 i2c_wr begin status DS3231 i2c_rd 4 and 0= until h20 control DS3231 i2c_wr thens drop phsa COG@ 0 phsa COG! 0 mSQW waitpeq \ Wait for pulse-pin go to lo phsb COG@ + 1 2 lcd_pos lcd_dec 0 phsb COG! mSQW mSQW waitpeq \ Wait for pulse-pin go to hi 1 1 lcd_pos ticks L@ dup dup 0< swap d900000 > and if drop else lcd_dec then Aging DS3231 i2c_rd \ Get Aging register 9 2 lcd_pos c" " lcd_str d10 2 lcd_pos dup h80 and if hFFFFFF00 or then lcd_dec fkey? swap drop until 0 cogreset 1 cogreset ;