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)
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
129 self.out_ann = self.register(srd.OUTPUT_ANN)
131 # Assume that the initial pin state is high (logic 1).
132 self.initial_pins = [1]
134 def metadata(self, key, value):
135 if key != srd.SRD_CONF_SAMPLERATE:
137 self.samplerate = value
138 # Convert microseconds to sample counts.
143 self.cnt[e][t] = timing[e][t] * self.samplerate / 1000000
145 def handle_byte(self, bit):
146 self.bits.append(bit)
147 self.putfs([2, ['Bit: %d' % bit, '%d' % bit]])
148 self.fall = self.samplenum
149 self.state = 'WAIT FOR BIT HIGH'
150 if len(self.bits) % 8 == 0:
151 byte = self.bits2num(self.bits[-8:])
152 self.putb([4, ['Byte: %#04x' % byte, '%#04x' % byte]])
153 if len(self.bits) == 16:
154 h = self.calculate_humidity(self.bits[-16:])
155 self.putv([5, ['Humidity: %.1f %%' % h, 'RH = %.1f %%' % h]])
156 elif len(self.bits) == 32:
157 t = self.calculate_temperature(self.bits[-16:])
158 self.putv([6, ['Temperature: %.1f °C' % t, 'T = %.1f °C' % t]])
159 elif len(self.bits) == 40:
160 parity = self.bits2num(self.bits[-8:])
161 if parity == self.calculate_checksum(self.bits[0:32]):
162 self.putb([7, ['Checksum: OK', 'OK']])
164 self.putb([7, ['Checksum: not OK', 'NOK']])
165 self.state = 'WAIT FOR END'
166 self.bytepos.append(self.samplenum)
169 if not self.samplerate:
170 raise SamplerateError('Cannot decode without samplerate.')
173 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':
179 if self.is_valid('START LOW'):
180 self.rise = self.samplenum
181 self.state = 'WAIT FOR RESPONSE LOW'
184 elif self.state == 'WAIT FOR RESPONSE LOW':
186 if self.is_valid('START HIGH'):
187 self.putfs([0, ['Start', 'S']])
188 self.fall = self.samplenum
189 self.state = 'WAIT FOR RESPONSE HIGH'
192 elif self.state == 'WAIT FOR RESPONSE HIGH':
194 if self.is_valid('RESPONSE LOW'):
195 self.rise = self.samplenum
196 self.state = 'WAIT FOR FIRST BIT'
199 elif self.state == 'WAIT FOR FIRST BIT':
201 if self.is_valid('RESPONSE HIGH'):
202 self.putfs([1, ['Response', 'R']])
203 self.fall = self.samplenum
204 self.bytepos.append(self.samplenum)
205 self.state = 'WAIT FOR BIT HIGH'
208 elif self.state == 'WAIT FOR BIT HIGH':
210 if self.is_valid('BIT LOW'):
211 self.rise = self.samplenum
212 self.state = 'WAIT FOR BIT LOW'
215 elif self.state == 'WAIT FOR BIT LOW':
217 if self.is_valid('BIT 0 HIGH'):
219 elif self.is_valid('BIT 1 HIGH'):
224 self.handle_byte(bit)
225 elif self.state == 'WAIT FOR END':
227 self.putfs([3, ['End', 'E']])