Пример #1
0
/*
 * 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);
}
Пример #2
0
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;
  }
}