]> sigrok.org Git - libsigrokdecode.git/blob - decoders/ssi32/pd.py
Add Bosch SSI32 protocol decoder.
[libsigrokdecode.git] / decoders / ssi32 / pd.py
1 ##
2 ## This file is part of the libsigrokdecode project.
3 ##
4 ## Copyright (C) 2016 Robert Bosch Car Multimedia GmbH
5 ## Authors: Oleksij Rempel
6 ##              <fixed-term.Oleksij.Rempel@de.bosch.com>
7 ##              <linux@rempel-privat.de>
8 ##
9 ## This program is free software; you can redistribute it and/or modify
10 ## it under the terms of the GNU General Public License as published by
11 ## the Free Software Foundation; either version 2 of the License, or
12 ## (at your option) any later version.
13 ##
14
15 import sigrokdecode as srd
16 from .lists import *
17
18 class Decoder(srd.Decoder):
19     api_version = 2
20     id = 'ssi32'
21     name = 'SSI32'
22     longname = 'Bosch SSI32 Protocol'
23     desc = 'Bosch SSI32 Protocol'
24     license = 'gplv2+'
25     inputs = ['spi']
26     outputs = ['ssi32']
27     options = (
28         {'id': 'msgsize', 'desc': 'Message size', 'default': 64},
29     )
30     annotations = (
31         ('ctrl-tx', 'CTRL TX'),
32         ('ack-tx', 'ACK TX'),
33         ('ctrl-rx', 'CTRL RX'),
34         ('ack-rx', 'ACK Tx'),
35     )
36     annotation_rows = (
37         ('tx', 'TX', (0, 1,)),
38         ('rx', 'RX', (2, 3,)),
39     )
40
41     def __init__(self):
42         self.ss_cmd, self.es_cmd = 0, 0
43         self.mosi_bytes = []
44         self.miso_bytes = []
45         self.es_array = []
46         self.rx_size = 0
47         self.tx_size = 0
48
49     def start(self):
50         self.out_ann = self.register(srd.OUTPUT_ANN)
51
52     def putx(self, data):
53         self.put(self.ss_cmd, self.es_cmd, self.out_ann, data)
54
55     def reset(self):
56         self.mosi_bytes = []
57         self.miso_bytes = []
58         self.es_array = []
59
60     def handle_ack(self):
61         # Only first byte should have ACK data, other 3 bytes
62         # are reserved.
63
64         self.es_cmd = self.es_array[0]
65         self.putx([1, ['> ACK:0x%02x' % (self.mosi_bytes[0])]])
66         self.putx([3, ['< ACK:0x%02x' % (self.miso_bytes[0])]])
67
68     def handle_ctrl(self):
69         mosi = miso = ''
70         self.tx_size = self.mosi_bytes[2]
71         self.rx_size = self.miso_bytes[2]
72
73         if self.tx_size > 0:
74             mosi = ', DATA:0x' + ''.join(format(x, '02x') for x in self.mosi_bytes[4:self.tx_size + 4])
75         if self.rx_size > 0:
76             miso = ', DATA:0x' + ''.join(format(x, '02x') for x in self.miso_bytes[4:self.rx_size + 4])
77
78         self.es_cmd = self.es_array[self.tx_size + 3]
79         self.putx([0,
80                   ['> CTRL:0x%02x, LUN:0x%02x, SIZE:0x%02x, CRC:0x%02x%s'
81                    % (self.mosi_bytes[0], self.mosi_bytes[1],
82                       self.mosi_bytes[2], self.mosi_bytes[3], mosi)]])
83
84         self.es_cmd = self.es_array[self.rx_size + 3]
85         self.putx([2,
86                   ['< CTRL:0x%02x, LUN:0x%02x, SIZE:0x%02x, CRC:0x%02x%s'
87                    % (self.miso_bytes[0], self.miso_bytes[1],
88                       self.miso_bytes[2], self.miso_bytes[3], miso)]])
89
90     def decode(self, ss, es, data):
91         ptype = data[0]
92         if ptype == 'CS-CHANGE':
93             self.reset()
94             return
95
96         # Don't care about anything else.
97         if ptype != 'DATA':
98             return
99         mosi, miso = data[1:]
100
101         self.ss, self.es = ss, es
102
103         if len(self.mosi_bytes) == 0:
104             self.ss_cmd = ss
105         self.mosi_bytes.append(mosi)
106         self.miso_bytes.append(miso)
107         self.es_array.append(es)
108
109         if self.mosi_bytes[0] & 0x80:
110             if len(self.mosi_bytes) < 4:
111                 return
112
113             self.handle_ack()
114             self.reset()
115         else:
116             if len(self.mosi_bytes) < self.options['msgsize']:
117                 return
118
119             self.handle_ctrl()
120             self.reset()