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):
40 name = 'AM230x/DHTxx/RHTxx'
41 longname = 'Aosong AM230x/DHTxx/RHTxx'
42 desc = 'Aosong AM230x/DHTxx/RHTxx 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/rht', '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'
85 def is_valid(self, name):
87 if name.endswith('LOW'):
88 dt = self.samplenum - self.fall
89 elif name.endswith('HIGH'):
90 dt = self.samplenum - self.rise
91 if dt >= self.cnt[name]['min'] and dt <= self.cnt[name]['max']:
95 def bits2num(self, bitlist):
97 for i in range(len(bitlist)):
98 number += bitlist[-1 - i] * 2**i
101 def calculate_humidity(self, bitlist):
103 if self.options['device'] == 'dht11':
104 h = self.bits2num(bitlist[0:8])
106 h = self.bits2num(bitlist) / 10
109 def calculate_temperature(self, bitlist):
111 if self.options['device'] == 'dht11':
112 t = self.bits2num(bitlist[0:8])
114 t = self.bits2num(bitlist[1:]) / 10
119 def calculate_checksum(self, bitlist):
121 for i in range(8, len(bitlist) + 1, 8):
122 checksum += self.bits2num(bitlist[i-8:i])
123 return checksum % 256
126 self.samplerate = None
130 self.out_ann = self.register(srd.OUTPUT_ANN)
132 # Assume that the initial pin state is high (logic 1).
133 self.initial_pins = [1]
135 def metadata(self, key, value):
136 if key != srd.SRD_CONF_SAMPLERATE:
138 self.samplerate = value
139 # Convert microseconds to sample counts.
144 self.cnt[e][t] = timing[e][t] * self.samplerate / 1000000
146 def handle_byte(self, bit):
147 self.bits.append(bit)
148 self.putfs([2, ['Bit: %d' % bit, '%d' % bit]])
149 self.fall = self.samplenum
150 self.state = 'WAIT FOR BIT HIGH'
151 if len(self.bits) % 8 == 0:
152 byte = self.bits2num(self.bits[-8:])
153 self.putb([4, ['Byte: %#04x' % byte, '%#04x' % byte]])
154 if len(self.bits) == 16:
155 h = self.calculate_humidity(self.bits[-16:])
156 self.putv([5, ['Humidity: %.1f %%' % h, 'RH = %.1f %%' % h]])
157 elif len(self.bits) == 32:
158 t = self.calculate_temperature(self.bits[-16:])
159 self.putv([6, ['Temperature: %.1f °C' % t, 'T = %.1f °C' % t]])
160 elif len(self.bits) == 40:
161 parity = self.bits2num(self.bits[-8:])
162 if parity == self.calculate_checksum(self.bits[0:32]):
163 self.putb([7, ['Checksum: OK', 'OK']])
165 self.putb([7, ['Checksum: not OK', 'NOK']])
166 self.state = 'WAIT FOR END'
167 self.bytepos.append(self.samplenum)
170 if not self.samplerate:
171 raise SamplerateError('Cannot decode without samplerate.')
174 if self.state == 'WAIT FOR START LOW':
176 self.fall = self.samplenum
177 self.state = 'WAIT FOR START HIGH'
178 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':
187 if self.is_valid('START HIGH'):
188 self.putfs([0, ['Start', 'S']])
189 self.fall = self.samplenum
190 self.state = 'WAIT FOR RESPONSE HIGH'
193 elif self.state == 'WAIT FOR RESPONSE HIGH':
195 if self.is_valid('RESPONSE LOW'):
196 self.rise = self.samplenum
197 self.state = 'WAIT FOR FIRST BIT'
200 elif self.state == 'WAIT FOR FIRST BIT':
202 if self.is_valid('RESPONSE HIGH'):
203 self.putfs([1, ['Response', 'R']])
204 self.fall = self.samplenum
205 self.bytepos.append(self.samplenum)
206 self.state = 'WAIT FOR BIT HIGH'
209 elif self.state == 'WAIT FOR BIT HIGH':
211 if self.is_valid('BIT LOW'):
212 self.rise = self.samplenum
213 self.state = 'WAIT FOR BIT LOW'
216 elif self.state == 'WAIT FOR BIT LOW':
218 if self.is_valid('BIT 0 HIGH'):
220 elif self.is_valid('BIT 1 HIGH'):
225 self.handle_byte(bit)
226 elif self.state == 'WAIT FOR END':
228 self.putfs([3, ['End', 'E']])