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 = 'Dallas DS1307 realtime clock module protocol.'
63 tags = ['Clock/timing', 'IC']
64 annotations = regs_and_bits() + (
65 ('read-datetime', 'Read date/time'),
66 ('write-datetime', 'Write date/time'),
67 ('reg-read', 'Register read'),
68 ('reg-write', 'Register write'),
69 ('warnings', 'Warnings'),
72 ('bits', 'Bits', tuple(range(9, 24))),
73 ('regs', 'Registers', tuple(range(9))),
74 ('date-time', 'Date/time', (24, 25, 26, 27)),
75 ('warnings', 'Warnings', (28,)),
93 self.out_ann = self.register(srd.OUTPUT_ANN)
96 self.put(self.ss, self.es, self.out_ann, data)
98 def putd(self, bit1, bit2, data):
99 self.put(self.bits[bit1][1], self.bits[bit2][2], self.out_ann, data)
102 self.put(self.bits[bit][1], self.bits[bit][2], self.out_ann,
103 [11, ['Reserved bit', 'Reserved', 'Rsvd', 'R']])
105 def handle_reg_0x00(self, b): # Seconds (0-59) / Clock halt bit
106 self.putd(7, 0, [0, ['Seconds', 'Sec', 'S']])
107 ch = 1 if (b & (1 << 7)) else 0
108 self.putd(7, 7, [9, ['Clock halt: %d' % ch, 'Clk hlt: %d' % ch,
109 'CH: %d' % ch, 'CH']])
110 s = self.seconds = bcd2int(b & 0x7f)
111 self.putd(6, 0, [10, ['Second: %d' % s, 'Sec: %d' % s, 'S: %d' % s, 'S']])
113 def handle_reg_0x01(self, b): # Minutes (0-59)
114 self.putd(7, 0, [1, ['Minutes', 'Min', 'M']])
116 m = self.minutes = bcd2int(b & 0x7f)
117 self.putd(6, 0, [12, ['Minute: %d' % m, 'Min: %d' % m, 'M: %d' % m, 'M']])
119 def handle_reg_0x02(self, b): # Hours (1-12+AM/PM or 0-23)
120 self.putd(7, 0, [2, ['Hours', 'H']])
122 ampm_mode = True if (b & (1 << 6)) else False
124 self.putd(6, 6, [13, ['12-hour mode', '12h mode', '12h']])
125 a = 'PM' if (b & (1 << 5)) else 'AM'
126 self.putd(5, 5, [14, [a, a[0]]])
127 h = self.hours = bcd2int(b & 0x1f)
128 self.putd(4, 0, [15, ['Hour: %d' % h, 'H: %d' % h, 'H']])
130 self.putd(6, 6, [13, ['24-hour mode', '24h mode', '24h']])
131 h = self.hours = bcd2int(b & 0x3f)
132 self.putd(5, 0, [15, ['Hour: %d' % h, 'H: %d' % h, 'H']])
134 def handle_reg_0x03(self, b): # Day / day of week (1-7)
135 self.putd(7, 0, [3, ['Day of week', 'Day', 'D']])
136 for i in (7, 6, 5, 4, 3):
138 w = self.days = bcd2int(b & 0x07)
139 ws = days_of_week[self.days - 1]
140 self.putd(2, 0, [16, ['Weekday: %s' % ws, 'WD: %s' % ws, 'WD', 'W']])
142 def handle_reg_0x04(self, b): # Date (1-31)
143 self.putd(7, 0, [4, ['Date', 'D']])
146 d = self.date = bcd2int(b & 0x3f)
147 self.putd(5, 0, [17, ['Date: %d' % d, 'D: %d' % d, 'D']])
149 def handle_reg_0x05(self, b): # Month (1-12)
150 self.putd(7, 0, [5, ['Month', 'Mon', 'M']])
153 m = self.months = bcd2int(b & 0x1f)
154 self.putd(4, 0, [18, ['Month: %d' % m, 'Mon: %d' % m, 'M: %d' % m, 'M']])
156 def handle_reg_0x06(self, b): # Year (0-99)
157 self.putd(7, 0, [6, ['Year', 'Y']])
158 y = self.years = bcd2int(b & 0xff)
160 self.putd(7, 0, [19, ['Year: %d' % y, 'Y: %d' % y, 'Y']])
162 def handle_reg_0x07(self, b): # Control Register
163 self.putd(7, 0, [7, ['Control', 'Ctrl', 'C']])
164 for i in (6, 5, 3, 2):
166 o = 1 if (b & (1 << 7)) else 0
167 s = 1 if (b & (1 << 4)) else 0
168 s2 = 'en' if (b & (1 << 4)) else 'dis'
170 self.putd(7, 7, [20, ['Output control: %d' % o,
171 'OUT: %d' % o, 'O: %d' % o, 'O']])
172 self.putd(4, 4, [21, ['Square wave output: %sabled' % s2,
173 'SQWE: %sabled' % s2, 'SQWE: %d' % s, 'S: %d' % s, 'S']])
174 self.putd(1, 0, [22, ['Square wave output rate: %s' % r,
175 'Square wave rate: %s' % r, 'SQW rate: %s' % r, 'Rate: %s' % r,
176 'RS: %s' % s, 'RS', 'R']])
178 def handle_reg_0x3f(self, b): # RAM (bytes 0x08-0x3f)
179 self.putd(7, 0, [8, ['RAM', 'R']])
180 self.putd(7, 0, [23, ['SRAM: 0x%02X' % b, '0x%02X' % b]])
182 def output_datetime(self, cls, rw):
183 # TODO: Handle read/write of only parts of these items.
184 d = '%s, %02d.%02d.%4d %02d:%02d:%02d' % (
185 days_of_week[self.days - 1], self.date, self.months,
186 self.years, self.hours, self.minutes, self.seconds)
187 self.put(self.ss_block, self.es, self.out_ann,
188 [cls, ['%s date/time: %s' % (rw, d)]])
190 def handle_reg(self, b):
191 r = self.reg if self.reg < 8 else 0x3f
192 fn = getattr(self, 'handle_reg_0x%02x' % r)
194 # Honor address auto-increment feature of the DS1307. When the
195 # address reaches 0x3f, it will wrap around to address 0.
200 def is_correct_chip(self, addr):
201 if addr == DS1307_I2C_ADDRESS:
203 self.put(self.ss_block, self.es, self.out_ann,
204 [28, ['Ignoring non-DS1307 data (slave 0x%02X)' % addr]])
207 def decode(self, ss, es, data):
210 # Collect the 'BITS' packet, then return. The next packet is
211 # guaranteed to belong to these bits we just stored.
216 # Store the start/end samples of this I²C packet.
217 self.ss, self.es = ss, es
220 if self.state == 'IDLE':
221 # Wait for an I²C START condition.
224 self.state = 'GET SLAVE ADDR'
226 elif self.state == 'GET SLAVE ADDR':
227 # Wait for an address write operation.
228 if cmd != 'ADDRESS WRITE':
230 if not self.is_correct_chip(databyte):
233 self.state = 'GET REG ADDR'
234 elif self.state == 'GET REG ADDR':
235 # Wait for a data write (master selects the slave register).
236 if cmd != 'DATA WRITE':
239 self.state = 'WRITE RTC REGS'
240 elif self.state == 'WRITE RTC REGS':
241 # If we see a Repeated Start here, it's an RTC read.
242 if cmd == 'START REPEAT':
243 self.state = 'READ RTC REGS'
245 # Otherwise: Get data bytes until a STOP condition occurs.
246 if cmd == 'DATA WRITE':
247 self.handle_reg(databyte)
249 self.output_datetime(25, 'Written')
251 elif self.state == 'READ RTC REGS':
252 # Wait for an address read operation.
253 if cmd != 'ADDRESS READ':
255 if not self.is_correct_chip(databyte):
258 self.state = 'READ RTC REGS2'
259 elif self.state == 'READ RTC REGS2':
260 if cmd == 'DATA READ':
261 self.handle_reg(databyte)
263 self.output_datetime(24, 'Read')