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