]> sigrok.org Git - libsigrokdecode.git/blame - decoders/sle44xx/pd.py
sle44xx: rephrase annotation text construction
[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
5c47b179
GS
22class Pin:
23 RST, CLK, IO, = range(3)
24
52f08e6d
GS
25class Ann:
26 BIT, ATR, CMD, DATA, RESET, = range(5)
27
28class Bin:
29 SEND_DATA, = range(1)
30
c328c181 31# CMD: [annotation class index, annotation texts for zoom levels]
7e87b2f7 32proto = {
c328c181
GS
33 'BIT': [Ann.BIT, '{bit}',],
34 'ATR': [Ann.ATR, 'Answer To Reset: {data:02x}', 'ATR: {data:02x}', '{data:02x}',],
35 'CMD': [Ann.CMD, 'Command: {data:02x}', 'Cmd: {data:02x}', '{data:02x}',],
36 'DATA': [Ann.DATA, 'Data: {data:02x}', '{data:02x}',],
37 'RESET': [Ann.RESET, 'Reset', 'R',],
7e87b2f7
FC
38}
39
c328c181
GS
40def lookup_proto_ann_txt(cmd, variables):
41 ann = proto.get(cmd, None)
42 if ann is None:
43 return None, []
44 cls, texts = ann[0], ann[1:]
45 texts = [t.format(**variables) for t in texts]
46 return cls, texts
47
7e87b2f7
FC
48class Decoder(srd.Decoder):
49 api_version = 3
50 id = 'sle44xx'
51 name = 'SLE 44xx'
b46b88f3 52 longname = 'SLE44xx memory card'
7e87b2f7
FC
53 desc = 'SLE 4418/28/32/42 memory card serial protocol'
54 license = 'gplv2+'
55 inputs = ['logic']
0411c41c 56 outputs = []
ead00318 57 tags = ['Memory']
7e87b2f7
FC
58 channels = (
59 {'id': 'rst', 'name': 'RST', 'desc': 'Reset line'},
60 {'id': 'clk', 'name': 'CLK', 'desc': 'Clock line'},
61 {'id': 'io', 'name': 'I/O', 'desc': 'I/O data line'},
62 )
63 annotations = (
52f08e6d 64 ('bit', 'Bit'),
7e87b2f7
FC
65 ('atr', 'ATR'),
66 ('cmd', 'Command'),
67 ('data', 'Data exchange'),
52f08e6d 68 ('reset', 'Reset'),
7e87b2f7
FC
69 )
70 annotation_rows = (
52f08e6d
GS
71 ('bits', 'Bits', (Ann.BIT,)),
72 ('fields', 'Fields', (Ann.ATR, Ann.CMD, Ann.DATA)),
73 ('interrupts', 'Interrupts', (Ann.RESET,)),
7e87b2f7
FC
74 )
75 binary = (
76 ('send-data', 'Send data'),
77 )
78
79 def __init__(self):
80 self.reset()
81
82 def reset(self):
83 self.ss = self.es = self.ss_byte = -1
84 self.bitcount = 0
85 self.databyte = 0
86 self.bits = []
87 self.cmd = 'RESET'
88
89 def metadata(self, key, value):
90 if key == srd.SRD_CONF_SAMPLERATE:
91 self.samplerate = value
92
93 def start(self):
7e87b2f7
FC
94 self.out_ann = self.register(srd.OUTPUT_ANN)
95 self.out_binary = self.register(srd.OUTPUT_BINARY)
96
97 def putx(self, data):
98 self.put(self.ss, self.es, self.out_ann, data)
99
7e87b2f7
FC
100 def putb(self, data):
101 self.put(self.ss, self.es, self.out_binary, data)
102
103 def handle_reset(self, pins):
104 self.ss, self.es = self.samplenum, self.samplenum
c328c181
GS
105 self.cmd = 'RESET'
106 cls, texts = lookup_proto_ann_txt(self.cmd, {})
107 self.putx([cls, texts])
7e87b2f7
FC
108 self.bitcount = self.databyte = 0
109 self.bits = []
110 self.cmd = 'ATR' # Next data bytes will be ATR
111
112 def handle_command(self, pins):
113 rst, clk, io = pins
114 self.ss, self.es = self.samplenum, self.samplenum
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'
118 self.bitcount = self.databyte = 0
119 self.bits = []
120
121 # Gather 8 bits of data
122 def handle_data(self, pins):
123 rst, clk, io = pins
124
125 # Data is transmitted LSB-first.
126 self.databyte |= (io << self.bitcount)
127
128 # Remember the start of the first data/address bit.
129 if self.bitcount == 0:
130 self.ss_byte = self.samplenum
131
132 # Store individual bits and their start/end samplenumbers.
133 # In the list, index 0 represents the LSB (SLE44xx transmits LSB-first).
134 self.bits.insert(0, [io, self.samplenum, self.samplenum])
135 if self.bitcount > 0:
136 self.bits[1][2] = self.samplenum
137 if self.bitcount == 7:
138 self.bitwidth = self.bits[1][2] - self.bits[2][2]
139 self.bits[0][2] += self.bitwidth
140
141 # Return if we haven't collected all 8 bits, yet.
142 if self.bitcount < 7:
143 self.bitcount += 1
144 return
145
146 self.ss, self.es = self.ss_byte, self.samplenum + self.bitwidth
147
52f08e6d 148 self.putb([Bin.SEND_DATA, bytes([self.databyte])])
7e87b2f7 149
c328c181
GS
150 for bit_val, bit_ss, bit_es in self.bits:
151 cls, texts = lookup_proto_ann_txt('BIT', {'bit': bit_val})
152 self.put(bit_ss, bit_es, self.out_ann, [cls, texts])
7e87b2f7 153
c328c181
GS
154 cls, texts = lookup_proto_ann_txt(self.cmd, {'data': self.databyte})
155 self.putx([cls, texts])
7e87b2f7
FC
156
157 # Done with this packet.
158 self.bitcount = self.databyte = 0
159 self.bits = []
160
161 def decode(self):
162 while True:
5c47b179
GS
163 # Signal conditions tracked by the protocol decoder:
164 # - RESET condition (R): RST = rising
165 # - Incoming data (D): RST = low, CLK = rising.
166 # - Command mode START: CLK = high, I/O = falling.
167 # - Command mode STOP: CLK = high, I/O = rising.
168 (COND_RESET, COND_DATA, COND_CMD_START, COND_CMD_STOP,) = range(4)
169 conditions = [
170 {Pin.RST: 'r'},
171 {Pin.RST: 'l', Pin.CLK: 'r'},
172 {Pin.CLK: 'h', Pin.IO: 'f'},
173 {Pin.CLK: 'h', Pin.IO: 'r'},
174 ]
175 pins = self.wait(conditions)
176 if self.matched[COND_RESET]:
7e87b2f7 177 self.handle_reset(pins)
5c47b179 178 elif self.matched[COND_DATA]:
7e87b2f7 179 self.handle_data(pins)
5c47b179 180 elif self.matched[COND_CMD_START]:
7e87b2f7 181 self.handle_command(pins)
5c47b179 182 elif self.matched[COND_CMD_STOP]:
ead00318 183 self.handle_command(pins)