sae_j1850_vpw: rewrite decoder to improve usability and maintenance
[libsigrokdecode/gsi.git] / decoders / amulet_ascii / pd.py
blob719532344727f98e566aeba51347644395b60907
1 ##
2 ## This file is part of the libsigrokdecode project.
3 ##
4 ## Copyright (C) 2019 Vesa-Pekka Palmu <vpalmu@depili.fi>
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 3 of the License, or
9 ## (at your option) any later version.
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.
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/>.
20 import sigrokdecode as srd
21 from math import ceil
22 from common.srdhelper import SrdIntEnum
23 from .lists import *
25 L = len(cmds)
26 RX = 0
27 TX = 1
29 Ann = SrdIntEnum.from_list('Ann',
30 [c[0] for c in cmds.values()] + ['BIT', 'FIELD', 'WARN'])
32 def cmd_annotation_classes():
33 return tuple([tuple([cmd[0].lower(), cmd[1]]) for cmd in cmds.values()])
35 class Decoder(srd.Decoder):
36 api_version = 3
37 id = 'amulet_ascii'
38 name = 'Amulet ASCII'
39 longname = 'Amulet LCD ASCII'
40 desc = 'Amulet Technologies LCD controller ASCII protocol.'
41 license = 'gplv3+'
42 inputs = ['uart']
43 outputs = []
44 tags = ['Display']
45 annotations = cmd_annotation_classes() + (
46 ('bit', 'Bit'),
47 ('field', 'Field'),
48 ('warning', 'Warning'),
50 annotation_rows = (
51 ('bits', 'Bits', (L + 0,)),
52 ('fields', 'Fields', (L + 1,)),
53 ('commands', 'Commands', tuple(range(L))),
54 ('warnings', 'Warnings', (L + 2,)),
56 options = (
57 {'id': 'ms_chan', 'desc': 'Master -> slave channel',
58 'default': 'RX', 'values': ('RX', 'TX')},
59 {'id': 'sm_chan', 'desc': 'Slave -> master channel',
60 'default': 'TX', 'values': ('RX', 'TX')},
63 def __init__(self):
64 self.reset()
66 def reset(self):
67 self.state = None
68 self.cmdstate = None
70 # Build dict mapping command keys to handler functions. Each
71 # command in 'cmds' (defined in lists.py) has a matching
72 # handler self.handle_<shortname>.
73 def get_handler(cmd):
74 s = 'handle_%s' % cmds[cmd][0].lower().replace('/', '_')
75 return getattr(self, s)
76 self.cmd_handlers = dict((cmd, get_handler(cmd)) for cmd in cmds.keys())
78 def start(self):
79 self.out_ann = self.register(srd.OUTPUT_ANN)
81 def putx(self, data):
82 # Simplification, most annotations span exactly one SPI byte/packet.
83 self.put(self.ss, self.es, self.out_ann, data)
85 def putf(self, data):
86 self.put(self.ss_field, self.es_field, self.out_ann, data)
88 def putc(self, data):
89 self.put(self.ss_cmd, self.es_cmd, self.out_ann, data)
91 def cmd_ann_list(self):
92 x, s = cmds[self.state][0], cmds[self.state][1]
93 return ['Command: %s (%s)' % (s, x), 'Command: %s' % s,
94 'Cmd: %s' % s, 'Cmd: %s' % x, x]
96 def emit_cmd_byte(self):
97 self.ss_cmd = self.ss
98 self.putx([Ann.FIELD, self.cmd_ann_list()])
100 def emit_addr_bytes(self, pdata):
101 if self.cmdstate == 2:
102 self.ss_field = self.ss
103 self.addr = chr(pdata)
104 self.putx([Ann.BIT, ['Address high nibble: %c' % pdata,
105 'Addr high 0x%c' % pdata, 'Addr h 0x%c' % pdata]])
106 elif self.cmdstate == 3:
107 self.es_field = self.es
108 self.addr += chr(pdata)
109 self.addr = int(self.addr, 16)
110 self.putx([Ann.BIT, ['Address low nibble: %c' % pdata,
111 'Addr low 0x%c' % pdata, 'Addr l 0x%c' % pdata]])
112 self.putf([Ann.FIELD, ['Address: 0x%02X' % self.addr,
113 'Addr: 0x%02X' % self.addr, '0x%02X' % self.addr]])
115 def emit_cmd_end(self, data):
116 self.es_cmd = self.es
117 self.putc(data)
118 self.state = None
120 def handle_read(self, data):
121 if self.cmdstate == 1:
122 self.emit_cmd_byte()
123 self.addr = 0
124 elif self.cmdstate == 2:
125 self.emit_addr_bytes(pdata)
126 elif self.cmdstate == 3:
127 self.emit_addr_bytes(pdata)
128 self.cmdstate += 1
130 def handle_set_common(self, pdata):
131 if self.cmdstate == 1:
132 self.addr = 0
133 self.emit_addr_bytes(pdata)
135 def emit_not_implemented(self, data):
136 self.es_cmd = self.es
137 self.putc([Ann.WARN, ['Command not decoded', 'Not decoded']])
138 self.emit_cmd_end(data)
140 def handle_string(self, pdata, ann_class):
141 # TODO: unicode / string modifiers...
142 self.handle_set_common(pdata)
143 if self.cmdstate == 4:
144 self.ss_field = self.ss
145 self.value = ''
146 if pdata == 0x00:
147 # Null terminated string ends.
148 self.es_field = self.es
149 self.putx([Ann.BIT, ['NULL']])
150 self.putf([Ann.FIELD, ['Value: %s' % self.value,
151 'Val: %s' % self.value, '%s' % self.value]])
152 self.emit_cmd_end([ann_class, self.cmd_ann_list()])
153 return
154 if self.cmdstate > 3:
155 self.value += chr(pdata)
156 self.putx([Ann.BIT, ['%c' % pdata]])
157 self.cmdstate += 1
159 # Command handlers
161 # Page change 0xA0, 0x02, index_high, index_low, checksum
162 def handle_page(self, pdata):
163 if self.cmdstate == 2:
164 if pdata == 0x02:
165 self.ss_field = self.ss_cmd
166 self.es_field = self.es
167 self.putf([Ann.FIELD, self.cmd_ann_list()])
168 self.checksum = 0xA0 + 0x02
169 else:
170 self.putx([Ann.WARN, ['Illegal second byte for page change',
171 'Illegal byte']])
172 self.state = None
173 elif self.cmdstate == 3:
174 self.ss_field = self.ss
175 self.checksum += pdata
176 self.page[0] = pdata
177 elif self.cmdstate == 4:
178 self.checksum += pdata
179 self.page[1] = pdata
180 self.es_field = self.es
181 if self.page[0] == self.page [1] == 0xFF:
182 # Soft reset trigger
183 self.putf(Ann.WARN, ['Soft reset', 'Reset'])
184 else:
185 page = chr(self.page[0]) + chr(self.page[1])
186 self.putf(Ann.FIELD, ['Page index: 0x%s' % page,
187 'Page: 0x%s' % page, '0x%s' % page])
188 elif self.cmdstate == 5:
189 self.checksum += pdata
190 if (self.checksum & 0xFF) != 0:
191 self.putx([Ann.WARN, ['Checksum error', 'Error', 'ERR']])
192 else:
193 self.putx([Ann.FIELD, ['Checksum OK', 'OK']])
194 self.emit_cmd_end(Ann.PAGE)
195 self.cmdstate += 1
197 # Value reads: command byte, address high nibble, address low nibble
199 # Get byte value
200 def handle_gbv(self, pdata):
201 self.handle_read(pdata)
202 self.emit_cmd_end([Ann.GBV, self.cmd_ann_list()])
204 # Get word value
205 def handle_gwv(self, pdata):
206 self.handle_read(pdata)
207 self.emit_cmd_end([Ann.GWV, self.cmd_ann_list()])
209 # Get string value
210 def handle_gsv(self, pdata):
211 self.handle_read(pdata)
212 self.emit_cmd_end([Ann.GSV, self.cmd_ann_list()])
214 # Get label value
215 def handle_glv(self, pdata):
216 self.handle_read(pdata)
217 self.emit_cmd_end([Ann.GLV, self.cmd_ann_list()])
219 # Get RPC buffer
220 def handle_grpc(self, pdata):
221 if self.cmdstate == 2:
222 self.ss_field = self.ss
223 self.flags = int(chr(pdata), 16) << 4
224 elif self.cmdstate == 3:
225 self.flags += int(chr(pdata), 16)
226 self.es_field = self.es
227 self.putf([Ann.FIELD, ['RPC flag: 0x%02X' % self.flags]])
228 self.emit_cmd_end([Ann.GRPC, self.cmd_ann_list()])
230 # Get byte value array
231 def handle_gbva(self, pdata):
232 self.handle_read(pdata)
233 self.emit_cmd_end([Ann.GBVA, self.cmd_ann_list()])
235 # Get word value array
236 def handle_gwva(self, pdata):
237 self.handle_read(pdata)
238 self.emit_cmd_end([Ann.GWVA, self.cmd_ann_list()])
240 # Get color variable
241 def handle_gcv(self, pdata):
242 self.handle_read(pdata)
243 self.emit_cmd_end([Ann.GCV, self.cmd_ann_list()])
245 # Value setters: command byte, address high nibble, address low nibble, data bytes
247 # Set byte value data = high nibble, low nibble
248 def handle_sbv(self, pdata):
249 self.handle_set_common(pdata)
250 if self.cmdstate == 4:
251 self.ss_field = self.ss
252 self.value = chr(pdata)
253 elif self.cmdstate == 5:
254 self.value += chr(pdata)
255 self.es_field = self.es
256 self.putf([Ann.FIELD, ['Value: 0x%s' % self.value,
257 'Val: 0x%s' % self.value, '0x%s' % self.value]])
258 self.emit_cmd_end([Ann.SBV, self.cmd_ann_list()])
259 self.cmdstate += 1
261 # Set word value, msb high, msb low, lsb high, lsb low
262 def handle_swv(self, pdata):
263 self.handle_set_common(pdata)
264 if self.cmdstate > 3:
265 nibble = self.cmdstate - 4
266 if nibble == 0:
267 self.ss_field = self.ss
268 self.value = 0
269 self.value += int(chr(pdata), 16) << 12 - (4 * nibble)
270 if nibble == 3:
271 self.es_field = self.es
272 self.putf([Ann.FIELD, ['Value: 0x%04x' % self.value,
273 'Val: 0x%04x' % self.value, '0x%04x' % self.value]])
274 self.emit_cmd_end([Ann.SWV, self.cmd_ann_list()])
275 return
276 self.cmdstate += 1
278 # Set string value, null terminated utf8 strings
279 def handle_ssv(self, pdata):
280 self.handle_string(pdata, Ann.SSV)
282 # Set byte value array
283 def handle_sbva(self, pdata):
284 nibble = (self.cmdstate - 3) % 2
285 if self.cmdstate == 2:
286 self.addr = int(chr(pdata), 16) << 4
287 self.ss_field = self.ss
288 self.putx([Ann.BIT, ['Address high nibble: %c' % pdata,
289 'Addr high 0x%c' % pdata, '0x%c' % pdata]])
290 elif self.cmdstate == 3:
291 self.addr += int(chr(pdata), 16)
292 self.es_field = self.ss
293 self.putx([Ann.BIT, ['Address low nibble: %c' % pdata,
294 'Addr low 0x%c' % pdata, '0x%c' % pdata]])
295 self.putf([Ann.FIELD, ['Address: 0x%02X' % self.addr,
296 'Addr: 0x%02X' % self.addr, '0x%02X' % self.addr]])
297 elif stage == 2:
298 if pdata == 0x00:
299 # Null terminated list
300 self.emit_cmd_end([Ann.SBVA, self.cmd_ann_list()])
301 return
302 self.value = int(chr(pdata), 16) << 4
303 else:
304 self.value += int(chr(pdata), 16)
305 self.es_field = self.es
306 self.putf([Ann.FIELD, ['Value 0x%02X' % self.value,
307 '0x%02X' % self.value]])
308 self.cmdstate += 1
310 # Set word value array
311 def handle_swva(self, pdata):
312 nibble = (self.cmdstate - 3) % 4
313 if self.cmdstate == 2:
314 self.addr = int(chr(pdata), 16) << 4
315 self.ss_field = self.ss
316 self.putx([Ann.BIT, ['Address high nibble: %c' % pdata,
317 'Addr high 0x%c' % pdata, '0x%c' % pdata]])
318 elif self.cmdstate == 3:
319 self.addr += int(chr(pdata), 16)
320 self.es_field = self.ss
321 self.putx([Ann.BIT, ['Address low nibble: %c' % pdata,
322 'Addr low 0x%c' % pdata, '0x%c' % pdata]])
323 self.putf([Ann.FIELD, ['Address: 0x%02X' % self.addr,
324 'Addr: 0x%02X' % self.addr, '0x%02X' % self.addr]])
325 self.value = 0
326 else:
327 self.value += int(chr(pdata), 16) << 12 - (4 * nibble)
328 if nibble == 0:
329 if pdata == 0x00:
330 # Null terminated list
331 self.emit_cmd_end([Ann.SWVA, self.cmd_ann_list()])
332 return
333 self.ss_field = self.ss
334 if nibble == 3:
335 self.es_field = self.es
336 self.putf([Ann.FIELD, ['Value 0x%04X' % self.value,
337 '0x%04X' % self.value]])
338 self.cmdstate += 1
340 # Set color variable
341 def handle_scv(self, pdata):
342 if self.cmdstate == 8:
343 self.emit_not_implemented([Ann.SCV, self.cmd_ann_list()])
344 self.cmdstate += 1
346 # RPC trigger
347 def handle_rpc(self, pdata):
348 self.handle_read(pdata)
349 self.emit_cmd_end([Ann.RPC, self.cmd_ann_list()])
351 # Drawing
353 # Decode pair of (x,y) 16bit coordinates
354 def decode_coords(self, pdata):
355 if self.cmdstate == 1:
356 self.coords[0] = 0
357 self.coords[1] = 0
358 self.coords[2] = 0
359 self.coords[3] = 0
360 if self.cmdstate < 18:
361 # Coordinates
362 nibble = (self.cmdstate - 1) % 4
363 i = (self.cmdstate - 1) / 4
364 self.coords[i] += int(chr(pdata), 16) << 12 - (4 * nibble)
365 if nibble == 0:
366 self.ss_field = self.ss
367 elif nibble == 3:
368 self.es_field = self.es
369 self.putf([Ann.FIELD, ['Coordinate 0x%04X' % self.coords[i]],
370 ['0x%04X' % self.coords[i]]])
372 # TODO: There are actually two protocol revisions for drawing.
373 # Both use 4 bytes for 16bit x and y pairs for start and end.
374 # The older follows this by a pattern selector and then line weight.
375 # Newer version has 6 bytes for 8bit RGB color...
377 # Draw line
378 def handle_line(self, pdata):
379 decode_coords(pdata)
380 if self.cmdstate == 18:
381 self.es_cmd = self.es
382 self.putc([Ann.LINE, self.cmd_ann_list()])
383 self.putc([Ann.WARN, ['Line pattern / Color not implemented']])
384 self.state = None
385 self.cmdstate += 1
387 # Draw rectange
388 def handle_rect(self, pdata):
389 decode_coords(pdata)
390 if self.cmdstate == 18:
391 self.es_cmd = self.es
392 self.putc([Ann.RECT, self.cmd_ann_list()])
393 self.putc([Ann.WARN, ['Line pattern / Color not implemented']])
394 self.state = None
395 self.cmdstate += 1
397 # Draw filled rectangle
398 def handle_frect(self, pdata):
399 decode_coords(pdata)
400 if self.cmdstate == 18:
401 self.es_cmd = self.es
402 self.putc([Ann.FRECT, self.cmd_ann_list()])
403 self.putc([Ann.WARN, ['Fill pattern / Color not implemented']])
404 self.state = None
405 self.cmdstate += 1
407 # Draw pixel
408 def handle_pixel(self, pdata):
409 self.es_cmd = self.es
410 self.putc([Ann.WARN, ['Draw pixel documentation is missing.', 'Undocumented']])
411 self.state = None
413 # Replies
414 def handle_gbvr(self, pdata):
415 self.emit_add_bytes(pdata)
416 if self.cmdstate == 4:
417 self.ss_field = self.ss
418 self.value = int(chr(pdata), 16) << 4
419 self.putx([Ann.BIT, ['High nibble 0x%s' % pdata, '0x%s' % pdata]])
420 elif self.cmdstate == 5:
421 self.value += int(chr(pdata), 16)
422 self.putx([Ann.BIT, ['Low nibble 0x%s' % pdata, '0x%s' % pdata]])
423 self.es_field = self.es
424 self.putf([Ann.FIELD, ['Value: 0x%02X' % self.value,
425 '0x%02X' % self.value]])
426 self.emit_cmd_end([Ann.GBVR, self.cmd_ann_list()])
427 self.cmdstate += 1
429 def handle_gwvr(self, pdata):
430 self.emit_add_bytes(pdata)
431 if self.cmdstate > 3:
432 nibble = self.cmdstate - 3
433 if nibble == 0:
434 self.value = 0
435 self.ss_field = self.ss
436 self.value += int(chr(pdata), 16) << 12 - (4 * nibble)
437 self.putx([Ann.BIT, ['0x%s' % pdata]])
438 if nibble == 3:
439 self.putf([Ann.FIELD, ['Value: 0x%04x' % self.value,
440 '0x%04X' % self.value]])
441 self.es_cmd = self.ss
442 self.emit_cmd_end([Ann.GWVR, self.cmd_ann_list()])
443 self.cmdstate += 1
445 def handle_gsvr(self, pdata):
446 self.handle_string(pdata, Ann.GSVR)
448 def handle_glvr(self, pdata):
449 self.handle_string(pdata, Ann.GLVR)
451 def handle_grpcr(self, pdata):
452 self.handle_addr(pdata)
453 if self.cmdstate > 3:
454 nibble = (self.cmdstate - 3) % 2
455 if nibble == 0:
456 if pdata == 0x00:
457 self.emit_cmd_end([Ann.GRPCR, self.cmd_ann_list()])
458 return
459 self.value = int(chr(pdata), 16) << 4
460 self.ss_field = self.ss
461 self.putx([Ann.BIT, ['0x%s' % pdata]])
462 if nibble == 2:
463 self.value += int(chr(pdata), 16)
464 self.es_field = self.es
465 self.putx([Ann.BIT, ['0x%s' % pdata]])
466 self.putf([Ann.FIELD, ['0x%02X' % self.value]])
467 self.cmdstate += 1
469 def handle_sbvr(self, pdata):
470 self.handle_set_common(pdata)
471 if self.cmdstate == 4:
472 self.ss_field = self.ss
473 self.value = chr(pdata)
474 elif self.cmdstate == 5:
475 self.value += chr(pdata)
476 self.es_field = self.es
477 self.putf([Ann.FIELD, ['Value: 0x%s' % self.value,
478 'Val: 0x%s' % self.value, '0x%s' % self.value]])
479 self.emit_cmd_end([Ann.SBVR, self.cmd_ann_list()])
480 self.cmdstate += 1
482 def handle_swvr(self, pdata):
483 self.handle_set_common(pdata)
484 if self.cmdstate == 4:
485 self.ss_field = self.ss
486 self.value = (pdata - 0x30) << 4
487 elif self.cmdstate == 5:
488 self.value += (pdata - 0x30)
489 self.value = self.value << 8
490 elif self.cmdstate == 6:
491 self.value += (pdata - 0x30) << 4
492 elif self.cmdstate == 7:
493 self.value += (pdata - 0x30)
494 self.es_field = self.es
495 self.putf([Ann.FIELD, ['Value: 0x%04x' % self.value,
496 'Val: 0x%04x' % self.value, '0x%04x' % self.value]])
497 self.emit_cmd_end([Ann.SWVR, self.cmd_ann_list()])
498 self.state = None
499 self.cmdstate += 1
501 def handle_ssvr(self, pdata):
502 self.handle_string(pdata, Ann.SSVR)
504 def handle_rpcr(self, pdata):
505 self.handle_read(pdata)
506 self.emit_cmd_end([Ann.RPCR, self.cmd_ann_list()])
508 def handle_liner(self, pdata):
509 decode_coords(pdata)
510 if self.cmdstate == 18:
511 self.es_cmd = self.es
512 self.putc([Ann.LINER, self.cmd_ann_list()])
513 self.putc([Ann.WARN, ['Line pattern / Color not implemented']])
514 self.state = None
515 self.cmdstate += 1
517 def handle_rectr(self, pdata):
518 decode_coords(pdata)
519 if self.cmdstate == 18:
520 self.es_cmd = self.es
521 self.putc([Ann.RECTR, self.cmd_ann_list()])
522 self.putc([Ann.WARN, ['Line pattern / Color not implemented']])
523 self.state = None
524 self.cmdstate += 1
526 def handle_frectr(self, pdata):
527 decode_coords(pdata)
528 if self.cmdstate == 18:
529 self.es_cmd = self.es
530 self.putc([Ann.FRECTR, self.cmd_ann_list()])
531 self.putc([Ann.WARN, ['Line pattern / Color not implemented']])
532 self.state = None
533 self.cmdstate += 1
535 def handle_pixelr(self, pdata):
536 self.es_cmd = self.es
537 self.putc([Ann.WARN,['Draw pixel documentation is missing.', 'Undocumented']])
538 self.state = None
540 def handle_gbvar(self, pdata):
541 nibble = (self.cmdstate - 3) % 2
542 if self.cmdstate == 2:
543 self.addr = int(chr(pdata), 16) << 4
544 self.ss_field = self.ss
545 self.putx([Ann.BIT, ['Address high nibble: %c' % pdata,
546 'Addr high 0x%c' % pdata, '0x%c' % pdata]])
547 elif self.cmdstate == 3:
548 self.addr += int(chr(pdata), 16)
549 self.es_field = self.ss
550 self.putx([Ann.BIT, ['Address low nibble: %c' % pdata,
551 'Addr low 0x%c' % pdata, '0x%c' % pdata]])
552 self.putf([Ann.FIELD, ['Address: 0x%02X' % self.addr,
553 'Addr: 0x%02X' % self.addr, '0x%02X' % self.addr]])
554 elif stage == 2:
555 if pdata == 0x00:
556 # Null terminated list
557 self.emit_cmd_end([Ann.GBVAR, self.cmd_ann_list()])
558 return
559 self.value = int(chr(pdata), 16) << 4
560 else:
561 self.value += int(chr(pdata), 16)
562 self.es_field = self.es
563 self.putf([Ann.FIELD, ['Value 0x%02X' % self.value,
564 '0x%02X' % self.value]])
565 self.cmdstate += 1
567 def handle_gwvar(self, pdata):
568 nibble = (self.cmdstate - 3) % 4
569 if self.cmdstate == 2:
570 self.addr = int(chr(pdata), 16) << 4
571 self.ss_field = self.ss
572 self.putx([Ann.BIT, ['Address high nibble: %c' % pdata,
573 'Addr high 0x%c' % pdata, '0x%c' % pdata]])
574 elif self.cmdstate == 3:
575 self.addr += int(chr(pdata), 16)
576 self.es_field = self.ss
577 self.putx([Ann.BIT, ['Address low nibble: %c' % pdata,
578 'Addr low 0x%c' % pdata, '0x%c' % pdata]])
579 self.putf([Ann.FIELD, ['Address: 0x%02X' % self.addr,
580 'Addr: 0x%02X' % self.addr, '0x%02X' % self.addr]])
581 self.value = 0
582 else:
583 self.value += int(chr(pdata), 16) << 12 - (4 * nibble)
584 if nibble == 0:
585 if pdata == 0x00:
586 # Null terminated list
587 self.emit_cmd_end([Ann.GWVAR, self.cmd_ann_list()])
588 return
589 self.ss_field = self.ss
590 if nibble == 3:
591 self.es_field = self.es
592 self.putf([Ann.FIELD, ['Value 0x%04X' % self.value,
593 '0x%04X' % self.value]])
594 self.cmdstate += 1
596 # Get byte variable array reply
597 def handle_sbvar(self, pdata):
598 nibble = (self.cmdstate - 3) % 2
599 if self.cmdstate == 2:
600 self.addr = int(chr(pdata), 16) << 4
601 self.ss_field = self.ss
602 self.putx([Ann.BIT, ['Address high nibble: %c' % pdata,
603 'Addr high 0x%c' % pdata, '0x%c' % pdata]])
604 elif self.cmdstate == 3:
605 self.addr += int(chr(pdata), 16)
606 self.es_field = self.ss
607 self.putx([Ann.BIT, ['Address low nibble: %c' % pdata,
608 'Addr low 0x%c' % pdata, '0x%c' % pdata]])
609 self.putf([Ann.FIELD, ['Address: 0x%02X' % self.addr,
610 'Addr: 0x%02X' % self.addr, '0x%02X' % self.addr]])
611 elif stage == 2:
612 if pdata == 0x00:
613 # Null terminated list
614 self.emit_cmd_end([Ann.SBVAR, self.cmd_ann_list()])
615 return
616 self.value = int(chr(pdata), 16) << 4
617 else:
618 self.value += int(chr(pdata), 16)
619 self.es_field = self.es
620 self.putf([Ann.FIELD, ['Value 0x%02X' % self.value,
621 '0x%02X' % self.value]])
622 self.cmdstate += 1
624 # Set word variable array reply
625 def handle_swvar(self, pdata):
626 nibble = (self.cmdstate - 3) % 4
627 if self.cmdstate == 2:
628 self.addr = int(chr(pdata), 16) << 4
629 self.ss_field = self.ss
630 self.putx([Ann.BIT, ['Address high nibble: %c' % pdata,
631 'Addr high 0x%c' % pdata, '0x%c' % pdata]])
632 elif self.cmdstate == 3:
633 self.addr += int(chr(pdata), 16)
634 self.es_field = self.ss
635 self.putx([Ann.BIT, ['Address low nibble: %c' % pdata,
636 'Addr low 0x%c' % pdata, '0x%c' % pdata]])
637 self.putf([Ann.FIELD, ['Address: 0x%02X' % self.addr,
638 'Addr: 0x%02X' % self.addr, '0x%02X' % self.addr]])
639 self.value = 0
640 else:
641 self.value += int(chr(pdata), 16) << 12 - (4 * nibble)
642 if nibble == 0:
643 if pdata == 0x00:
644 # Null terminated list
645 self.emit_cmd_end([Ann.SWVAR, self.cmd_ann_list()])
646 return
647 self.ss_field = self.ss
648 if nibble == 3:
649 self.es_field = self.es
650 self.putf([Ann.FIELD, ['Value 0x%04X' % self.value,
651 '0x%04X' % self.value]])
652 self.cmdstate += 1
654 def handle_gcvr(self, pdata):
655 if self.cmdstate == 8:
656 self.emit_not_implemented([Ann.SCV, self.cmd_ann_list()])
657 self.cmdstate += 1
659 def handle_scvr(self, pdata):
660 if self.cmdstate == 8:
661 self.emit_not_implemented([Ann.SCV, self.cmd_ann_list()])
662 self.cmdstate += 1
664 # ACK & NACK
666 def handle_ack(self, pdata):
667 self.putx([Ann.ACK, self.cmd_ann_list()])
668 self.state = None
670 def handle_nack(self, pdata):
671 self.putx([Ann.NACK, self.cmd_ann_list()])
672 self.state = None
674 def decode(self, ss, es, data):
675 ptype, rxtx, pdata = data
677 self.ss, self.es = ss, es
679 if ptype != 'DATA':
680 return
682 # Handle commands.
683 try:
684 abort_current = (0xD0 <= pdata[0] <= 0xF7) and \
685 (not (self.state in cmds_with_high_bytes)) and \
686 self.state != None
687 if abort_current:
688 self.putx([Ann.WARN, ['Command aborted by invalid byte', 'Abort']])
689 self.state = pdata[0]
690 self.emit_cmd_byte()
691 self.cmdstate = 1
692 if self.state is None:
693 self.state = pdata[0]
694 self.emit_cmd_byte()
695 self.cmdstate = 1
696 self.cmd_handlers[self.state](pdata[0])
697 except KeyError:
698 self.putx([Ann.WARN, ['Unknown command: 0x%02x' % pdata[0]]])
699 self.state = None