2 ## This file is part of the libsigrokdecode project.
4 ## Copyright (C) 2012-2020 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, SrdIntEnum
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 a = ['REG_' + r.upper() for r in regs] + \
55 ['BIT_' + re.sub('\/| ', '_', b).upper() for b in bits] + \
56 ['READ_DATE_TIME', 'WRITE_DATE_TIME', 'READ_REG', 'WRITE_REG', 'WARNING']
57 Ann = SrdIntEnum.from_list('Ann', a)
59 class Decoder(srd.Decoder):
63 longname = 'Dallas DS1307'
64 desc = 'Dallas DS1307 realtime clock module protocol.'
68 tags = ['Clock/timing', 'IC']
69 annotations = regs_and_bits() + (
70 ('read_date_time', 'Read date/time'),
71 ('write_date_time', 'Write date/time'),
72 ('read_reg', 'Register read'),
73 ('write_reg', 'Register write'),
74 ('warning', 'Warning'),
77 ('bits', 'Bits', Ann.prefixes('BIT_')),
78 ('regs', 'Registers', Ann.prefixes('REG_')),
79 ('date_time', 'Date/time', Ann.prefixes('READ_ WRITE_')),
80 ('warnings', 'Warnings', (Ann.WARNING,)),
98 self.out_ann = self.register(srd.OUTPUT_ANN)
100 def putx(self, data):
101 self.put(self.ss, self.es, self.out_ann, data)
103 def putd(self, bit1, bit2, data):
104 self.put(self.bits[bit1][1], self.bits[bit2][2], self.out_ann, data)
107 self.put(self.bits[bit][1], self.bits[bit][2], self.out_ann,
108 [Ann.BIT_RESERVED, ['Reserved bit', 'Reserved', 'Rsvd', 'R']])
110 def handle_reg_0x00(self, b): # Seconds (0-59) / Clock halt bit
111 self.putd(7, 0, [Ann.REG_SECONDS, ['Seconds', 'Sec', 'S']])
112 ch = 1 if (b & (1 << 7)) else 0
113 self.putd(7, 7, [Ann.BIT_CLOCK_HALT, ['Clock halt: %d' % ch,
114 'Clk hlt: %d' % ch, 'CH: %d' % ch, 'CH']])
115 s = self.seconds = bcd2int(b & 0x7f)
116 self.putd(6, 0, [Ann.BIT_SECONDS, ['Second: %d' % s, 'Sec: %d' % s,
119 def handle_reg_0x01(self, b): # Minutes (0-59)
120 self.putd(7, 0, [Ann.REG_MINUTES, ['Minutes', 'Min', 'M']])
122 m = self.minutes = bcd2int(b & 0x7f)
123 self.putd(6, 0, [Ann.BIT_MINUTES, ['Minute: %d' % m, 'Min: %d' % m, 'M: %d' % m, 'M']])
125 def handle_reg_0x02(self, b): # Hours (1-12+AM/PM or 0-23)
126 self.putd(7, 0, [Ann.REG_HOURS, ['Hours', 'H']])
128 ampm_mode = True if (b & (1 << 6)) else False
130 self.putd(6, 6, [Ann.BIT_12_24_HOURS, ['12-hour mode', '12h mode', '12h']])
131 a = 'PM' if (b & (1 << 5)) else 'AM'
132 self.putd(5, 5, [Ann.BIT_AM_PM, [a, a[0]]])
133 h = self.hours = bcd2int(b & 0x1f)
134 self.putd(4, 0, [Ann.BIT_HOURS, ['Hour: %d' % h, 'H: %d' % h, 'H']])
136 self.putd(6, 6, [Ann.BIT_12_24_HOURS, ['24-hour mode', '24h mode', '24h']])
137 h = self.hours = bcd2int(b & 0x3f)
138 self.putd(5, 0, [Ann.BIT_HOURS, ['Hour: %d' % h, 'H: %d' % h, 'H']])
140 def handle_reg_0x03(self, b): # Day / day of week (1-7)
141 self.putd(7, 0, [Ann.REG_DAY, ['Day of week', 'Day', 'D']])
142 for i in (7, 6, 5, 4, 3):
144 w = self.days = bcd2int(b & 0x07)
145 ws = days_of_week[self.days - 1]
146 self.putd(2, 0, [Ann.BIT_DAY, ['Weekday: %s' % ws, 'WD: %s' % ws, 'WD', 'W']])
148 def handle_reg_0x04(self, b): # Date (1-31)
149 self.putd(7, 0, [Ann.REG_DATE, ['Date', 'D']])
152 d = self.date = bcd2int(b & 0x3f)
153 self.putd(5, 0, [Ann.BIT_DATE, ['Date: %d' % d, 'D: %d' % d, 'D']])
155 def handle_reg_0x05(self, b): # Month (1-12)
156 self.putd(7, 0, [Ann.REG_MONTH, ['Month', 'Mon', 'M']])
159 m = self.months = bcd2int(b & 0x1f)
160 self.putd(4, 0, [Ann.BIT_MONTH, ['Month: %d' % m, 'Mon: %d' % m, 'M: %d' % m, 'M']])
162 def handle_reg_0x06(self, b): # Year (0-99)
163 self.putd(7, 0, [Ann.REG_YEAR, ['Year', 'Y']])
164 y = self.years = bcd2int(b & 0xff)
166 self.putd(7, 0, [Ann.BIT_YEAR, ['Year: %d' % y, 'Y: %d' % y, 'Y']])
168 def handle_reg_0x07(self, b): # Control Register
169 self.putd(7, 0, [Ann.REG_CONTROL, ['Control', 'Ctrl', 'C']])
170 for i in (6, 5, 3, 2):
172 o = 1 if (b & (1 << 7)) else 0
173 s = 1 if (b & (1 << 4)) else 0
174 s2 = 'en' if (b & (1 << 4)) else 'dis'
176 self.putd(7, 7, [Ann.BIT_OUT, ['Output control: %d' % o,
177 'OUT: %d' % o, 'O: %d' % o, 'O']])
178 self.putd(4, 4, [Ann.BIT_SQWE, ['Square wave output: %sabled' % s2,
179 'SQWE: %sabled' % s2, 'SQWE: %d' % s, 'S: %d' % s, 'S']])
180 self.putd(1, 0, [Ann.BIT_RS, ['Square wave output rate: %s' % r,
181 'Square wave rate: %s' % r, 'SQW rate: %s' % r, 'Rate: %s' % r,
182 'RS: %s' % s, 'RS', 'R']])
184 def handle_reg_0x3f(self, b): # RAM (bytes 0x08-0x3f)
185 self.putd(7, 0, [Ann.REG_RAM, ['RAM', 'R']])
186 self.putd(7, 0, [Ann.BIT_RAM, ['SRAM: 0x%02X' % b, '0x%02X' % b]])
188 def output_datetime(self, cls, rw):
189 # TODO: Handle read/write of only parts of these items.
190 d = '%s, %02d.%02d.%4d %02d:%02d:%02d' % (
191 days_of_week[self.days - 1], self.date, self.months,
192 self.years, self.hours, self.minutes, self.seconds)
193 self.put(self.ss_block, self.es, self.out_ann,
194 [cls, ['%s date/time: %s' % (rw, d)]])
196 def handle_reg(self, b):
197 r = self.reg if self.reg < 8 else 0x3f
198 fn = getattr(self, 'handle_reg_0x%02x' % r)
200 # Honor address auto-increment feature of the DS1307. When the
201 # address reaches 0x3f, it will wrap around to address 0.
206 def is_correct_chip(self, addr):
207 if addr == DS1307_I2C_ADDRESS:
209 self.put(self.ss_block, self.es, self.out_ann,
210 [Ann.WARNING, ['Ignoring non-DS1307 data (slave 0x%02X)' % addr]])
213 def decode(self, ss, es, data):
216 # Collect the 'BITS' packet, then return. The next packet is
217 # guaranteed to belong to these bits we just stored.
222 # Store the start/end samples of this I²C packet.
223 self.ss, self.es = ss, es
226 if self.state == 'IDLE':
227 # Wait for an I²C START condition.
230 self.state = 'GET SLAVE ADDR'
232 elif self.state == 'GET SLAVE ADDR':
233 # Wait for an address write operation.
234 if cmd != 'ADDRESS WRITE':
236 if not self.is_correct_chip(databyte):
239 self.state = 'GET REG ADDR'
240 elif self.state == 'GET REG ADDR':
241 # Wait for a data write (master selects the slave register).
242 if cmd != 'DATA WRITE':
245 self.state = 'WRITE RTC REGS'
246 elif self.state == 'WRITE RTC REGS':
247 # If we see a Repeated Start here, it's an RTC read.
248 if cmd == 'START REPEAT':
249 self.state = 'READ RTC REGS'
251 # Otherwise: Get data bytes until a STOP condition occurs.
252 if cmd == 'DATA WRITE':
253 self.handle_reg(databyte)
255 self.output_datetime(Ann.WRITE_DATE_TIME, 'Written')
257 elif self.state == 'READ RTC REGS':
258 # Wait for an address read operation.
259 if cmd != 'ADDRESS READ':
261 if not self.is_correct_chip(databyte):
264 self.state = 'READ RTC REGS2'
265 elif self.state == 'READ RTC REGS2':
266 if cmd == 'DATA READ':
267 self.handle_reg(databyte)
269 self.output_datetime(Ann.READ_DATE_TIME, 'Read')