2 ## This file is part of the libsigrokdecode project.
4 ## Copyright (C) 2012-2014 Uwe Hermann <uwe@hermann-uwe.de>
5 ## Copyright (C) 2013 Matt Ranostay <mranostay@gmail.com>
7 ## This program is free software; you can redistribute it and/or modify
8 ## it under the terms of the GNU General Public License as published by
9 ## the Free Software Foundation; either version 2 of the License, or
10 ## (at your option) any later version.
12 ## This program is distributed in the hope that it will be useful,
13 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ## GNU General Public License for more details.
17 ## You should have received a copy of the GNU General Public License
18 ## along with this program; if not, see <http://www.gnu.org/licenses/>.
22 import sigrokdecode as srd
23 from common.srdhelper import bcd2int
26 'Sunday', 'Monday', 'Tuesday', 'Wednesday',
27 'Thursday', 'Friday', 'Saturday',
31 'Seconds', 'Minutes', 'Hours', 'Day', 'Date', 'Month', 'Year',
36 'Clock halt', 'Seconds', 'Reserved', 'Minutes', '12/24 hours', 'AM/PM',
37 'Hours', 'Day', 'Date', 'Month', 'Year', 'OUT', 'SQWE', 'RS', 'RAM',
47 DS1307_I2C_ADDRESS = 0x68
50 l = [('reg-' + r.lower(), r + ' register') for r in regs]
51 l += [('bit-' + re.sub('\/| ', '-', b).lower(), b + ' bit') for b in bits]
54 class Decoder(srd.Decoder):
58 longname = 'Dallas DS1307'
59 desc = 'Realtime clock module protocol.'
63 annotations = regs_and_bits() + (
64 ('read-datetime', 'Read date/time'),
65 ('write-datetime', 'Write date/time'),
66 ('reg-read', 'Register read'),
67 ('reg-write', 'Register write'),
68 ('warnings', 'Warnings'),
71 ('bits', 'Bits', tuple(range(9, 24))),
72 ('regs', 'Registers', tuple(range(9))),
73 ('date-time', 'Date/time', (24, 25, 26, 27)),
74 ('warnings', 'Warnings', (28,)),
89 self.out_ann = self.register(srd.OUTPUT_ANN)
92 self.put(self.ss, self.es, self.out_ann, data)
94 def putd(self, bit1, bit2, data):
95 self.put(self.bits[bit1][1], self.bits[bit2][2], self.out_ann, data)
98 self.put(self.bits[bit][1], self.bits[bit][2], self.out_ann,
99 [11, ['Reserved bit', 'Reserved', 'Rsvd', 'R']])
101 def handle_reg_0x00(self, b): # Seconds (0-59) / Clock halt bit
102 self.putd(7, 0, [0, ['Seconds', 'Sec', 'S']])
103 ch = 1 if (b & (1 << 7)) else 0
104 self.putd(7, 7, [9, ['Clock halt: %d' % ch, 'Clk hlt: %d' % ch,
105 'CH: %d' % ch, 'CH']])
106 s = self.seconds = bcd2int(b & 0x7f)
107 self.putd(6, 0, [10, ['Second: %d' % s, 'Sec: %d' % s, 'S: %d' % s, 'S']])
109 def handle_reg_0x01(self, b): # Minutes (0-59)
110 self.putd(7, 0, [1, ['Minutes', 'Min', 'M']])
112 m = self.minutes = bcd2int(b & 0x7f)
113 self.putd(6, 0, [12, ['Minute: %d' % m, 'Min: %d' % m, 'M: %d' % m, 'M']])
115 def handle_reg_0x02(self, b): # Hours (1-12+AM/PM or 0-23)
116 self.putd(7, 0, [2, ['Hours', 'H']])
118 ampm_mode = True if (b & (1 << 6)) else False
120 self.putd(6, 6, [13, ['12-hour mode', '12h mode', '12h']])
121 a = 'AM' if (b & (1 << 6)) else 'PM'
122 self.putd(5, 5, [14, [a, a[0]]])
123 h = self.hours = bcd2int(b & 0x1f)
124 self.putd(4, 0, [15, ['Hour: %d' % h, 'H: %d' % h, 'H']])
126 self.putd(6, 6, [13, ['24-hour mode', '24h mode', '24h']])
127 h = self.hours = bcd2int(b & 0x3f)
128 self.putd(5, 0, [15, ['Hour: %d' % h, 'H: %d' % h, 'H']])
130 def handle_reg_0x03(self, b): # Day / day of week (1-7)
131 self.putd(7, 0, [3, ['Day of week', 'Day', 'D']])
132 for i in (7, 6, 5, 4, 3):
134 w = self.days = bcd2int(b & 0x07)
135 ws = days_of_week[self.days - 1]
136 self.putd(2, 0, [16, ['Weekday: %s' % ws, 'WD: %s' % ws, 'WD', 'W']])
138 def handle_reg_0x04(self, b): # Date (1-31)
139 self.putd(7, 0, [4, ['Date', 'D']])
142 d = self.date = bcd2int(b & 0x3f)
143 self.putd(5, 0, [17, ['Date: %d' % d, 'D: %d' % d, 'D']])
145 def handle_reg_0x05(self, b): # Month (1-12)
146 self.putd(7, 0, [5, ['Month', 'Mon', 'M']])
149 m = self.months = bcd2int(b & 0x1f)
150 self.putd(4, 0, [18, ['Month: %d' % m, 'Mon: %d' % m, 'M: %d' % m, 'M']])
152 def handle_reg_0x06(self, b): # Year (0-99)
153 self.putd(7, 0, [6, ['Year', 'Y']])
154 y = self.years = bcd2int(b & 0xff)
156 self.putd(7, 0, [19, ['Year: %d' % y, 'Y: %d' % y, 'Y']])
158 def handle_reg_0x07(self, b): # Control Register
159 self.putd(7, 0, [7, ['Control', 'Ctrl', 'C']])
160 for i in (6, 5, 3, 2):
162 o = 1 if (b & (1 << 7)) else 0
163 s = 1 if (b & (1 << 4)) else 0
164 s2 = 'en' if (b & (1 << 4)) else 'dis'
166 self.putd(7, 7, [20, ['Output control: %d' % o,
167 'OUT: %d' % o, 'O: %d' % o, 'O']])
168 self.putd(4, 4, [21, ['Square wave output: %sabled' % s2,
169 'SQWE: %sabled' % s2, 'SQWE: %d' % s, 'S: %d' % s, 'S']])
170 self.putd(1, 0, [22, ['Square wave output rate: %s' % r,
171 'Square wave rate: %s' % r, 'SQW rate: %s' % r, 'Rate: %s' % r,
172 'RS: %s' % s, 'RS', 'R']])
174 def handle_reg_0x3f(self, b): # RAM (bytes 0x08-0x3f)
175 self.putd(7, 0, [8, ['RAM', 'R']])
176 self.putd(7, 0, [23, ['SRAM: 0x%02X' % b, '0x%02X' % b]])
178 def output_datetime(self, cls, rw):
179 # TODO: Handle read/write of only parts of these items.
180 d = '%s, %02d.%02d.%4d %02d:%02d:%02d' % (
181 days_of_week[self.days - 1], self.date, self.months,
182 self.years, self.hours, self.minutes, self.seconds)
183 self.put(self.ss_block, self.es, self.out_ann,
184 [cls, ['%s date/time: %s' % (rw, d)]])
186 def handle_reg(self, b):
187 r = self.reg if self.reg < 8 else 0x3f
188 fn = getattr(self, 'handle_reg_0x%02x' % r)
190 # Honor address auto-increment feature of the DS1307. When the
191 # address reaches 0x3f, it will wrap around to address 0.
196 def is_correct_chip(self, addr):
197 if addr == DS1307_I2C_ADDRESS:
199 self.put(self.ss_block, self.es, self.out_ann,
200 [28, ['Ignoring non-DS1307 data (slave 0x%02X)' % addr]])
203 def decode(self, ss, es, data):
206 # Collect the 'BITS' packet, then return. The next packet is
207 # guaranteed to belong to these bits we just stored.
212 # Store the start/end samples of this I²C packet.
213 self.ss, self.es = ss, es
216 if self.state == 'IDLE':
217 # Wait for an I²C START condition.
220 self.state = 'GET SLAVE ADDR'
222 elif self.state == 'GET SLAVE ADDR':
223 # Wait for an address write operation.
224 if cmd != 'ADDRESS WRITE':
226 if not self.is_correct_chip(databyte):
229 self.state = 'GET REG ADDR'
230 elif self.state == 'GET REG ADDR':
231 # Wait for a data write (master selects the slave register).
232 if cmd != 'DATA WRITE':
235 self.state = 'WRITE RTC REGS'
236 elif self.state == 'WRITE RTC REGS':
237 # If we see a Repeated Start here, it's an RTC read.
238 if cmd == 'START REPEAT':
239 self.state = 'READ RTC REGS'
241 # Otherwise: Get data bytes until a STOP condition occurs.
242 if cmd == 'DATA WRITE':
243 self.handle_reg(databyte)
245 self.output_datetime(25, 'Written')
247 elif self.state == 'READ RTC REGS':
248 # Wait for an address read operation.
249 if cmd != 'ADDRESS READ':
251 if not self.is_correct_chip(databyte):
254 self.state = 'READ RTC REGS2'
255 elif self.state == 'READ RTC REGS2':
256 if cmd == 'DATA READ':
257 self.handle_reg(databyte)
259 self.output_datetime(24, 'Read')