]>
Commit | Line | Data |
---|---|---|
1 | ## | |
2 | ## This file is part of the libsigrokdecode project. | |
3 | ## | |
4 | ## Copyright (C) 2019 Shirow Miura <shirowmiura@gmail.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 | ||
22 | symbol_map = { | |
23 | 0b0000: '0', | |
24 | 0b1000: '1', | |
25 | 0b0100: '2', | |
26 | 0b1100: '3', | |
27 | 0b0010: '4', | |
28 | 0b1010: '5', | |
29 | 0b0110: '6', | |
30 | 0b1110: '7', | |
31 | 0b0001: '8', | |
32 | 0b1001: '9', | |
33 | 0b0101: 'A', | |
34 | 0b1101: 'C', | |
35 | 0b0011: 'F', | |
36 | 0b1011: 'H', | |
37 | 0b0111: 'P', | |
38 | 0b1111: 'U', | |
39 | } | |
40 | ||
41 | START, STOP, CLOCK, DATA = range(4) | |
42 | ||
43 | class Decoder(srd.Decoder): | |
44 | api_version = 3 | |
45 | id = 'signature' | |
46 | name = 'Signature' | |
47 | longname = 'Signature analysis' | |
48 | desc = 'Annotate signature of logic patterns.' | |
49 | license = 'gplv2+' | |
50 | inputs = ['logic'] | |
51 | outputs = [] | |
52 | tags = ['Debug/trace', 'Util', 'Encoding'] | |
53 | channels = ( | |
54 | {'id': 'start', 'name': 'START', 'desc': 'START channel'}, | |
55 | {'id': 'stop', 'name': 'STOP', 'desc': 'STOP channel'}, | |
56 | {'id': 'clk', 'name': 'CLOCK', 'desc': 'CLOCK channel'}, | |
57 | {'id': 'data', 'name': 'DATA', 'desc': 'DATA channel'}, | |
58 | ) | |
59 | options = ( | |
60 | {'id': 'start_edge', 'desc': 'START edge polarity', | |
61 | 'default': 'rising', 'values': ('rising', 'falling')}, | |
62 | {'id': 'stop_edge', 'desc': 'STOP edge polarity', | |
63 | 'default': 'rising', 'values': ('rising', 'falling')}, | |
64 | {'id': 'clk_edge', 'desc': 'CLOCK edge polarity', | |
65 | 'default': 'falling', 'values': ('rising', 'falling')}, | |
66 | {'id': 'annbits', 'desc': 'Enable bit level annotations', | |
67 | 'default': 'no', 'values': ('yes', 'no')}, | |
68 | ) | |
69 | annotations = ( | |
70 | ('bit0', 'Bit0'), | |
71 | ('bit1', 'Bit1'), | |
72 | ('start', 'START'), | |
73 | ('stop', 'STOP'), | |
74 | ('sig', 'Sig') | |
75 | ) | |
76 | annotation_rows = ( | |
77 | ('bits', 'Bits', (0, 1, 2, 3)), | |
78 | ('sig', 'Sig', (4,)) | |
79 | ) | |
80 | ||
81 | def __init__(self): | |
82 | self.reset() | |
83 | ||
84 | def reset(self): | |
85 | pass | |
86 | ||
87 | def start(self): | |
88 | self.out_ann = self.register(srd.OUTPUT_ANN) | |
89 | ||
90 | def putsig(self, ss, es, signature): | |
91 | s = ''.join([symbol_map[(signature >> 0) & 0x0f], | |
92 | symbol_map[(signature >> 4) & 0x0f], | |
93 | symbol_map[(signature >> 8) & 0x0f], | |
94 | symbol_map[(signature >> 12) & 0x0f]]) | |
95 | self.put(ss, es, self.out_ann, [4, [s]]) | |
96 | ||
97 | def putb(self, ss, ann): | |
98 | self.put(ss, self.samplenum, self.out_ann, ann) | |
99 | ||
100 | def decode(self): | |
101 | opt = self.options | |
102 | start_edge_mode_rising = opt['start_edge'] == 'rising' | |
103 | stop_edge_mode_rising = opt['stop_edge'] == 'rising' | |
104 | annbits = opt['annbits'] == 'yes' | |
105 | gate_is_open = False | |
106 | sample_start = None | |
107 | started = False | |
108 | last_samplenum = 0 | |
109 | prev_start = 0 if start_edge_mode_rising else 1 | |
110 | prev_stop = 0 if stop_edge_mode_rising else 1 | |
111 | shiftreg = 0 | |
112 | ||
113 | while True: | |
114 | start, stop, _, data = self.wait({CLOCK: opt['clk_edge']}) | |
115 | if start != prev_start and not gate_is_open: | |
116 | gate_is_open = (start == 1) if start_edge_mode_rising else (start == 0) | |
117 | if gate_is_open: | |
118 | # Start sampling. | |
119 | sample_start = self.samplenum | |
120 | started = True | |
121 | elif stop != prev_stop and gate_is_open: | |
122 | gate_is_open = not ((stop == 1) if stop_edge_mode_rising else (stop == 0)) | |
123 | if not gate_is_open: | |
124 | # Stop sampling. | |
125 | if annbits: | |
126 | self.putb(last_samplenum, [3, ['STOP', 'STP', 'P']]) | |
127 | self.putsig(sample_start, self.samplenum, shiftreg) | |
128 | shiftreg = 0 | |
129 | sample_start = None | |
130 | if gate_is_open: | |
131 | if annbits: | |
132 | if started: | |
133 | s = '<{}>'.format(data) | |
134 | self.putb(last_samplenum, [2, ['START' + s, 'STR' + s, 'S' + s]]) | |
135 | started = False | |
136 | else: | |
137 | self.putb(last_samplenum, [data, [str(data)]]) | |
138 | incoming = (bin(shiftreg & 0b0000_0010_1001_0001).count('1') + data) & 1 | |
139 | shiftreg = (incoming << 15) | (shiftreg >> 1) | |
140 | prev_start = start | |
141 | prev_stop = stop | |
142 | last_samplenum = self.samplenum |