]> sigrok.org Git - libsigrokdecode.git/blame - decoders/maple_bus/pd.py
Backport recent changes from mainline.
[libsigrokdecode.git] / decoders / maple_bus / pd.py
CommitLineData
2ba06442
UH
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
20import sigrokdecode as srd
21
22ann = [
23 ['Size', 'L'],
24 ['SrcAP', 'S'],
25 ['DstAP', 'D'],
26 ['Cmd', 'C'],
27 ['Data'],
28 ['Cksum', 'K'],
29]
30
31class 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 self.reset()
77
78 def reset(self):
79 pass
80
81 def start(self):
82 self.out_ann = self.register(srd.OUTPUT_ANN)
83 self.out_binary = self.register(srd.OUTPUT_BINARY)
84 self.pending_bit_pos = None
85
86 def putx(self, data):
87 self.put(self.ss, self.es, self.out_ann, data)
88
89 def putb(self, data):
90 self.put(self.ss, self.es, self.out_binary, data)
91
92 def byte_annotation(self, bintype, d):
93 return [bintype + 6,
94 ['%s: %02X' % (name, d) for name in ann[bintype]] + ['%02X' % d]]
95
96 def got_start(self):
97 self.putx([0, ['Start pattern', 'Start', 'S']])
98
99 def got_end(self):
100 self.putx([1, ['End pattern', 'End', 'E']])
101 if self.length != self.expected_length + 1:
102 self.putx([14, ['Size error', 'L error', 'LE']])
103
104 def got_start_with_crc(self):
105 self.putx([2, ['Start pattern with CRC', 'Start CRC', 'SC']])
106
107 def got_occupancy(self):
108 self.putx([3, ['SDCKB occupancy pattern', 'Occupancy', 'O']])
109
110 def got_reset(self):
111 self.putx([4, ['RESET pattern', 'RESET', 'R']])
112
113 def output_pending_bit(self):
114 if self.pending_bit_pos:
115 self.put(self.pending_bit_pos, self.pending_bit_pos, self.out_ann, [5, ['Bit: %d' % self.pending_bit, '%d' % self.pending_bit]])
116
117 def got_bit(self, n):
118 self.output_pending_bit()
119 self.data = self.data * 2 + n
120 self.pending_bit = n
121 self.pending_bit_pos = self.samplenum
122
123 def got_byte(self):
124 self.output_pending_bit()
125 bintype = 4
126 if self.length < 4:
127 if self.length == 0:
128 self.expected_length = 4 * (self.data + 1)
129 bintype = self.length
130 elif self.length == self.expected_length:
131 bintype = 5
132 if self.data != self.checksum:
133 self.putx([13, ['Cksum error', 'K error', 'KE']])
134 self.length = self.length + 1
135 self.checksum = self.checksum ^ self.data
136 self.putx(self.byte_annotation(bintype, self.data))
137 self.putb([bintype, bytes([self.data])])
138 self.pending_bit_pos = None
139
140 def frame_error(self):
141 self.putx([7, ['Frame error', 'F error', 'FE']])
142
143 def handle_start(self):
144 self.wait({0: 'l', 1: 'h'})
145 self.ss = self.samplenum
146 count = 0
147 while True:
148 sdcka, sdckb = self.wait([{1: 'f'}, {0: 'r'}])
149 if self.matched[0]:
150 count = count + 1
151 if self.matched[1]:
152 self.es = self.samplenum
153 if sdckb == 1:
154 if count == 4:
155 self.got_start()
156 return True
157 elif count == 6:
158 self.got_start_with_crc()
159 return True
160 elif count == 8:
161 self.got_occupancy()
162 return False
163 elif count >= 14:
164 self.got_reset()
165 return False
166 self.frame_error()
167 return False
168
169 def handle_byte_or_stop(self):
170 self.ss = self.samplenum
171 self.pending_bit_pos = None
172 initial = True
173 counta = 0
174 countb = 0
175 self.data = 0
176 while countb < 4:
177 sdcka, sdckb = self.wait([{0: 'f'}, {1: 'f'}])
178 self.es = self.samplenum
179 if self.matched[0]:
180 if counta == countb:
181 self.got_bit(sdckb)
182 counta = counta + 1
183 elif counta == 1 and countb == 0 and self.data == 0 and sdckb == 0:
184 self.wait([{0: 'h', 1: 'h'}, {0: 'f'}, {1: 'f'}])
185 self.es = self.samplenum
186 if self.matched[0]:
187 self.got_end()
188 else:
189 self.frame_error()
190 return False
191 else:
192 self.frame_error()
193 return False
194 elif self.matched[1]:
195 if counta == countb + 1:
196 self.got_bit(sdcka)
197 countb = countb + 1
198 elif counta == 0 and countb == 0 and sdcka == 1 and initial:
199 self.ss = self.samplenum
200 initial = False
201 else:
202 self.frame_error()
203 return False
204 self.wait({0: 'h'})
205 self.es = self.samplenum
206 self.got_byte()
207 return True
208
209 def decode(self):
210 while True:
211 while not self.handle_start():
212 pass
213 self.length = 0
214 self.expected_length = 4
215 self.checksum = 0
216 while self.handle_byte_or_stop():
217 pass