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 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,)), 56 ('commands', 'Commands', tuple(range(len(cmds)))), 57 ('warnings', 'Warnings', (L + 2,)), 58 ) 59 options = ( 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')}, 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) 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]]) 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']]) 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()]) 156 return 157 if self.cmdstate > 3: 158 self.value += chr(pdata) 159 self.putx([Ann.BIT, ['%c' % pdata]]) 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]) 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']]) 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 230 self.putf([Ann.FIELD, ['RPC flag: 0x%02X' % self.flags]]) 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 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]]) 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 309 self.putf([Ann.FIELD, ['Value 0x%02X' % self.value, 310 '0x%02X' % self.value]]) 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 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]]) 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 339 self.putf([Ann.FIELD, ['Value 0x%04X' % self.value, 340 '0x%04X' % self.value]]) 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 372 self.putf([Ann.FIELD, ['Coordinate 0x%04X' % self.coords[i]], 373 ['0x%04X' % self.coords[i]]]) 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 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()]) 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) 440 self.putx([Ann.BIT, ['0x%s' % pdata]]) 441 if nibble == 3: 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()]) 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 464 self.putx([Ann.BIT, ['0x%s' % pdata]]) 465 if nibble == 2: 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]]) 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 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]]) 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 566 self.putf([Ann.FIELD, ['Value 0x%02X' % self.value, 567 '0x%02X' % self.value]]) 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 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]]) 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 595 self.putf([Ann.FIELD, ['Value 0x%04X' % self.value, 596 '0x%04X' % self.value]]) 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 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]]) 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 623 self.putf([Ann.FIELD, ['Value 0x%02X' % self.value, 624 '0x%02X' % self.value]]) 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 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]]) 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 653 self.putf([Ann.FIELD, ['Value 0x%04X' % self.value, 654 '0x%04X' % self.value]]) 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 695 if self.state is None: 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 703