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