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