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