]> sigrok.org Git - libsigrokdecode.git/blame - decoders/microwire/pd.py
microwire: Make Ready/Busy extra annotation classes.
[libsigrokdecode.git] / decoders / microwire / pd.py
CommitLineData
bf014116
KR
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 = (
bf3d8c80 56 ('start-bit', 'Start bit'),
bf014116
KR
57 ('si-bit', 'SI bit'),
58 ('so-bit', 'SO bit'),
0e081655
UH
59 ('status-check-ready', 'Status check ready'),
60 ('status-check-busy', 'Status check busy'),
bf014116
KR
61 ('warning', 'Warning'),
62 )
63 annotation_rows = (
bf3d8c80
UH
64 ('si-bits', 'SI bits', (0, 1)),
65 ('so-bits', 'SO bits', (2,)),
0e081655
UH
66 ('status', 'Status', (3, 4)),
67 ('warnings', 'Warnings', (5,)),
bf014116
KR
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,
0e081655 80 [5, ['Clock should be low on start',
bf014116
KR
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 if sk == 0:
93 cs, sk, si, so = self.wait([{0: 'l'}, {1: 'r'}, {3: 'e'}])
94 else:
95 cs, sk, si, so = self.wait([{0: 'l'}, {1: 'f'}, {3: 'e'}])
96 # Save last change.
97 packet.append({'samplenum': self.samplenum,
98 'matched': self.matched,
99 'cs': cs, 'sk': sk, 'si': si, 'so': so})
100
101 # Figure out if this is a status check.
102 # Either there is no clock or no start bit (on first rising edge).
103 status_check = True
104 for change in packet:
105 # Get first clock rising edge.
106 if len(change['matched']) > 1 and change['matched'][1] \
107 and change['sk']:
108 if change['si']:
109 status_check = False
110 break
111
112 # The packet is for a status check.
113 # SO low = busy, SO high = ready.
114 # The SO signal might be noisy in the beginning because it starts
115 # in high impedance.
116 if status_check:
117 start_samplenum = packet[0]['samplenum']
118 bit_so = packet[0]['so']
119 # Check for SO edges.
120 for change in packet:
121 if len(change['matched']) > 2 and change['matched'][2]:
122 if bit_so == 0 and change['so']:
123 # Rising edge Busy -> Ready.
124 self.put(start_samplenum, change['samplenum'],
0e081655 125 self.out_ann, [4, ['Busy', 'B']])
bf014116
KR
126 start_samplenum = change['samplenum']
127 bit_so = change['so']
128 # Put last state.
129 if bit_so == 0:
130 self.put(start_samplenum, packet[-1]['samplenum'],
0e081655 131 self.out_ann, [4, ['Busy', 'B']])
bf014116
KR
132 else:
133 self.put(start_samplenum, packet[-1]['samplenum'],
bf3d8c80 134 self.out_ann, [3, ['Ready', 'R']])
bf014116
KR
135 else:
136 # Bit communication.
137 # Since the slave samples SI on clock rising edge we do the
138 # same. Because the slave changes SO on clock rising edge we
139 # sample on the falling edge.
140 bit_start = 0 # Rising clock sample of bit start.
141 bit_si = 0 # SI value at rising clock edge.
142 bit_so = 0 # SO value at falling clock edge.
143 start_bit = True # Start bit incoming (first bit).
144 python_output = [] # Python output data.
145 for change in packet:
146 if len(change['matched']) > 1 and change['matched'][1]:
147 # Clock edge.
148 if change['sk']: # Rising clock edge.
149 if bit_start > 0: # Bit completed.
150 if start_bit:
151 if bit_si == 0: # Start bit missing.
152 self.put(bit_start, change['samplenum'],
153 self.out_ann,
0e081655 154 [5, ['Start bit not high',
bf014116
KR
155 'Start bit low']])
156 else:
157 self.put(bit_start, change['samplenum'],
158 self.out_ann,
159 [0, ['Start bit', 'S']])
160 start_bit = False
161 else:
162 self.put(bit_start, change['samplenum'],
163 self.out_ann,
bf3d8c80 164 [1, ['SI bit: %d' % bit_si,
bf014116
KR
165 'SI: %d' % bit_si,
166 '%d' % bit_si]])
167 self.put(bit_start, change['samplenum'],
168 self.out_ann,
bf3d8c80 169 [2, ['SO bit: %d' % bit_so,
bf014116
KR
170 'SO: %d' % bit_so,
171 '%d' % bit_so]])
172 python_output.append({'ss': bit_start,
173 'se': change['samplenum'],
174 'si': bit_si, 'so': bit_so})
175 bit_start = change['samplenum']
176 bit_si = change['si']
177 else: # Falling clock edge.
178 bit_so = change['so']
179 elif change['matched'][0] and \
180 change['cs'] == 0 and change['sk'] == 0:
181 # End of packet.
182 self.put(bit_start, change['samplenum'], self.out_ann,
bf3d8c80 183 [1, ['SI bit: %d' % bit_si,
bf014116
KR
184 'SI: %d' % bit_si, '%d' % bit_si]])
185 self.put(bit_start, change['samplenum'], self.out_ann,
bf3d8c80 186 [2, ['SO bit: %d' % bit_so,
bf014116
KR
187 'SO: %d' % bit_so, '%d' % bit_so]])
188 python_output.append({'ss': bit_start,
189 'se': change['samplenum'],
190 'si': bit_si, 'so': bit_so})
191 self.put(packet[0]['samplenum'],
192 packet[len(packet) - 1]['samplenum'],
193 self.out_python, python_output)