]> sigrok.org Git - libsigrokdecode.git/commitdiff
Add ADXL345 decoder.
authorTeo Perisanu <redacted>
Tue, 17 Mar 2020 08:52:37 +0000 (10:52 +0200)
committerUwe Hermann <redacted>
Fri, 10 Apr 2020 23:13:59 +0000 (01:13 +0200)
Signed-off-by: Teo Perisanu <redacted>
decoders/adxl345/__init__.py [new file with mode: 0644]
decoders/adxl345/lists.py [new file with mode: 0644]
decoders/adxl345/pd.py [new file with mode: 0644]

diff --git a/decoders/adxl345/__init__.py b/decoders/adxl345/__init__.py
new file mode 100644 (file)
index 0000000..e46bce9
--- /dev/null
@@ -0,0 +1,26 @@
+##
+## This file is part of the libsigrokdecode project.
+##
+## Copyright (C) 2020 Analog Devices Inc.
+##
+## 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
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+##
+
+'''
+This decoder stacks on top of the 'spi' PD and decodes the
+Analog Devices ADXL345 protocol.
+'''
+
+from .pd import Decoder
diff --git a/decoders/adxl345/lists.py b/decoders/adxl345/lists.py
new file mode 100644 (file)
index 0000000..c22ef3e
--- /dev/null
@@ -0,0 +1,96 @@
+##
+## This file is part of the libsigrokdecode project.
+##
+## Copyright (C) 2020 Analog Devices Inc.
+##
+## 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
+## the Free Software Foundation; either version 2 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+##
+
+error_messages = {
+    'interrupt': ['Interrupt'],
+    'undesirable':  ['Undesirable behavior'],
+    'dis_single': ['Disable single tap'],
+    'dis_double': ['Disable double tap'],
+    'dis_single_double': ['Disable single/double tap'],
+}
+
+rate_code = {
+    0x00: 0.1,
+    0x01: 0.2,
+    0x02: 0.39,
+    0x03: 0.78,
+    0x04: 1.56,
+    0x05: 3.13,
+    0x06: 6.25,
+    0x07: 12.5,
+    0x08: 25,
+    0x09: 50,
+    0x0A: 100,
+    0x0B: 200,
+    0x0C: 400,
+    0x0D: 800,
+    0x0E: 1600,
+    0x0F: 3200,
+}
+
+fifo_modes = {
+    0x00: 'Bypass',
+    0x01: 'FIFO',
+    0x02: 'Stream',
+    0x03: 'Trigger',
+}
+
+operations = {
+    0x00: ['WRITE REG', 'WRITE', 'W'],
+    0x01: ['READ REG', 'READ', 'R'],
+}
+
+number_bytes = {
+    0x00: ['SINGLE BYTE', 'SING BYTE', '1 BYTE', '1B'],
+    0x01: ['MULTIPLE BYTES', 'MULTI BYTES', 'n*BYTES', 'n*B'],
+}
+
+registers = {
+    0x00: ['DEVID', 'DID', 'ID'],
+    0x1D: ['THRESH_TAP', 'TH_TAP', 'TH_T'],
+    0x1E: ['OFSX', 'OFX'],
+    0x1F: ['OFSY', 'OFY'],
+    0x20: ['OFSZ', 'OFZ'],
+    0x21: ['DUR'],
+    0x22: ['Latent', 'Lat'],
+    0x23: ['Window', 'Win'],
+    0x24: ['THRESH_ACT', 'TH_ACT', 'TH_A'],
+    0x25: ['THRESH_INACT', 'TH_INACT', 'TH_I'],
+    0x26: ['TIME_INACT', 'TI_INACT', 'TI_I'],
+    0x27: ['ACT_INACT_CTL', 'ACT_I_CTL', 'A_I_C'],
+    0x28: ['THRESH_FF', 'TH_FF'],
+    0x29: ['TIME_FF', 'TI_FF'],
+    0x2A: ['TAP_AXES', 'TAP_AX', 'TP_AX'],
+    0x2B: ['ACT_TAP_STATUS', 'ACT_TAP_STAT', 'ACT_TP_ST', 'A_T_S'],
+    0x2C: ['BW_RATE', 'BW_R'],
+    0x2D: ['POWER_CTL', 'PW_CTL', 'PW_C'],
+    0x2E: ['INT_ENABLE', 'INT_EN', 'I_EN'],
+    0x2F: ['INT_MAP', 'I_M'],
+    0x30: ['INT_SOURCE', 'INT_SRC', 'I_SRC', 'I_S'],
+    0x31: ['DATA_FORMAT', 'DATA_FRM', 'D_FRM', 'D_F'],
+    0x32: ['DATAX0', 'DX0', 'X0'],
+    0x33: ['DATAX1', 'DX1', 'X1'],
+    0x34: ['DATAY0', 'DY0', 'Y0'],
+    0x35: ['DATAY1', 'DY1', 'Y1'],
+    0x36: ['DATAZ0', 'DZ0', 'Z0'],
+    0x37: ['DATAZ1', 'DZ1', 'Z1'],
+    0x38: ['FIFO_CTL', 'FIF_CT', 'F_C'],
+    0x39: ['FIFO_STATUS', 'FIFO_STAT', 'FIF_ST', 'F_S'],
+}
diff --git a/decoders/adxl345/pd.py b/decoders/adxl345/pd.py
new file mode 100644 (file)
index 0000000..5b47c0b
--- /dev/null
@@ -0,0 +1,484 @@
+##
+## This file is part of the libsigrokdecode project.
+##
+## Copyright (C) 2020 Analog Devices Inc.
+##
+## 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
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, see <http://www.gnu.org/licenses/>.
+##
+
+import sigrokdecode as srd
+from .lists import *
+
+WORD_SIZE = 8
+
+class Channel():
+    MISO = 0
+    MOSI = 1
+
+class Operation():
+    READ = 0
+    WRITE = 1
+
+class BitType():
+    ENABLE = {1: ['Enable %s', 'En %s', '%s '], 0: ['Disable %s', 'Dis %s', '!%s '],}
+    SOURCE = {1: ['Involve %s', 'Inv %s', '%s'], 0: ['Not involve %s', 'Not inv %s', '!%s'],}
+    INTERRUPT = {1: ['INT2 %s', 'I2: %s '], 0: ['INT1 %s', 'I1:%s '],}
+    AC_DC = {1: ['%s ac', 'ac'], 0: ['%s dc', 'dc'],}
+    UNUSED = {1: ['N/A'], 0: ['N/A'],}
+    OTHER = 0
+
+class Bit():
+    def __init__(self, name, type, values=None):
+        self.value = 0
+        self.name = name
+        self.type = type
+        self.values = values
+
+    def set_value(self, value):
+        self.value = value
+
+    def get_bit_annotation(self):
+        if self.type == BitType.OTHER:
+            annotation = self.values[self.value].copy()
+        else:
+            annotation = self.type[self.value].copy()
+
+        for index in range(len(annotation)):
+            if '%s' in annotation[index]:
+                annotation[index] = str(annotation[index] % self.name)
+        return annotation
+
+class Decoder(srd.Decoder):
+    api_version = 3
+    id = 'adxl345'
+    name = 'ADXL345'
+    longname = 'Analog Devices ADXL345'
+    desc = 'Analog Devices ADXL345 3-axis accelerometer.'
+    license = 'gplv2+'
+    inputs = ['spi']
+    outputs = []
+    tags = ['IC', 'Sensor']
+    annotations = (
+        ('read', 'Read'),
+        ('write', 'Write'),
+        ('mb', 'Multiple bytes'),
+        ('reg-address', 'Register address'),
+        ('reg-data', 'Register data'),
+        ('warning', 'Warning'),
+    )
+    annotation_rows = (
+        ('reg', 'Registers', (0, 1, 2, 3)),
+        ('data', 'Data', (4, 5)),
+    )
+
+    def __init__(self):
+        self.reset()
+
+    def reset(self):
+        self.mosi = []
+        self.miso = []
+        self.reg = []
+        self.operation = None
+        self.address = 0
+        self.data = -1
+        self.state = 'IDLE'
+        self.ss = -1
+        self.es = -1
+        self.samples_per_bit = 0
+
+    def start(self):
+        self.out_ann = self.register(srd.OUTPUT_ANN)
+
+    def putx(self, data):
+        self.put(self.ss, self.es, self.out_ann, data)
+
+    def putb(self, data, index):
+        start = self.ss + (self.samples_per_bit * index)
+        self.put(start, start + self.samples_per_bit, self.out_ann, data)
+
+    def putbs(self, data, start_index, stop_index):
+        start = self.ss + (self.samples_per_bit * start_index)
+        stop = start + (self.samples_per_bit * (stop_index - start_index + 1))
+        self.put(start, stop, self.out_ann, data)
+
+    def handle_reg_with_scaling_factor(self, data, factor, name, unit, error_msg):
+        if data == 0 and error_msg is not None:
+            self.putx([5, error_msg])
+        else:
+            result = (data * factor) / 1000
+            ann = ['%s: %f %s' % (name, result, unit), '%f %s' % (result, unit)]
+            self.putx([4, ann])
+
+    def handle_reg_bit_msg(self, bit, index, en_msg, dis_msg):
+        if bit:
+            self.putb([4, [en_msg]], index)
+        else:
+            self.putb([4, [dis_msg]], index)
+
+    def interpret_bits(self, data, bits):
+        bits_values = []
+        for offset in range(8):
+            bits_values.insert(0, (data & (1 << offset)) >> offset)
+
+        for index in range(len(bits)):
+            if bits[index] is None:
+                continue
+            bit = bits[index]
+            bit.set_value(bits_values[index])
+            bit_annotation = bit.get_bit_annotation()
+            self.putb([4, bit_annotation], index)
+
+        return list(reversed(bits_values))
+
+    def reverse_bit_index(self, index, word_size):
+        return word_size - index - 1
+
+    def get_decimal_number(self, bits, start_index, stop_index):
+        number = 0
+        interval = range(start_index, stop_index + 1, 1)
+        for index, offset in zip(interval, range(len(interval))):
+            bit = bits[index]
+            number = number | (bit << offset)
+        return number
+
+    def get_axis_value(self, data, axis):
+        if self.data != - 1:
+            data <<= 8
+            self.data |= data
+            self.put(self.start_index, self.es, self.out_ann,
+                [4, ['%s: 0x%04X' % (axis, self.data), str(data)]])
+            self.data = -1
+        else:
+            self.putx([4, [str(data)]])
+
+    def handle_reg_0x1D(self, data):
+        self.handle_reg_with_scaling_factor(data, 62.5, 'Threshold', 'g',
+            error_messages['undesirable'])
+
+    def handle_reg_0x1E(self, data):
+        self.handle_reg_with_scaling_factor(data, 15.6, 'OFSX', 'g', None)
+
+    def handle_reg_0x1F(self, data):
+        self.handle_reg_with_scaling_factor(data, 15.6, 'OFSY', 'g', None)
+
+    def handle_reg_0x20(self, data):
+        self.handle_reg_with_scaling_factor(data, 15.6, 'OFSZ', 'g', None)
+
+    def handle_reg_0x21(self, data):
+        self.handle_reg_with_scaling_factor(data, 0.625, 'Time', 's',
+            error_messages['dis_single_double'])
+
+    def handle_reg_0x22(self, data):
+        self.handle_reg_with_scaling_factor(data, 62.5, 'Latent', 's',
+            error_messages['dis_double'])
+
+    def handle_reg_0x23(self, data):
+        self.handle_reg_with_scaling_factor(data, 1.25, 'Latent', 's',
+            error_messages['dis_double'])
+
+    def handle_reg_0x24(self, data):
+        self.handle_reg_with_scaling_factor(data, 62.5, 'Latent', 's',
+            error_messages['undesirable'])
+
+    def handle_reg_0x25(self, data):
+        self.handle_reg_0x1D(data)
+
+    def handle_reg_0x26(self, data):
+        self.handle_reg_with_scaling_factor(data, 1000, 'Time', 's',
+            error_messages['interrupt'])
+
+    def handle_reg_0x27(self, data):
+        bits = [Bit('ACT', BitType.AC_DC),
+                Bit('ACT_X', BitType.ENABLE),
+                Bit('ACT_Y', BitType.ENABLE),
+                Bit('ACT_Z', BitType.ENABLE),
+                Bit('INACT', BitType.AC_DC),
+                Bit('INACT_X', BitType.ENABLE),
+                Bit('INACT_Y', BitType.ENABLE),
+                Bit('INACT_Z', BitType.ENABLE)]
+        self.interpret_bits(data, bits)
+
+    def handle_reg_0x28(self, data):
+        self.handle_reg_0x1D(data)
+
+    def handle_reg_0x29(self, data):
+        self.handle_reg_with_scaling_factor(data, 5, 'Time', 's',
+            error_messages['undesirable'])
+
+    def handle_reg_0x2A(self, data):
+        bits = [Bit('', BitType.UNUSED),
+                Bit('', BitType.UNUSED),
+                Bit('', BitType.UNUSED),
+                Bit('', BitType.UNUSED),
+                Bit('', BitType.OTHER, {1: ['Suppressed', 'Suppr', 'S'],
+                    0: ['Unsuppressed', 'Unsuppr', 'Uns'],}),
+                Bit('TAP_X', BitType.ENABLE),
+                Bit('TAP_Y', BitType.ENABLE),
+                Bit('TAP_Z', BitType.ENABLE)]
+        self.interpret_bits(data, bits)
+
+    def handle_reg_0x2B(self, data):
+        bits = [Bit('', BitType.UNUSED),
+                Bit('ACT_X', BitType.SOURCE),
+                Bit('ACT_Y', BitType.SOURCE),
+                Bit('ACT_Z', BitType.SOURCE),
+                Bit('', BitType.OTHER, {1: ['Asleep', 'Asl'],
+                    0: ['Not asleep', 'Not asl', '!Asl'],}),
+                Bit('TAP_X', BitType.SOURCE),
+                Bit('TAP_Y', BitType.SOURCE),
+                Bit('TAP_Z', BitType.SOURCE)]
+        self.interpret_bits(data, bits)
+
+    def handle_reg_0x2C(self, data):
+        bits = [Bit('', BitType.UNUSED),
+                Bit('', BitType.UNUSED),
+                Bit('', BitType.UNUSED),
+                Bit('', BitType.OTHER, {1: ['Reduce power', 'Reduce pw', 'Red pw'], 0: ['Normal operation', 'Normal op', 'Norm op'],})]
+        bits_values = self.interpret_bits(data, bits)
+
+        start_index = 0
+        stop_index = 3
+        rate = self.get_decimal_number(bits_values, start_index, start_index)
+        self.putbs([4, ['%f' % rate_code[rate]]],
+            self.reverse_bit_index(stop_index, WORD_SIZE),
+            self.reverse_bit_index(start_index, WORD_SIZE))
+
+    def handle_reg_0x2D(self, data):
+        bits = [Bit('', BitType.UNUSED),
+                Bit('', BitType.UNUSED),
+                Bit('', BitType.OTHER, {1: ['Link'], 0: ['Unlink'], }),
+                Bit('AUTO_SLEEP', BitType.ENABLE),
+                Bit('', BitType.OTHER, {1: ['Measurement mode', 'Measurement', 'Meas'], 0: ['Standby mode', 'Standby'], }),
+                Bit('', BitType.OTHER, {1: ['Sleep mode', 'Sleep', 'Slp'], 0: ['Normal mode', 'Normal', 'Nrm'],})]
+        bits_values = self.interpret_bits(data, bits)
+
+        start_index = 0
+        stop_index = 1
+        wakeup = self.get_decimal_number(bits_values, start_index, stop_index)
+        frequency = 2 ** (~wakeup & 0x03)
+        self.putbs([4, ['%d Hz' % frequency]],
+            self.reverse_bit_index(stop_index, WORD_SIZE),
+            self.reverse_bit_index(start_index, WORD_SIZE))
+
+    def handle_reg_0x2E(self, data):
+        bits = [Bit('DATA_READY', BitType.ENABLE),
+                Bit('SINGLE_TAP', BitType.ENABLE),
+                Bit('DOUBLE_TAP', BitType.ENABLE),
+                Bit('Activity', BitType.ENABLE),
+                Bit('Inactivity', BitType.ENABLE),
+                Bit('FREE_FALL', BitType.ENABLE),
+                Bit('Watermark', BitType.ENABLE),
+                Bit('Overrun', BitType.ENABLE)]
+        self.interpret_bits(data, bits)
+
+    def handle_reg_0x2F(self, data):
+        bits = [Bit('DATA_READY', BitType.INTERRUPT),
+                Bit('SINGLE_TAP', BitType.INTERRUPT),
+                Bit('DOUBLE_TAP', BitType.INTERRUPT),
+                Bit('Activity', BitType.INTERRUPT),
+                Bit('Inactivity', BitType.INTERRUPT),
+                Bit('FREE_FALL', BitType.INTERRUPT),
+                Bit('Watermark', BitType.INTERRUPT),
+                Bit('Overrun', BitType.INTERRUPT)]
+        self.interpret_bits(data, bits)
+
+    def handle_reg_0x30(self, data):
+        bits = [Bit('DATA_READY', BitType.SOURCE),
+                Bit('SINGLE_TAP', BitType.SOURCE),
+                Bit('DOUBLE_TAP', BitType.SOURCE),
+                Bit('Activity', BitType.SOURCE),
+                Bit('Inactivity', BitType.SOURCE),
+                Bit('FREE_FALL', BitType.SOURCE),
+                Bit('Watermark', BitType.SOURCE),
+                Bit('Overrun', BitType.SOURCE)]
+        self.interpret_bits(data, bits)
+
+    def handle_reg_0x31(self, data):
+        bits = [Bit('SELF_TEST', BitType.ENABLE),
+                Bit('', BitType.OTHER, {1: ['3-wire SPI', '3-SPI'], 0: ['4-wire SPI', '4-SPI'],}),
+                Bit('', BitType.OTHER, {1: ['INT ACT LOW', 'INT LOW'], 0: ['INT ACT HIGH', 'INT HIGH'],}),
+                Bit('', BitType.UNUSED),
+                Bit('', BitType.OTHER, {1: ['Full resolution', 'Full res'], 0: ['10-bit mode', '10-bit'],}),
+                Bit('', BitType.OTHER, {1: ['MSB mode', 'MSB'], 0: ['LSB mode', 'LSB'],})]
+        bits_values = self.interpret_bits(data, bits)
+
+        start_index = 0
+        stop_index = 1
+        range_g = self.get_decimal_number(bits_values, start_index, stop_index)
+        result = 2 ** (range_g + 1)
+        self.putbs([4, ['+/-%d g' % result]],
+            self.reverse_bit_index(stop_index, WORD_SIZE),
+            self.reverse_bit_index(start_index, WORD_SIZE))
+
+    def handle_reg_0x32(self, data):
+        self.data = data
+        self.putx([4, [str(data)]])
+
+    def handle_reg_0x33(self, data):
+        self.get_axis_value(data, 'X')
+
+    def handle_reg_0x34(self, data):
+        self.handle_reg_0x32(data)
+
+    def handle_reg_0x35(self, data):
+        self.get_axis_value(data, 'Y')
+
+    def handle_reg_0x36(self, data):
+        self.handle_reg_0x32(data)
+
+    def handle_reg_0x37(self, data):
+        self.get_axis_value(data, 'Z')
+
+    def handle_reg_0x38(self, data):
+        bits = [None,
+                None,
+                Bit('', BitType.OTHER, {1: ['Trig-INT2', 'INT2'], 0: ['Trig-INT1', 'INT1'], })]
+        bits_values = self.interpret_bits(data, bits)
+
+        start_index = 6
+        stop_index = 7
+        fifo = self.get_decimal_number(bits_values, start_index, stop_index)
+        self.putbs([4, [fifo_modes[fifo]]],
+            self.reverse_bit_index(stop_index, WORD_SIZE),
+            self.reverse_bit_index(start_index, WORD_SIZE))
+
+        start_index = 0
+        stop_index = 4
+        samples = self.get_decimal_number(bits_values, start_index, stop_index)
+        self.putbs([4, ['Samples: %d' % samples, '%d' % samples]],
+            self.reverse_bit_index(stop_index, WORD_SIZE),
+            self.reverse_bit_index(start_index, WORD_SIZE))
+
+    def handle_reg_0x39(self, data):
+        bits = [Bit('', BitType.OTHER, {1: ['Triggered', 'Trigg'], 0: ['Not triggered', 'Not trigg'],}),
+                Bit('', BitType.UNUSED)]
+        bits_values = self.interpret_bits(data, bits)
+
+        start_index = 0
+        stop_index = 5
+        entries = self.get_decimal_number(bits_values, start_index, stop_index)
+        self.putbs([4, ['Entries: %d' % entries, '%d' % entries]],
+            self.reverse_bit_index(stop_index, WORD_SIZE),
+            self.reverse_bit_index(start_index, WORD_SIZE))
+
+    def get_bit(self, channel):
+        if (channel == Channel.MOSI and self.mosi is None) or \
+                (channel == Channel.MISO and self.miso is None):
+            raise Exception('No available data')
+
+        mosi_bit, miso_bit = 0, 0
+        if self.miso is not None:
+            if len(self.mosi) < 0:
+                raise Exception('No available data')
+            miso_bit = self.miso.pop(0)
+        if self.miso is not None:
+            if len(self.miso) < 0:
+                raise Exception('No available data')
+            mosi_bit = self.mosi.pop(0)
+
+        if channel == Channel.MOSI:
+            return mosi_bit
+        return miso_bit
+
+    def decode(self, ss, es, data):
+        ptype = data[0]
+
+        if ptype == 'CS-CHANGE':
+            cs_old, cs_new = data[1:]
+            if cs_old is not None and cs_old == 1 and cs_new == 0:
+                self.ss = ss
+                self.es = es
+                self.state = 'ADDRESS-BYTE'
+            else:
+                self.state = 'IDLE'
+
+        elif ptype == 'BITS':
+            if data[1] is not None:
+                self.mosi = list(reversed(data[1]))
+            if data[2] is not None:
+                self.miso = list(reversed(data[2]))
+
+            if self.mosi is None and self.miso is None:
+                return
+
+            if self.state == 'ADDRESS-BYTE':
+                # OPERATION BIT
+                op_bit = self.get_bit(Channel.MOSI)
+                if op_bit[0]:
+                    self.put(op_bit[1], op_bit[2], self.out_ann, [0, operations[op_bit[0]]])
+                    self.operation = Operation.READ
+                else:
+                    self.put(op_bit[1], op_bit[2], self.out_ann, [1, operations[op_bit[0]]])
+                    self.operation = Operation.WRITE
+
+                # MULTIPLE-BYTE BIT
+                mb_bit = self.get_bit(Channel.MOSI)
+                self.put(mb_bit[1], mb_bit[2], self.out_ann, [2, number_bytes[mb_bit[0]]])
+
+                # REGISTER 6-BIT ADDRESS
+                self.address = 0
+                start_sample = self.mosi[0][1]
+                addr_bit = []
+                for i in range(6):
+                    addr_bit = self.get_bit(Channel.MOSI)
+                    self.address |= addr_bit[0]
+                    self.address <<= 1
+                self.address >>= 1
+                self.put(start_sample, addr_bit[2], self.out_ann,
+                    [3, ['ADDRESS: 0x%02X' % self.address, 'ADDR: 0x%02X'
+                    % self.address, '0x%02X' % self.address]])
+                self.ss = -1
+                self.state = 'DATA'
+
+            elif self.state == 'DATA':
+                if self.operation == Operation.WRITE:
+                    self.reg.extend(self.mosi)
+                elif self.operation == Operation.READ:
+                    self.reg.extend(self.miso)
+
+                self.mosi = []
+                self.miso = []
+                if self.ss == -1:
+                    self.ss = self.reg[0][1]
+                    self.es = es
+                    self.samples_per_bit = self.reg[0][2] - self.ss
+
+                if len(self.reg) < 8:
+                    return
+                else:
+                    reg_value = 0
+                    reg_bit = []
+                    for offset in range(7, -1, -1):
+                        reg_bit = self.reg.pop(0)
+
+                        mask = reg_bit[0] << offset
+                        reg_value |= mask
+
+                    if self.address < 0x00 or self.address > 0x39:
+                        return
+
+                    if self.address in [0x32, 0x34, 0x36]:
+                        self.start_index = self.ss
+
+                    if 0x1D > self.address >= 0x00:
+                        self.put(self.ss, reg_bit[2], self.out_ann, [3, [str(self.address)]])
+                        self.put(self.ss, reg_bit[2], self.out_ann, [4, [str(reg_value)]])
+                    else:
+                        self.put(self.ss, reg_bit[2], self.out_ann, [3, registers[self.address]])
+                        handle_reg = getattr(self, 'handle_reg_0x%02X' % self.address)
+                        handle_reg(reg_value)
+
+                    self.reg = []
+                    self.address += 1
+                    self.ss = -1