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