2 ## This file is part of the libsigrokdecode project.
4 ## Copyright (C) 2019 Vesa-Pekka Palmu <vpalmu@depili.fi>
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
28 # Don't forget to keep this in sync with 'cmds' is lists.py.
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)
35 def cmd_annotation_classes():
36 return tuple([tuple([cmd[0].lower(), cmd[1]]) for cmd in cmds.values()])
38 class Decoder(srd.Decoder):
42 longname = 'Amulet LCD ASCII'
43 desc = 'Amulet Technologies LCD controller ASCII protocol.'
48 annotations = cmd_annotation_classes() + (
51 ('warning', 'Warning'),
54 ('bits', 'Bits', (L + 0,)),
55 ('fields', 'Fields', (L + 1,)),
56 ('commands', 'Commands', tuple(range(L))),
57 ('warnings', 'Warnings', (L + 2,)),
60 {'id': 'ms_chan', 'desc': 'Master -> slave channel',
61 'default': 'RX', 'values': ('RX', 'TX')},
62 {'id': 'sm_chan', 'desc': 'Slave -> master channel',
63 'default': 'TX', 'values': ('RX', 'TX')},
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>.
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())
82 self.out_ann = self.register(srd.OUTPUT_ANN)
85 # Simplification, most annotations span exactly one SPI byte/packet.
86 self.put(self.ss, self.es, self.out_ann, data)
89 self.put(self.ss_field, self.es_field, self.out_ann, data)
92 self.put(self.ss_cmd, self.es_cmd, self.out_ann, data)
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]
99 def emit_cmd_byte(self):
100 self.ss_cmd = self.ss
101 self.putx([Ann.FIELD, self.cmd_ann_list()])
103 def emit_addr_bytes(self, pdata):
104 if self.cmdstate == 2:
105 self.ss_field = self.ss
106 self.addr = chr(pdata)
107 self.putx([Ann.BIT, ['Address high nibble: %c' % pdata,
108 'Addr high 0x%c' % pdata, 'Addr h 0x%c' % pdata]])
109 elif self.cmdstate == 3:
110 self.es_field = self.es
111 self.addr += chr(pdata)
112 self.addr = int(self.addr, 16)
113 self.putx([Ann.BIT, ['Address low nibble: %c' % pdata,
114 'Addr low 0x%c' % pdata, 'Addr l 0x%c' % pdata]])
115 self.putf([Ann.FIELD, ['Address: 0x%02X' % self.addr,
116 'Addr: 0x%02X' % self.addr, '0x%02X' % self.addr]])
118 def emit_cmd_end(self, data):
119 self.es_cmd = self.es
123 def handle_read(self, data):
124 if self.cmdstate == 1:
127 elif self.cmdstate == 2:
128 self.emit_addr_bytes(pdata)
129 elif self.cmdstate == 3:
130 self.emit_addr_bytes(pdata)
133 def handle_set_common(self, pdata):
134 if self.cmdstate == 1:
136 self.emit_addr_bytes(pdata)
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)
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
150 # Null terminated string ends.
151 self.es_field = self.es
152 self.putx([Ann.BIT, ['NULL']])
153 self.putf([Ann.FIELD, ['Value: %s' % self.value,
154 'Val: %s' % self.value, '%s' % self.value]])
155 self.emit_cmd_end([ann_class, self.cmd_ann_list()])
157 if self.cmdstate > 3:
158 self.value += chr(pdata)
159 self.putx([Ann.BIT, ['%c' % pdata]])
164 # Page change 0xA0, 0x02, index_high, index_low, checksum
165 def handle_page(self, pdata):
166 if self.cmdstate == 2:
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
173 self.putx([Ann.WARN, ['Illegal second byte for page change',
176 elif self.cmdstate == 3:
177 self.ss_field = self.ss
178 self.checksum += pdata
180 elif self.cmdstate == 4:
181 self.checksum += pdata
183 self.es_field = self.es
184 if self.page[0] == self.page [1] == 0xFF:
186 self.putf(Ann.WARN, ['Soft reset', 'Reset'])
188 page = chr(self.page[0]) + chr(self.page[1])
189 self.putf(Ann.FIELD, ['Page index: 0x%s' % page,
190 'Page: 0x%s' % page, '0x%s' % page])
191 elif self.cmdstate == 5:
192 self.checksum += pdata
193 if (self.checksum & 0xFF) != 0:
194 self.putx([Ann.WARN, ['Checksum error', 'Error', 'ERR']])
196 self.putx([Ann.FIELD, ['Checksum OK', 'OK']])
197 self.emit_cmd_end(Ann.PAGE)
200 # Value reads: command byte, address high nibble, address low nibble
203 def handle_gbv(self, pdata):
204 self.handle_read(pdata)
205 self.emit_cmd_end([Ann.GBV, self.cmd_ann_list()])
208 def handle_gwv(self, pdata):
209 self.handle_read(pdata)
210 self.emit_cmd_end([Ann.GWV, self.cmd_ann_list()])
213 def handle_gsv(self, pdata):
214 self.handle_read(pdata)
215 self.emit_cmd_end([Ann.GSV, self.cmd_ann_list()])
218 def handle_glv(self, pdata):
219 self.handle_read(pdata)
220 self.emit_cmd_end([Ann.GLV, self.cmd_ann_list()])
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
230 self.putf([Ann.FIELD, ['RPC flag: 0x%02X' % self.flags]])
231 self.emit_cmd_end([Ann.GRPC, self.cmd_ann_list()])
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()])
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()])
244 def handle_gcv(self, pdata):
245 self.handle_read(pdata)
246 self.emit_cmd_end([Ann.GCV, self.cmd_ann_list()])
248 # Value setters: command byte, address high nibble, address low nibble, data bytes
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()])
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
270 self.ss_field = self.ss
272 self.value += int(chr(pdata), 16) << 12 - (4 * nibble)
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()])
281 # Set string value, null terminated utf8 strings
282 def handle_ssv(self, pdata):
283 self.handle_string(pdata, Ann.SSV)
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
291 self.putx([Ann.BIT, ['Address high nibble: %c' % pdata,
292 'Addr high 0x%c' % pdata, '0x%c' % pdata]])
293 elif self.cmdstate == 3:
294 self.addr += int(chr(pdata), 16)
295 self.es_field = self.ss
296 self.putx([Ann.BIT, ['Address low nibble: %c' % pdata,
297 'Addr low 0x%c' % pdata, '0x%c' % pdata]])
298 self.putf([Ann.FIELD, ['Address: 0x%02X' % self.addr,
299 'Addr: 0x%02X' % self.addr, '0x%02X' % self.addr]])
302 # Null terminated list
303 self.emit_cmd_end([Ann.SBVA, self.cmd_ann_list()])
305 self.value = int(chr(pdata), 16) << 4
307 self.value += int(chr(pdata), 16)
308 self.es_field = self.es
309 self.putf([Ann.FIELD, ['Value 0x%02X' % self.value,
310 '0x%02X' % self.value]])
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
319 self.putx([Ann.BIT, ['Address high nibble: %c' % pdata,
320 'Addr high 0x%c' % pdata, '0x%c' % pdata]])
321 elif self.cmdstate == 3:
322 self.addr += int(chr(pdata), 16)
323 self.es_field = self.ss
324 self.putx([Ann.BIT, ['Address low nibble: %c' % pdata,
325 'Addr low 0x%c' % pdata, '0x%c' % pdata]])
326 self.putf([Ann.FIELD, ['Address: 0x%02X' % self.addr,
327 'Addr: 0x%02X' % self.addr, '0x%02X' % self.addr]])
330 self.value += int(chr(pdata), 16) << 12 - (4 * nibble)
333 # Null terminated list
334 self.emit_cmd_end([Ann.SWVA, self.cmd_ann_list()])
336 self.ss_field = self.ss
338 self.es_field = self.es
339 self.putf([Ann.FIELD, ['Value 0x%04X' % self.value,
340 '0x%04X' % self.value]])
344 def handle_scv(self, pdata):
345 if self.cmdstate == 8:
346 self.emit_not_implemented([Ann.SCV, self.cmd_ann_list()])
350 def handle_rpc(self, pdata):
351 self.handle_read(pdata)
352 self.emit_cmd_end([Ann.RPC, self.cmd_ann_list()])
356 # Decode pair of (x,y) 16bit coordinates
357 def decode_coords(self, pdata):
358 if self.cmdstate == 1:
363 if self.cmdstate < 18:
365 nibble = (self.cmdstate - 1) % 4
366 i = (self.cmdstate - 1) / 4
367 self.coords[i] += int(chr(pdata), 16) << 12 - (4 * nibble)
369 self.ss_field = self.ss
371 self.es_field = self.es
372 self.putf([Ann.FIELD, ['Coordinate 0x%04X' % self.coords[i]],
373 ['0x%04X' % self.coords[i]]])
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...
381 def handle_line(self, 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']])
391 def handle_rect(self, 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']])
400 # Draw filled rectangle
401 def handle_frect(self, 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']])
411 def handle_pixel(self, pdata):
412 self.es_cmd = self.es
413 self.putc([Ann.WARN, ['Draw pixel documentation is missing.', 'Undocumented']])
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
422 self.putx([Ann.BIT, ['High nibble 0x%s' % pdata, '0x%s' % pdata]])
423 elif self.cmdstate == 5:
424 self.value += int(chr(pdata), 16)
425 self.putx([Ann.BIT, ['Low nibble 0x%s' % pdata, '0x%s' % pdata]])
426 self.es_field = self.es
427 self.putf([Ann.FIELD, ['Value: 0x%02X' % self.value,
428 '0x%02X' % self.value]])
429 self.emit_cmd_end([Ann.GBVR, self.cmd_ann_list()])
432 def handle_gwvr(self, pdata):
433 self.emit_add_bytes(pdata)
434 if self.cmdstate > 3:
435 nibble = self.cmdstate - 3
438 self.ss_field = self.ss
439 self.value += int(chr(pdata), 16) << 12 - (4 * nibble)
440 self.putx([Ann.BIT, ['0x%s' % pdata]])
442 self.putf([Ann.FIELD, ['Value: 0x%04x' % self.value,
443 '0x%04X' % self.value]])
444 self.es_cmd = self.ss
445 self.emit_cmd_end([Ann.GWVR, self.cmd_ann_list()])
448 def handle_gsvr(self, pdata):
449 self.handle_string(pdata, Ann.GSVR)
451 def handle_glvr(self, pdata):
452 self.handle_string(pdata, Ann.GLVR)
454 def handle_grpcr(self, pdata):
455 self.handle_addr(pdata)
456 if self.cmdstate > 3:
457 nibble = (self.cmdstate - 3) % 2
460 self.emit_cmd_end([Ann.GRPCR, self.cmd_ann_list()])
462 self.value = int(chr(pdata), 16) << 4
463 self.ss_field = self.ss
464 self.putx([Ann.BIT, ['0x%s' % pdata]])
466 self.value += int(chr(pdata), 16)
467 self.es_field = self.es
468 self.putx([Ann.BIT, ['0x%s' % pdata]])
469 self.putf([Ann.FIELD, ['0x%02X' % self.value]])
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()])
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()])
504 def handle_ssvr(self, pdata):
505 self.handle_string(pdata, Ann.SSVR)
507 def handle_rpcr(self, pdata):
508 self.handle_read(pdata)
509 self.emit_cmd_end([Ann.RPCR, self.cmd_ann_list()])
511 def handle_liner(self, 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']])
520 def handle_rectr(self, 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']])
529 def handle_frectr(self, 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']])
538 def handle_pixelr(self, pdata):
539 self.es_cmd = self.es
540 self.putc([Ann.WARN,['Draw pixel documentation is missing.', 'Undocumented']])
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
548 self.putx([Ann.BIT, ['Address high nibble: %c' % pdata,
549 'Addr high 0x%c' % pdata, '0x%c' % pdata]])
550 elif self.cmdstate == 3:
551 self.addr += int(chr(pdata), 16)
552 self.es_field = self.ss
553 self.putx([Ann.BIT, ['Address low nibble: %c' % pdata,
554 'Addr low 0x%c' % pdata, '0x%c' % pdata]])
555 self.putf([Ann.FIELD, ['Address: 0x%02X' % self.addr,
556 'Addr: 0x%02X' % self.addr, '0x%02X' % self.addr]])
559 # Null terminated list
560 self.emit_cmd_end([Ann.GBVAR, self.cmd_ann_list()])
562 self.value = int(chr(pdata), 16) << 4
564 self.value += int(chr(pdata), 16)
565 self.es_field = self.es
566 self.putf([Ann.FIELD, ['Value 0x%02X' % self.value,
567 '0x%02X' % self.value]])
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
575 self.putx([Ann.BIT, ['Address high nibble: %c' % pdata,
576 'Addr high 0x%c' % pdata, '0x%c' % pdata]])
577 elif self.cmdstate == 3:
578 self.addr += int(chr(pdata), 16)
579 self.es_field = self.ss
580 self.putx([Ann.BIT, ['Address low nibble: %c' % pdata,
581 'Addr low 0x%c' % pdata, '0x%c' % pdata]])
582 self.putf([Ann.FIELD, ['Address: 0x%02X' % self.addr,
583 'Addr: 0x%02X' % self.addr, '0x%02X' % self.addr]])
586 self.value += int(chr(pdata), 16) << 12 - (4 * nibble)
589 # Null terminated list
590 self.emit_cmd_end([Ann.GWVAR, self.cmd_ann_list()])
592 self.ss_field = self.ss
594 self.es_field = self.es
595 self.putf([Ann.FIELD, ['Value 0x%04X' % self.value,
596 '0x%04X' % self.value]])
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
605 self.putx([Ann.BIT, ['Address high nibble: %c' % pdata,
606 'Addr high 0x%c' % pdata, '0x%c' % pdata]])
607 elif self.cmdstate == 3:
608 self.addr += int(chr(pdata), 16)
609 self.es_field = self.ss
610 self.putx([Ann.BIT, ['Address low nibble: %c' % pdata,
611 'Addr low 0x%c' % pdata, '0x%c' % pdata]])
612 self.putf([Ann.FIELD, ['Address: 0x%02X' % self.addr,
613 'Addr: 0x%02X' % self.addr, '0x%02X' % self.addr]])
616 # Null terminated list
617 self.emit_cmd_end([Ann.SBVAR, self.cmd_ann_list()])
619 self.value = int(chr(pdata), 16) << 4
621 self.value += int(chr(pdata), 16)
622 self.es_field = self.es
623 self.putf([Ann.FIELD, ['Value 0x%02X' % self.value,
624 '0x%02X' % self.value]])
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
633 self.putx([Ann.BIT, ['Address high nibble: %c' % pdata,
634 'Addr high 0x%c' % pdata, '0x%c' % pdata]])
635 elif self.cmdstate == 3:
636 self.addr += int(chr(pdata), 16)
637 self.es_field = self.ss
638 self.putx([Ann.BIT, ['Address low nibble: %c' % pdata,
639 'Addr low 0x%c' % pdata, '0x%c' % pdata]])
640 self.putf([Ann.FIELD, ['Address: 0x%02X' % self.addr,
641 'Addr: 0x%02X' % self.addr, '0x%02X' % self.addr]])
644 self.value += int(chr(pdata), 16) << 12 - (4 * nibble)
647 # Null terminated list
648 self.emit_cmd_end([Ann.SWVAR, self.cmd_ann_list()])
650 self.ss_field = self.ss
652 self.es_field = self.es
653 self.putf([Ann.FIELD, ['Value 0x%04X' % self.value,
654 '0x%04X' % self.value]])
657 def handle_gcvr(self, pdata):
658 if self.cmdstate == 8:
659 self.emit_not_implemented([Ann.SCV, self.cmd_ann_list()])
662 def handle_scvr(self, pdata):
663 if self.cmdstate == 8:
664 self.emit_not_implemented([Ann.SCV, self.cmd_ann_list()])
669 def handle_ack(self, pdata):
670 self.putx([Ann.ACK, self.cmd_ann_list()])
673 def handle_nack(self, pdata):
674 self.putx([Ann.NACK, self.cmd_ann_list()])
677 def decode(self, ss, es, data):
678 ptype, rxtx, pdata = data
680 self.ss, self.es = ss, es
687 abort_current = (0xD0 <= pdata[0] <= 0xF7) and \
688 (not (self.state in cmds_with_high_bytes)) and \
691 self.putx([Ann.WARN, ['Command aborted by invalid byte', 'Abort']])
692 self.state = pdata[0]
695 if self.state is None:
696 self.state = pdata[0]
699 self.cmd_handlers[self.state](pdata[0])
701 self.putx([Ann.WARN, ['Unknown command: 0x%02x' % pdata[0]]])