]> sigrok.org Git - libsigrokdecode.git/blame_incremental - decoders/microwire/pd.py
jtag_ejtag: Move bin2int() to common/srdhelper.
[libsigrokdecode.git] / decoders / microwire / pd.py
... / ...
CommitLineData
1##
2## This file is part of the libsigrokdecode project.
3##
4## Copyright (C) 2017 Kevin Redon <kingkevin@cuvoodoo.info>
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
21from collections import namedtuple
22
23'''
24OUTPUT_PYTHON format:
25
26Packet:
27[namedtuple('ss': bit start sample number,
28 'es': bit end sample number,
29 'si': SI bit,
30 'so': SO bit,
31 ), ...]
32
33Since address and word size are variable, a list of all bits in each packet
34need to be output. Since Microwire is a synchronous protocol with separate
35input and output lines (SI and SO) they are provided together, but because
36Microwire is half-duplex only the SI or SO bits will be considered at once.
37To be able to annotate correctly the instructions formed by the bit, the start
38and end sample number of each bit (pair of SI/SO bit) are provided.
39'''
40
41PyPacket = namedtuple('PyPacket', 'ss es si so')
42Packet = namedtuple('Packet', 'samplenum matched cs sk si so')
43
44class Decoder(srd.Decoder):
45 api_version = 3
46 id = 'microwire'
47 name = 'Microwire'
48 longname = 'Microwire'
49 desc = '3-wire, half-duplex, synchronous serial bus.'
50 license = 'gplv2+'
51 inputs = ['logic']
52 outputs = ['microwire']
53 channels = (
54 {'id': 'cs', 'name': 'CS', 'desc': 'Chip select'},
55 {'id': 'sk', 'name': 'SK', 'desc': 'Clock'},
56 {'id': 'si', 'name': 'SI', 'desc': 'Slave in'},
57 {'id': 'so', 'name': 'SO', 'desc': 'Slave out'},
58 )
59 annotations = (
60 ('start-bit', 'Start bit'),
61 ('si-bit', 'SI bit'),
62 ('so-bit', 'SO bit'),
63 ('status-check-ready', 'Status check ready'),
64 ('status-check-busy', 'Status check busy'),
65 ('warning', 'Warning'),
66 )
67 annotation_rows = (
68 ('si-bits', 'SI bits', (0, 1)),
69 ('so-bits', 'SO bits', (2,)),
70 ('status', 'Status', (3, 4)),
71 ('warnings', 'Warnings', (5,)),
72 )
73
74 def __init__(self):
75 self.reset()
76
77 def reset(self):
78 pass
79
80 def start(self):
81 self.out_python = self.register(srd.OUTPUT_PYTHON)
82 self.out_ann = self.register(srd.OUTPUT_ANN)
83
84 def decode(self):
85 while True:
86 # Wait for slave to be selected on rising CS.
87 cs, sk, si, so = self.wait({0: 'r'})
88 if sk:
89 self.put(self.samplenum, self.samplenum, self.out_ann,
90 [5, ['Clock should be low on start',
91 'Clock high on start', 'Clock high', 'SK high']])
92 sk = 0 # Enforce correct state for correct clock handling.
93 # Because we don't know if this is bit communication or a
94 # status check we have to collect the SI and SO values on SK
95 # edges while the chip is selected and figure out afterwards.
96 packet = []
97 while cs:
98 # Save change.
99 packet.append(Packet(self.samplenum, self.matched, cs, sk, si, so))
100 edge = 'r' if sk == 0 else 'f'
101 cs, sk, si, so = self.wait([{0: 'l'}, {1: edge}, {3: 'e'}])
102 # Save last change.
103 packet.append(Packet(self.samplenum, self.matched, cs, sk, si, so))
104
105 # Figure out if this is a status check.
106 # Either there is no clock or no start bit (on first rising edge).
107 status_check = True
108 for change in packet:
109 # Get first clock rising edge.
110 if len(change.matched) > 1 and change.matched[1] and change.sk:
111 if change.si:
112 status_check = False
113 break
114
115 # The packet is for a status check.
116 # SO low = busy, SO high = ready.
117 # The SO signal might be noisy in the beginning because it starts
118 # in high impedance.
119 if status_check:
120 start_samplenum = packet[0].samplenum
121 bit_so = packet[0].so
122 # Check for SO edges.
123 for change in packet:
124 if len(change.matched) > 2 and change.matched[2]:
125 if bit_so == 0 and change.so:
126 # Rising edge Busy -> Ready.
127 self.put(start_samplenum, change.samplenum,
128 self.out_ann, [4, ['Busy', 'B']])
129 start_samplenum = change.samplenum
130 bit_so = change.so
131 # Put last state.
132 if bit_so == 0:
133 self.put(start_samplenum, packet[-1].samplenum,
134 self.out_ann, [4, ['Busy', 'B']])
135 else:
136 self.put(start_samplenum, packet[-1].samplenum,
137 self.out_ann, [3, ['Ready', 'R']])
138 else:
139 # Bit communication.
140 # Since the slave samples SI on clock rising edge we do the
141 # same. Because the slave changes SO on clock rising edge we
142 # sample on the falling edge.
143 bit_start = 0 # Rising clock sample of bit start.
144 bit_si = 0 # SI value at rising clock edge.
145 bit_so = 0 # SO value at falling clock edge.
146 start_bit = True # Start bit incoming (first bit).
147 pydata = [] # Python output data.
148 for change in packet:
149 if len(change.matched) > 1 and change.matched[1]:
150 # Clock edge.
151 if change.sk: # Rising clock edge.
152 if bit_start > 0: # Bit completed.
153 if start_bit:
154 if bit_si == 0: # Start bit missing.
155 self.put(bit_start, change.samplenum,
156 self.out_ann,
157 [5, ['Start bit not high',
158 'Start bit low']])
159 else:
160 self.put(bit_start, change.samplenum,
161 self.out_ann,
162 [0, ['Start bit', 'S']])
163 start_bit = False
164 else:
165 self.put(bit_start, change.samplenum,
166 self.out_ann,
167 [1, ['SI bit: %d' % bit_si,
168 'SI: %d' % bit_si,
169 '%d' % bit_si]])
170 self.put(bit_start, change.samplenum,
171 self.out_ann,
172 [2, ['SO bit: %d' % bit_so,
173 'SO: %d' % bit_so,
174 '%d' % bit_so]])
175 pydata.append(PyPacket(bit_start,
176 change.samplenum, bit_si, bit_so))
177 bit_start = change.samplenum
178 bit_si = change.si
179 else: # Falling clock edge.
180 bit_so = change.so
181 elif change.matched[0] and \
182 change.cs == 0 and change.sk == 0:
183 # End of packet.
184 self.put(bit_start, change.samplenum, self.out_ann,
185 [1, ['SI bit: %d' % bit_si,
186 'SI: %d' % bit_si, '%d' % bit_si]])
187 self.put(bit_start, change.samplenum, self.out_ann,
188 [2, ['SO bit: %d' % bit_so,
189 'SO: %d' % bit_so, '%d' % bit_so]])
190 pydata.append(PyPacket(bit_start, change.samplenum,
191 bit_si, bit_so))
192 self.put(packet[0].samplenum, packet[len(packet) - 1].samplenum,
193 self.out_python, pydata)