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