]> sigrok.org Git - libsigrokdecode.git/blame - decoders/sle44xx/pd.py
sle44xx: rephrase ss/es passing for annotation emission
[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
80c76d20 20from common.srdhelper import bitpack_lsb
7e87b2f7
FC
21import sigrokdecode as srd
22
5c47b179
GS
23class Pin:
24 RST, CLK, IO, = range(3)
25
52f08e6d
GS
26class Ann:
27 BIT, ATR, CMD, DATA, RESET, = range(5)
28
29class Bin:
30 SEND_DATA, = range(1)
31
c328c181 32# CMD: [annotation class index, annotation texts for zoom levels]
7e87b2f7 33proto = {
c328c181
GS
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',],
7e87b2f7
FC
39}
40
c328c181
GS
41def lookup_proto_ann_txt(cmd, variables):
42 ann = proto.get(cmd, None)
43 if ann is None:
44 return None, []
45 cls, texts = ann[0], ann[1:]
46 texts = [t.format(**variables) for t in texts]
47 return cls, texts
48
7e87b2f7
FC
49class Decoder(srd.Decoder):
50 api_version = 3
51 id = 'sle44xx'
52 name = 'SLE 44xx'
b46b88f3 53 longname = 'SLE44xx memory card'
7e87b2f7
FC
54 desc = 'SLE 4418/28/32/42 memory card serial protocol'
55 license = 'gplv2+'
56 inputs = ['logic']
0411c41c 57 outputs = []
ead00318 58 tags = ['Memory']
7e87b2f7
FC
59 channels = (
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'},
63 )
64 annotations = (
52f08e6d 65 ('bit', 'Bit'),
7e87b2f7
FC
66 ('atr', 'ATR'),
67 ('cmd', 'Command'),
68 ('data', 'Data exchange'),
52f08e6d 69 ('reset', 'Reset'),
7e87b2f7
FC
70 )
71 annotation_rows = (
52f08e6d
GS
72 ('bits', 'Bits', (Ann.BIT,)),
73 ('fields', 'Fields', (Ann.ATR, Ann.CMD, Ann.DATA)),
74 ('interrupts', 'Interrupts', (Ann.RESET,)),
7e87b2f7
FC
75 )
76 binary = (
77 ('send-data', 'Send data'),
78 )
79
80 def __init__(self):
81 self.reset()
82
83 def reset(self):
7e87b2f7 84 self.bits = []
d25293e6 85 self.cmd = None
7e87b2f7
FC
86
87 def metadata(self, key, value):
88 if key == srd.SRD_CONF_SAMPLERATE:
89 self.samplerate = value
90
91 def start(self):
7e87b2f7
FC
92 self.out_ann = self.register(srd.OUTPUT_ANN)
93 self.out_binary = self.register(srd.OUTPUT_BINARY)
94
1dfaf1e8
GS
95 def putx(self, ss, es, cls, data):
96 self.put(ss, es, self.out_ann, [cls, data,])
7e87b2f7 97
1dfaf1e8
GS
98 def putb(self, ss, es, cls , data):
99 self.put(ss, es, self.out_binary, [cls, data,])
7e87b2f7
FC
100
101 def handle_reset(self, pins):
c328c181
GS
102 self.cmd = 'RESET'
103 cls, texts = lookup_proto_ann_txt(self.cmd, {})
1dfaf1e8 104 self.putx(self.samplenum, self.samplenum, cls, texts)
7e87b2f7 105 self.bits = []
e4f70391
GS
106 # Next data bytes will be Answer To Reset.
107 self.cmd = 'ATR'
7e87b2f7
FC
108
109 def handle_command(self, pins):
110 rst, clk, io = pins
e4f70391 111 # XXX Is the comment inverted?
7e87b2f7
FC
112 # If I/O is rising -> command START
113 # if I/O is falling -> command STOP and response data incoming
e4f70391 114 self.cmd = 'CMD' if io == 0 else 'DATA'
7e87b2f7
FC
115 self.bits = []
116
117 # Gather 8 bits of data
118 def handle_data(self, pins):
119 rst, clk, io = pins
120
80c76d20
GS
121 # Remember the start of the first data/address bit. Collect
122 # bits in LSB first order. "Estimate" the bit's width at first,
123 # update end times as better data becomes available.
124 # TODO This estimation logic is imprecise and fragile. A single
125 # slightly stretched clock period throws off the following bit
126 # annotation. Better look for more reliable conditions. Available
127 # documentation suggests bit values are valid during high CLK.
80c76d20
GS
128 bit_val = io
129 bit_ss = self.samplenum
130 bit_es = bit_ss # self.bitwidth is not known yet.
131 if self.bits:
132 self.bits[-1][2] = bit_ss
133 self.bits.append([bit_val, bit_ss, bit_es])
134 if len(self.bits) < 8:
7e87b2f7 135 return
80c76d20
GS
136 bitwidth = self.bits[-1][1] - self.bits[-2][1]
137 self.bits[-1][2] += bitwidth
7e87b2f7 138
80c76d20
GS
139 # Get the data byte value, and byte's ss/es.
140 databyte = bitpack_lsb(self.bits, 0)
1dfaf1e8
GS
141 byte_ss = self.bits[0][1]
142 byte_es = self.bits[-1][2]
7e87b2f7 143
1dfaf1e8 144 self.putb(byte_ss, byte_es, Bin.SEND_DATA, bytes([databyte]))
7e87b2f7 145
80c76d20 146 # TODO Present bit values earlier. As soon as their es is known.
c328c181
GS
147 for bit_val, bit_ss, bit_es in self.bits:
148 cls, texts = lookup_proto_ann_txt('BIT', {'bit': bit_val})
1dfaf1e8 149 self.putx(bit_ss, bit_es, cls, texts)
7e87b2f7 150
80c76d20 151 cls, texts = lookup_proto_ann_txt(self.cmd, {'data': databyte})
d25293e6 152 if cls:
1dfaf1e8 153 self.putx(byte_ss, byte_es, cls, texts)
7e87b2f7
FC
154
155 # Done with this packet.
7e87b2f7
FC
156 self.bits = []
157
158 def decode(self):
159 while True:
5c47b179
GS
160 # Signal conditions tracked by the protocol decoder:
161 # - RESET condition (R): RST = rising
162 # - Incoming data (D): RST = low, CLK = rising.
80c76d20 163 # TODO Add "RST low, CLK fall" for "end of DATA" here?
5c47b179
GS
164 # - Command mode START: CLK = high, I/O = falling.
165 # - Command mode STOP: CLK = high, I/O = rising.
166 (COND_RESET, COND_DATA, COND_CMD_START, COND_CMD_STOP,) = range(4)
167 conditions = [
168 {Pin.RST: 'r'},
169 {Pin.RST: 'l', Pin.CLK: 'r'},
170 {Pin.CLK: 'h', Pin.IO: 'f'},
171 {Pin.CLK: 'h', Pin.IO: 'r'},
172 ]
173 pins = self.wait(conditions)
174 if self.matched[COND_RESET]:
7e87b2f7 175 self.handle_reset(pins)
5c47b179 176 elif self.matched[COND_DATA]:
7e87b2f7 177 self.handle_data(pins)
5c47b179 178 elif self.matched[COND_CMD_START]:
7e87b2f7 179 self.handle_command(pins)
5c47b179 180 elif self.matched[COND_CMD_STOP]:
ead00318 181 self.handle_command(pins)