|
| 1 | +{{ DS1302_full.spin2 |
| 2 | +┌─────────────────────────────────────┬────────────────┬─────────────────────┬───────────────┐ |
| 3 | +│ DS1302 driver v1.3 (Spin2 version) │ dgately │ (C)2021 │ 1Jan2021 │ |
| 4 | +├─────────────────────────────────────┴────────────────┴─────────────────────┴───────────────┤ |
| 5 | +│ DS1302 driver v1.3 │ BR │ (C)2010 │ 8Jul2010 │ |
| 6 | +├─────────────────────────────────────┴────────────────┴─────────────────────┴───────────────┤ |
| 7 | +│ │ |
| 8 | +│ A full-featured DS1302 timekeeping chip driver. Based on the original object by │ |
| 9 | +│ Daniel Robert. │ |
| 10 | +│ │ |
| 11 | +│ Notes: │ |
| 12 | +│ •Original object here: http://obex.parallax.com/objects/89/ │ |
| 13 | +│ •12 hour mode is not supported in this object. The reason is that it would add │ |
| 14 | +│ significant complexity to this object for minimal benefit. A better solution is │ |
| 15 | +│ to handle the 12/24 hour conversion in software outside of this object if needed. │ |
| 16 | +│ Okay. So it is nearly full-featured. │ |
| 17 | +│ •The DS1302 data sheet specs the maximum frequency on the clk pin as: │ |
| 18 | +│ 0.5MHz@2V, 2MHz@5V --> 1.5MHz@3.3V (1.5 uS per clock, 120 ticks@clkfreq=80MHz) │ |
| 19 | +│ Original object had a 2 uS pause between clock pin transitions. However, it seems to │ |
| 20 | +│ work fine with no wait @ clkfreq=80MHz...apparently spin can't outrun the DS1302. │ |
| 21 | +│ Not tested at clkfreq=100MHz. │ |
| 22 | +│ •Experimented with trickle charger using 1 diode+2K resistor setting. 10µF │ |
| 23 | +│ electrolytic cap kept DS1302 powered up for >10 minutes. Implies a 1000µF should be good │ |
| 24 | +│ for ~16 hrs of backup power...enough to last through a typical brown-out or black-out │ |
| 25 | +│ (if leakage current and wide tolerance band of electrolytics doesn't kill it first) │ |
| 26 | +│ •Note that this device needs to have a 32.768KHz crystal with 6pF capacitance in order to │ |
| 27 | +│ keep accurate time: http://forums.parallax.com/forums/default.aspx?f=25&m=467246 │ |
| 28 | +│ │ |
| 29 | +│ See end of file for terms of use. │ |
| 30 | +└────────────────────────────────────────────────────────────────────────────────────────────┘ |
| 31 | +DEVICE PINOUT & REFERENCE CIRCUIT |
| 32 | + ┌────┐ 1000µF |
| 33 | + 3.3V │ │ backup_Vin ── to gnd |
| 34 | + xtal xi │DS1302│ clk ─── to prop pin |
| 35 | + 32.768 KHz xo │ │ io ─ 1KΩ resistor to prop pin |
| 36 | + ┌│ │ ce ─── to prop pin |
| 37 | + GND └──────┘ |
| 38 | + |
| 39 | + |
| 40 | +TRICKLE CHARGER NOTES |
| 41 | +'Trickle charger setup tc_enable diodeSel resistSel |
| 42 | +' | | | |
| 43 | +' write(command(clock,tc,w),(%1010 << 4) + (2 << 2)+ ( 3 )) |
| 44 | + |
| 45 | +Diode select register bits: 00 = trickle charger disabled |
| 46 | + 01 = 1 diode enabled |
| 47 | + 10 = 2 diodes connected in series (more voltage drop when in charging mode) |
| 48 | + 11 = trickle charger disabled |
| 49 | + |
| 50 | +Resistor select bits: 00 = no resistor 0Ω |
| 51 | + 01 = R1 2KΩ |
| 52 | + 10 = R2 4KΩ |
| 53 | + 11 = R3 8KΩ |
| 54 | + |
| 55 | +'Examples of other useful config and control commands |
| 56 | +'write(command(clock,sec,w),read(command(clock,sec,r))&%1000_0000) 'set clock halt bit |
| 57 | +'write(command(clock,ctrl,w),%1000_0000) 'set write-protect bit |
| 58 | +'write(command(clock,hr,w),read(command(clock,hr,r))&%1000_0000) 'set 12h mode |
| 59 | + |
| 60 | +V1.1 - 27Oct09 fixed mis-labeled pins in docs (clk and io were swapped in 1.0) |
| 61 | +V1.2 - 28Mar10 fixed bug in config method that caused seconds to be reset (thanks, Doug!) |
| 62 | +v1.3 - 26Jun10 cleanup and additional documentation |
| 63 | +v1.3 - 01Jan21 Spin2 version, no functional changes |
| 64 | + |
| 65 | +}} |
| 66 | + |
| 67 | +CON |
| 68 | +'command byte options |
| 69 | + #0, clock,ram |
| 70 | + #0, sec, mi, hr, day, mo, dow, yr, ctrl, tc, #31, burst |
| 71 | + #0, w,r |
| 72 | + |
| 73 | + |
| 74 | +VAR |
| 75 | + byte clk 'clock |
| 76 | + byte io 'data io |
| 77 | + byte ce 'chip enable |
| 78 | + byte datar |
| 79 | + |
| 80 | + |
| 81 | +PUB command(clock_or_ram, register, r_or_w): result |
| 82 | +''Returns a DS1302 command byte |
| 83 | +''clock_or_ram : select clock or ram (allowed values: clock, ram) |
| 84 | +''register : register name (allowed values: 0-30, sec, mi, hr, day, mo, dow, yr, ctrl, tc, burst) |
| 85 | +''r_or_w : read or write (allowed values: w, r) |
| 86 | +''Usage : cmd:=command(rtc#ram, 21, rtc#w) --> write to RAM byte 21 |
| 87 | +'' cmd:=command(rtc#clock, rtc#min, rtc#r) --> read minute register |
| 88 | + |
| 89 | + return (1<<7) + (clock_or_ram<<6) + (register<<1) + r_or_w |
| 90 | + |
| 91 | + |
| 92 | +PUB init( inClk, inIo, inCe ) |
| 93 | +''Initialize propeller serial com channel with DS1302. Call once after prop power-up. |
| 94 | +''Usage: rtc.init(clk_pin, io_pin, chipEnable_pin) |
| 95 | + |
| 96 | + clk := inClk 'save pin numbers |
| 97 | + io := inIo |
| 98 | + ce := inCe |
| 99 | + |
| 100 | + pinl(ce) 'configure chip enable pin |
| 101 | + pinl(clk) 'configure clock pin |
| 102 | + |
| 103 | +PUB config() |
| 104 | +''Config DS1302. Call once after DS1302 power-up. |
| 105 | +''Usage: rtc.config |
| 106 | + |
| 107 | + write(command(clock,ctrl,w),0) 'clear write-protect bit |
| 108 | + write(command(clock,sec,w),read(command(clock,sec,r)) & %0111_1111) 'clear halt bit |
| 109 | + write(command(clock,hr,w),read(command(clock,hr,r)) & %0111_1111) 'set 24hr mode |
| 110 | + write(command(clock,tc,w),0) 'disable trickle charger |
| 111 | + |
| 112 | + |
| 113 | +PUB setDatetime( _mth, _day, _year, _dow, _hr, _min, _sec ) |
| 114 | +''Set date and time |
| 115 | + |
| 116 | + write($8c, bin2bcd( _year ) ) |
| 117 | + write($8a, _dow ) |
| 118 | + write($88, bin2bcd( _mth ) ) |
| 119 | + write($86, bin2bcd( _day ) ) |
| 120 | + write($84, bin2bcd( _hr ) ) |
| 121 | + write($82, bin2bcd( _min ) ) |
| 122 | + write($80, bin2bcd( _sec ) ) |
| 123 | + |
| 124 | + |
| 125 | +PUB readDate( _day, _mth, _year, _dow ) |
| 126 | +''Read current date (day, month, year, day-of-week) |
| 127 | +''Usage: rtc.readDate( @day, @month, @year, @dow ) |
| 128 | + |
| 129 | + byte[_year] := bcd2bin( read($8d) ) |
| 130 | + byte[_mth] := bcd2bin( read($89) ) |
| 131 | + byte[_day] := bcd2bin( read($87) ) |
| 132 | + byte[_dow] := bcd2bin( read($8b) ) |
| 133 | + |
| 134 | + |
| 135 | +PUB readTime( _hr, _min, _sec ) | tmp1, tmp2 |
| 136 | +''Read current hour, minute, second |
| 137 | +''Usage: rtc.readTime( @hour, @minute, @second ) |
| 138 | + |
| 139 | + byte[_hr] := bcd2bin( read($85) ) |
| 140 | + byte[_min] := bcd2bin( read($83) ) |
| 141 | + byte[_sec] := bcd2bin( read($81) ) |
| 142 | + |
| 143 | + |
| 144 | +Pub read( cmd ): result | i |
| 145 | +''Read a byte of data per command byte |
| 146 | + |
| 147 | + pinh(ce) ' enable the RTC |
| 148 | + writeByte( cmd ) ' send the command (RTC register) |
| 149 | + pinf(io) ' make IO an input |
| 150 | + readByte() ' read back the result |
| 151 | + pinl(ce) ' disable the RTC |
| 152 | + return(datar) |
| 153 | + |
| 154 | + |
| 155 | +Pub write( cmd, data ) |
| 156 | +''Write a byte of data per cmd byte |
| 157 | + |
| 158 | + pinh(ce) ' enable the RTC |
| 159 | + writeByte( cmd ) ' send the command (RTC register) |
| 160 | + writeByte( data ) ' send the data byte to the RTC |
| 161 | + pinl(ce) ' disable the RTC |
| 162 | + |
| 163 | + |
| 164 | +PUB writeN(cmd, dataPtr, n)|i |
| 165 | +''Write a stream of n bytes from byte array pointed to by dataPtr |
| 166 | + |
| 167 | + pinh(ce) ' enable the RTC |
| 168 | + writeByte( cmd ) ' send the command (RTC register) |
| 169 | + repeat i from 0 to n ' send the data as single bytes |
| 170 | + writeByte(byte[dataPtr][i]) |
| 171 | + pinl(ce) ' disable the RTC |
| 172 | + |
| 173 | + |
| 174 | +Pub readN(cmd, dataPtr, n)|i |
| 175 | +''Read a stream of n bytes of data and put in byte array pointed |
| 176 | +''to by dataPtr |
| 177 | + |
| 178 | + pinh(ce) ' enable the RTC |
| 179 | + writeByte( cmd ) ' send the command (RTC register) |
| 180 | + dira[io]~ ' set to input |
| 181 | + repeat i from 0 to n ' get the data as single bytes |
| 182 | + readByte() |
| 183 | + byte[dataPtr][i]:=datar |
| 184 | + pinl(ce) ' disable the RTC |
| 185 | + |
| 186 | + |
| 187 | +PRI readByte()|i |
| 188 | + |
| 189 | + repeat i from 0 to 7 |
| 190 | + datar.[i] := pinr(io) ' set the bits 0..7 |
| 191 | + pinh(clk) ' strobe the clock |
| 192 | + pinl(clk) |
| 193 | + |
| 194 | + |
| 195 | +PRI writeByte( cmd ) | i |
| 196 | + |
| 197 | + repeat 8 |
| 198 | + pinw(io, cmd) ' set the IO pin high if LSB is 1 |
| 199 | + pinh(clk) ' strobe the clock |
| 200 | + cmd >>= 1 ' move next bit into LSB |
| 201 | + pinl(clk) |
| 202 | + |
| 203 | + |
| 204 | +PRI bin2bcd(dataIn): result | tmp |
| 205 | +'Convert a byte of binary data to binary coded decimal |
| 206 | + |
| 207 | + tmp:= dataIn/10 |
| 208 | + result := dataIn - ( tmp * 10 ) + ( tmp << 4 ) |
| 209 | + |
| 210 | + |
| 211 | +PRI bcd2bin(dataIn): result |
| 212 | +'Convert a byte of binary coded decimal data to binary |
| 213 | + |
| 214 | + result := (dataIn & %00001111) + ((dataIn >> 4) & %00001111)*10 |
| 215 | + |
| 216 | + |
| 217 | +DAT |
| 218 | + |
| 219 | +{{ |
| 220 | +┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐ |
| 221 | +│ TERMS OF USE: MIT License │ |
| 222 | +├─────────────────────────────────────────────────────────────────────────────────────────────────────┤ |
| 223 | +│Permission is hereby granted, free of charge, to any person obtaining a copy of this software and │ |
| 224 | +│associated documentation files (the "Software"), to deal in the Software without restriction, │ |
| 225 | +│including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,│ |
| 226 | +│and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,│ |
| 227 | +│subject to the following conditions: │ |
| 228 | +│ │ │ |
| 229 | +│The above copyright notice and this permission notice shall be included in all copies or substantial │ |
| 230 | +│portions of the Software. │ |
| 231 | +│ │ │ |
| 232 | +│THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT│ |
| 233 | +│LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. │ |
| 234 | +│IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER │ |
| 235 | +│LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION│ |
| 236 | +│WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. │ |
| 237 | +└─────────────────────────────────────────────────────────────────────────────────────────────────────┘ |
| 238 | +}} |
0 commit comments