]> sigrok.org Git - libsigrokdecode.git/commitdiff
nunchuk: Fix PD to become usable in GUIs.
authorUwe Hermann <redacted>
Wed, 5 Feb 2014 17:25:22 +0000 (18:25 +0100)
committerUwe Hermann <redacted>
Tue, 15 Apr 2014 08:43:49 +0000 (10:43 +0200)
 - Provide proper annotation classes and annotation rows.
 - Emit bit-exact annotations for some registers.
 - Output short and long annotations (for use when zooming).
 - Various minor fixes.

This fixes bug #344.

decoders/nunchuk/pd.py

index dfe9abe4e0a0d78a0fc4e03ccabc64a1f3ab0eee..5eccd53d6bb9c2ad7e53d581eb16146cec9b46c2 100644 (file)
@@ -1,7 +1,7 @@
 ##
 ## This file is part of the libsigrokdecode project.
 ##
-## Copyright (C) 2010-2012 Uwe Hermann <uwe@hermann-uwe.de>
+## Copyright (C) 2010-2014 Uwe Hermann <uwe@hermann-uwe.de>
 ##
 ## This program is free software; you can redistribute it and/or modify
 ## it under the terms of the GNU General Public License as published by
@@ -29,10 +29,22 @@ class Decoder(srd.Decoder):
     license = 'gplv2+'
     inputs = ['i2c']
     outputs = ['nunchuck']
