]>
Commit | Line | Data |
---|---|---|
51990c45 IJ |
1 | ## |
2 | ## This file is part of the sigrok project. | |
3 | ## | |
4 | ## Copyright (C) 2011-2012 Uwe Hermann <uwe@hermann-uwe.de> | |
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, write to the Free Software | |
18 | ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | |
19 | ## | |
20 | ||
21 | # 1-Wire protocol decoder | |
22 | ||
23 | import sigrokdecode as srd | |
24 | ||
25 | # Annotation feed formats | |
13329e2d IJ |
26 | ANN_LINK = 0 |
27 | ANN_NETWORK = 1 | |
28 | ANN_TRANSPORT = 2 | |
51990c45 IJ |
29 | |
30 | class Decoder(srd.Decoder): | |
31 | api_version = 1 | |
32 | id = 'onewire' | |
33 | name = '1-Wire' | |
34 | longname = '' | |
35 | desc = '1-Wire bus and MicroLan' | |
36 | license = 'gplv2+' | |
37 | inputs = ['logic'] | |
38 | outputs = ['onewire'] | |
39 | probes = [ | |
40 | {'id': 'owr', 'name': 'OWR', 'desc': '1-Wire bus'}, | |
41 | ] | |
42 | optional_probes = [ | |
43 | {'id': 'pwr', 'name': 'PWR', 'desc': '1-Wire power'}, | |
44 | ] | |
45 | options = { | |
41e5c645 IJ |
46 | 'overdrive' : ['Overdrive', 1], |
47 | 'cnt_normal_bit' : ['Time (in samplerate periods) for normal mode sample bit' , 0], | |
48 | 'cnt_normal_presence' : ['Time (in samplerate periods) for normal mode sample presence', 0], | |
c08aea7e | 49 | 'cnt_normal_reset' : ['Time (in samplerate periods) for normal mode reset' , 0], |
41e5c645 IJ |
50 | 'cnt_overdrive_bit' : ['Time (in samplerate periods) for overdrive mode sample bit' , 0], |
51 | 'cnt_overdrive_presence': ['Time (in samplerate periods) for overdrive mode sample presence', 0], | |
c08aea7e | 52 | 'cnt_overdrive_reset' : ['Time (in samplerate periods) for overdrive mode reset' , 0], |
51990c45 IJ |
53 | } |
54 | annotations = [ | |
0bd62eb1 IJ |
55 | ['Link', 'Link layer events (reset, presence, bit slots)'], |
56 | ['Network', 'Network layer events (device addressing)'], | |
13329e2d | 57 | ['Transport', 'Transport layer events'], |
51990c45 IJ |
58 | ] |
59 | ||
51990c45 IJ |
60 | def __init__(self, **kwargs): |
61 | # Common variables | |
62 | self.samplenum = 0 | |
63 | # Link layer variables | |
af623785 IJ |
64 | self.lnk_state = 'WAIT FOR FALLING EDGE' |
65 | self.lnk_event = 'NONE' | |
af623785 IJ |
66 | self.lnk_present = 0 |
67 | self.lnk_bit = 0 | |
c08aea7e IJ |
68 | self.lnk_overdrive = 0 |
69 | # Event timing variables | |
70 | self.lnk_fall = 0 | |
71 | self.lnk_rise = 0 | |
72 | self.net_beg = 0 | |
73 | self.net_end = 0 | |
51990c45 | 74 | # Network layer variables |
af5ec813 | 75 | self.net_state = 'IDLE' |
af623785 | 76 | self.net_cnt = 0 |
d2b6e141 IJ |
77 | self.net_search = "P" |
78 | self.net_data_p = 0x0 | |
79 | self.net_data_n = 0x0 | |
80 | self.net_data = 0x0 | |
af5ec813 | 81 | self.net_rom = 0x0000000000000000 |
51990c45 IJ |
82 | |
83 | def start(self, metadata): | |
51990c45 | 84 | self.out_proto = self.add(srd.OUTPUT_PROTO, 'onewire') |
4fe36ec3 | 85 | self.out_ann = self.add(srd.OUTPUT_ANN , 'onewire') |
51990c45 | 86 | |
41e5c645 IJ |
87 | # check if samplerate is appropriate |
88 | self.samplerate = metadata['samplerate'] | |
89 | if (self.options['overdrive']): | |
c08aea7e | 90 | self.put(0, 0, self.out_ann, [ANN_LINK, ['NOTE: Sample rate checks assume overdrive mode.']]) |
41e5c645 | 91 | if (self.samplerate < 2000000): |
c08aea7e | 92 | self.put(0, 0, self.out_ann, [ANN_LINK, ['ERROR: Sampling rate is too low must be above 2MHz for proper overdrive mode decoding.']]) |
41e5c645 | 93 | elif (self.samplerate < 5000000): |
c08aea7e | 94 | self.put(0, 0, self.out_ann, [ANN_LINK, ['WARNING: Sampling rate is suggested to be above 5MHz for proper overdrive mode decoding.']]) |
41e5c645 | 95 | else: |
c08aea7e | 96 | self.put(0, 0, self.out_ann, [ANN_LINK, ['NOTE: Sample rate checks assume normal mode only.']]) |
41e5c645 | 97 | if (self.samplerate < 400000): |
c08aea7e | 98 | self.put(0, 0, self.out_ann, [ANN_LINK, ['ERROR: Sampling rate is too low must be above 400kHz for proper normal mode decoding.']]) |
41e5c645 | 99 | elif (self.samplerate < 1000000): |
c08aea7e | 100 | self.put(0, 0, self.out_ann, [ANN_LINK, ['WARNING: Sampling rate is suggested to be above 1MHz for proper normal mode decoding.']]) |
41e5c645 IJ |
101 | |
102 | # The default 1-Wire time base is 30us, this is used to calculate sampling times. | |
103 | if (self.options['cnt_normal_bit']): self.cnt_normal_bit = self.options['cnt_normal_bit'] | |
c08aea7e | 104 | else: self.cnt_normal_bit = int(float(self.samplerate) * 0.000015) - 1 # 15ns |
41e5c645 | 105 | if (self.options['cnt_normal_presence']): self.cnt_normal_presence = self.options['cnt_normal_presence'] |
c08aea7e IJ |
106 | else: self.cnt_normal_presence = int(float(self.samplerate) * 0.000075) - 1 # 75ns |
107 | if (self.options['cnt_normal_reset']): self.cnt_normal_reset = self.options['cnt_normal_reset'] | |
108 | else: self.cnt_normal_reset = int(float(self.samplerate) * 0.000480) - 1 # 480ns | |
41e5c645 | 109 | if (self.options['cnt_overdrive_bit']): self.cnt_overdrive_bit = self.options['cnt_overdrive_bit'] |
c08aea7e | 110 | else: self.cnt_overdrive_bit = int(float(self.samplerate) * 0.000002) - 1 # 2ns |
41e5c645 | 111 | if (self.options['cnt_overdrive_presence']): self.cnt_overdrive_presence = self.options['cnt_overdrive_presence'] |
c08aea7e IJ |
112 | else: self.cnt_overdrive_presence = int(float(self.samplerate) * 0.000010) - 1 # 10ns |
113 | if (self.options['cnt_overdrive_reset']): self.cnt_overdrive_reset = self.options['cnt_overdrive_reset'] | |
114 | else: self.cnt_overdrive_reset = int(float(self.samplerate) * 0.000048) - 1 # 48ns | |
115 | ||
41e5c645 | 116 | # Check if sample times are in the allowed range |
c08aea7e IJ |
117 | time_min = float(self.cnt_normal_bit ) / self.samplerate |
118 | time_max = float(self.cnt_normal_bit+1) / self.samplerate | |
119 | if ( (time_min < 0.000005) or (time_max > 0.000015) ) : | |
120 | self.put(0, 0, self.out_ann, [ANN_LINK, ['WARNING: The normal mode data sample time interval (%2.1fus-%2.1fus) should be inside (5.0us, 15.0us).' % (time_min*1000000, time_max*1000000)]]) | |
121 | time_min = float(self.cnt_normal_presence ) / self.samplerate | |
122 | time_max = float(self.cnt_normal_presence+1) / self.samplerate | |
123 | if ( (time_min < 0.0000681) or (time_max > 0.000075) ) : | |
124 | self.put(0, 0, self.out_ann, [ANN_LINK, ['WARNING: The normal mode presence sample time interval (%2.1fus-%2.1fus) should be inside (68.1us, 75.0us).' % (time_min*1000000, time_max*1000000)]]) | |
125 | time_min = float(self.cnt_overdrive_bit ) / self.samplerate | |
126 | time_max = float(self.cnt_overdrive_bit+1) / self.samplerate | |
127 | if ( (time_min < 0.000001) or (time_max > 0.000002) ) : | |
128 | self.put(0, 0, self.out_ann, [ANN_LINK, ['WARNING: The overdrive mode data sample time interval (%2.1fus-%2.1fus) should be inside (1.0us, 2.0us).' % (time_min*1000000, time_max*1000000)]]) | |
129 | time_min = float(self.cnt_overdrive_presence ) / self.samplerate | |
130 | time_max = float(self.cnt_overdrive_presence+1) / self.samplerate | |
131 | if ( (time_min < 0.0000073) or (time_max > 0.000010) ) : | |
132 | self.put(0, 0, self.out_ann, [ANN_LINK, ['WARNING: The overdrive mode presence sample time interval (%2.1fus-%2.1fus) should be inside (7.3us, 10.0us).' % (time_min*1000000, time_max*1000000)]]) | |
51990c45 IJ |
133 | |
134 | def report(self): | |
135 | pass | |
136 | ||
51990c45 | 137 | def decode(self, ss, es, data): |
af623785 | 138 | for (self.samplenum, (owr, pwr)) in data: |
51990c45 | 139 | |
51990c45 | 140 | # Data link layer |
39a0219a IJ |
141 | |
142 | # Clear events. | |
af623785 | 143 | self.lnk_event = "NONE" |
39a0219a | 144 | # State machine. |
51990c45 IJ |
145 | if self.lnk_state == 'WAIT FOR FALLING EDGE': |
146 | # The start of a cycle is a falling edge. | |
39a0219a IJ |
147 | if (owr == 0): |
148 | # Save the sample number for the falling edge. | |
149 | self.lnk_fall = self.samplenum | |
51990c45 | 150 | # Go to waiting for sample time |
39a0219a IJ |
151 | self.lnk_state = 'WAIT FOR DATA SAMPLE' |
152 | elif self.lnk_state == 'WAIT FOR DATA SAMPLE': | |
c08aea7e IJ |
153 | # Sample data bit |
154 | if (self.lnk_overdrive): cnt = self.cnt_overdrive_bit | |
155 | else : cnt = self.cnt_normal_bit | |
156 | if (self.samplenum - self.lnk_fall == cnt): | |
51990c45 | 157 | self.lnk_bit = owr & 0x1 |
39a0219a | 158 | self.lnk_event = "DATA BIT" |
c08aea7e IJ |
159 | if (self.lnk_bit): self.lnk_state = 'WAIT FOR FALLING EDGE' |
160 | else : self.lnk_state = 'WAIT FOR RISING EDGE' | |
0bd62eb1 | 161 | self.put(self.lnk_fall, self.samplenum, self.out_ann, [ANN_LINK, ['BIT: %01x' % self.lnk_bit]]) |
51990c45 IJ |
162 | elif self.lnk_state == 'WAIT FOR RISING EDGE': |
163 | # The end of a cycle is a rising edge. | |
39a0219a | 164 | if (owr == 1): |
c08aea7e IJ |
165 | # Check if this was a reset cycle |
166 | if (self.samplenum - self.lnk_fall > self.cnt_normal_reset): | |
39a0219a IJ |
167 | # Save the sample number for the falling edge. |
168 | self.lnk_rise = self.samplenum | |
af623785 | 169 | # Send a reset event to the next protocol layer. |
39a0219a IJ |
170 | self.lnk_event = "RESET" |
171 | self.lnk_state = "WAIT FOR PRESENCE DETECT" | |
0bd62eb1 | 172 | self.put(self.lnk_fall, self.samplenum, self.out_proto, ['RESET']) |
41e5c645 IJ |
173 | self.put(self.lnk_fall, self.samplenum, self.out_ann, [ANN_LINK , ['RESET']]) |
174 | self.put(self.lnk_fall, self.samplenum, self.out_ann, [ANN_NETWORK , ['RESET']]) | |
af623785 IJ |
175 | # Reset the timer. |
176 | self.lnk_fall = self.samplenum | |
c08aea7e IJ |
177 | elif ((self.samplenum - self.lnk_fall > self.cnt_overdrive_reset) and (self.lnk_overdrive)): |
178 | # Save the sample number for the falling edge. | |
179 | self.lnk_rise = self.samplenum | |
180 | # Send a reset event to the next protocol layer. | |
181 | self.lnk_event = "RESET" | |
182 | self.lnk_state = "WAIT FOR PRESENCE DETECT" | |
183 | self.put(self.lnk_fall, self.samplenum, self.out_proto, ['RESET OVERDRIVE']) | |
184 | self.put(self.lnk_fall, self.samplenum, self.out_ann, [ANN_LINK , ['RESET OVERDRIVE']]) | |
185 | self.put(self.lnk_fall, self.samplenum, self.out_ann, [ANN_NETWORK , ['RESET OVERDRIVE']]) | |
186 | # Reset the timer. | |
187 | self.lnk_fall = self.samplenum | |
af623785 IJ |
188 | # Otherwise this is assumed to be a data bit. |
189 | else : | |
190 | self.lnk_state = "WAIT FOR FALLING EDGE" | |
39a0219a | 191 | elif self.lnk_state == 'WAIT FOR PRESENCE DETECT': |
c08aea7e IJ |
192 | # Sample presence status |
193 | if (self.lnk_overdrive): cnt = self.cnt_overdrive_presence | |
194 | else : cnt = self.cnt_normal_presence | |
195 | if (self.samplenum - self.lnk_rise == cnt): | |
af623785 | 196 | self.lnk_present = owr & 0x1 |
cf0f9df0 IJ |
197 | # Save the sample number for the falling edge. |
198 | if not (self.lnk_present) : self.lnk_fall = self.samplenum | |
199 | # create presence detect event | |
af623785 | 200 | #self.lnk_event = "PRESENCE DETECT" |
cf0f9df0 IJ |
201 | if (self.lnk_present) : self.lnk_state = 'WAIT FOR FALLING EDGE' |
202 | else : self.lnk_state = 'WAIT FOR RISING EDGE' | |
0bd62eb1 IJ |
203 | present_str = "False" if self.lnk_present else "True" |
204 | self.put(self.lnk_fall, self.samplenum, self.out_ann, [ANN_LINK , ['PRESENCE: ' + present_str]]) | |
205 | self.put(self.lnk_fall, self.samplenum, self.out_ann, [ANN_NETWORK, ['PRESENCE: ' + present_str]]) | |
39a0219a | 206 | else: |
0631e33d | 207 | raise Exception('Invalid lnk_state: %d' % self.lnk_state) |
39a0219a IJ |
208 | |
209 | # Network layer | |
210 | ||
39a0219a | 211 | # State machine. |
4fe36ec3 | 212 | if (self.lnk_event == "RESET"): |
af5ec813 | 213 | self.net_state = "COMMAND" |
d2b6e141 IJ |
214 | self.net_search = "P" |
215 | self.net_cnt = 0 | |
af5ec813 IJ |
216 | elif (self.net_state == "IDLE"): |
217 | pass | |
218 | elif (self.net_state == "COMMAND"): | |
c08aea7e IJ |
219 | # Receiving and decoding a ROM command |
220 | if (self.onewire_collect(8)): | |
221 | self.put(self.net_beg, self.net_end, self.out_ann, [ANN_NETWORK, ['ROM COMMAND: 0x%02x' % self.net_data]]) | |
af5ec813 IJ |
222 | if (self.net_data == 0x33): |
223 | # READ ROM | |
c08aea7e | 224 | self.put(self.net_beg, self.net_end, self.out_ann, [ANN_NETWORK, ['ROM COMMAND: \'READ ROM\'']]) |
af5ec813 IJ |
225 | self.net_state = "GET ROM" |
226 | elif (self.net_data == 0x0f): | |
13329e2d | 227 | # CONDITIONAL READ ROM |
c08aea7e | 228 | self.put(self.net_beg, self.net_end, self.out_ann, [ANN_NETWORK, ['ROM COMMAND: \'CONDITIONAL READ ROM\'']]) |
af5ec813 IJ |
229 | self.net_state = "GET ROM" |
230 | elif (self.net_data == 0xcc): | |
231 | # SKIP ROM | |
c08aea7e | 232 | self.put(self.net_beg, self.net_end, self.out_ann, [ANN_NETWORK, ['ROM COMMAND: \'SKIP ROM\'']]) |
41e5c645 | 233 | self.net_state = "TRANSPORT" |
af5ec813 IJ |
234 | elif (self.net_data == 0x55): |
235 | # MATCH ROM | |
c08aea7e | 236 | self.put(self.net_beg, self.net_end, self.out_ann, [ANN_NETWORK, ['ROM COMMAND: \'MATCH ROM\'']]) |
af5ec813 IJ |
237 | self.net_state = "GET ROM" |
238 | elif (self.net_data == 0xf0): | |
239 | # SEARCH ROM | |
c08aea7e | 240 | self.put(self.net_beg, self.net_end, self.out_ann, [ANN_NETWORK, ['ROM COMMAND: \'SEARCH ROM\'']]) |
af5ec813 | 241 | self.net_state = "SEARCH ROM" |
13329e2d IJ |
242 | elif (self.net_data == 0xec): |
243 | # CONDITIONAL SEARCH ROM | |
c08aea7e | 244 | self.put(self.net_beg, self.net_end, self.out_ann, [ANN_NETWORK, ['ROM COMMAND: \'CONDITIONAL SEARCH ROM\'']]) |
13329e2d | 245 | self.net_state = "SEARCH ROM" |
af5ec813 IJ |
246 | elif (self.net_data == 0x3c): |
247 | # OVERDRIVE SKIP ROM | |
c08aea7e IJ |
248 | self.put(self.net_beg, self.net_end, self.out_ann, [ANN_NETWORK, ['ROM COMMAND: \'OVERDRIVE SKIP ROM\'']]) |
249 | self.lnk_overdrive = 1 | |
41e5c645 | 250 | self.net_state = "TRANSPORT" |
af5ec813 IJ |
251 | elif (self.net_data == 0x69): |
252 | # OVERDRIVE MATCH ROM | |
c08aea7e IJ |
253 | self.put(self.net_beg, self.net_end, self.out_ann, [ANN_NETWORK, ['ROM COMMAND: \'OVERDRIVE MATCH ROM\'']]) |
254 | self.lnk_overdrive = 1 | |
af5ec813 IJ |
255 | self.net_state = "GET ROM" |
256 | elif (self.net_state == "GET ROM"): | |
c08aea7e | 257 | # A 64 bit device address is selected |
af5ec813 | 258 | # family code (1B) + serial number (6B) + CRC (1B) |
c08aea7e | 259 | if (self.onewire_collect(64)): |
af5ec813 | 260 | self.net_rom = self.net_data & 0xffffffffffffffff |
c08aea7e | 261 | self.put(self.net_beg, self.net_end, self.out_ann, [ANN_NETWORK, ['ROM: 0x%016x' % self.net_rom]]) |
41e5c645 | 262 | self.net_state = "TRANSPORT" |
af5ec813 | 263 | elif (self.net_state == "SEARCH ROM"): |
c08aea7e | 264 | # A 64 bit device address is searched for |
af5ec813 | 265 | # family code (1B) + serial number (6B) + CRC (1B) |
c08aea7e | 266 | if (self.onewire_search(64)): |
af5ec813 | 267 | self.net_rom = self.net_data & 0xffffffffffffffff |
c08aea7e | 268 | self.put(self.net_beg, self.net_end, self.out_ann, [ANN_NETWORK, ['ROM: 0x%016x' % self.net_rom]]) |
41e5c645 | 269 | self.net_state = "TRANSPORT" |
c08aea7e IJ |
270 | elif (self.net_state == "TRANSPORT"): |
271 | # The transport layer is handled in byte sized units | |
272 | if (self.onewire_collect(8)): | |
273 | self.put(self.net_beg, self.net_end, self.out_ann, [ANN_NETWORK , ['TRANSPORT: 0x%02x' % self.net_data]]) | |
274 | self.put(self.net_beg, self.net_end, self.out_ann, [ANN_TRANSPORT, ['TRANSPORT: 0x%02x' % self.net_data]]) | |
275 | self.put(self.net_beg, self.net_end, self.out_proto, ['transfer', self.net_data]) | |
276 | # TODO: Sending translort layer data to 1-Wire device models | |
af5ec813 IJ |
277 | else: |
278 | raise Exception('Invalid net_state: %s' % self.net_state) | |
51990c45 | 279 | |
51990c45 | 280 | |
d2b6e141 | 281 | # Link/Network layer data collector |
c08aea7e | 282 | def onewire_collect (self, length): |
af5ec813 | 283 | if (self.lnk_event == "DATA BIT"): |
c08aea7e IJ |
284 | # Storing the sampe this sequence begins with |
285 | if (self.net_cnt == 1): | |
286 | self.net_beg = self.samplenum | |
af5ec813 IJ |
287 | self.net_data = self.net_data & ~(1 << self.net_cnt) | (self.lnk_bit << self.net_cnt) |
288 | self.net_cnt = self.net_cnt + 1 | |
c08aea7e IJ |
289 | # Storing the sampe this sequence ends with |
290 | # In case the full length of the sequence is received, return 1 | |
af5ec813 | 291 | if (self.net_cnt == length): |
c08aea7e | 292 | self.net_end = self.samplenum |
af5ec813 IJ |
293 | self.net_data = self.net_data & ((1<<length)-1) |
294 | self.net_cnt = 0 | |
295 | return (1) | |
296 | else: | |
297 | return (0) | |
d2b6e141 IJ |
298 | else: |
299 | return (0) | |
300 | ||
301 | # Link/Network layer search collector | |
c08aea7e | 302 | def onewire_search (self, length): |
af5ec813 | 303 | if (self.lnk_event == "DATA BIT"): |
c08aea7e IJ |
304 | # Storing the sampe this sequence begins with |
305 | if ((self.net_cnt == 0) and (self.net_search == "P")): | |
306 | self.net_beg = self.samplenum | |
307 | # Master receives an original address bit | |
af5ec813 IJ |
308 | if (self.net_search == "P"): |
309 | self.net_data_p = self.net_data_p & ~(1 << self.net_cnt) | (self.lnk_bit << self.net_cnt) | |
310 | self.net_search = "N" | |
c08aea7e | 311 | # Master receives a complemented address bit |
af5ec813 IJ |
312 | elif (self.net_search == "N"): |
313 | self.net_data_n = self.net_data_n & ~(1 << self.net_cnt) | (self.lnk_bit << self.net_cnt) | |
314 | self.net_search = "D" | |
c08aea7e | 315 | # Master transmits an address bit |
af5ec813 IJ |
316 | elif (self.net_search == "D"): |
317 | self.net_data = self.net_data & ~(1 << self.net_cnt) | (self.lnk_bit << self.net_cnt) | |
318 | self.net_search = "P" | |
319 | self.net_cnt = self.net_cnt + 1 | |
c08aea7e IJ |
320 | # Storing the sampe this sequence ends with |
321 | # In case the full length of the sequence is received, return 1 | |
af5ec813 | 322 | if (self.net_cnt == length): |
c08aea7e | 323 | self.net_end = self.samplenum |
af5ec813 IJ |
324 | self.net_data_p = self.net_data_p & ((1<<length)-1) |
325 | self.net_data_n = self.net_data_n & ((1<<length)-1) | |
326 | self.net_data = self.net_data & ((1<<length)-1) | |
327 | self.net_search = "P" | |
328 | self.net_cnt = 0 | |
329 | return (1) | |
330 | else: | |
331 | return (0) | |
d2b6e141 IJ |
332 | else: |
333 | return (0) |