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,)),
92 self.out_ann = self.register(srd.OUTPUT_ANN)
95 self.put(self.ss, self.es, self.out_ann, data)
97 def putd(self, bit1, bit2, data):
98 self.put(self.bits[bit1][1], self.bits[bit2][2], self.out_ann, data)
101 self.put(self.bits[bit][1], self.bits[bit][2], self.out_ann,
102 [11, ['Reserved bit', 'Reserved', 'Rsvd', 'R']])
104 def handle_reg_0x00(self, b): # Seconds (0-59) / Clock halt bit
105 self.putd(7, 0, [0, ['Seconds', 'Sec', 'S']])
106 ch = 1 if (b & (1 << 7)) else 0
107 self.putd(7, 7, [9, ['Clock halt: %d' % ch, 'Clk hlt: %d' % ch,
108 'CH: %d' % ch, 'CH']])
109 s = self.seconds = bcd2int(b & 0x7f)
110 self.putd(6, 0, [10, ['Second: %d' % s, 'Sec: %d' % s, 'S: %d' % s, 'S']])
112 def handle_reg_0x01(self, b): # Minutes (0-59)
113 self.putd(7, 0, [1, ['Minutes', 'Min', 'M']])
115 m = self.minutes = bcd2int(b & 0x7f)
116 self.putd(6, 0, [12, ['Minute: %d' % m, 'Min: %d' % m, 'M: %d' % m, 'M']])
118 def handle_reg_0x02(self, b): # Hours (1-12+AM/PM or 0-23)
119 self.putd(7, 0, [2, ['Hours', 'H']])
121 ampm_mode = True if (b & (1 << 6)) else False
123 self.putd(6, 6, [13, ['12-hour mode', '12h mode', '12h']])
124 a = 'AM' if (b & (1 << 6)) else 'PM'
125 self.putd(5, 5, [14, [a, a[0]]])
126 h = self.hours = bcd2int(b & 0x1f)
127 self.putd(4, 0, [15, ['Hour: %d' % h, 'H: %d' % h, 'H']])
129 self.putd(6, 6, [13, ['24-hour mode', '24h mode', '24h']])
130 h = self.hours = bcd2int(b & 0x3f)
131 self.putd(5, 0, [15, ['Hour: %d' % h, 'H: %d' % h, 'H']])
133 def handle_reg_0x03(self, b): # Day / day of week (1-7)
134 self.putd(7, 0, [3, ['Day of week', 'Day', 'D']])
135 for i in (7, 6, 5, 4, 3):
137 w = self.days = bcd2int(b & 0x07)
138 ws = days_of_week[self.days - 1]
139 self.putd(2, 0, [16, ['Weekday: %s' % ws, 'WD: %s' % ws, 'WD', 'W']])
141 def handle_reg_0x04(self, b): # Date (1-31)
142 self.putd(7, 0, [4, ['Date', 'D']])
145 d = self.date = bcd2int(b & 0x3f)
146 self.putd(5, 0, [17, ['Date: %d' % d, 'D: %d' % d, 'D']])
148 def handle_reg_0x05(self, b): # Month (1-12)
149 self.putd(7, 0, [5, ['Month', 'Mon', 'M']])
152 m = self.months = bcd2int(b & 0x1f)
153 self.putd(4, 0, [18, ['Month: %d' % m, 'Mon: %d' % m, 'M: %d' % m, 'M']])
155 def handle_reg_0x06(self, b): # Year (0-99)
156 self.putd(7, 0, [6, ['Year', 'Y']])
157 y = self.years = bcd2int(b & 0xff)
159 self.putd(7, 0, [19, ['Year: %d' % y, 'Y: %d' % y, 'Y']])
161 def handle_reg_0x07(self, b): # Control Register
162 self.putd(7, 0, [7, ['Control', 'Ctrl', 'C']])
163 for i in (6, 5, 3, 2):
165 o = 1 if (b & (1 << 7)) else 0
166 s = 1 if (b & (1 << 4)) else 0
167 s2 = 'en' if (b & (1 << 4)) else 'dis'
169 self.putd(7, 7, [20, ['Output control: %d' % o,
170 'OUT: %d' % o, 'O: %d' % o, 'O']])
171 self.putd(4, 4, [21, ['Square wave output: %sabled' % s2,
172 'SQWE: %sabled' % s2, 'SQWE: %d' % s, 'S: %d' % s, 'S']])
173 self.putd(1, 0, [22, ['Square wave output rate: %s' % r,
174 'Square wave rate: %s' % r, 'SQW rate: %s' % r, 'Rate: %s' % r,
175 'RS: %s' % s, 'RS', 'R']])
177 def handle_reg_0x3f(self, b): # RAM (bytes 0x08-0x3f)
178 self.putd(7, 0, [8, ['RAM', 'R']])
179 self.putd(7, 0, [23, ['SRAM: 0x%02X' % b, '0x%02X' % b]])
181 def output_datetime(self, cls, rw):
182 # TODO: Handle read/write of only parts of these items.
183 d = '%s, %02d.%02d.%4d %02d:%02d:%02d' % (
184 days_of_week[self.days - 1], self.date, self.months,
185 self.years, self.hours, self.minutes, self.seconds)
186 self.put(self.ss_block, self.es, self.out_ann,
187 [cls, ['%s date/time: %s' % (rw, d)]])
189 def handle_reg(self, b):
190 r = self.reg if self.reg < 8 else 0x3f
191 fn = getattr(self, 'handle_reg_0x%02x' % r)
193 # Honor address auto-increment feature of the DS1307. When the
194 # address reaches 0x3f, it will wrap around to address 0.
199 def is_correct_chip(self, addr):
200 if addr == DS1307_I2C_ADDRESS:
202 self.put(self.ss_block, self.es, self.out_ann,
203 [28, ['Ignoring non-DS1307 data (slave 0x%02X)' % addr]])
206 def decode(self, ss, es, data):
209 # Collect the 'BITS' packet, then return. The next packet is
210 # guaranteed to belong to these bits we just stored.
215 # Store the start/end samples of this I²C packet.
216 self.ss, self.es = ss, es
219 if self.state == 'IDLE':
220 # Wait for an I²C START condition.
223 self.state = 'GET SLAVE ADDR'
225 elif self.state == 'GET SLAVE ADDR':
226 # Wait for an address write operation.
227 if cmd != 'ADDRESS WRITE':
229 if not self.is_correct_chip(databyte):
232 self.state = 'GET REG ADDR'
233 elif self.state == 'GET REG ADDR':
234 # Wait for a data write (master selects the slave register).
235 if cmd != 'DATA WRITE':
238 self.state = 'WRITE RTC REGS'
239 elif self.state == 'WRITE RTC REGS':
240 # If we see a Repeated Start here, it's an RTC read.
241 if cmd == 'START REPEAT':
242 self.state = 'READ RTC REGS'
244 # Otherwise: Get data bytes until a STOP condition occurs.
245 if cmd == 'DATA WRITE':
246 self.handle_reg(databyte)
248 self.output_datetime(25, 'Written')
250 elif self.state == 'READ RTC REGS':
251 # Wait for an address read operation.
252 if cmd != 'ADDRESS READ':
254 if not self.is_correct_chip(databyte):
257 self.state = 'READ RTC REGS2'
258 elif self.state == 'READ RTC REGS2':
259 if cmd == 'DATA READ':
260 self.handle_reg(databyte)
262 self.output_datetime(24, 'Read')