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