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