bool OneWireSlave::waitReset(uint16_t timeout_ms) { uint8_t mask = pin_bitmask; volatile uint8_t *reg asm("r30") = baseReg; unsigned long time_stamp; errno = ONEWIRE_NO_ERROR; cli(); DIRECT_MODE_INPUT(reg, mask); sei(); if (timeout_ms != 0) { time_stamp = micros() + timeout_ms*1000; while (DIRECT_READ(reg, mask)) { if (micros() > time_stamp) { errno = ONEWIRE_WAIT_RESET_TIMEOUT; return FALSE; } } } else while (DIRECT_READ(reg, mask)) {}; time_stamp = micros() + 540; while (DIRECT_READ(reg, mask) == 0) { if (micros() > time_stamp) { errno = ONEWIRE_VERY_LONG_RESET; return FALSE; } } if ((time_stamp - micros()) > 70) { errno = ONEWIRE_VERY_SHORT_RESET; return FALSE; } delayMicroseconds(30); return TRUE; }
int CapacitiveSensor::SenseOneCycle(void) { noInterrupts(); DIRECT_WRITE_LOW(sReg, sBit); // sendPin Register low DIRECT_MODE_INPUT(rReg, rBit); // receivePin to input (pullups are off) DIRECT_MODE_OUTPUT(rReg, rBit); // receivePin to OUTPUT DIRECT_WRITE_LOW(rReg, rBit); // pin is now LOW AND OUTPUT delayMicroseconds(10); DIRECT_MODE_INPUT(rReg, rBit); // receivePin to input (pullups are off) DIRECT_WRITE_HIGH(sReg, sBit); // sendPin High interrupts(); while ( !DIRECT_READ(rReg, rBit) && (total < CS_Timeout_Millis) ) { // while receive pin is LOW AND total is positive value total++; } //Serial.print("SenseOneCycle(1): "); //Serial.println(total); if (total > CS_Timeout_Millis) { return -2; // total variable over timeout } // set receive pin HIGH briefly to charge up fully - because the while loop above will exit when pin is ~ 2.5V noInterrupts(); DIRECT_WRITE_HIGH(rReg, rBit); DIRECT_MODE_OUTPUT(rReg, rBit); // receivePin to OUTPUT - pin is now HIGH AND OUTPUT DIRECT_WRITE_HIGH(rReg, rBit); DIRECT_MODE_INPUT(rReg, rBit); // receivePin to INPUT (pullup is off) DIRECT_WRITE_LOW(sReg, sBit); // sendPin LOW interrupts(); #ifdef FIVE_VOLT_TOLERANCE_WORKAROUND DIRECT_MODE_OUTPUT(rReg, rBit); DIRECT_WRITE_LOW(rReg, rBit); delayMicroseconds(10); DIRECT_MODE_INPUT(rReg, rBit); // receivePin to INPUT (pullup is off) #else while ( DIRECT_READ(rReg, rBit) && (total < CS_Timeout_Millis) ) { // while receive pin is HIGH AND total is less than timeout total++; } #endif //Serial.print("SenseOneCycle(2): "); //Serial.println(total); if (total >= CS_Timeout_Millis) { return -2; // total variable over timeout } else { return 1; } }
bool OneWireSlave::waitTimeSlot() { uint8_t mask = pin_bitmask; volatile uint8_t *reg asm("r30") = baseReg; uint16_t retries; retries = TIMESLOT_WAIT_RETRY_COUNT; while ( !DIRECT_READ(reg, mask)) if (--retries == 0) return FALSE; retries = TIMESLOT_WAIT_RETRY_COUNT; while ( DIRECT_READ(reg, mask)) if (--retries == 0) return FALSE; return TRUE; }
uint8_t OneWireSlave::recvBit(void) { uint8_t mask = pin_bitmask; volatile uint8_t *reg asm("r30") = baseReg; uint8_t r; cli(); DIRECT_MODE_INPUT(reg, mask); if (!waitTimeSlot() ) { errno = ONEWIRE_READ_TIMESLOT_TIMEOUT; sei(); return 0; } delayMicroseconds(30); r = DIRECT_READ(reg, mask); sei(); return r; }
bool OneWireSlave::presence(uint8_t delta) { uint8_t mask = pin_bitmask; volatile uint8_t *reg asm("r30") = baseReg; errno = ONEWIRE_NO_ERROR; cli(); DIRECT_WRITE_LOW(reg, mask); DIRECT_MODE_OUTPUT(reg, mask); // drive output low sei(); delayMicroseconds(120); cli(); DIRECT_MODE_INPUT(reg, mask); // allow it to float sei(); delayMicroseconds(300 - delta); if ( !DIRECT_READ(reg, mask)) { errno = ONEWIRE_PRESENCE_LOW_ON_LINE; return FALSE; } else return TRUE; }
// // Read the 40 bit data stream from the DHT 22 // Store the results in private member data to be read by public member functions // DHT22_ERROR_t DHT22::readData() { uint8_t bitmask = _bitmask; volatile uint8_t *reg asm("r30") = _baseReg; uint8_t retryCount; uint8_t bitTimes[DHT22_DATA_BIT_COUNT]; int currentHumidity; int currentTemperature; uint8_t checkSum, csPart1, csPart2, csPart3, csPart4; unsigned long currentTime; int i; currentHumidity = 0; currentTemperature = 0; checkSum = 0; currentTime = millis(); for(i = 0; i < DHT22_DATA_BIT_COUNT; i++) { bitTimes[i] = 0; } if(currentTime - _lastReadTime < 2000) { // Caller needs to wait 2 seconds between each call to readData return DHT_ERROR_TOOQUICK; } _lastReadTime = currentTime; // Pin needs to start HIGH, wait until it is HIGH with a timeout cli(); DIRECT_MODE_INPUT(reg, bitmask); sei(); retryCount = 0; do { if (retryCount > 125) { return DHT_BUS_HUNG; } retryCount++; delayMicroseconds(2); } while(!DIRECT_READ(reg, bitmask)); // Send the activate pulse cli(); DIRECT_WRITE_LOW(reg, bitmask); DIRECT_MODE_OUTPUT(reg, bitmask); // Output Low sei(); delayMicroseconds(1100); // 1.1 ms cli(); DIRECT_MODE_INPUT(reg, bitmask); // Switch back to input so pin can float sei(); // Find the start of the ACK Pulse retryCount = 0; do { if (retryCount > 25) //(Spec is 20 to 40 us, 25*2 == 50 us) { return DHT_ERROR_NOT_PRESENT; } retryCount++; delayMicroseconds(2); } while(!DIRECT_READ(reg, bitmask)); // Find the end of the ACK Pulse retryCount = 0; do { if (retryCount > 50) //(Spec is 80 us, 50*2 == 100 us) { return DHT_ERROR_ACK_TOO_LONG; } retryCount++; delayMicroseconds(2); } while(DIRECT_READ(reg, bitmask)); // Read the 40 bit data stream for(i = 0; i < DHT22_DATA_BIT_COUNT; i++) { // Find the start of the sync pulse retryCount = 0; do { if (retryCount > 35) //(Spec is 50 us, 35*2 == 70 us) { return DHT_ERROR_SYNC_TIMEOUT; } retryCount++; delayMicroseconds(2); } while(!DIRECT_READ(reg, bitmask)); // Measure the width of the data pulse retryCount = 0; do { if (retryCount > 50) //(Spec is 80 us, 50*2 == 100 us) { return DHT_ERROR_DATA_TIMEOUT; } retryCount++; delayMicroseconds(2); } while(DIRECT_READ(reg, bitmask)); bitTimes[i] = retryCount; } // Now bitTimes have the number of retries (us *2) // that were needed to find the end of each data bit // Spec: 0 is 26 to 28 us // Spec: 1 is 70 us // bitTimes[x] <= 11 is a 0 // bitTimes[x] > 11 is a 1 // Note: the bits are offset by one from the data sheet, not sure why for(i = 0; i < 16; i++) { if(bitTimes[i + 1] > 11) { currentHumidity |= (1 << (15 - i)); } } for(i = 0; i < 16; i++) { if(bitTimes[i + 17] > 11) { currentTemperature |= (1 << (15 - i)); } } for(i = 0; i < 8; i++) { if(bitTimes[i + 33] > 11) { checkSum |= (1 << (7 - i)); } } _lastHumidity = currentHumidity & 0x7FFF; if(currentTemperature & 0x8000) { // Below zero, non standard way of encoding negative numbers! // Convert to native negative format. currentTemperature &= 0x7FFF; _lastTemperature = -currentTemperature; } else { _lastTemperature = currentTemperature; } csPart1 = currentHumidity >> 8; csPart2 = currentHumidity & 0xFF; csPart3 = currentTemperature >> 8; csPart4 = currentTemperature & 0xFF; if(checkSum == ((csPart1 + csPart2 + csPart3 + csPart4) & 0xFF)) { return DHT_ERROR_NONE; } return DHT_ERROR_CHECKSUM; }
// return values: // DHTLIB_OK // DHTLIB_ERROR_TIMEOUT int dht_readSensor(uint8_t pin, uint8_t wakeupDelay) { // INIT BUFFERVAR TO RECEIVE DATA uint8_t mask = 128; uint8_t idx = 0; uint8_t i = 0; // replace digitalRead() with Direct Port Reads. // reduces footprint ~100 bytes => portability issue? // direct port read is about 3x faster // uint8_t bit = digitalPinToBitMask(pin); // uint8_t port = digitalPinToPort(pin); // volatile uint8_t *PIR = portInputRegister(port); // EMPTY BUFFER for (i = 0; i < 5; i++) dht_bytes[i] = 0; // REQUEST SAMPLE // pinMode(pin, OUTPUT); platform_gpio_mode(pin, PLATFORM_GPIO_OUTPUT, PLATFORM_GPIO_PULLUP); DIRECT_MODE_OUTPUT(pin); // digitalWrite(pin, LOW); // T-be DIRECT_WRITE_LOW(pin); // delay(wakeupDelay); for (i = 0; i < wakeupDelay; i++) os_delay_us(1000); // Disable interrupts ets_intr_lock(); // digitalWrite(pin, HIGH); // T-go DIRECT_WRITE_HIGH(pin); os_delay_us(40); // pinMode(pin, INPUT); DIRECT_MODE_INPUT(pin); // GET ACKNOWLEDGE or TIMEOUT uint16_t loopCntLOW = DHTLIB_TIMEOUT; while (DIRECT_READ(pin) == LOW ) // T-rel { os_delay_us(1); if (--loopCntLOW == 0) return DHTLIB_ERROR_TIMEOUT; } uint16_t loopCntHIGH = DHTLIB_TIMEOUT; while (DIRECT_READ(pin) != LOW ) // T-reh { os_delay_us(1); if (--loopCntHIGH == 0) return DHTLIB_ERROR_TIMEOUT; } // READ THE OUTPUT - 40 BITS => 5 BYTES for (i = 40; i != 0; i--) { loopCntLOW = DHTLIB_TIMEOUT; while (DIRECT_READ(pin) == LOW ) { os_delay_us(1); if (--loopCntLOW == 0) return DHTLIB_ERROR_TIMEOUT; } uint32_t t = system_get_time(); loopCntHIGH = DHTLIB_TIMEOUT; while (DIRECT_READ(pin) != LOW ) { os_delay_us(1); if (--loopCntHIGH == 0) return DHTLIB_ERROR_TIMEOUT; } if ((system_get_time() - t) > 40) { dht_bytes[idx] |= mask; } mask >>= 1; if (mask == 0) // next byte? { mask = 128; idx++; } } // Enable interrupts ets_intr_unlock(); // pinMode(pin, OUTPUT); DIRECT_MODE_OUTPUT(pin); // digitalWrite(pin, HIGH); DIRECT_WRITE_HIGH(pin); return DHTLIB_OK; }