]> sigrok.org Git - libsigrokdecode.git/blame - decoders/sle44xx/pd.py
sle44xx: fixup boilerplate, add missing required fields
[libsigrokdecode.git] / decoders / sle44xx / pd.py
CommitLineData
7e87b2f7
FC
1##
2## This file is part of the libsigrokdecode project.
3##
4## Copyright (C) 2019 Federico Cerutti <federico@ceres-c.it>
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
20import sigrokdecode as srd
21
22'''
23OUTPUT_PYTHON format:
24
25Packet:
26[<ptype>, <pdata>]
27
28<ptype>:
29 - 'RESET' (Reset/Abort condition)
30 - 'ATR' (ATR data from card)
31 - 'CMD' (Command from reader)
32 - 'DATA' (Data from card)
33
34<pdata> is the data to/from the card
35For 'RESET' <pdata> is None.
36'''
37
38# CMD: [annotation-type-index, long annotation, short annotation]
39proto = {
40 'RESET': [0, 'Reset', 'R'],
41 'ATR': [1, 'ATR', 'ATR'],
42 'CMD': [2, 'Command', 'C'],
43 'DATA': [3, 'Data', 'D'],
44}
45
46class Decoder(srd.Decoder):
47 api_version = 3
48 id = 'sle44xx'
49 name = 'SLE 44xx'
50 longname = 'SLE44xx protocol'
51 desc = 'SLE 4418/28/32/42 memory card serial protocol'
52 license = 'gplv2+'
53 inputs = ['logic']
54 outputs = ['sle44xx']
ead00318 55 tags = ['Memory']
7e87b2f7
FC
56 channels = (
57 {'id': 'rst', 'name': 'RST', 'desc': 'Reset line'},
58 {'id': 'clk', 'name': 'CLK', 'desc': 'Clock line'},
59 {'id': 'io', 'name': 'I/O', 'desc': 'I/O data line'},
60 )
61 annotations = (
62 ('reset', 'Reset'),
63 ('atr', 'ATR'),
64 ('cmd', 'Command'),
65 ('data', 'Data exchange'),
66 ('bit', 'Bit'),
67 )
68 annotation_rows = (
69 ('bits', 'Bits', (4,)),
ead00318 70 ('fields', 'Fields', (1, 2, 3)),
7e87b2f7
FC
71 ('interrupts', 'Interrupts', (0,)),
72 )
73 binary = (
74 ('send-data', 'Send data'),
75 )
76
77 def __init__(self):
78 self.reset()
79
80 def reset(self):
81 self.ss = self.es = self.ss_byte = -1
82 self.bitcount = 0
83 self.databyte = 0
84 self.bits = []
85 self.cmd = 'RESET'
86
87 def metadata(self, key, value):
88 if key == srd.SRD_CONF_SAMPLERATE:
89 self.samplerate = value
90
91 def start(self):
92 self.out_python = self.register(srd.OUTPUT_PYTHON)
93 self.out_ann = self.register(srd.OUTPUT_ANN)
94 self.out_binary = self.register(srd.OUTPUT_BINARY)
95
96 def putx(self, data):
97 self.put(self.ss, self.es, self.out_ann, data)
98
99 def putp(self, data):
100 self.put(self.ss, self.es, self.out_python, data)
101
102 def putb(self, data):
103 self.put(self.ss, self.es, self.out_binary, data)
104
105 def handle_reset(self, pins):
106 self.ss, self.es = self.samplenum, self.samplenum
107 cmd = 'RESET' # No need to set the global self.cmd as this command is atomic
108 self.putp([cmd, None])
109 self.putx([proto[cmd][0], proto[cmd][1:]])
110 self.bitcount = self.databyte = 0
111 self.bits = []
112 self.cmd = 'ATR' # Next data bytes will be ATR
113
114 def handle_command(self, pins):
115 rst, clk, io = pins
116 self.ss, self.es = self.samplenum, self.samplenum
117 # If I/O is rising -> command START
118 # if I/O is falling -> command STOP and response data incoming
119 self.cmd = 'CMD' if (io == 0) else 'DATA'
120 self.bitcount = self.databyte = 0
121 self.bits = []
122
123 # Gather 8 bits of data
124 def handle_data(self, pins):
125 rst, clk, io = pins
126
127 # Data is transmitted LSB-first.
128 self.databyte |= (io << self.bitcount)
129
130 # Remember the start of the first data/address bit.
131 if self.bitcount == 0:
132 self.ss_byte = self.samplenum
133
134 # Store individual bits and their start/end samplenumbers.
135 # In the list, index 0 represents the LSB (SLE44xx transmits LSB-first).
136 self.bits.insert(0, [io, self.samplenum, self.samplenum])
137 if self.bitcount > 0:
138 self.bits[1][2] = self.samplenum
139 if self.bitcount == 7:
140 self.bitwidth = self.bits[1][2] - self.bits[2][2]
141 self.bits[0][2] += self.bitwidth
142
143 # Return if we haven't collected all 8 bits, yet.
144 if self.bitcount < 7:
145 self.bitcount += 1
146 return
147
148 self.ss, self.es = self.ss_byte, self.samplenum + self.bitwidth
149
150 self.putb([0, bytes([self.databyte])])
151
152 for bit in self.bits:
153 self.put(bit[1], bit[2], self.out_ann, [4, ['%d' % bit[0]]])
154
155 self.putx([proto[self.cmd][0], ['%s: %02X' % (proto[self.cmd][1], self.databyte),
156 '%s: %02X' % (proto[self.cmd][2], self.databyte), '%02X' % self.databyte]])
157
158 # Done with this packet.
159 self.bitcount = self.databyte = 0
160 self.bits = []
161
162 def decode(self):
163 while True:
164 pins = self.wait([{0: 'r'}, {0: 'l', 1: 'r'}, {1: 'h', 2: 'f'}, {1: 'h', 2: 'r'}])
165 if self.matched[0]: # RESET condition (R): RST = rising
166 self.handle_reset(pins)
167 elif self.matched[1]: # Incoming data (D): RST = low, CLK = rising.
168 self.handle_data(pins)
169 elif self.matched[2]: # Command mode START: CLK = high, I/O = falling.
170 self.handle_command(pins)
171 elif self.matched[3]: # Command mode STOP: CLK = high, I/O = rising.
ead00318 172 self.handle_command(pins)