]> sigrok.org Git - libsigrokdecode.git/blame - decoders/eeprom24xx/pd.py
all decoders: introduce a reset() method
[libsigrokdecode.git] / decoders / eeprom24xx / pd.py
CommitLineData
c4d52210
UH
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
4539e9ca 17## along with this program; if not, see <http://www.gnu.org/licenses/>.
c4d52210
UH
18##
19
20import sigrokdecode as srd
21from .lists import *
22
23class Decoder(srd.Decoder):
b197383c 24 api_version = 3
c4d52210
UH
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
92b7b49f 75 def __init__(self):
10aeb8ea
GS
76 self.reset()
77
78 def reset(self):
0f4d8807 79 self.reset_variables()
c4d52210
UH
80
81 def start(self):
82 self.out_ann = self.register(srd.OUTPUT_ANN)
2f370328 83 self.out_binary = self.register(srd.OUTPUT_BINARY)
c4d52210
UH
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):
2f370328 91 self.put(self.ss_block, self.es_block, self.out_binary, data)
c4d52210
UH
92
93 def putbits(self, bit1, bit2, bits, data):
94 self.put(bits[bit1][1], bits[bit2][2], self.out_ann, data)
95
0f4d8807 96 def reset_variables(self):
c4d52210
UH
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]]])
2824e811 170 self.putbin([0, bytes(self.bytebuf[self.chip['addr_bytes']:])])
c4d52210
UH
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:
0f4d8807 185 self.reset_variables()
c4d52210
UH
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']])
2824e811 220 self.putbin([0, bytes([self.bytebuf[0]])])
c4d52210
UH
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'):
0f4d8807 243 self.reset_variables()
c4d52210
UH
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!']])
0f4d8807 255 self.reset_variables()
c4d52210 256 else:
0f4d8807 257 self.reset_variables()
c4d52210
UH
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!']])
0f4d8807 263 self.reset_variables()
c4d52210
UH
264 return
265 elif self.cmd != 'DATA READ':
0f4d8807 266 self.reset_variables()
c4d52210
UH
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:
0f4d8807 278 self.reset_variables()
c4d52210
UH
279
280 def handle_r_get_restart(self):
281 if self.cmd == 'RESTART':
282 self.state = 'R READ BYTE'
283 else:
0f4d8807 284 self.reset_variables()
c4d52210
UH
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:
0f4d8807 291 self.reset_variables()
c4d52210
UH
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:
0f4d8807 300 self.reset_variables()
c4d52210
UH
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!']])
0f4d8807 308 self.reset_variables()
c4d52210 309 else:
0f4d8807 310 self.reset_variables()
c4d52210
UH
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!']])
0f4d8807 316 self.reset_variables()
c4d52210
UH
317 return
318 elif self.cmd != 'DATA WRITE':
0f4d8807 319 self.reset_variables()
c4d52210
UH
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:
0f4d8807 328 self.reset_variables()
c4d52210
UH
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:
0f4d8807 338 self.reset_variables()
c4d52210
UH
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:
0f4d8807 346 self.reset_variables()
c4d52210
UH
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()
0f4d8807 354 self.reset_variables()
c4d52210
UH
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:
0f4d8807 359 self.reset_variables()
c4d52210
UH
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:
0f4d8807 365 self.reset_variables()
c4d52210
UH
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:
0f4d8807 372 self.reset_variables()
c4d52210
UH
373
374 def handle_r2_get_ack_after_addr_read(self):
375 if self.cmd == 'ACK':
376 self.state = 'R2 READ BYTE'
377 else:
0f4d8807 378 self.reset_variables()
c4d52210
UH
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()
0f4d8807 389 self.reset_variables()
c4d52210 390 else:
0f4d8807 391 self.reset_variables()
c4d52210
UH
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:
0f4d8807 400 self.reset_variables()
c4d52210
UH
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()
0f4d8807 406 self.reset_variables()
c4d52210
UH
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()
0f4d8807 411 self.reset_variables()
c4d52210
UH
412 self.ss_block = self.ss
413 self.state = 'GET CONTROL WORD'
414 else:
0f4d8807 415 self.reset_variables()
c4d52210
UH
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()