]> sigrok.org Git - libsigrokdecode.git/blob - decoders/maple_bus/pd.py
maple_bus: Add helpers to make the call sites a bit shorter.
[libsigrokdecode.git] / decoders / maple_bus / pd.py
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
20 import sigrokdecode as srd
21
22 ann = [
23     ['Size', 'L'],
24     ['SrcAP', 'S'],
25     ['DstAP', 'D'],
26     ['Cmd', 'C'],
27     ['Data'],
28     ['Cksum', 'K'],
29 ]
30
31 class 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