-    annotations = (
-        ('text-verbose', 'Human-readable text (verbose)'),
-        ('text', 'Human-readable text'),
-        ('warnings', 'Human-readable warnings'),
+    annotations = \
+        tuple(('reg-0x%02X' % i, 'Register 0x%02X' % i) for i in range(6)) + (
+        ('bit-bz', 'BZ bit'),
+        ('bit-bc', 'BC bit'),
+        ('bit-ax', 'AX bits'),
+        ('bit-ay', 'AY bits'),
+        ('bit-az', 'AZ bits'),
+        ('nunchuk-write', 'Nunchuk write'),
+        ('cmd-init', 'Init command'),
+        ('summary', 'Summary'),
+        ('warnings', 'Warnings'),
+    )
+    annotation_rows = (
+        ('regs', 'Registers', tuple(range(13))),
+        ('summary', 'Summary', (13,)),
+        ('warnings', 'Warnings', (14,)),
     )
 
     def __init__(self, **kwargs):
@@ -40,6 +52,7 @@ class Decoder(srd.Decoder):
         self.sx = self.sy = self.ax = self.ay = self.az = self.bz = self.bc = -1
         self.databytecount = 0
         self.reg = 0x00
+        self.ss = self.es = self.block_ss = self.block_es = 0
         self.init_seq = []
 
     def start(self):
@@ -47,41 +60,42 @@ class Decoder(srd.Decoder):
         self.out_ann = self.register(srd.OUTPUT_ANN)
 
     def putx(self, data):
-        # Helper for annotations which span exactly one I²C packet.
         self.put(self.ss, self.es, self.out_ann, data)
 
     def putb(self, data):
-        # Helper for annotations which span a block of I²C packets.
-        self.put(self.block_start_sample, self.block_end_sample,
-                 self.out_ann, data)
+        self.put(self.block_ss, self.block_es, self.out_ann, data)
+
+    def putd(self, bit1, bit2, data):
+        self.put(self.bits[bit1][1], self.bits[bit2][2], self.out_ann, data)
 
     def handle_reg_0x00(self, databyte):
+        self.block_ss = self.ss
         self.sx = databyte
-        self.putx([0, ['Analog stick X position: 0x%02x' % self.sx]])
-        self.putx([1, ['SX: 0x%02x' % self.sx]])
+        self.putx([0, ['Analog stick X position: 0x%02X' % self.sx,
+                       'SX: 0x%02X' % self.sx]])
 
     def handle_reg_0x01(self, databyte):
         self.sy = databyte
-        self.putx([0, ['Analog stick Y position: 0x%02x' % self.sy]])
-        self.putx([1, ['SY: 0x%02x' % self.sy]])
+        self.putx([1, ['Analog stick Y position: 0x%02X' % self.sy,
+                       'SY: 0x%02X' % self.sy]])
 
     def handle_reg_0x02(self, databyte):
         self.ax = databyte << 2
-        self.putx([0, ['Accelerometer X value bits[9:2]: 0x%03x' % self.ax]])
-        self.putx([1, ['AX[9:2]: 0x%03x' % self.ax]])
+        self.putx([2, ['Accelerometer X value bits[9:2]: 0x%03X' % self.ax,
+                       'AX[9:2]: 0x%03X' % self.ax]])
 
     def handle_reg_0x03(self, databyte):
         self.ay = databyte << 2
-        self.putx([0, ['Accelerometer Y value bits[9:2]: 0x%03x' % self.ay]])
-        self.putx([1, ['AY[9:2]: 0x%x' % self.ay]])
+        self.putx([3, ['Accelerometer Y value bits[9:2]: 0x%03X' % self.ay,
+                       'AY[9:2]: 0x%03X' % self.ay]])
 
     def handle_reg_0x04(self, databyte):
         self.az = databyte << 2
-        self.putx([0, ['Accelerometer Z value bits[9:2]: 0x%03x' % self.az]])
-        self.putx([1, ['AZ[9:2]: 0x%x' % self.az]])
+        self.putx([4, ['Accelerometer Z value bits[9:2]: 0x%03X' % self.az,
+                       'AZ[9:2]: 0x%03X' % self.az]])
 
-    # TODO: Bit-exact annotations.
     def handle_reg_0x05(self, databyte):
+        self.block_es = self.es
         self.bz = (databyte & (1 << 0)) >> 0 # Bits[0:0]
         self.bc = (databyte & (1 << 1)) >> 1 # Bits[1:1]
         ax_rest = (databyte & (3 << 2)) >> 2 # Bits[3:2]
@@ -91,68 +105,64 @@ class Decoder(srd.Decoder):
         self.ay |= ay_rest
         self.az |= az_rest
 
+        # self.putx([5, ['Register 5', 'Reg 5', 'R5']])
+
         s = '' if (self.bz == 0) else 'not '
-        self.putx([0, ['Z button: %spressed' % s]])
-        self.putx([1, ['BZ: %d' % self.bz]])
+        self.putd(0, 0, [6, ['Z: %spressed' % s, 'BZ: %d' % self.bz]])
 
         s = '' if (self.bc == 0) else 'not '
-        self.putx([0, ['C button: %spressed' % s]])
-        self.putx([1, ['BC: %d' % self.bc]])
+        self.putd(1, 1, [7, ['C: %spressed' % s, 'BC: %d' % self.bc]])
 
-        self.putx([0, ['Accelerometer X value bits[1:0]: 0x%x' % ax_rest]])
-        self.putx([1, ['AX[1:0]: 0x%x' % ax_rest]])
+        self.putd(3, 2, [8, ['Accelerometer X value bits[1:0]: 0x%X' % ax_rest,
+                             'AX[1:0]: 0x%X' % ax_rest]])
 
-        self.putx([0, ['Accelerometer Y value bits[1:0]: 0x%x' % ay_rest]])
-        self.putx([1, ['AY[1:0]: 0x%x' % ay_rest]])
+        self.putd(5, 4, [9, ['Accelerometer Y value bits[1:0]: 0x%X' % ay_rest,
+                             'AY[1:0]: 0x%X' % ay_rest]])
 
-        self.putx([0, ['Accelerometer Z value bits[1:0]: 0x%x' % az_rest]])
-        self.putx([1, ['AZ[1:0]: 0x%x' % az_rest]])
+        self.putd(7, 6, [10, ['Accelerometer Z value bits[1:0]: 0x%X' % az_rest,
+                              'AZ[1:0]: 0x%X' % az_rest]])
+
+        self.reg = 0x00
 
     def output_full_block_if_possible(self):
-        # For now, only output summary annotation if all values are available.
+        # For now, only output summary annotations if all values are available.
         t = (self.sx, self.sy, self.ax, self.ay, self.az, self.bz, self.bc)
         if -1 in t:
             return
-
-        s = 'Analog stick X position: 0x%02x\n' % self.sx
-        s += 'Analog stick Y position: 0x%02x\n' % self.sy
-        s += 'Z button: %spressed\n' % ('' if (self.bz == 0) else 'not ')
-        s += 'C button: %spressed\n' % ('' if (self.bc == 0) else 'not ')
-        s += 'Accelerometer X value: 0x%03x\n' % self.ax
-        s += 'Accelerometer Y value: 0x%03x\n' % self.ay
-        s += 'Accelerometer Z value: 0x%03x\n' % self.az
-        self.put(self.block_start_sample, self.block_end_sample,
-                 self.out_ann, [0, [s]])
-
-        s = 'SX = 0x%02x, SY = 0x%02x, AX = 0x%02x, AY = 0x%02x, ' \
-            'AZ = 0x%02x, BZ = 0x%02x, BC = 0x%02x' % (self.sx, \
-            self.sy, self.ax, self.ay, self.az, self.bz, self.bc)
-        self.put(self.block_start_sample, self.block_end_sample,
-                 self.out_ann, [1, [s]])
+        bz = 'pressed' if self.bz == 1 else 'not pressed'
+        bc = 'pressed' if self.bc == 1 else 'not pressed'
+        s = 'Analog stick: %d/%d, accelerometer: %d/%d/%d, Z: %s, C: %s' % \
+            (self.sx, self.sy, self.ax, self.ay, self.az, bz, bc)
+        self.putb([13, [s]])
 
     def handle_reg_write(self, databyte):
-        self.putx([0, ['Nunchuk write: 0x%02x' % databyte]])
+        self.putx([11, ['Nunchuk write: 0x%02X' % databyte]])
         if len(self.init_seq) < 2:
             self.init_seq.append(databyte)
 
     def output_init_seq(self):
         if len(self.init_seq) != 2:
-            self.putb([2, ['Init sequence was %d bytes long (2 expected)' % \
+            self.putb([14, ['Init sequence was %d bytes long (2 expected)' % \
                       len(self.init_seq)]])
+            return
 
-        if self.init_seq != (0x40, 0x00):
-            self.putb([2, ['Unknown init sequence (expected: 0x40 0x00)']])
+        if self.init_seq != [0x40, 0x00]:
+            self.putb([14, ['Unknown init sequence (expected: 0x40 0x00)']])
+            return
 
         # TODO: Detect Nunchuk clones (they have different init sequences).
-        s = 'Initialized Nintendo Wii Nunchuk'
 
-        self.putb([0, [s]])
-        self.putb([1, ['INIT']])
+        self.putb([12, ['Initialize Nunchuk', 'Init Nunchuk', 'Init', 'I']])
 
     def decode(self, ss, es, data):
         cmd, databyte = data
 
-        # Store the start/end samples of this I²C packet.
+        # Collect the 'BITS' packet, then return. The next packet is
+        # guaranteed to belong to these bits we just stored.
+        if cmd == 'BITS':
+            self.bits = databyte
+            return
+
         self.ss, self.es = ss, es
 
         # State machine.
@@ -180,7 +190,7 @@ class Decoder(srd.Decoder):
                 self.bz = self.bc = -1
                 self.state = 'IDLE'
             else:
-                # self.putx([0, ['Ignoring: %s (data=%s)' % (cmd, databyte)]])
+                # self.putx([14, ['Ignoring: %s (data=%s)' % (cmd, databyte)]])
                 pass
         elif self.state == 'WRITE REGS':
             if cmd == 'DATA WRITE':
@@ -191,7 +201,7 @@ class Decoder(srd.Decoder):
                 self.init_seq = []
                 self.state = 'IDLE'
             else:
-                # self.putx([0, ['Ignoring: %s (data=%s)' % (cmd, databyte)]])
+                # self.putx([14, ['Ignoring: %s (data=%s)' % (cmd, databyte)]])
                 pass
         else:
             raise Exception('Invalid state: %s' % self.state)