2 ## This file is part of the libsigrokdecode project.
4 ## Copyright (C) 2017 Kevin Redon <kingkevin@cuvoodoo.info>
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.
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.
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/>.
20 import sigrokdecode as srd
21 from collections import namedtuple
27 [namedtuple('ss': bit start sample number,
28 'es': bit end sample number,
33 Since address and word size are variable, a list of all bits in each packet
34 need to be output. Since Microwire is a synchronous protocol with separate
35 input and output lines (SI and SO) they are provided together, but because
36 Microwire is half-duplex only the SI or SO bits will be considered at once.
37 To be able to annotate correctly the instructions formed by the bit, the start
38 and end sample number of each bit (pair of SI/SO bit) are provided.
41 PyPacket = namedtuple('PyPacket', 'ss es si so')
42 Packet = namedtuple('Packet', 'samplenum matched cs sk si so')
44 class Decoder(srd.Decoder):
48 longname = 'Microwire'
49 desc = '3-wire, half-duplex, synchronous serial bus.'
52 outputs = ['microwire']
53 tags = ['Embedded/industrial']
55 {'id': 'cs', 'name': 'CS', 'desc': 'Chip select'},
56 {'id': 'sk', 'name': 'SK', 'desc': 'Clock'},
57 {'id': 'si', 'name': 'SI', 'desc': 'Slave in'},
58 {'id': 'so', 'name': 'SO', 'desc': 'Slave out'},
61 ('start-bit', 'Start bit'),
64 ('status-check-ready', 'Status check ready'),
65 ('status-check-busy', 'Status check busy'),
66 ('warning', 'Warning'),
69 ('si-bits', 'SI bits', (0, 1)),
70 ('so-bits', 'SO bits', (2,)),
71 ('status', 'Status', (3, 4)),
72 ('warnings', 'Warnings', (5,)),
82 self.out_python = self.register(srd.OUTPUT_PYTHON)
83 self.out_ann = self.register(srd.OUTPUT_ANN)
87 # Wait for slave to be selected on rising CS.
88 cs, sk, si, so = self.wait({0: 'r'})
90 self.put(self.samplenum, self.samplenum, self.out_ann,
91 [5, ['Clock should be low on start',
92 'Clock high on start', 'Clock high', 'SK high']])
93 sk = 0 # Enforce correct state for correct clock handling.
94 # Because we don't know if this is bit communication or a
95 # status check we have to collect the SI and SO values on SK
96 # edges while the chip is selected and figure out afterwards.
100 packet.append(Packet(self.samplenum, self.matched, cs, sk, si, so))
101 edge = 'r' if sk == 0 else 'f'
102 cs, sk, si, so = self.wait([{0: 'l'}, {1: edge}, {3: 'e'}])
104 packet.append(Packet(self.samplenum, self.matched, cs, sk, si, so))
106 # Figure out if this is a status check.
107 # Either there is no clock or no start bit (on first rising edge).
109 for change in packet:
110 # Get first clock rising edge.
111 if len(change.matched) > 1 and change.matched[1] and change.sk:
116 # The packet is for a status check.
117 # SO low = busy, SO high = ready.
118 # The SO signal might be noisy in the beginning because it starts
121 start_samplenum = packet[0].samplenum
122 bit_so = packet[0].so
123 # Check for SO edges.
124 for change in packet:
125 if len(change.matched) > 2 and change.matched[2]:
126 if bit_so == 0 and change.so:
127 # Rising edge Busy -> Ready.
128 self.put(start_samplenum, change.samplenum,
129 self.out_ann, [4, ['Busy', 'B']])
130 start_samplenum = change.samplenum
134 self.put(start_samplenum, packet[-1].samplenum,
135 self.out_ann, [4, ['Busy', 'B']])
137 self.put(start_samplenum, packet[-1].samplenum,
138 self.out_ann, [3, ['Ready', 'R']])
141 # Since the slave samples SI on clock rising edge we do the
142 # same. Because the slave changes SO on clock rising edge we
143 # sample on the falling edge.
144 bit_start = 0 # Rising clock sample of bit start.
145 bit_si = 0 # SI value at rising clock edge.
146 bit_so = 0 # SO value at falling clock edge.
147 start_bit = True # Start bit incoming (first bit).
148 pydata = [] # Python output data.
149 for change in packet:
150 if len(change.matched) > 1 and change.matched[1]:
152 if change.sk: # Rising clock edge.
153 if bit_start > 0: # Bit completed.
155 if bit_si == 0: # Start bit missing.
156 self.put(bit_start, change.samplenum,
158 [5, ['Start bit not high',
161 self.put(bit_start, change.samplenum,
163 [0, ['Start bit', 'S']])
166 self.put(bit_start, change.samplenum,
168 [1, ['SI bit: %d' % bit_si,
171 self.put(bit_start, change.samplenum,
173 [2, ['SO bit: %d' % bit_so,
176 pydata.append(PyPacket(bit_start,
177 change.samplenum, bit_si, bit_so))
178 bit_start = change.samplenum
180 else: # Falling clock edge.
182 elif change.matched[0] and \
183 change.cs == 0 and change.sk == 0:
185 self.put(bit_start, change.samplenum, self.out_ann,
186 [1, ['SI bit: %d' % bit_si,
187 'SI: %d' % bit_si, '%d' % bit_si]])
188 self.put(bit_start, change.samplenum, self.out_ann,
189 [2, ['SO bit: %d' % bit_so,
190 'SO: %d' % bit_so, '%d' % bit_so]])
191 pydata.append(PyPacket(bit_start, change.samplenum,
193 self.put(packet[0].samplenum, packet[len(packet) - 1].samplenum,
194 self.out_python, pydata)