9af4eb43fd32c2d4ef6fc4d66496218125ba82d6
[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     tags = ['Retro computing']
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