]> sigrok.org Git - libsigrokdecode.git/blob - decoders/ook_vis/pd.py
f985b96f1909e96edc0face8294df51068cf0375
[libsigrokdecode.git] / decoders / ook_vis / pd.py
1 ##
2 ## This file is part of the libsigrokdecode project.
3 ##
4 ## Copyright (C) 2018 Steve R <steversig@virginmedia.com>
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 2 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
20 import sigrokdecode as srd
21 from common.srdhelper import bcd2int
22
23 class Decoder(srd.Decoder):
24     api_version = 3
25     id = 'ook_vis'
26     name = 'OOK visualisation'
27     longname = 'On-off keying visualisation'
28     desc = 'OOK visualisation in various formats.'
29     license = 'gplv2+'
30     inputs = ['ook']
31     outputs = ['ook']
32     tags = ['Encoding']
33     annotations = (
34         ('bit', 'Bit'),
35         ('ref', 'Reference'),
36         ('field', 'Field'),
37         ('ref_field', 'Ref field'),
38         ('level2', 'L2'),
39         ('ref_level2', 'Ref L2'),
40     )
41     annotation_rows = (
42         ('bits', 'Bits', (0,)),
43         ('compare', 'Compare', (1,)),
44         ('fields', 'Fields', (2,)),
45         ('ref_fields', 'Ref fields', (3,)),
46         ('level2', 'L2', (4,)),
47         ('ref_level2', 'Ref L2', (5,)),
48     )
49     options = (
50         {'id': 'displayas', 'desc': 'Display as', 'default': 'Nibble - Hex',
51          'values': ('Byte - Hex', 'Byte - Hex rev', 'Byte - BCD',
52          'Byte - BCD rev', 'Nibble - Hex', 'Nibble - Hex rev', 'Nibble - BCD',
53          'Nibble - BCD rev')},
54         {'id': 'synclen', 'desc': 'Sync length', 'default': '4',
55          'values': ('0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10')},
56         {'id': 'syncoffset', 'desc': 'Sync offset', 'default': '0',
57          'values': ('-4', '-3', '-2', '-1', '0', '1', '2', '3', '4')},
58         {'id': 'refsample', 'desc': 'Compare', 'default': 'off', 'values':
59         ('off', 'show numbers', '1', '2', '3', '4', '5', '6', '7', '8', '9',
60          '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20',
61          '21', '22', '23', '24', '25', '26', '27', '28', '29', '30')},
62     )
63
64     def __init__(self):
65         self.reset()
66
67     def reset(self):
68         self.decoded = [] # Local cache of decoded OOK.
69         self.ookstring = ''
70         self.ookcache = []
71         self.trace_num = 0
72
73     def start(self):
74         self.out_ann = self.register(srd.OUTPUT_ANN)
75         self.out_python = self.register(srd.OUTPUT_PYTHON)
76         self.displayas = self.options['displayas']
77         self.sync_length = self.options['synclen']
78         self.sync_offset = self.options['syncoffset']
79         self.ref = self.options['refsample']
80
81     def putx(self, data):
82         self.put(self.ss, self.es, self.out_ann, data)
83
84     def putp(self, data):
85         self.put(self.ss, self.es, self.out_python, data)
86
87     def display_level2(self, bits, line):
88         self.decode_pos = 0
89         ook = self.decoded
90         # Find the end of the preamble which could be 1010 or 1111.
91         if len(ook) > 1:
92             preamble_end = len(ook) + 1
93             char_first = ook[0][2]
94             char_second = ook[1][2]
95             if char_first == char_second: # 1111
96                 preamble = '1111'
97                 char_last = char_first
98             else:
99                 preamble = '1010'
100                 char_last = char_second
101             for i in range(len(ook)):
102                 if preamble == '1111':
103                     if ook[i][2] != char_last:
104                         preamble_end = i
105                         break
106                     else:
107                         char_last = ook[i][2]
108                 else:
109                     if ook[i][2] != char_last:
110                         char_last = ook[i][2]
111                     else:
112                         preamble_end = i
113                         break
114
115             if len(ook) >= preamble_end:
116                 preamble_end += int(self.sync_offset) - 1
117                 self.ss, self.es = ook[0][0], ook[preamble_end][1]
118                 self.putx([line, ['Preamble', 'Pre', 'P']])
119                 self.decode_pos += preamble_end
120
121                 if len(ook) > self.decode_pos + int(self.sync_length):
122                     self.ss = self.es
123                     self.es = ook[self.decode_pos + int(self.sync_length)][1]
124                     self.putx([line, ['Sync', 'Syn', 'S']])
125                     self.decode_pos += int(self.sync_length) + 1
126
127                 ookstring = self.ookstring[self.decode_pos:]
128                 rem_nibbles = len(ookstring) // bits
129                 for i in range(rem_nibbles): # Display the rest of nibbles.
130                     self.ss = ook[self.decode_pos][0]
131                     self.es = ook[self.decode_pos + bits - 1][1]
132                     self.put_field(bits, line)
133
134     def put_field(self, numbits, line):
135         param = self.ookstring[self.decode_pos:self.decode_pos + numbits]
136         if 'rev' in self.displayas:
137             param = param[::-1]     # Reversed from right.
138         if not 'E' in param:        # Format if no errors.
139             if 'Hex' in self.displayas:
140                 param = hex(int(param, 2))[2:]
141             elif 'BCD' in self.displayas:
142                 param = bcd2int(int(param, 2))
143         self.putx([line, [str(param)]])
144         self.decode_pos += numbits
145
146     def display_all(self):
147         ookstring = ''
148         self.decode_pos = 0
149         ook = self.decoded
150         for i in range(len(ook)):
151             self.ookstring += ook[i][2]
152         bits = 4 if 'Nibble' in self.displayas else 8
153         rem_nibbles = len(self.ookstring) // bits
154         for i in range(rem_nibbles): # Display the rest of the nibbles.
155             self.ss = ook[self.decode_pos][0]
156             self.es = ook[self.decode_pos + bits - 1][1]
157             self.put_field(bits, 2)
158
159         self.display_level2(bits, 4) # Display L2 decode.
160
161         if (self.ref != 'off' and self.ref != 'show numbers' and
162             len(self.ookcache) >= int(self.ref)): # Compare traces.
163             ref = int(self.ref) - 1
164             self.display_ref(self.trace_num, ref)
165             if len(self.ookcache) == int(self.ref): # Backfill.
166                 for i in range(0, ref):
167                     self.display_ref(i, ref)
168         elif self.ref == 'show numbers': # Display ref numbers.
169             self.ss = self.ookcache[self.trace_num][0][0]
170             end_sig = len(self.ookcache[self.trace_num]) - 1
171             self.es = self.ookcache[self.trace_num][end_sig][1]
172             self.putx([1, [str(self.trace_num + 1)]])
173
174     def display_ref(self, t_num, ref):
175         display_len = len(self.ookcache[ref])
176         if len(self.ookcache[t_num]) < len(self.ookcache[ref]):
177             display_len = len(self.ookcache[t_num])
178         for i in range(display_len):
179             self.ss = self.ookcache[t_num][i][0]
180             self.es = self.ookcache[t_num][i][1]
181             self.putx([1, [self.ookcache[ref][i][2]]])
182
183     def add_to_cache(self): # Cache the OOK so it can be used as a reference.
184         self.ookcache.append(self.decoded)
185
186     def decode(self, ss, es, data):
187         self.decoded = data
188         self.add_to_cache()
189         self.display_all()
190         self.ookstring = ''
191         self.trace_num += 1
192         self.ss = ss
193         self.es = es
194         self.putp(data) # Send data up the stack.