]>
Commit | Line | Data |
---|---|---|
4cd8ac1d MC |
1 | ## |
2 | ## This file is part of the libsigrokdecode project. | |
3 | ## | |
4 | ## Copyright (C) 2017 Marcus Comstedt <marcus@mc.pp.se> | |
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 | ann = [ | |
23 | ['Size', 'L'], | |
24 | ['SrcAP', 'S'], | |
25 | ['DstAP', 'D'], | |
26 | ['Cmd', 'C'], | |
27 | ['Data'], | |
28 | ['Cksum', 'K'], | |
29 | ] | |
30 | ||
31 | class Decoder(srd.Decoder): | |
32 | api_version = 3 | |
33 | id = 'maple_bus' | |
34 | name = 'Maple bus' | |
35 | longname = 'SEGA Maple bus' | |
36 | desc = 'Maple bus peripheral protocol for SEGA Dreamcast.' | |
37 | license = 'gplv2+' | |
38 | inputs = ['logic'] | |
39 | outputs = ['maple_bus'] | |
40 | channels = ( | |
41 | {'id': 'sdcka', 'name': 'SDCKA', 'desc': 'Data/clock line A'}, | |
42 | {'id': 'sdckb', 'name': 'SDCKB', 'desc': 'Data/clock line B'}, | |
43 | ) | |
44 | annotations = ( | |
45 | ('start', 'Start pattern'), | |
46 | ('end', 'End pattern'), | |
47 | ('start-with-crc', 'Start pattern with CRC'), | |
48 | ('occupancy', 'SDCKB occupancy pattern'), | |
49 | ('reset', 'RESET pattern'), | |
50 | ('bit', 'Bit'), | |
51 | ('size', 'Data size'), | |
52 | ('source', 'Source AP'), | |
53 | ('dest', 'Destination AP'), | |
54 | ('command', 'Command'), | |
55 | ('data', 'Data'), | |
56 | ('checksum', 'Checksum'), | |
57 | ('frame-error', 'Frame error'), | |
58 | ('checksum-error', 'Checksum error'), | |
59 | ('size-error', 'Size error'), | |
60 | ) | |
61 | annotation_rows = ( | |
62 | ('bits', 'Bits', (0, 1, 2, 3, 4, 5)), | |
63 | ('fields', 'Fields', (6, 7, 8, 9, 10, 11)), | |
64 | ('warnings', 'Warnings', (12, 13, 14)), | |
65 | ) | |
66 | binary = ( | |
67 | ('size', 'Data size'), | |
68 | ('source', 'Source AP'), | |
69 | ('dest', 'Destination AP'), | |
70 | ('command', 'Command code'), | |
71 | ('data', 'Data'), | |
72 | ('checksum', 'Checksum'), | |
73 | ) | |
74 | ||
75 | def __init__(self): | |
76 | pass | |
77 | ||
78 | def start(self): | |
79 | self.out_ann = self.register(srd.OUTPUT_ANN) | |
80 | self.out_binary = self.register(srd.OUTPUT_BINARY) | |
81 | self.pending_bit_pos = None | |
82 | ||
83 | def byte_annotation(self, bintype, d): | |
84 | return [bintype + 6, | |
85 | ['%s: %02X' % (name, d) for name in ann[bintype]] + ['%02X' % d]] | |
86 | ||
87 | def got_start(self): | |
88 | self.put(self.ss, self.es, self.out_ann, [0, ['Start pattern', 'Start', 'S']]) | |
89 | ||
90 | def got_end(self): | |
91 | self.put(self.ss, self.es, self.out_ann, [1, ['End pattern', 'End', 'E']]) | |
92 | if self.length != self.expected_length + 1: | |
93 | self.put(self.ss, self.es, self.out_ann, [14, ['Size error', 'L error', 'LE']]) | |
94 | ||
95 | def got_start_with_crc(self): | |
96 | self.put(self.ss, self.es, self.out_ann, [2, ['Start pattern with CRC', 'Start CRC', 'SC']]) | |
97 | ||
98 | def got_occupancy(self): | |
99 | self.put(self.ss, self.es, self.out_ann, [3, ['SDCKB occupancy pattern', 'Occupancy', 'O']]) | |
100 | ||
101 | def got_reset(self): | |
102 | self.put(self.ss, self.es, self.out_ann, [4, ['RESET pattern', 'RESET', 'R']]) | |
103 | ||
104 | def output_pending_bit(self): | |
105 | if self.pending_bit_pos: | |
106 | self.put(self.pending_bit_pos, self.pending_bit_pos, self.out_ann, [5, ['Bit: %d' % self.pending_bit, '%d' % self.pending_bit]]) | |
107 | ||
108 | def got_bit(self, n): | |
109 | self.output_pending_bit() | |
110 | self.data = self.data * 2 + n | |
111 | self.pending_bit = n | |
112 | self.pending_bit_pos = self.samplenum | |
113 | ||
114 | def got_byte(self): | |
115 | self.output_pending_bit() | |
116 | bintype = 4 | |
117 | if self.length < 4: | |
118 | if self.length == 0: | |
119 | self.expected_length = 4 * (self.data + 1) | |
120 | bintype = self.length | |
121 | elif self.length == self.expected_length: | |
122 | bintype = 5 | |
123 | if self.data != self.checksum: | |
124 | self.put(self.ss, self.es, self.out_ann, [13, ['Cksum error', 'K error', 'KE']]) | |
125 | self.length = self.length + 1 | |
126 | self.checksum = self.checksum ^ self.data | |
127 | self.put(self.ss, self.es, self.out_ann, self.byte_annotation(bintype, self.data)) | |
128 | self.put(self.ss, self.es, self.out_binary, [bintype, bytes([self.data])]) | |
129 | self.pending_bit_pos = None | |
130 | ||
131 | def frame_error(self): | |
132 | self.put(self.ss, self.es, self.out_ann, [7, ['Frame error', 'F error', 'FE']]) | |
133 | ||
134 | def handle_start(self): | |
135 | self.wait({0: 'l', 1: 'h'}) | |
136 | self.ss = self.samplenum | |
137 | count = 0 | |
138 | while True: | |
139 | sdcka, sdckb = self.wait([{1: 'f'}, {0: 'r'}]) | |
140 | if self.matched[0]: | |
141 | count = count + 1 | |
142 | if self.matched[1]: | |
143 | self.es = self.samplenum | |
144 | if sdckb == 1: | |
145 | if count == 4: | |
146 | self.got_start() | |
147 | return True | |
148 | elif count == 6: | |
149 | self.got_start_with_crc() | |
150 | return True | |
151 | elif count == 8: | |
152 | self.got_occupancy() | |
153 | return False | |
154 | elif count >= 14: | |
155 | self.got_reset() | |
156 | return False | |
157 | self.frame_error() | |
158 | return False | |
159 | ||
160 | def handle_byte_or_stop(self): | |
161 | self.ss = self.samplenum | |
162 | self.pending_bit_pos = None | |
163 | initial = True | |
164 | counta = 0 | |
165 | countb = 0 | |
166 | self.data = 0 | |
167 | while countb < 4: | |
168 | sdcka, sdckb = self.wait([{0: 'f'}, {1: 'f'}]) | |
169 | self.es = self.samplenum | |
170 | if self.matched[0]: | |
171 | if counta == countb: | |
172 | self.got_bit(sdckb) | |
173 | counta = counta + 1 | |
174 | elif counta == 1 and countb == 0 and self.data == 0 and sdckb == 0: | |
175 | self.wait([{0: 'h', 1: 'h'}, {0: 'f'}, {1: 'f'}]) | |
176 | self.es = self.samplenum | |
177 | if self.matched[0]: | |
178 | self.got_end() | |
179 | else: | |
180 | self.frame_error() | |
181 | return False | |
182 | else: | |
183 | self.frame_error() | |
184 | return False | |
185 | elif self.matched[1]: | |
186 | if counta == countb + 1: | |
187 | self.got_bit(sdcka) | |
188 | countb = countb + 1 | |
189 | elif counta == 0 and countb == 0 and sdcka == 1 and initial: | |
190 | self.ss = self.samplenum | |
191 | initial = False | |
192 | else: | |
193 | self.frame_error() | |
194 | return False | |
195 | self.wait({0: 'h'}) | |
196 | self.es = self.samplenum | |
197 | self.got_byte() | |
198 | return True | |
199 | ||
200 | def decode(self): | |
201 | while True: | |
202 | while not self.handle_start(): | |
203 | pass | |
204 | self.length = 0 | |
205 | self.expected_length = 4 | |
206 | self.checksum = 0 | |
207 | while self.handle_byte_or_stop(): | |
208 | pass |