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