]> sigrok.org Git - libsigrokdecode.git/blobdiff - decoders/nunchuk/nunchuk.py
srd: nunchuk: Support for the Nunchuk init sequence.
[libsigrokdecode.git] / decoders / nunchuk / nunchuk.py
index b274f4ad00578ab08fc9eb616ae23b9471df4869..0dae39c504114ec3013d1bece3e4141e216e760a 100644 (file)
@@ -37,13 +37,15 @@ class Decoder(srd.Decoder):
     annotations = [
         ['Text (verbose)', 'Human-readable text (verbose)'],
         ['Text', 'Human-readable text'],
+        ['Warnings', 'Human-readable warnings'],
     ]
 
     def __init__(self, **kwargs):
         self.state = 'IDLE'
-        self.sx = self.sy = self.ax = self.ay = self.az = self.bz = self.bc = 0
+        self.sx = self.sy = self.ax = self.ay = self.az = self.bz = self.bc = -1
         self.databytecount = 0
         self.reg = 0x00
+        self.init_seq = []
 
     def start(self, metadata):
         # self.out_proto = self.add(srd.OUTPUT_PROTO, 'nunchuk')
@@ -56,6 +58,11 @@ class Decoder(srd.Decoder):
         # Helper for annotations which span exactly one I2C packet.
         self.put(self.ss, self.es, self.out_ann, data)
 
+    def putb(self, data):
+        # Helper for annotations which span a block of I2C packets.
+        self.put(self.block_start_sample, self.block_end_sample,
+                 self.out_ann, data)
+
     def handle_reg_0x00(self, databyte):
         self.sx = databyte
         self.putx([0, ['Analog stick X position: 0x%02x' % self.sx]])
@@ -109,6 +116,47 @@ class Decoder(srd.Decoder):
         self.putx([0, ['Accelerometer Z value bits[1:0]: 0x%x' % az_rest]])
         self.putx([1, ['AZ[1:0]: 0x%x' % az_rest]])
 
+    def output_full_block_if_possible(self):
+        # For now, only output summary annotation 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]])
+
+    def handle_reg_write(self, databyte):
+        self.putx([0, ['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)' % \
+                      len(self.init_seq)]])
+
+        if self.init_seq != (0x40, 0x00):
+            self.putb([2, ['Unknown init sequence (expected: 0x40 0x00)']])
+
+        # TODO: Detect Nunchuk clones (they have different init sequences).
+        s = 'Initialized Nintendo Wii Nunchuk'
+
+        self.putb([0, [s]])
+        self.putb([1, ['INIT']])
+
     def decode(self, ss, es, data):
         cmd, databyte = data
 
@@ -123,10 +171,11 @@ class Decoder(srd.Decoder):
             self.state = 'GET SLAVE ADDR'
             self.block_start_sample = ss
         elif self.state == 'GET SLAVE ADDR':
-            # Wait for an address read operation.
-            if cmd != 'ADDRESS READ':
-                return
-            self.state = 'READ REGS'
+            # Wait for an address read/write operation.
+            if cmd == 'ADDRESS READ':
+                self.state = 'READ REGS'
+            elif cmd == 'ADDRESS WRITE':
+                self.state = 'WRITE REGS'
         elif self.state == 'READ REGS':
             if cmd == 'DATA READ':
                 handle_reg = getattr(self, 'handle_reg_0x%02x' % self.reg)
@@ -134,17 +183,20 @@ class Decoder(srd.Decoder):
                 self.reg += 1
             elif cmd == 'STOP':
                 self.block_end_sample = es
-
-                # TODO: Only works if host reads _all_ regs (0x00 - 0x05).
-                d = '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, [0, [d]])
-
-                self.sx = self.sy = self.ax = self.ay = self.az = 0
-                self.bz = self.bc = 0
-
+                self.output_full_block_if_possible()
+                self.sx = self.sy = self.ax = self.ay = self.az = -1
+                self.bz = self.bc = -1
+                self.state = 'IDLE'
+            else:
+                # self.putx([0, ['Ignoring: %s (data=%s)' % (cmd, databyte)]])
+                pass
+        elif self.state == 'WRITE REGS':
+            if cmd == 'DATA WRITE':
+                self.handle_reg_write(databyte)
+            elif cmd == 'STOP':
+                self.block_end_sample = es
+                self.output_init_seq()
+                self.init_seq = []
                 self.state = 'IDLE'
             else:
                 # self.putx([0, ['Ignoring: %s (data=%s)' % (cmd, databyte)]])