/* * The interrupt handler, enabled after the request pulse, and on * falling (low to high) transition. This allows lower interrupt * frequency than on change mode (which would be required for pin * change interrupts. First pulse is the device response and a * one(1) bit is encoded as a long pulse (54 + 80 = 134 us), a * zero(0) bit as a short pulse (54 + 24 = 78 us). Sequence ends * with a low pulse (54 us) which allows falling/rising detection. */ void DHT::on_interrupt(uint16_t arg) { UNUSED(arg); // Calculate the pulse width and check against thresholds uint16_t stop = RTT::micros(); uint16_t us = (stop - m_start); bool valid = false; // Check the initial response pulse if (m_state == RESPONSE) { if (us < BIT_THRESHOLD) goto exception; m_state = SAMPLING; m_start = stop; m_bits = 0; m_ix = 0; return; } // Sanity check the pulse length if (us < LOW_THRESHOLD || us > HIGH_THRESHOLD) goto exception; m_start = stop; // Sample was valid, collect bit and check for more m_value = (m_value << 1) + (us > BIT_THRESHOLD); m_bits += 1; if (m_bits != CHARBITS) return; // Next byte ready m_data.as_byte[m_ix++] = m_value; m_bits = 0; valid = (m_ix == DATA_MAX); if (valid) goto completed; return; // Invalid sample reject sequence exception: m_ix = 0; // Sequence completed completed: m_state = COMPLETED; disable(); if (valid) adjust_data(); on_sample_completed(valid); }
void DHT::on_event(uint8_t type, uint16_t value) { UNUSED(type); UNUSED(value); switch (m_state) { case IDLE: // Issue a request; pull down for more than 18 ms m_state = REQUEST; set_mode(OUTPUT_MODE); clear(); Watchdog::attach(this, 32); break; case REQUEST: // Request pulse completed; pull up for 40 us and collect // data as a sequence of on rising mode interrupts m_state = RESPONSE; m_start = 0; detach(); set(); set_mode(INPUT_MODE); DELAY(40); enable(); break; case COMPLETED: // Data reading was completed; validate data and check sum // Wait before issueing the next request uint8_t invalid = 1; if (m_ix == DATA_MAX) { uint8_t sum = 0; for (uint8_t i = 0; i < DATA_LAST; i++) sum += m_data.as_byte[i]; if (sum == m_data.chksum) { invalid = 0; adjust_data(); } on_sample_completed(); } m_errors += invalid; m_state = IDLE; Watchdog::attach(this, m_period); break; } }
bool DHT::sample_await() { if (m_period != 0) return (true); uint32_t start = RTC::millis(); while (m_state != COMPLETED && RTC::since(start) < MIN_PERIOD) yield(); if (m_state != COMPLETED) return (false); // Data reading was completed; validate data and check sum m_state = INIT; if (m_ix != DATA_MAX) return (false); uint8_t sum = 0; for (uint8_t i = 0; i < DATA_LAST; i++) sum += m_data.as_byte[i]; if (sum != m_data.chksum) return (false); adjust_data(); return (true); }
static float read_sample(struct sr_channel *ch) { struct channel_priv *chp; char buf[16]; ssize_t len; int fd; chp = ch->priv; fd = chp->fd; lseek(fd, 0, SEEK_SET); len = read(fd, buf, sizeof(buf)); if (len < 0) { sr_err("Error reading from channel %s (hwmon: %d): %s", ch->name, chp->probe->hwmon_num, g_strerror(errno)); ch->enabled = FALSE; return -1.0; } return adjust_data(strtol(buf, NULL, 10), chp->ch_type); }