73269a6daf67979c3c8e71282c828d4326167253
[libsigrokdecode.git] / decoders / eeprom24xx / pd.py
1 ##
2 ## This file is part of the libsigrokdecode project.
3 ##
4 ## Copyright (C) 2014 Uwe Hermann <uwe@hermann-uwe.de>
5 ##
6 ## This program is free software; you can redistribute it and/or modify
7 ## it under the terms of the GNU General Public License as published by
8 ## the Free Software Foundation; either version 2 of the License, or
9 ## (at your option) any later version.
10 ##
11 ## This program is distributed in the hope that it will be useful,
12 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 ## GNU General Public License for more details.
15 ##
16 ## You should have received a copy of the GNU General Public License
17 ## along with this program; if not, write to the Free Software
18 ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
19 ##
20
21 import sigrokdecode as srd
22 from .lists import *
23
24 class Decoder(srd.Decoder):
25     api_version = 2
26     id = 'eeprom24xx'
27     name = '24xx EEPROM'
28     longname = '24xx I²C EEPROM'
29     desc = '24xx series I²C EEPROM protocol.'
30     license = 'gplv2+'
31     inputs = ['i2c']
32     outputs = ['eeprom24xx']
33     options = (
34         {'id': 'chip', 'desc': 'Chip', 'default': 'generic',
35             'values': tuple(chips.keys())},
36         {'id': 'addr_counter', 'desc': 'Initial address counter value',
37             'default': 0},
38     )
39     annotations = (
40         # Warnings
41         ('warnings', 'Warnings'),
42         # Bits/bytes
43         ('control-code', 'Control code'),
44         ('address-pin', 'Address pin (A0/A1/A2)'),
45         ('rw-bit', 'Read/write bit'),
46         ('word-addr-byte', 'Word address byte'),
47         ('data-byte', 'Data byte'),
48         # Fields
49         ('control-word', 'Control word'),
50         ('word-addr', 'Word address'),
51         ('data', 'Data'),
52         # Operations
53         ('byte-write', 'Byte write'),
54         ('page-write', 'Page write'),
55         ('cur-addr-read', 'Current address read'),
56         ('random-read', 'Random read'),
57         ('seq-random-read', 'Sequential random read'),
58         ('seq-cur-addr-read', 'Sequential current address read'),
59         ('ack-polling', 'Acknowledge polling'),
60         ('set-bank-addr', 'Set bank address'), # SBA. Only 34AA04.
61         ('read-bank-addr', 'Read bank address'), # RBA. Only 34AA04.
62         ('set-wp', 'Set write protection'), # SWP
63         ('clear-all-wp', 'Clear all write protection'), # CWP
64         ('read-wp', 'Read write protection status'), # RPS
65     )
66     annotation_rows = (
67         ('bits-bytes', 'Bits/bytes', (1, 2, 3, 4, 5)),
68         ('fields', 'Fields', (6, 7, 8)),
69         ('ops', 'Operations', tuple(range(9, 21))),
70         ('warnings', 'Warnings', (0,)),
71     )
72     binary = (
73         ('binary', 'Binary'),
74     )
75
76     def __init__(self):
77         self.reset()
78
79     def start(self):
80         self.out_ann = self.register(srd.OUTPUT_ANN)
81         self.out_binary = self.register(srd.OUTPUT_BINARY)
82         self.chip = chips[self.options['chip']]
83         self.addr_counter = self.options['addr_counter']
84
85     def putb(self, data):
86         self.put(self.ss_block, self.es_block, self.out_ann, data)
87
88     def putbin(self, data):
89         self.put(self.ss_block, self.es_block, self.out_binary, data)
90
91     def putbits(self, bit1, bit2, bits, data):
92         self.put(bits[bit1][1], bits[bit2][2], self.out_ann, data)
93
94     def reset(self):
95         self.state = 'WAIT FOR START'
96         self.packets = []
97         self.bytebuf = []
98         self.is_cur_addr_read = False
99         self.is_random_access_read = False
100         self.is_seq_random_read = False
101         self.is_byte_write = False
102         self.is_page_write = False
103
104     def packet_append(self):
105         self.packets.append([self.ss, self.es, self.cmd, self.databyte, self.bits])
106         if self.cmd in ('DATA READ', 'DATA WRITE'):
107             self.bytebuf.append(self.databyte)
108
109     def hexbytes(self, idx):
110         return ' '.join(['%02X' % b for b in self.bytebuf[idx:]])
111
112     def put_control_word(self, bits):
113         s = ''.join(['%d' % b[0] for b in reversed(bits[4:])])
114         self.putbits(7, 4, bits, [1, ['Control code bits: ' + s,
115             'Control code: ' + s, 'Ctrl code: ' + s, 'Ctrl code', 'Ctrl', 'C']])
116         for i in reversed(range(self.chip['addr_pins'])):
117             self.putbits(i + 1, i + 1, bits,
118                 [2, ['Address bit %d: %d' % (i, bits[i + 1][0]),
119                      'Addr bit %d' % i, 'A%d' % i, 'A']])
120         s1 = 'read' if bits[0][0] == 1 else 'write'
121         s2 = 'R' if bits[0][0] == 1 else 'W'
122         self.putbits(0, 0, bits, [3, ['R/W bit: ' + s1, 'R/W', 'RW', s2]])
123         self.putbits(7, 0, bits, [6, ['Control word', 'Control', 'CW', 'C']])
124
125     def put_word_addr(self, p):
126         if self.chip['addr_bytes'] == 1:
127             a = p[1][3]
128             self.put(p[1][0], p[1][1], self.out_ann,
129                 [4, ['Word address byte: %02X' % a, 'Word addr byte: %02X' % a,
130                      'Addr: %02X' % a, 'A: %02X' % a, '%02X' % a]])
131             self.put(p[1][0], p[1][1], self.out_ann, [7, ['Word address',
132                      'Word addr', 'Addr', 'A']])
133             self.addr_counter = a
134         else:
135             a = p[1][3]
136             self.put(p[1][0], p[1][1], self.out_ann,
137                 [4, ['Word address high byte: %02X' % a,
138                      'Word addr high byte: %02X' % a,
139                      'Addr high: %02X' % a, 'AH: %02X' % a, '%02X' % a]])
140             a = p[2][3]
141             self.put(p[2][0], p[2][1], self.out_ann,
142                 [4, ['Word address low byte: %02X' % a,
143                      'Word addr low byte: %02X' % a,
144                      'Addr low: %02X' % a, 'AL: %02X' % a, '%02X' % a]])
145             self.put(p[1][0], p[2][1], self.out_ann, [7, ['Word address',
146                      'Word addr', 'Addr', 'A']])
147             self.addr_counter = (p[1][3] << 8) | p[2][3]
148
149     def put_data_byte(self, p):
150         if self.chip['addr_bytes'] == 1:
151             s = '%02X' % self.addr_counter
152         else:
153             s = '%04X' % self.addr_counter
154         self.put(p[0], p[1], self.out_ann, [5, ['Data byte %s: %02X' % \
155             (s, p[3]), 'Data byte: %02X' % p[3], \
156             'Byte: %02X' % p[3], 'DB: %02X' % p[3], '%02X' % p[3]]])
157
158     def put_data_bytes(self, idx, cls, s):
159         for p in self.packets[idx:]:
160             self.put_data_byte(p)
161             self.addr_counter += 1
162         self.put(self.packets[idx][0], self.packets[-1][1], self.out_ann,
163             [8, ['Data', 'D']])
164         a = ''.join(['%s' % c[0] for c in s.split()]).upper()
165         self.putb([cls, ['%s (%s): %s' % (s, self.addr_and_len(), \
166                   self.hexbytes(self.chip['addr_bytes'])),
167                   '%s (%s)' % (s, self.addr_and_len()), s, a, s[0]]])
168         self.putbin([0, bytes(self.bytebuf[self.chip['addr_bytes']:])])
169
170     def addr_and_len(self):
171         if self.chip['addr_bytes'] == 1:
172             a = '%02X' % self.bytebuf[0]
173         else:
174             a = '%02X%02X' % tuple(self.bytebuf[:2])
175         num_data_bytes = len(self.bytebuf) - self.chip['addr_bytes']
176         d = '%d bytes' % num_data_bytes
177         if num_data_bytes <= 1:
178             d = d[:-1]
179         return 'addr=%s, %s' % (a, d)
180
181     def decide_on_seq_or_rnd_read(self):
182         if len(self.bytebuf) < 2:
183             self.reset()
184             return
185         if len(self.bytebuf) == 2:
186             self.is_random_access_read = True
187         else:
188             self.is_seq_random_read = True
189
190     def put_operation(self):
191         idx = 1 + self.chip['addr_bytes']
192         if self.is_byte_write:
193             # Byte write: word address, one data byte.
194             self.put_word_addr(self.packets)
195             self.put_data_bytes(idx, 9, 'Byte write')
196         elif self.is_page_write:
197             # Page write: word address, two or more data bytes.
198             self.put_word_addr(self.packets)
199             intitial_addr = self.addr_counter
200             self.put_data_bytes(idx, 10, 'Page write')
201             num_bytes_to_write = len(self.packets[idx:])
202             if num_bytes_to_write > self.chip['page_size']:
203                 self.putb([0, ['Warning: Wrote %d bytes but page size is '
204                                'only %d bytes!' % (num_bytes_to_write,
205                                self.chip['page_size'])]])
206             page1 = int(intitial_addr / self.chip['page_size'])
207             page2 = int((self.addr_counter - 1) / self.chip['page_size'])
208             if page1 != page2:
209                 self.putb([0, ['Warning: Page write crossed page boundary '
210                                'from page %d to %d!' % (page1, page2)]])
211         elif self.is_cur_addr_read:
212             # Current address read: no word address, one data byte.
213             self.put_data_byte(self.packets[1])
214             self.put(self.packets[1][0], self.packets[-1][1], self.out_ann,
215                 [8, ['Data', 'D']])
216             self.putb([11, ['Current address read: %02X' % self.bytebuf[0],
217                        'Current address read', 'Cur addr read', 'CAR', 'C']])
218             self.putbin([0, bytes([self.bytebuf[0]])])
219             self.addr_counter += 1
220         elif self.is_random_access_read:
221             # Random access read: word address, one data byte.
222             self.put_control_word(self.packets[idx][4])
223             self.put_word_addr(self.packets)
224             self.put_data_bytes(idx + 1, 12, 'Random access read')
225         elif self.is_seq_random_read:
226             # Sequential random read: word address, two or more data bytes.
227             self.put_control_word(self.packets[idx][4])
228             self.put_word_addr(self.packets)
229             self.put_data_bytes(idx + 1, 13, 'Sequential random read')
230
231     def handle_wait_for_start(self):
232         # Wait for an I²C START condition.
233         if self.cmd not in ('START', 'START REPEAT'):
234             return
235         self.ss_block = self.ss
236         self.state = 'GET CONTROL WORD'
237
238     def handle_get_control_word(self):
239         # The packet after START must be an ADDRESS READ or ADDRESS WRITE.
240         if self.cmd not in ('ADDRESS READ', 'ADDRESS WRITE'):
241             self.reset()
242             return
243         self.packet_append()
244         self.put_control_word(self.bits)
245         self.state = '%s GET ACK NACK AFTER CONTROL WORD' % self.cmd[8]
246
247     def handle_r_get_ack_nack_after_control_word(self):
248         if self.cmd == 'ACK':
249             self.state = 'R GET WORD ADDR OR BYTE'
250         elif self.cmd == 'NACK':
251             self.es_block = self.es
252             self.putb([0, ['Warning: No reply from slave!']])
253             self.reset()
254         else:
255             self.reset()
256
257     def handle_r_get_word_addr_or_byte(self):
258         if self.cmd == 'STOP':
259             self.es_block = self.es
260             self.putb([0, ['Warning: Slave replied, but master aborted!']])
261             self.reset()
262             return
263         elif self.cmd != 'DATA READ':
264             self.reset()
265             return
266         self.packet_append()
267         self.state = 'R GET ACK NACK AFTER WORD ADDR OR BYTE'
268
269     def handle_r_get_ack_nack_after_word_addr_or_byte(self):
270         if self.cmd == 'ACK':
271             self.state = 'R GET RESTART'
272         elif self.cmd == 'NACK':
273             self.is_cur_addr_read = True
274             self.state = 'GET STOP AFTER LAST BYTE'
275         else:
276             self.reset()
277
278     def handle_r_get_restart(self):
279         if self.cmd == 'RESTART':
280             self.state = 'R READ BYTE'
281         else:
282             self.reset()
283
284     def handle_r_read_byte(self):
285         if self.cmd == 'DATA READ':
286             self.packet_append()
287             self.state = 'R GET ACK NACK AFTER BYTE WAS READ'
288         else:
289             self.reset()
290
291     def handle_r_get_ack_nack_after_byte_was_read(self):
292         if self.cmd == 'ACK':
293             self.state = 'R READ BYTE'
294         elif self.cmd == 'NACK':
295             # It's either a RANDOM READ or a SEQUENTIAL READ.
296             self.state = 'GET STOP AFTER LAST BYTE'
297         else:
298             self.reset()
299
300     def handle_w_get_ack_nack_after_control_word(self):
301         if self.cmd == 'ACK':
302             self.state = 'W GET WORD ADDR'
303         elif self.cmd == 'NACK':
304             self.es_block = self.es
305             self.putb([0, ['Warning: No reply from slave!']])
306             self.reset()
307         else:
308             self.reset()
309
310     def handle_w_get_word_addr(self):
311         if self.cmd == 'STOP':
312             self.es_block = self.es
313             self.putb([0, ['Warning: Slave replied, but master aborted!']])
314             self.reset()
315             return
316         elif self.cmd != 'DATA WRITE':
317             self.reset()
318             return
319         self.packet_append()
320         self.state = 'W GET ACK AFTER WORD ADDR'
321
322     def handle_w_get_ack_after_word_addr(self):
323         if self.cmd == 'ACK':
324             self.state = 'W DETERMINE EEPROM READ OR WRITE'
325         else:
326             self.reset()
327
328     def handle_w_determine_eeprom_read_or_write(self):
329         if self.cmd == 'START REPEAT':
330             # It's either a RANDOM ACCESS READ or SEQUENTIAL RANDOM READ.
331             self.state = 'R2 GET CONTROL WORD'
332         elif self.cmd == 'DATA WRITE':
333             self.packet_append()
334             self.state = 'W GET ACK NACK AFTER BYTE WAS WRITTEN'
335         else:
336             self.reset()
337
338     def handle_w_write_byte(self):
339         if self.cmd == 'DATA WRITE':
340             self.packet_append()
341             self.state = 'W GET ACK NACK AFTER BYTE WAS WRITTEN'
342         elif self.cmd == 'STOP':
343             if len(self.bytebuf) < 2:
344                 self.reset()
345                 return
346             self.es_block = self.es
347             if len(self.bytebuf) == 2:
348                 self.is_byte_write = True
349             else:
350                 self.is_page_write = True
351             self.put_operation()
352             self.reset()
353         elif self.cmd == 'START REPEAT':
354             # It's either a RANDOM ACCESS READ or SEQUENTIAL RANDOM READ.
355             self.state = 'R2 GET CONTROL WORD'
356         else:
357             self.reset()
358
359     def handle_w_get_ack_nack_after_byte_was_written(self):
360         if self.cmd == 'ACK':
361             self.state = 'W WRITE BYTE'
362         else:
363             self.reset()
364
365     def handle_r2_get_control_word(self):
366         if self.cmd == 'ADDRESS READ':
367             self.packet_append()
368             self.state = 'R2 GET ACK AFTER ADDR READ'
369         else:
370             self.reset()
371
372     def handle_r2_get_ack_after_addr_read(self):
373         if self.cmd == 'ACK':
374             self.state = 'R2 READ BYTE'
375         else:
376             self.reset()
377
378     def handle_r2_read_byte(self):
379         if self.cmd == 'DATA READ':
380             self.packet_append()
381             self.state = 'R2 GET ACK NACK AFTER BYTE WAS READ'
382         elif self.cmd == 'STOP':
383             self.decide_on_seq_or_rnd_read()
384             self.es_block = self.es
385             self.putb([0, ['Warning: STOP expected after a NACK (not ACK)']])
386             self.put_operation()
387             self.reset()
388         else:
389             self.reset()
390
391     def handle_r2_get_ack_nack_after_byte_was_read(self):
392         if self.cmd == 'ACK':
393             self.state = 'R2 READ BYTE'
394         elif self.cmd == 'NACK':
395             self.decide_on_seq_or_rnd_read()
396             self.state = 'GET STOP AFTER LAST BYTE'
397         else:
398             self.reset()
399
400     def handle_get_stop_after_last_byte(self):
401         if self.cmd == 'STOP':
402             self.es_block = self.es
403             self.put_operation()
404             self.reset()
405         elif self.cmd == 'START REPEAT':
406             self.es_block = self.es
407             self.putb([0, ['Warning: STOP expected (not RESTART)']])
408             self.put_operation()
409             self.reset()
410             self.ss_block = self.ss
411             self.state = 'GET CONTROL WORD'
412         else:
413             self.reset()
414
415     def decode(self, ss, es, data):
416         self.cmd, self.databyte = data
417
418         # Collect the 'BITS' packet, then return. The next packet is
419         # guaranteed to belong to these bits we just stored.
420         if self.cmd == 'BITS':
421             self.bits = self.databyte
422             return
423
424         # Store the start/end samples of this I²C packet.
425         self.ss, self.es = ss, es
426
427         # State machine.
428         s = 'handle_%s' % self.state.lower().replace(' ', '_')
429         handle_state = getattr(self, s)
430         handle_state()