]> sigrok.org Git - libsigrokdecode.git/blame_incremental - 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
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 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
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):
94 self.putx([0, ['Start pattern', 'Start', 'S']])
95
96 def got_end(self):
97 self.putx([1, ['End pattern', 'End', 'E']])
98 if self.length != self.expected_length + 1:
99 self.putx([14, ['Size error', 'L error', 'LE']])
100
101 def got_start_with_crc(self):
102 self.putx([2, ['Start pattern with CRC', 'Start CRC', 'SC']])
103
104 def got_occupancy(self):
105 self.putx([3, ['SDCKB occupancy pattern', 'Occupancy', 'O']])
106
107 def got_reset(self):
108 self.putx([4, ['RESET pattern', 'RESET', 'R']])
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:
130 self.putx([13, ['Cksum error', 'K error', 'KE']])
131 self.length = self.length + 1
132 self.checksum = self.checksum ^ self.data
133 self.putx(self.byte_annotation(bintype, self.data))
134 self.putb([bintype, bytes([self.data])])
135 self.pending_bit_pos = None
136
137 def frame_error(self):
138 self.putx([7, ['Frame error', 'F error', 'FE']])
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