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