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