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