2 ## This file is part of the libsigrokdecode project.
4 ## Copyright (C) 2019 Federico Cerutti <federico@ceres-c.it>
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.
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.
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/>.
20 from common.srdhelper import bitpack_lsb
21 import sigrokdecode as srd
24 RST, CLK, IO, = range(3)
27 BIT, ATR, CMD, DATA, RESET, = range(5)
32 # CMD: [annotation class index, annotation texts for zoom levels]
34 'BIT': [Ann.BIT, '{bit}',],
35 'ATR': [Ann.ATR, 'Answer To Reset: {data:02x}', 'ATR: {data:02x}', '{data:02x}',],
36 'CMD': [Ann.CMD, 'Command: {data:02x}', 'Cmd: {data:02x}', '{data:02x}',],
37 'DATA': [Ann.DATA, 'Data: {data:02x}', '{data:02x}',],
38 'RESET': [Ann.RESET, 'Reset', 'R',],
41 def lookup_proto_ann_txt(cmd, variables):
42 ann = proto.get(cmd, None)
45 cls, texts = ann[0], ann[1:]
46 texts = [t.format(**variables) for t in texts]
49 class Decoder(srd.Decoder):
53 longname = 'SLE44xx memory card'
54 desc = 'SLE 4418/28/32/42 memory card serial protocol'
60 {'id': 'rst', 'name': 'RST', 'desc': 'Reset line'},
61 {'id': 'clk', 'name': 'CLK', 'desc': 'Clock line'},
62 {'id': 'io', 'name': 'I/O', 'desc': 'I/O data line'},
68 ('data', 'Data exchange'),
72 ('bits', 'Bits', (Ann.BIT,)),
73 ('fields', 'Fields', (Ann.ATR, Ann.CMD, Ann.DATA)),
74 ('interrupts', 'Interrupts', (Ann.RESET,)),
77 ('send-data', 'Send data'),
84 self.ss = self.es = self.ss_byte = -1
88 def metadata(self, key, value):
89 if key == srd.SRD_CONF_SAMPLERATE:
90 self.samplerate = value
93 self.out_ann = self.register(srd.OUTPUT_ANN)
94 self.out_binary = self.register(srd.OUTPUT_BINARY)
97 self.put(self.ss, self.es, self.out_ann, data)
100 self.put(self.ss, self.es, self.out_binary, data)
102 def handle_reset(self, pins):
103 self.ss, self.es = self.samplenum, self.samplenum
105 cls, texts = lookup_proto_ann_txt(self.cmd, {})
106 self.putx([cls, texts])
108 # Next data bytes will be Answer To Reset.
111 def handle_command(self, pins):
113 self.ss, self.es = self.samplenum, self.samplenum
114 # XXX Is the comment inverted?
115 # If I/O is rising -> command START
116 # if I/O is falling -> command STOP and response data incoming
117 self.cmd = 'CMD' if io == 0 else 'DATA'
120 # Gather 8 bits of data
121 def handle_data(self, pins):
124 # Remember the start of the first data/address bit. Collect
125 # bits in LSB first order. "Estimate" the bit's width at first,
126 # update end times as better data becomes available.
127 # TODO This estimation logic is imprecise and fragile. A single
128 # slightly stretched clock period throws off the following bit
129 # annotation. Better look for more reliable conditions. Available
130 # documentation suggests bit values are valid during high CLK.
132 self.ss_byte = self.samplenum
134 bit_ss = self.samplenum
135 bit_es = bit_ss # self.bitwidth is not known yet.
137 self.bits[-1][2] = bit_ss
138 self.bits.append([bit_val, bit_ss, bit_es])
139 if len(self.bits) < 8:
141 bitwidth = self.bits[-1][1] - self.bits[-2][1]
142 self.bits[-1][2] += bitwidth
144 # Get the data byte value, and byte's ss/es.
145 databyte = bitpack_lsb(self.bits, 0)
146 self.ss_byte = self.bits[0][1]
147 self.es_byte = self.bits[-1][2]
149 self.ss, self.es = self.ss_byte, self.es_byte
150 self.putb([Bin.SEND_DATA, bytes([databyte])])
152 # TODO Present bit values earlier. As soon as their es is known.
153 for bit_val, bit_ss, bit_es in self.bits:
154 cls, texts = lookup_proto_ann_txt('BIT', {'bit': bit_val})
155 self.put(bit_ss, bit_es, self.out_ann, [cls, texts])
157 cls, texts = lookup_proto_ann_txt(self.cmd, {'data': databyte})
159 self.putx([cls, texts])
161 # Done with this packet.
166 # Signal conditions tracked by the protocol decoder:
167 # - RESET condition (R): RST = rising
168 # - Incoming data (D): RST = low, CLK = rising.
169 # TODO Add "RST low, CLK fall" for "end of DATA" here?
170 # - Command mode START: CLK = high, I/O = falling.
171 # - Command mode STOP: CLK = high, I/O = rising.
172 (COND_RESET, COND_DATA, COND_CMD_START, COND_CMD_STOP,) = range(4)
175 {Pin.RST: 'l', Pin.CLK: 'r'},
176 {Pin.CLK: 'h', Pin.IO: 'f'},
177 {Pin.CLK: 'h', Pin.IO: 'r'},
179 pins = self.wait(conditions)
180 if self.matched[COND_RESET]:
181 self.handle_reset(pins)
182 elif self.matched[COND_DATA]:
183 self.handle_data(pins)
184 elif self.matched[COND_CMD_START]:
185 self.handle_command(pins)
186 elif self.matched[COND_CMD_STOP]:
187 self.handle_command(pins)