]> sigrok.org Git - libsigrokdecode.git/blame - decoders/microwire/pd.py
decoders: Add/update tags for each PD.
[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,
5f914c47 28 'es': bit end sample number,
bf014116
KR
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
5f914c47 41PyPacket = namedtuple('PyPacket', 'ss es si so')
9fb04bdf 42Packet = namedtuple('Packet', 'samplenum matched cs sk si so')
15c107c2 43
bf014116
KR
44class Decoder(srd.Decoder):
45 api_version = 3
46 id = 'microwire'
47 name = 'Microwire'
48 longname = 'Microwire'
49 desc = '3-wire, half-duplex, synchronous serial bus.'
50 license = 'gplv2+'
51 inputs = ['logic']
52 outputs = ['microwire']
d6d8a8a4 53 tags = ['Embedded/industrial']
bf014116
KR
54 channels = (
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'},
59 )
60 annotations = (
bf3d8c80 61 ('start-bit', 'Start bit'),
bf014116
KR
62 ('si-bit', 'SI bit'),
63 ('so-bit', 'SO bit'),
0e081655
UH
64 ('status-check-ready', 'Status check ready'),
65 ('status-check-busy', 'Status check busy'),
bf014116
KR
66 ('warning', 'Warning'),
67 )
68 annotation_rows = (
bf3d8c80
UH
69 ('si-bits', 'SI bits', (0, 1)),
70 ('so-bits', 'SO bits', (2,)),
0e081655
UH
71 ('status', 'Status', (3, 4)),
72 ('warnings', 'Warnings', (5,)),
bf014116
KR
73 )
74
67e51696
GS
75 def __init__(self):
76 self.reset()
77
78 def reset(self):
79 pass
80
bf014116
KR
81 def start(self):
82 self.out_python = self.register(srd.OUTPUT_PYTHON)
83 self.out_ann = self.register(srd.OUTPUT_ANN)
84
85 def decode(self):
86 while True:
87 # Wait for slave to be selected on rising CS.
88 cs, sk, si, so = self.wait({0: 'r'})
89 if sk:
90 self.put(self.samplenum, self.samplenum, self.out_ann,
0e081655 91 [5, ['Clock should be low on start',
bf014116
KR
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.
97 packet = []
98 while cs:
99 # Save change.
9fb04bdf 100 packet.append(Packet(self.samplenum, self.matched, cs, sk, si, so))
13c484dd
UH
101 edge = 'r' if sk == 0 else 'f'
102 cs, sk, si, so = self.wait([{0: 'l'}, {1: edge}, {3: 'e'}])
bf014116 103 # Save last change.
9fb04bdf 104 packet.append(Packet(self.samplenum, self.matched, cs, sk, si, so))
bf014116
KR
105
106 # Figure out if this is a status check.
107 # Either there is no clock or no start bit (on first rising edge).
108 status_check = True
109 for change in packet:
110 # Get first clock rising edge.
9fb04bdf
UH
111 if len(change.matched) > 1 and change.matched[1] and change.sk:
112 if change.si:
bf014116
KR
113 status_check = False
114 break
115
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
119 # in high impedance.
120 if status_check:
9fb04bdf
UH
121 start_samplenum = packet[0].samplenum
122 bit_so = packet[0].so
bf014116
KR
123 # Check for SO edges.
124 for change in packet:
9fb04bdf
UH
125 if len(change.matched) > 2 and change.matched[2]:
126 if bit_so == 0 and change.so:
bf014116 127 # Rising edge Busy -> Ready.
9fb04bdf 128 self.put(start_samplenum, change.samplenum,
0e081655 129 self.out_ann, [4, ['Busy', 'B']])
9fb04bdf
UH
130 start_samplenum = change.samplenum
131 bit_so = change.so
bf014116
KR
132 # Put last state.
133 if bit_so == 0:
9fb04bdf 134 self.put(start_samplenum, packet[-1].samplenum,
0e081655 135 self.out_ann, [4, ['Busy', 'B']])
bf014116 136 else:
9fb04bdf 137 self.put(start_samplenum, packet[-1].samplenum,
bf3d8c80 138 self.out_ann, [3, ['Ready', 'R']])
bf014116
KR
139 else:
140 # Bit communication.
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).
15c107c2 148 pydata = [] # Python output data.
bf014116 149 for change in packet:
9fb04bdf 150 if len(change.matched) > 1 and change.matched[1]:
bf014116 151 # Clock edge.
9fb04bdf 152 if change.sk: # Rising clock edge.
bf014116
KR
153 if bit_start > 0: # Bit completed.
154 if start_bit:
155 if bit_si == 0: # Start bit missing.
9fb04bdf 156 self.put(bit_start, change.samplenum,
bf014116 157 self.out_ann,
0e081655 158 [5, ['Start bit not high',
bf014116
KR
159 'Start bit low']])
160 else:
9fb04bdf 161 self.put(bit_start, change.samplenum,
bf014116
KR
162 self.out_ann,
163 [0, ['Start bit', 'S']])
164 start_bit = False
165 else:
9fb04bdf 166 self.put(bit_start, change.samplenum,
bf014116 167 self.out_ann,
bf3d8c80 168 [1, ['SI bit: %d' % bit_si,
bf014116
KR
169 'SI: %d' % bit_si,
170 '%d' % bit_si]])
9fb04bdf 171 self.put(bit_start, change.samplenum,
bf014116 172 self.out_ann,
bf3d8c80 173 [2, ['SO bit: %d' % bit_so,
bf014116
KR
174 'SO: %d' % bit_so,
175 '%d' % bit_so]])
15c107c2 176 pydata.append(PyPacket(bit_start,
9fb04bdf
UH
177 change.samplenum, bit_si, bit_so))
178 bit_start = change.samplenum
179 bit_si = change.si
bf014116 180 else: # Falling clock edge.
9fb04bdf
UH
181 bit_so = change.so
182 elif change.matched[0] and \
183 change.cs == 0 and change.sk == 0:
bf014116 184 # End of packet.
9fb04bdf 185 self.put(bit_start, change.samplenum, self.out_ann,
bf3d8c80 186 [1, ['SI bit: %d' % bit_si,
bf014116 187 'SI: %d' % bit_si, '%d' % bit_si]])
9fb04bdf 188 self.put(bit_start, change.samplenum, self.out_ann,
bf3d8c80 189 [2, ['SO bit: %d' % bit_so,
bf014116 190 'SO: %d' % bit_so, '%d' % bit_so]])
9fb04bdf 191 pydata.append(PyPacket(bit_start, change.samplenum,
15c107c2 192 bit_si, bit_so))
9fb04bdf 193 self.put(packet[0].samplenum, packet[len(packet) - 1].samplenum,
15c107c2 194 self.out_python, pydata)