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