]> sigrok.org Git - libsigrokdecode.git/blob - decoders/onewire_link/pd.py
Implement new 1-Wire link decoder using time ranges
[libsigrokdecode.git] / decoders / onewire_link / 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 class SamplerateError(Exception):
23     pass
24
25 # Timing values in us for the signal at regular and overdrive speed.
26 timing = {
27     'RSTL': {
28         'min': {
29             False: 480.0,
30             True: 48.0,
31         },
32         'max': {
33             False: 960.0,
34             True: 80.0,
35         },
36     },
37     'RSTH': {
38         'min': {
39             False: 480.0,
40             True: 48.0,
41         },
42     },
43     'PDH': {
44         'min': {
45             False: 15.0,
46             True: 2.0,
47         },
48         'max': {
49             False: 60.0,
50             True: 6.0,
51         },
52     },
53     'PDL': {
54         'min': {
55             False: 60.0,
56             True: 8.0,
57         },
58         'max': {
59             False: 240.0,
60             True: 24.0,
61         },
62     },
63     'SLOT': {
64         'min': {
65             False: 60.0,
66             True: 6.0,
67         },
68         'max': {
69             False: 120.0,
70             True: 16.0,
71         },
72     },
73     'REC': {
74         'min': {
75             False: 1.0,
76             True: 1.0,
77         },
78     },
79     'LOWR': {
80         'min': {
81             False: 1.0,
82             True: 1.0,
83         },
84         'max': {
85             False: 15.0,
86             True: 2.0,
87         },
88     },
89 }
90
91 class Decoder(srd.Decoder):
92     api_version = 2
93     id = 'onewire_link'
94     name = '1-Wire link layer'
95     longname = '1-Wire serial communication bus (link layer)'
96     desc = 'Bidirectional, half-duplex, asynchronous serial bus.'
97     license = 'gplv2+'
98     inputs = ['logic']
99     outputs = ['onewire_link']
100     channels = (
101         {'id': 'owr', 'name': 'OWR', 'desc': '1-Wire signal line'},
102     )
103     options = (
104         {'id': 'overdrive', 'desc': 'Start in overdrive speed',
105             'default': 'no', 'values': ('yes', 'no')},
106     )
107     annotations = (
108         ('bit', 'Bit'),
109         ('warnings', 'Warnings'),
110         ('reset', 'Reset'),
111         ('presence', 'Presence'),
112         ('overdrive', 'Overdrive speed notifications'),
113     )
114     annotation_rows = (
115         ('bits', 'Bits', (0, 2, 3)),
116         ('info', 'Info', (4,)),
117         ('warnings', 'Warnings', (1,)),
118     )
119
120     def __init__(self):
121         self.samplerate = None
122         self.samplenum = 0
123         self.state = 'INITIAL'
124         self.present = 0
125         self.bit = 0
126         self.bit_count = -1
127         self.command = 0
128         self.overdrive = False
129         self.fall = 0
130         self.rise = 0
131
132     def start(self):
133         self.out_python = self.register(srd.OUTPUT_PYTHON)
134         self.out_ann = self.register(srd.OUTPUT_ANN)
135         self.overdrive = (self.options['overdrive'] == 'yes')
136         self.fall = 0
137         self.rise = 0
138         self.bit_count = -1
139
140     def checks(self):
141         # Check if samplerate is appropriate.
142         if self.options['overdrive'] == 'yes':
143             if self.samplerate < 2000000:
144                 self.putm([1, ['Sampling rate is too low. Must be above ' +
145                                '2MHz for proper overdrive mode decoding.']])
146             elif self.samplerate < 5000000:
147                 self.putm([1, ['Sampling rate is suggested to be above 5MHz ' +
148                                'for proper overdrive mode decoding.']])
149         else:
150             if self.samplerate < 400000:
151                 self.putm([1, ['Sampling rate is too low. Must be above ' +
152                                '400kHz for proper normal mode decoding.']])
153             elif self.samplerate < 1000000:
154                 self.putm([1, ['Sampling rate is suggested to be above ' +
155                                '1MHz for proper normal mode decoding.']])
156
157     def metadata(self, key, value):
158         if key != srd.SRD_CONF_SAMPLERATE:
159             return
160         self.samplerate = value
161
162     def decode(self, ss, es, data):
163         if not self.samplerate:
164             raise SamplerateError('Cannot decode without samplerate.')
165         for (self.samplenum, (owr,)) in data:
166             if self.samplenum == 0:
167                 self.checks()
168
169             # State machine.
170             if self.state == 'INITIAL': # Unknown initial state.
171                 # Wait until we reach the idle high state.
172                 if owr == 0:
173                     continue
174                 self.rise = self.samplenum
175                 self.state = 'IDLE'
176             elif self.state == 'IDLE': # Idle high state.
177                 # Wait for falling edge.
178                 if owr != 0:
179                     continue
180                 self.fall = self.samplenum
181                 # Get time since last rising edge.
182                 time = ((self.fall - self.rise) / self.samplerate) * 1000000.0
183                 if self.rise > 0 and \
184                     time < timing['REC']['min'][self.overdrive]:
185                     self.put(self.fall, self.rise, self.out_ann,
186                         [1, ['Recovery time not long enough'
187                         'Recovery too short',
188                         'REC < ' + str(timing['REC']['min'][self.overdrive])]])
189                 # A reset pulse or slot can start on a falling edge.
190                 self.state = 'LOW'
191                 # TODO: Check minimum recovery time.
192             elif self.state == 'LOW': # Reset pulse or slot.
193                 # Wait for rising edge.
194                 if owr == 0:
195                     continue
196                 self.rise = self.samplenum
197                 # Detect reset or slot base on timing.
198                 time = ((self.rise - self.fall) / self.samplerate) * 1000000.0
199                 if time >= timing['RSTL']['min'][False]: # Normal reset pulse.
200                     if time > timing['RSTL']['max'][False]:
201                         self.put(self.fall, self.rise, self.out_ann,
202                             [1, ['Too long reset pulse might mask interrupt ' +
203                             'signalling by other devices',
204                             'Reset pulse too long',
205                             'RST > ' + str(timing['RSTL']['max'][False])]])
206                     # Regular reset pulse clears overdrive speed.
207                     if self.overdrive:
208                         self.put(self.fall, self.rise, self.out_ann,
209                             [4, ['Exiting overdrive mode', 'Overdrive off']])
210                     self.overdrive = False
211                     self.put(self.fall, self.rise, self.out_ann,
212                         [2, ['Reset', 'Rst', 'R']])
213                     self.state = 'PRESENCE DETECT HIGH'
214                 elif self.overdrive == True and \
215                     time >= timing['RSTL']['min'][self.overdrive] and \
216                     time < timing['RSTL']['max'][self.overdrive]:
217                     # Overdrive reset pulse.
218                     self.put(self.fall, self.rise, self.out_ann,
219                         [2, ['Reset', 'Rst', 'R']])
220                     self.state = 'PRESENCE DETECT HIGH'
221                 elif time < timing['SLOT']['max'][self.overdrive]:
222                     # Read/write time slot.
223                     if time < timing['LOWR']['min'][self.overdrive]:
224                         self.put(self.fall, self.rise, self.out_ann,
225                             [1, ['Low signal not long enough',
226                             'Low too short',
227                             'LOW < ' + str(timing['LOWR']['min'][self.overdrive])]])
228                     if time < timing['LOWR']['max'][self.overdrive]:
229                         self.bit = 1 # Short pulse is a 1 bit.
230                     else:
231                         self.bit = 0 # Long pulse is a 0 bit.
232                     # Wait for end of slot.
233                     self.state = 'SLOT'
234                 else:
235                     # Timing outside of known states.
236                     self.put(self.fall, self.rise, self.out_ann,
237                         [1, ['Erroneous signal', 'Error', 'Err', 'E']])
238                     self.state = 'IDLE'
239             elif self.state == 'PRESENCE DETECT HIGH': # Wait for slave presence signal.
240                 # Calculate time since rising edge.
241                 time = ((self.samplenum - self.rise) / self.samplerate) * 1000000.0
242                 if owr != 0 and time < timing['PDH']['max'][self.overdrive]:
243                     continue
244                 elif owr == 0: # Presence detected.
245                     if time < timing['PDH']['min'][self.overdrive]:
246                         self.put(self.rise, self.samplenum, self.out_ann,
247                             [1, ['Presence detect signal is too early',
248                             'Presence detect too early',
249                             'PDH < ' + str(timing['PDH']['min'][self.overdrive])]])
250                     self.fall = self.samplenum
251                     self.state = 'PRESENCE DETECT LOW'
252                 else: # No presence detected.
253                     self.put(self.rise, self.samplenum, self.out_ann,
254                         [3, ['Presence: false', 'Presence', 'Pres', 'P']])
255                     self.put(self.rise, self.samplenum, self.out_python,
256                         ['RESET/PRESENCE', False])
257                     self.state = 'IDLE'
258             elif self.state == 'PRESENCE DETECT LOW': # Slave presence signalled.
259                 # Wait for end of presence signal (on rising edge).
260                 if owr == 0:
261                     continue
262                 # Calculate time since start of presence signal.
263                 time = ((self.samplenum - self.fall) / self.samplerate) * 1000000.0
264                 if time < timing['PDL']['min'][self.overdrive]:
265                     self.put(self.fall, self.samplenum, self.out_ann,
266                         [1, ['Presence detect signal is too short',
267                         'Presence detect too short',
268                         'PDL < ' + str(timing['PDL']['min'][self.overdrive])]])
269                 elif time > timing['PDL']['max'][self.overdrive]:
270                     self.put(self.fall, self.samplenum, self.out_ann,
271                         [1, ['Presence detect signal is too long',
272                         'Presence detect too long',
273                         'PDL > ' + str(timing['PDL']['max'][self.overdrive])]])
274                 if time > timing['RSTH']['min'][self.overdrive]:
275                     self.rise = self.samplenum
276                 # Wait for end of presence detect.
277                 self.state = 'PRESENCE DETECT'
278
279             # End states (for additional checks).
280             if self.state == 'SLOT': # Wait for end of time slot.
281                 # Calculate time since falling edge.
282                 time = ((self.samplenum - self.fall) / self.samplerate) * 1000000.0
283                 if owr != 0 and time < timing['SLOT']['min'][self.overdrive]:
284                     continue
285                 elif owr == 0: # Low detected before end of slot.
286                     # Warn about irregularity.
287                     self.put(self.fall, self.samplenum, self.out_ann,
288                         [1, ['Time slot not long enough',
289                         'Slot too short',
290                         'SLOT < ' + str(timing['SLOT']['min'][self.overdrive])]])
291                     # Don't output invalid bit.
292                     self.fall = self.samplenum
293                     self.state = 'LOW'
294                 else: # End of time slot.
295                     # Output bit.
296                     self.put(self.fall, self.samplenum, self.out_ann,
297                         [0, ['Bit: %d' % self.bit, '%d' % self.bit]])
298                     self.put(self.fall, self.samplenum, self.out_python,
299                         ['BIT', self.bit])
300                     # Save command bits.
301                     if self.bit_count >= 0:
302                         self.command += (self.bit << self.bit_count)
303                         self.bit_count += 1
304                     # Check for overdrive ROM command.
305                     if self.bit_count >= 8:
306                         if self.command == 0x3c or self.command == 0x69:
307                             self.overdrive = True
308                             self.put(self.samplenum, self.samplenum,
309                                 self.out_ann,
310                                 [4, ['Entering overdrive mode', 'Overdrive on']])
311                         self.bit_count = -1
312                     self.state = 'IDLE'
313
314             if self.state == 'PRESENCE DETECT':
315                 # Wait for end of presence detect.
316                 # Calculate time since falling edge.
317                 time = ((self.samplenum - self.rise) / self.samplerate) * 1000000.0
318                 if owr != 0 and time < timing['RSTH']['min'][self.overdrive]:
319                     continue
320                 elif owr == 0: # Low detected before end of presence detect.
321                     # Warn about irregularity.
322                     self.put(self.fall, self.samplenum, self.out_ann,
323                         [1, ['Presence detect not long enough',
324                         'Presence detect too short',
325                         'RTSH < ' + str(timing['RSTH']['min'][self.overdrive])]])
326                     # Inform about presence detected.
327                     self.put(self.rise, self.samplenum, self.out_ann,
328                         [3, ['Slave presence detected', 'Slave present',
329                         'Present', 'P']])
330                     self.put(self.rise, self.samplenum, self.out_python,
331                         ['RESET/PRESENCE', True])
332                     self.fall = self.samplenum
333                     self.state = 'LOW'
334                 else: # End of time slot.
335                     # Inform about presence detected.
336                     self.put(self.rise, self.samplenum, self.out_ann,
337                         [3, ['Presence: true', 'Presence', 'Pres', 'P']])
338                     self.put(self.rise, self.samplenum, self.out_python,
339                         ['RESET/PRESENCE', True])
340                     self.rise = self.samplenum
341                     # Start counting the first 8 bits to get the ROM command.
342                     self.bit_count = 0
343                     self.command = 0
344                     self.state = 'IDLE'