]> sigrok.org Git - libsigrokdecode.git/blame - decoders/maple_bus/pd.py
Add an initial Maple bus decoder.
[libsigrokdecode.git] / decoders / maple_bus / pd.py
CommitLineData
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
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 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