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 import sigrokdecode as srd
22 # CMD: [annotation-type-index, long annotation, short annotation]
24 'RESET': [0, 'Reset', 'R'],
25 'ATR': [1, 'ATR', 'ATR'],
26 'CMD': [2, 'Command', 'C'],
27 'DATA': [3, 'Data', 'D'],
30 class Decoder(srd.Decoder):
34 longname = 'SLE44xx memory card'
35 desc = 'SLE 4418/28/32/42 memory card serial protocol'
41 {'id': 'rst', 'name': 'RST', 'desc': 'Reset line'},
42 {'id': 'clk', 'name': 'CLK', 'desc': 'Clock line'},
43 {'id': 'io', 'name': 'I/O', 'desc': 'I/O data line'},
49 ('data', 'Data exchange'),
53 ('bits', 'Bits', (4,)),
54 ('fields', 'Fields', (1, 2, 3)),
55 ('interrupts', 'Interrupts', (0,)),
58 ('send-data', 'Send data'),
65 self.ss = self.es = self.ss_byte = -1
71 def metadata(self, key, value):
72 if key == srd.SRD_CONF_SAMPLERATE:
73 self.samplerate = value
76 self.out_ann = self.register(srd.OUTPUT_ANN)
77 self.out_binary = self.register(srd.OUTPUT_BINARY)
80 self.put(self.ss, self.es, self.out_ann, data)
83 self.put(self.ss, self.es, self.out_binary, data)
85 def handle_reset(self, pins):
86 self.ss, self.es = self.samplenum, self.samplenum
87 cmd = 'RESET' # No need to set the global self.cmd as this command is atomic
88 self.putx([proto[cmd][0], proto[cmd][1:]])
89 self.bitcount = self.databyte = 0
91 self.cmd = 'ATR' # Next data bytes will be ATR
93 def handle_command(self, pins):
95 self.ss, self.es = self.samplenum, self.samplenum
96 # If I/O is rising -> command START
97 # if I/O is falling -> command STOP and response data incoming
98 self.cmd = 'CMD' if (io == 0) else 'DATA'
99 self.bitcount = self.databyte = 0
102 # Gather 8 bits of data
103 def handle_data(self, pins):
106 # Data is transmitted LSB-first.
107 self.databyte |= (io << self.bitcount)
109 # Remember the start of the first data/address bit.
110 if self.bitcount == 0:
111 self.ss_byte = self.samplenum
113 # Store individual bits and their start/end samplenumbers.
114 # In the list, index 0 represents the LSB (SLE44xx transmits LSB-first).
115 self.bits.insert(0, [io, self.samplenum, self.samplenum])
116 if self.bitcount > 0:
117 self.bits[1][2] = self.samplenum
118 if self.bitcount == 7:
119 self.bitwidth = self.bits[1][2] - self.bits[2][2]
120 self.bits[0][2] += self.bitwidth
122 # Return if we haven't collected all 8 bits, yet.
123 if self.bitcount < 7:
127 self.ss, self.es = self.ss_byte, self.samplenum + self.bitwidth
129 self.putb([0, bytes([self.databyte])])
131 for bit in self.bits:
132 self.put(bit[1], bit[2], self.out_ann, [4, ['%d' % bit[0]]])
134 self.putx([proto[self.cmd][0], ['%s: %02X' % (proto[self.cmd][1], self.databyte),
135 '%s: %02X' % (proto[self.cmd][2], self.databyte), '%02X' % self.databyte]])
137 # Done with this packet.
138 self.bitcount = self.databyte = 0
143 pins = self.wait([{0: 'r'}, {0: 'l', 1: 'r'}, {1: 'h', 2: 'f'}, {1: 'h', 2: 'r'}])
144 if self.matched[0]: # RESET condition (R): RST = rising
145 self.handle_reset(pins)
146 elif self.matched[1]: # Incoming data (D): RST = low, CLK = rising.
147 self.handle_data(pins)
148 elif self.matched[2]: # Command mode START: CLK = high, I/O = falling.
149 self.handle_command(pins)
150 elif self.matched[3]: # Command mode STOP: CLK = high, I/O = rising.
151 self.handle_command(pins)