iio: dht11: Simplify decoding algorithm

The new algorithm uses a 'one size fits em all' threshold, which should
be easier to understand and debug. I believe there are no regressions
compared to the old adaptive threshold algorithm. I don't remember why
I chose the old algorithm when I initially wrote the driver.

Signed-off-by: Harald Geyer <harald@ccbib.org>
Signed-off-by: Jonathan Cameron <jic23@kernel.org>
This commit is contained in:
Harald Geyer 2016-01-17 16:13:30 +00:00 committed by Jonathan Cameron
parent 22acc120a1
commit 155a57593d
1 changed files with 42 additions and 22 deletions

View File

@ -50,12 +50,32 @@
#define DHT11_EDGES_PER_READ (2 * DHT11_BITS_PER_READ + \
DHT11_EDGES_PREAMBLE + 1)
/* Data transmission timing (nano seconds) */
/*
* Data transmission timing:
* Data bits are encoded as pulse length (high time) on the data line.
* 0-bit: 22-30uS -- typically 26uS (AM2302)
* 1-bit: 68-75uS -- typically 70uS (AM2302)
* The acutal timings also depend on the properties of the cable, with
* longer cables typically making pulses shorter.
*
* Our decoding depends on the time resolution of the system:
* timeres > 34uS ... don't know what a 1-tick pulse is
* 34uS > timeres > 30uS ... no problem (30kHz and 32kHz clocks)
* 30uS > timeres > 23uS ... don't know what a 2-tick pulse is
* timeres < 23uS ... no problem
*
* Luckily clocks in the 33-44kHz range are quite uncommon, so we can
* support most systems if the threshold for decoding a pulse as 1-bit
* is chosen carefully. If somebody really wants to support clocks around
* 40kHz, where this driver is most unreliable, there are two options.
* a) select an implementation using busy loop polling on those systems
* b) use the checksum to do some probabilistic decoding
*/
#define DHT11_START_TRANSMISSION 18 /* ms */
#define DHT11_SENSOR_RESPONSE 80000
#define DHT11_START_BIT 50000
#define DHT11_DATA_BIT_LOW 27000
#define DHT11_DATA_BIT_HIGH 70000
#define DHT11_MIN_TIMERES 34000 /* ns */
#define DHT11_THRESHOLD 49000 /* ns */
#define DHT11_AMBIG_LOW 23000 /* ns */
#define DHT11_AMBIG_HIGH 30000 /* ns */
struct dht11 {
struct device *dev;
@ -76,43 +96,39 @@ struct dht11 {
struct {s64 ts; int value; } edges[DHT11_EDGES_PER_READ];
};
static unsigned char dht11_decode_byte(int *timing, int threshold)
static unsigned char dht11_decode_byte(char *bits)
{
unsigned char ret = 0;
int i;
for (i = 0; i < 8; ++i) {
ret <<= 1;
if (timing[i] >= threshold)
if (bits[i])
++ret;
}
return ret;
}
static int dht11_decode(struct dht11 *dht11, int offset, int timeres)
static int dht11_decode(struct dht11 *dht11, int offset)
{
int i, t, timing[DHT11_BITS_PER_READ], threshold;
int i, t;
char bits[DHT11_BITS_PER_READ];
unsigned char temp_int, temp_dec, hum_int, hum_dec, checksum;
threshold = DHT11_DATA_BIT_HIGH / timeres;
if (DHT11_DATA_BIT_LOW / timeres + 1 >= threshold)
pr_err("dht11: WARNING: decoding ambiguous\n");
/* scale down with timeres and check validity */
for (i = 0; i < DHT11_BITS_PER_READ; ++i) {
t = dht11->edges[offset + 2 * i + 2].ts -
dht11->edges[offset + 2 * i + 1].ts;
if (!dht11->edges[offset + 2 * i + 1].value)
return -EIO; /* lost synchronisation */
timing[i] = t / timeres;
bits[i] = t > DHT11_THRESHOLD;
}
hum_int = dht11_decode_byte(timing, threshold);
hum_dec = dht11_decode_byte(&timing[8], threshold);
temp_int = dht11_decode_byte(&timing[16], threshold);
temp_dec = dht11_decode_byte(&timing[24], threshold);
checksum = dht11_decode_byte(&timing[32], threshold);
hum_int = dht11_decode_byte(bits);
hum_dec = dht11_decode_byte(&bits[8]);
temp_int = dht11_decode_byte(&bits[16]);
temp_dec = dht11_decode_byte(&bits[24]);
checksum = dht11_decode_byte(&bits[32]);
if (((hum_int + hum_dec + temp_int + temp_dec) & 0xff) != checksum)
return -EIO;
@ -166,7 +182,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
mutex_lock(&dht11->lock);
if (dht11->timestamp + DHT11_DATA_VALID_TIME < ktime_get_real_ns()) {
timeres = ktime_get_resolution_ns();
if (DHT11_DATA_BIT_HIGH < 2 * timeres) {
if (timeres > DHT11_MIN_TIMERES) {
dev_err(dht11->dev, "timeresolution %dns too low\n",
timeres);
/* In theory a better clock could become available
@ -176,6 +192,10 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
ret = -EAGAIN;
goto err;
}
if (timeres > DHT11_AMBIG_LOW && timeres < DHT11_AMBIG_HIGH)
dev_warn(dht11->dev,
"timeresolution: %dns - decoding ambiguous\n",
timeres);
reinit_completion(&dht11->completion);
@ -211,7 +231,7 @@ static int dht11_read_raw(struct iio_dev *iio_dev,
offset = DHT11_EDGES_PREAMBLE +
dht11->num_edges - DHT11_EDGES_PER_READ;
for (; offset >= 0; --offset) {
ret = dht11_decode(dht11, offset, timeres);
ret = dht11_decode(dht11, offset);
if (!ret)
break;
}