]> sigrok.org Git - libsigrokdecode.git/blob - decoders/amulet_ascii/pd.py
ntf905: Add/rename required self.reset() method.
[libsigrokdecode.git] / decoders / amulet_ascii / pd.py
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
20 import sigrokdecode as srd
21 from math import ceil
22 from common.srdhelper import SrdIntEnum
23 from .lists import *
24
25 L = len(cmds)
26 RX = 0
27 TX = 1
28
29 Ann = SrdIntEnum.from_list('Ann',
30     [c[0] for c in cmds.values()] + ['BIT', 'FIELD', 'WARN'])
31
32 def cmd_annotation_classes():
33     return tuple([tuple([cmd[0].lower(), cmd[1]]) for cmd in cmds.values()])
34
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'),
49     )
50     annotation_rows = (
51         ('bits', 'Bits', (L + 0,)),
52         ('fields', 'Fields', (L + 1,)),
53         ('commands', 'Commands', tuple(range(L))),
54         ('warnings', 'Warnings', (L + 2,)),
55     )
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')},
61     )
62
63     def __init__(self):
64         self.reset()
65
66     def reset(self):
67         self.state = None
68         self.cmdstate = None
69
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())
77
78     def start(self):
79         self.out_ann = self.register(srd.OUTPUT_ANN)
80
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)
84
85     def putf(self, data):
86         self.put(self.ss_field, self.es_field, self.out_ann, data)
87
88     def putc(self, data):
89         self.put(self.ss_cmd, self.es_cmd, self.out_ann, data)
90
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]
95
96     def emit_cmd_byte(self):
97         self.ss_cmd = self.ss
98         self.putx([Ann.FIELD, self.cmd_ann_list()])
99
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]])
114
115     def emit_cmd_end(self, data):
116         self.es_cmd = self.es
117         self.putc(data)
118         self.state = None
119
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
129
130     def handle_set_common(self, pdata):
131         if self.cmdstate == 1:
132             self.addr = 0
133         self.emit_addr_bytes(pdata)
134
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)
139
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
158
159     # Command handlers
160
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
196
197     # Value reads: command byte, address high nibble, address low nibble
198
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()])
203
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()])
208
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()])
213
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()])
218
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()])
229
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()])
234
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()])
239
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()])
244
245     # Value setters: command byte, address high nibble, address low nibble, data bytes
246
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
260
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
277
278     # Set string value, null terminated utf8 strings
279     def handle_ssv(self, pdata):
280         self.handle_string(pdata, Ann.SSV)
281
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
309
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
339
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
345
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()])
350
351     # Drawing
352
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]]])
371
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...
376
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
386
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
396
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
406
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
412
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
428
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
444
445     def handle_gsvr(self, pdata):
446         self.handle_string(pdata, Ann.GSVR)
447
448     def handle_glvr(self, pdata):
449         self.handle_string(pdata, Ann.GLVR)
450
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
468
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
481
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
500
501     def handle_ssvr(self, pdata):
502         self.handle_string(pdata, Ann.SSVR)
503
504     def handle_rpcr(self, pdata):
505         self.handle_read(pdata)
506         self.emit_cmd_end([Ann.RPCR, self.cmd_ann_list()])
507
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
516
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
525
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
534
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
539
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
566
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
595
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
623
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
653
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
658
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
663
664     # ACK & NACK
665
666     def handle_ack(self, pdata):
667         self.putx([Ann.ACK, self.cmd_ann_list()])
668         self.state = None
669
670     def handle_nack(self, pdata):
671         self.putx([Ann.NACK, self.cmd_ann_list()])
672         self.state = None
673
674     def decode(self, ss, es, data):
675         ptype, rxtx, pdata = data
676
677         self.ss, self.es = ss, es
678
679         if ptype != 'DATA':
680             return
681
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