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