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