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, see <http://www.gnu.org/licenses/>.
20 import sigrokdecode as srd
22 # Define valid timing values (in microseconds).
24 'START LOW' : {'min': 750, 'max': 25000},
25 'START HIGH' : {'min': 10, 'max': 10000},
26 'RESPONSE LOW' : {'min': 50, 'max': 90},
27 'RESPONSE HIGH' : {'min': 50, 'max': 90},
28 'BIT LOW' : {'min': 45, 'max': 90},
29 'BIT 0 HIGH' : {'min': 20, 'max': 35},
30 'BIT 1 HIGH' : {'min': 65, 'max': 80},
33 class SamplerateError(Exception):
36 class Decoder(srd.Decoder):
39 name = 'AM230x/DHTxx/RHTxx'
40 longname = 'Aosong AM230x/DHTxx/RHTxx'
41 desc = 'Aosong AM230x/DHTxx/RHTxx humidity/temperature sensor protocol.'
46 {'id': 'sda', 'name': 'SDA', 'desc': 'Single wire serial data line'},
49 {'id': 'device', 'desc': 'Device type',
50 'default': 'am230x', 'values': ('am230x/rht', 'dht11')},
54 ('response', 'Response'),
58 ('humidity', 'Relative humidity in percent'),
59 ('temperature', 'Temperature in degrees Celsius'),
60 ('checksum', 'Checksum'),
63 ('bits', 'Bits', (0, 1, 2, 3)),
64 ('bytes', 'Bytes', (4,)),
65 ('results', 'Results', (5, 6, 7)),
68 def putfs(self, data):
69 self.put(self.fall, self.samplenum, self.out_ann, data)
72 self.put(self.bytepos[-1], self.samplenum, self.out_ann, data)
75 self.put(self.bytepos[-2], self.samplenum, self.out_ann, data)
77 def reset_variables(self):
78 self.state = 'WAIT FOR START LOW'
84 def is_valid(self, name):
86 if name.endswith('LOW'):
87 dt = self.samplenum - self.fall
88 elif name.endswith('HIGH'):
89 dt = self.samplenum - self.rise
90 if dt >= self.cnt[name]['min'] and dt <= self.cnt[name]['max']:
94 def bits2num(self, bitlist):
96 for i in range(len(bitlist)):
97 number += bitlist[-1 - i] * 2**i
100 def calculate_humidity(self, bitlist):
102 if self.options['device'] == 'dht11':
103 h = self.bits2num(bitlist[0:8])
105 h = self.bits2num(bitlist) / 10
108 def calculate_temperature(self, bitlist):
110 if self.options['device'] == 'dht11':
111 t = self.bits2num(bitlist[0:8])
113 t = self.bits2num(bitlist[1:]) / 10
118 def calculate_checksum(self, bitlist):
120 for i in range(8, len(bitlist) + 1, 8):
121 checksum += self.bits2num(bitlist[i-8:i])
122 return checksum % 256
125 self.samplerate = None
126 self.reset_variables()
129 self.out_ann = self.register(srd.OUTPUT_ANN)
131 def metadata(self, key, value):
132 if key != srd.SRD_CONF_SAMPLERATE:
134 self.samplerate = value
135 # Convert microseconds to sample counts.
140 self.cnt[e][t] = timing[e][t] * self.samplerate / 1000000
142 def handle_byte(self, bit):
143 self.bits.append(bit)
144 self.putfs([2, ['Bit: %d' % bit, '%d' % bit]])
145 self.fall = self.samplenum
146 self.state = 'WAIT FOR BIT HIGH'
147 if len(self.bits) % 8 == 0:
148 byte = self.bits2num(self.bits[-8:])
149 self.putb([4, ['Byte: %#04x' % byte, '%#04x' % byte]])
150 if len(self.bits) == 16:
151 h = self.calculate_humidity(self.bits[-16:])
152 self.putv([5, ['Humidity: %.1f %%' % h, 'RH = %.1f %%' % h]])
153 elif len(self.bits) == 32:
154 t = self.calculate_temperature(self.bits[-16:])
155 self.putv([6, ['Temperature: %.1f °C' % t, 'T = %.1f °C' % t]])
156 elif len(self.bits) == 40:
157 parity = self.bits2num(self.bits[-8:])
158 if parity == self.calculate_checksum(self.bits[0:32]):
159 self.putb([7, ['Checksum: OK', 'OK']])
161 self.putb([7, ['Checksum: not OK', 'NOK']])
162 self.state = 'WAIT FOR END'
163 self.bytepos.append(self.samplenum)
166 if not self.samplerate:
167 raise SamplerateError('Cannot decode without samplerate.')
170 if self.state == 'WAIT FOR START LOW':
172 self.fall = self.samplenum
173 self.state = 'WAIT FOR START HIGH'
174 elif self.state == 'WAIT FOR START HIGH':
176 if self.is_valid('START LOW'):
177 self.rise = self.samplenum
178 self.state = 'WAIT FOR RESPONSE LOW'
180 self.reset_variables()
181 elif self.state == 'WAIT FOR RESPONSE LOW':
183 if self.is_valid('START HIGH'):
184 self.putfs([0, ['Start', 'S']])
185 self.fall = self.samplenum
186 self.state = 'WAIT FOR RESPONSE HIGH'
188 self.reset_variables()
189 elif self.state == 'WAIT FOR RESPONSE HIGH':
191 if self.is_valid('RESPONSE LOW'):
192 self.rise = self.samplenum
193 self.state = 'WAIT FOR FIRST BIT'
195 self.reset_variables()
196 elif self.state == 'WAIT FOR FIRST BIT':
198 if self.is_valid('RESPONSE HIGH'):
199 self.putfs([1, ['Response', 'R']])
200 self.fall = self.samplenum
201 self.bytepos.append(self.samplenum)
202 self.state = 'WAIT FOR BIT HIGH'
204 self.reset_variables()
205 elif self.state == 'WAIT FOR BIT HIGH':
207 if self.is_valid('BIT LOW'):
208 self.rise = self.samplenum
209 self.state = 'WAIT FOR BIT LOW'
211 self.reset_variables()
212 elif self.state == 'WAIT FOR BIT LOW':
214 if self.is_valid('BIT 0 HIGH'):
216 elif self.is_valid('BIT 1 HIGH'):
219 self.reset_variables()
221 self.handle_byte(bit)
222 elif self.state == 'WAIT FOR END':
224 self.putfs([3, ['End', 'E']])
225 self.reset_variables()