srd: add TODO comment on the SIGROKDECODE_DIR env var's motivation
[libsigrokdecode/gsi.git] / decoders / ook_vis / pd.py
blob1645ceb7deea00a96aafbb5d3ea806a3708f2987
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.
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.
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/>.
20 import sigrokdecode as srd
21 from common.srdhelper import bcd2int
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'),
41 annotation_rows = (
42 ('bits', 'Bits', (0,)),
43 ('compare', 'Compare', (1,)),
44 ('fields', 'Fields', (2,)),
45 ('ref_fields', 'Ref fields', (3,)),
46 ('level2_vals', 'L2', (4,)),
47 ('ref_level2_vals', 'Ref L2', (5,)),
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')},
64 def __init__(self):
65 self.reset()
67 def reset(self):
68 self.decoded = [] # Local cache of decoded OOK.
69 self.ookstring = ''
70 self.ookcache = []
71 self.trace_num = 0
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']
81 def putx(self, data):
82 self.put(self.ss, self.es, self.out_ann, data)
84 def putp(self, data):
85 self.put(self.ss, self.es, self.out_python, data)
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
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
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
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)
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
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)
159 self.display_level2(bits, 4) # Display L2 decode.
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)]])
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]]])
183 def add_to_cache(self): # Cache the OOK so it can be used as a reference.
184 self.ookcache.append(self.decoded)
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.