]> sigrok.org Git - libsigrokdecode.git/blob - decoders/microwire/pd.py
microwire: Make the start bit an extra annotation class.
[libsigrokdecode.git] / decoders / microwire / pd.py
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
20 import sigrokdecode as srd
21
22 '''
23 OUTPUT_PYTHON format:
24
25 Packet:
26 [{'ss': bit start sample number,
27   'se': bit end sample number,
28   'si': SI bit,
29   'so': SO bit,
30  }, ...]
31
32 Since address and word size are variable, a list of all bits in each packet 
33 need to be output. Since Microwire is a synchronous protocol with separate
34 input and output lines (SI and SO) they are provided together, but because
35 Microwire is half-duplex only the SI or SO bits will be considered at once.
36 To be able to annotate correctly the instructions formed by the bit, the start
37 and end sample number of each bit (pair of SI/SO bit) are provided.
38 '''
39
40 class 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 = (
56         ('start-bit', 'Start bit'),
57         ('si-bit', 'SI bit'),
58         ('so-bit', 'SO bit'),
59         ('status-check', 'Status check'),
60         ('warning', 'Warning'),
61     )
62     annotation_rows = (
63         ('si-bits', 'SI bits', (0, 1)),
64         ('so-bits', 'SO bits', (2,)),
65         ('status', 'Status', (3,)),
66         ('warnings', 'Warnings', (4,)),
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,
79                      [4, ['Clock should be low on start',
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'], 
124                                      self.out_ann, [3, ['Busy', 'B']])
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'], 
130                              self.out_ann, [3, ['Busy', 'B']])
131                 else:
132                     self.put(start_samplenum, packet[-1]['samplenum'], 
133                              self.out_ann, [3, ['Ready', 'R']])
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,
153                                                  [4, ['Start bit not high',
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,
163                                              [1, ['SI bit: %d' % bit_si,
164                                                   'SI: %d' % bit_si,
165                                                   '%d' % bit_si]])
166                                     self.put(bit_start, change['samplenum'],
167                                              self.out_ann,
168                                              [2, ['SO bit: %d' % bit_so,
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,
182                                  [1, ['SI bit: %d' % bit_si,
183                                       'SI: %d' % bit_si, '%d' % bit_si]])
184                         self.put(bit_start, change['samplenum'], self.out_ann,
185                                  [2, ['SO bit: %d' % bit_so,
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)