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, write to the Free Software
19 ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23 import sigrokdecode as srd
24 from common.srdhelper import bcd2int
27 'Sunday', 'Monday', 'Tuesday', 'Wednesday',
28 'Thursday', 'Friday', 'Saturday',
32 'Seconds', 'Minutes', 'Hours', 'Day', 'Date', 'Month', 'Year',
37 'Clock halt', 'Seconds', 'Reserved', 'Minutes', '12/24 hours', 'AM/PM',
38 'Hours', 'Day', 'Date', 'Month', 'Year', 'OUT', 'SQWE', 'RS', 'RAM',
48 DS1307_I2C_ADDRESS = 0x68
51 l = [('reg-' + r.lower(), r + ' register') for r in regs]
52 l += [('bit-' + re.sub('\/| ', '-', b).lower(), b + ' bit') for b in bits]
55 class Decoder(srd.Decoder):
59 longname = 'Dallas DS1307'
60 desc = 'Realtime clock module protocol.'
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,)),
90 self.out_ann = self.register(srd.OUTPUT_ANN)
93 self.put(self.ss, self.es, self.out_ann, data)
95 def putd(self, bit1, bit2, data):
96 self.put(self.bits[bit1][1], self.bits[bit2][2], self.out_ann, data)
99 self.put(self.bits[bit][1], self.bits[bit][2], self.out_ann,
100 [11, ['Reserved bit', 'Reserved', 'Rsvd', 'R']])
102 def handle_reg_0x00(self, b): # Seconds (0-59) / Clock halt bit
103 self.putd(7, 0, [0, ['Seconds', 'Sec', 'S']])
104 ch = 1 if (b & (1 << 7)) else 0
105 self.putd(7, 7, [9, ['Clock halt: %d' % ch, 'Clk hlt: %d' % ch,
106 'CH: %d' % ch, 'CH']])
107 s = self.seconds = bcd2int(b & 0x7f)
108 self.putd(6, 0, [10, ['Second: %d' % s, 'Sec: %d' % s, 'S: %d' % s, 'S']])
110 def handle_reg_0x01(self, b): # Minutes (0-59)
111 self.putd(7, 0, [1, ['Minutes', 'Min', 'M']])
113 m = self.minutes = bcd2int(b & 0x7f)
114 self.putd(6, 0, [12, ['Minute: %d' % m, 'Min: %d' % m, 'M: %d' % m, 'M']])
116 def handle_reg_0x02(self, b): # Hours (1-12+AM/PM or 0-23)
117 self.putd(7, 0, [2, ['Hours', 'H']])
119 ampm_mode = True if (b & (1 << 6)) else False
121 self.putd(6, 6, [13, ['12-hour mode', '12h mode', '12h']])
122 a = 'AM' if (b & (1 << 6)) else 'PM'
123 self.putd(5, 5, [14, [a, a[0]]])
124 h = self.hours = bcd2int(b & 0x1f)
125 self.putd(4, 0, [15, ['Hour: %d' % h, 'H: %d' % h, 'H']])
127 self.putd(6, 6, [13, ['24-hour mode', '24h mode', '24h']])
128 h = self.hours = bcd2int(b & 0x3f)
129 self.putd(5, 0, [15, ['Hour: %d' % h, 'H: %d' % h, 'H']])
131 def handle_reg_0x03(self, b): # Day / day of week (1-7)
132 self.putd(7, 0, [3, ['Day of week', 'Day', 'D']])
133 for i in (7, 6, 5, 4, 3):
135 w = self.days = bcd2int(b & 0x07)
136 ws = days_of_week[self.days - 1]
137 self.putd(2, 0, [16, ['Weekday: %s' % ws, 'WD: %s' % ws, 'WD', 'W']])
139 def handle_reg_0x04(self, b): # Date (1-31)
140 self.putd(7, 0, [4, ['Date', 'D']])
143 d = self.date = bcd2int(b & 0x3f)
144 self.putd(5, 0, [17, ['Date: %d' % d, 'D: %d' % d, 'D']])
146 def handle_reg_0x05(self, b): # Month (1-12)
147 self.putd(7, 0, [5, ['Month', 'Mon', 'M']])
150 m = self.months = bcd2int(b & 0x1f)
151 self.putd(4, 0, [18, ['Month: %d' % m, 'Mon: %d' % m, 'M: %d' % m, 'M']])
153 def handle_reg_0x06(self, b): # Year (0-99)
154 self.putd(7, 0, [6, ['Year', 'Y']])
155 y = self.years = bcd2int(b & 0xff)
157 self.putd(7, 0, [19, ['Year: %d' % y, 'Y: %d' % y, 'Y']])
159 def handle_reg_0x07(self, b): # Control Register
160 self.putd(7, 0, [7, ['Control', 'Ctrl', 'C']])
161 for i in (6, 5, 3, 2):
163 o = 1 if (b & (1 << 7)) else 0
164 s = 1 if (b & (1 << 4)) else 0
165 s2 = 'en' if (b & (1 << 4)) else 'dis'
167 self.putd(7, 7, [20, ['Output control: %d' % o,
168 'OUT: %d' % o, 'O: %d' % o, 'O']])
169 self.putd(4, 4, [21, ['Square wave output: %sabled' % s2,
170 'SQWE: %sabled' % s2, 'SQWE: %d' % s, 'S: %d' % s, 'S']])
171 self.putd(1, 0, [22, ['Square wave output rate: %s' % r,
172 'Square wave rate: %s' % r, 'SQW rate: %s' % r, 'Rate: %s' % r,
173 'RS: %s' % s, 'RS', 'R']])
175 def handle_reg_0x3f(self, b): # RAM (bytes 0x08-0x3f)
176 self.putd(7, 0, [8, ['RAM', 'R']])
177 self.putd(7, 0, [23, ['SRAM: 0x%02X' % b, '0x%02X' % b]])
179 def output_datetime(self, cls, rw):
180 # TODO: Handle read/write of only parts of these items.
181 d = '%s, %02d.%02d.%4d %02d:%02d:%02d' % (
182 days_of_week[self.days - 1], self.date, self.months,
183 self.years, self.hours, self.minutes, self.seconds)
184 self.put(self.ss_block, self.es, self.out_ann,
185 [cls, ['%s date/time: %s' % (rw, d)]])
187 def handle_reg(self, b):
188 r = self.reg if self.reg < 8 else 0x3f
189 fn = getattr(self, 'handle_reg_0x%02x' % r)
191 # Honor address auto-increment feature of the DS1307. When the
192 # address reaches 0x3f, it will wrap around to address 0.
197 def is_correct_chip(self, addr):
198 if addr == DS1307_I2C_ADDRESS:
200 self.put(self.ss_block, self.es, self.out_ann,
201 [28, ['Ignoring non-DS1307 data (slave 0x%02X)' % addr]])
204 def decode(self, ss, es, data):
207 # Collect the 'BITS' packet, then return. The next packet is
208 # guaranteed to belong to these bits we just stored.
213 # Store the start/end samples of this I²C packet.
214 self.ss, self.es = ss, es
217 if self.state == 'IDLE':
218 # Wait for an I²C START condition.
221 self.state = 'GET SLAVE ADDR'
223 elif self.state == 'GET SLAVE ADDR':
224 # Wait for an address write operation.
225 if cmd != 'ADDRESS WRITE':
227 if not self.is_correct_chip(databyte):
230 self.state = 'GET REG ADDR'
231 elif self.state == 'GET REG ADDR':
232 # Wait for a data write (master selects the slave register).
233 if cmd != 'DATA WRITE':
236 self.state = 'WRITE RTC REGS'
237 elif self.state == 'WRITE RTC REGS':
238 # If we see a Repeated Start here, it's an RTC read.
239 if cmd == 'START REPEAT':
240 self.state = 'READ RTC REGS'
242 # Otherwise: Get data bytes until a STOP condition occurs.
243 if cmd == 'DATA WRITE':
244 self.handle_reg(databyte)
246 self.output_datetime(25, 'Written')
248 elif self.state == 'READ RTC REGS':
249 # Wait for an address read operation.
250 if cmd != 'ADDRESS READ':
252 if not self.is_correct_chip(databyte):
255 self.state = 'READ RTC REGS2'
256 elif self.state == 'READ RTC REGS2':
257 if cmd == 'DATA READ':
258 self.handle_reg(databyte)
260 self.output_datetime(24, 'Read')