2 ## This file is part of the libsigrokdecode project.
4 ## Copyright (C) 2014 Johannes Roemer <jroemer@physik.uni-wuerzburg.de>
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.
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.
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
21 import sigrokdecode as srd
23 # Define valid timing values (in microseconds).
25 'START LOW' : {'min': 750, 'max': 25000},
26 'START HIGH' : {'min': 10, 'max': 10000},
27 'RESPONSE LOW' : {'min': 50, 'max': 90},
28 'RESPONSE HIGH' : {'min': 50, 'max': 90},
29 'BIT LOW' : {'min': 45, 'max': 90},
30 'BIT 0 HIGH' : {'min': 20, 'max': 35},
31 'BIT 1 HIGH' : {'min': 65, 'max': 80},
34 class SamplerateError(Exception):
37 class Decoder(srd.Decoder):
41 longname = 'Aosong AM230x/DHTxx'
42 desc = 'Aosong AM230x/DHTxx humidity/temperature sensor protocol.'
47 {'id': 'sda', 'name': 'SDA', 'desc': 'Single wire serial data line'},
50 {'id': 'device', 'desc': 'Device type',
51 'default': 'am230x', 'values': ('am230x', 'dht11')},
55 ('response', 'Response'),
59 ('humidity', 'Relative humidity in percent'),
60 ('temperature', 'Temperature in degrees Celsius'),
61 ('checksum', 'Checksum'),
64 ('bits', 'Bits', (0, 1, 2, 3)),
65 ('bytes', 'Bytes', (4,)),
66 ('results', 'Results', (5, 6, 7)),
69 def putfs(self, data):
70 self.put(self.fall, self.samplenum, self.out_ann, data)
73 self.put(self.bytepos[-1], self.samplenum, self.out_ann, data)
76 self.put(self.bytepos[-2], self.samplenum, self.out_ann, data)
79 self.state = 'WAIT FOR START LOW'
86 def is_valid(self, name):
88 if name.endswith('LOW'):
89 dt = self.samplenum - self.fall
90 elif name.endswith('HIGH'):
91 dt = self.samplenum - self.rise
92 if dt >= self.cnt[name]['min'] and dt <= self.cnt[name]['max']:
96 def bits2num(self, bitlist):
98 for i in range(len(bitlist)):
99 number += bitlist[-1 - i] * 2**i
102 def calculate_humidity(self, bitlist):
104 if self.options['device'] == 'dht11':
105 h = self.bits2num(bitlist[0:8])
107 h = self.bits2num(bitlist) / 10
110 def calculate_temperature(self, bitlist):
112 if self.options['device'] == 'dht11':
113 t = self.bits2num(bitlist[0:8])
115 t = self.bits2num(bitlist[1:]) / 10
120 def calculate_checksum(self, bitlist):
122 for i in range(8, len(bitlist) + 1, 8):
123 checksum += self.bits2num(bitlist[i-8:i])
124 return checksum % 256
126 def __init__(self, **kwargs):
127 self.samplerate = None
131 self.out_ann = self.register(srd.OUTPUT_ANN)
133 def metadata(self, key, value):
134 if key != srd.SRD_CONF_SAMPLERATE:
136 self.samplerate = value
137 # Convert microseconds to sample counts.
142 self.cnt[e][t] = timing[e][t] * self.samplerate / 1000000
144 def handle_byte(self, bit):
145 self.bits.append(bit)
146 self.putfs([2, ['Bit: %d' % bit, '%d' % bit]])
147 self.fall = self.samplenum
148 self.state = 'WAIT FOR BIT HIGH'
149 if len(self.bits) % 8 == 0:
150 byte = self.bits2num(self.bits[-8:])
151 self.putb([4, ['Byte: %#04x' % byte, '%#04x' % byte]])
152 if len(self.bits) == 16:
153 h = self.calculate_humidity(self.bits[-16:])
154 self.putv([5, ['Humidity: %.1f %%' % h, 'RH = %.1f %%' % h]])
155 elif len(self.bits) == 32:
156 t = self.calculate_temperature(self.bits[-16:])
157 self.putv([6, ['Temperature: %.1f °C' % t, 'T = %.1f °C' % t]])
158 elif len(self.bits) == 40:
159 parity = self.bits2num(self.bits[-8:])
160 if parity == self.calculate_checksum(self.bits[0:32]):
161 self.putb([7, ['Checksum: OK', 'OK']])
163 self.putb([7, ['Checksum: not OK', 'NOK']])
164 self.state = 'WAIT FOR END'
165 self.bytepos.append(self.samplenum)
167 def decode(self, ss, es, data):
168 if not self.samplerate:
169 raise SamplerateError('Cannot decode without samplerate.')
170 for (self.samplenum, (sda,)) in data:
172 if self.state == 'WAIT FOR START LOW':
175 self.fall = self.samplenum
176 self.state = 'WAIT FOR START HIGH'
177 elif self.state == 'WAIT FOR START HIGH':
180 if self.is_valid('START LOW'):
181 self.rise = self.samplenum
182 self.state = 'WAIT FOR RESPONSE LOW'
185 elif self.state == 'WAIT FOR RESPONSE LOW':
188 if self.is_valid('START HIGH'):
189 self.putfs([0, ['Start', 'S']])
190 self.fall = self.samplenum
191 self.state = 'WAIT FOR RESPONSE HIGH'
194 elif self.state == 'WAIT FOR RESPONSE HIGH':
197 if self.is_valid('RESPONSE LOW'):
198 self.rise = self.samplenum
199 self.state = 'WAIT FOR FIRST BIT'
202 elif self.state == 'WAIT FOR FIRST BIT':
205 if self.is_valid('RESPONSE HIGH'):
206 self.putfs([1, ['Response', 'R']])
207 self.fall = self.samplenum
208 self.bytepos.append(self.samplenum)
209 self.state = 'WAIT FOR BIT HIGH'
212 elif self.state == 'WAIT FOR BIT HIGH':
215 if self.is_valid('BIT LOW'):
216 self.rise = self.samplenum
217 self.state = 'WAIT FOR BIT LOW'
220 elif self.state == 'WAIT FOR BIT LOW':
223 if self.is_valid('BIT 0 HIGH'):
225 elif self.is_valid('BIT 1 HIGH'):
230 self.handle_byte(bit)
231 elif self.state == 'WAIT FOR END':
234 self.putfs([3, ['End', 'E']])