unsigned long Ping::pulseIn(uint8_t pin, uint8_t state, unsigned long timeout, unsigned long timeoutstop) { uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); uint8_t stateMask = (state ? bit : 0); unsigned long width = 0; unsigned long numloops = 0; unsigned long maxloops = microsecondsToClockCycles(timeout) / 16; unsigned long maxloopsstop = microsecondsToClockCycles(timeoutstop) / 16 ; // wait for any previous pulse to end while ((*portInputRegister(port) & bit) == stateMask) if (numloops++ == maxloops) return 0; // wait for the pulse to start while ((*portInputRegister(port) & bit) != stateMask) if (numloops++ == maxloops) return 0; // wait for the pulse to stop while ((*portInputRegister(port) & bit) == stateMask) if (width++ == maxloopsstop) return 5000 ; return clockCyclesToMicroseconds(width * 20 + 16); }
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds * to 3 minutes in length, but must be called at least a few dozen microseconds * before the start of the pulse. * * ATTENTION: * this function relies on micros() so cannot be used in noInterrupt() context */ unsigned long pulseInLong(uint8_t pin, uint8_t state, unsigned long timeout) { // cache the port and bit of the pin in order to speed up the // pulse width measuring loop and achieve finer resolution. calling // digitalRead() instead yields much coarser resolution. uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); uint8_t stateMask = (state ? bit : 0); // convert the timeout from microseconds to a number of times through // the initial loop; it takes 16 clock cycles per iteration. unsigned long numloops = 0; unsigned long maxloops = microsecondsToClockCycles(timeout); // wait for any previous pulse to end while ((*portInputRegister(port) & bit) == stateMask) if (numloops++ == maxloops) return 0; // wait for the pulse to start while ((*portInputRegister(port) & bit) != stateMask) if (numloops++ == maxloops) return 0; unsigned long start = micros(); // wait for the pulse to stop while ((*portInputRegister(port) & bit) == stateMask) { if (numloops++ == maxloops) return 0; } return micros() - start; }
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds * to 3 minutes in length, but must be called at least a few dozen microseconds * before the start of the pulse. */ extern uint32_t pulseIn(uint32_t pin, bool state, uint32_t timeout) { uint32_t numloops = 0; uint32_t maxloops = microsecondsToClockCycles(timeout) / 16; uint32_t start, end; // wait for any previous pulse to end while (digitalRead(pin) == state) if (numloops++ == maxloops) return 0; // wait for the pulse to start while (digitalRead(pin) != state) if (numloops++ == maxloops) return 0; // wait for the pulse to stop start = micros(); while (digitalRead(pin) == state) if (numloops++ == maxloops) return 0; end = micros(); return (end - start); }
DHT::DHT(void) { _maxCycles = microsecondsToClockCycles(DHT_MAX_CYCLES); _lastTemperature = _lastHumidity = 0; ADD_BIT(_status, STATUS_TEMP_GOOD | STATUS_HUMI_GOOD); DEBUG_PRINTLN("DHT loaded."); }
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds * to 3 minutes in length, but must be called at least a few dozen microseconds * before the start of the pulse. */ unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) { // cache the port and bit of the pin in order to speed up the // pulse width measuring loop and achieve finer resolution. calling // digitalRead() instead yields much coarser resolution. uint8_t bit = digitalPinToBitMask(pin); volatile uint8_t *reg = portInputRegister(digitalPinToPort(pin)); uint8_t stateMask = (state ? bit : 0); unsigned long width = 0; // keep initialization out of time critical area // convert the timeout from microseconds to a number of times through // the initial loop; it takes 16 clock cycles per iteration. unsigned long numloops = 0; unsigned long maxloops = microsecondsToClockCycles(timeout) / 16; // wait for any previous pulse to end while ((*reg & bit) == stateMask) if (numloops++ == maxloops) return 0; // wait for the pulse to start while ((*reg & bit) != stateMask) if (numloops++ == maxloops) return 0; // wait for the pulse to stop while ((*reg & bit) == stateMask) width++; // convert the reading to microseconds. The loop has been determined // to be 10 clock cycles long and have about 16 clocks between the edge // and the start of the loop. There will be some error introduced by // the interrupt handlers. return clockCyclesToMicroseconds(width * 10 + 16); }
unsigned int pulseIn(int pin, int state, unsigned int timeout) { const LPC_GPIO_TypeDef* port = gpioPorts[digitalPinToPort(pin)]; const unsigned int bitMask = digitalPinToBitMask(pin); const unsigned int stateMask = state ? bitMask : 0; unsigned long width = 0, numloops = 0; const unsigned int maxloops = microsecondsToClockCycles(timeout); // Wait for any previous pulse to end while (port->MASKED_ACCESS[bitMask] == stateMask) if (numloops++ == maxloops) return 0; // Wait for the pulse to start while (port->MASKED_ACCESS[bitMask] != stateMask) if (numloops++ == maxloops) return 0; // Wait for the pulse to stop while (port->MASKED_ACCESS[bitMask] == stateMask) { if (numloops++ == maxloops) return 0; width++; } // Convert the reading to microseconds. The loop has been determined to be // 20 clock cycles long and have about 16 clocks between the edge and the // start of the loop. There will be some error introduced by the interrupt // handlers. return clockCyclesToMicroseconds(width * 21 + 16); }
DHT::DHT(uint8_t pin, uint8_t type, uint8_t count) { _pin = pin; _type = type; _bit = digitalPinToBitMask(pin); _port = digitalPinToPort(pin); _maxcycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for // reading pulses from DHT sensor. // Note that count is now ignored as the DHT reading algorithm adjusts itself // basd on the speed of the processor. }
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds * to 3 minutes in length, but must be called at least a few dozen microseconds * before the start of the pulse. */ unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) { // cache the port and bit of the pin in order to speed up the // pulse width measuring loop and achieve finer resolution. calling // digitalRead() instead yields much coarser resolution. uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); uint8_t stateMask = (state ? bit : 0); unsigned long width = 0; // keep initialization out of time critical area // convert the timeout from microseconds to a number of times through // the initial loop; it takes 16 clock cycles per iteration. unsigned long numloops = 0; unsigned long maxloops = microsecondsToClockCycles(timeout) / 16; // wait for any previous pulse to end while ((*portInputRegister(port) & bit) == stateMask) if (numloops++ == maxloops) return 0; // wait for the pulse to start while ((*portInputRegister(port) & bit) != stateMask) if (numloops++ == maxloops) return 0; // wait for the pulse to stop while ((*portInputRegister(port) & bit) == stateMask) { if (numloops++ == maxloops) return 0; width++; } // convert the reading to microseconds. There will be some error introduced by // the interrupt handlers. // Conversion constants are compiler-dependent, different compiler versions // have different levels of optimization. #if __GNUC__==4 && __GNUC_MINOR__==3 && __GNUC_PATCHLEVEL__==2 // avr-gcc 4.3.2 return clockCyclesToMicroseconds(width * 21 + 16); #elif __GNUC__==4 && __GNUC_MINOR__==8 && __GNUC_PATCHLEVEL__==1 // avr-gcc 4.8.1 return clockCyclesToMicroseconds(width * 24 + 16); #elif __GNUC__<=4 && __GNUC_MINOR__<=3 // avr-gcc <=4.3.x #warning "pulseIn() results may not be accurate" return clockCyclesToMicroseconds(width * 21 + 16); #else // avr-gcc >4.3.x #warning "pulseIn() results may not be accurate" return clockCyclesToMicroseconds(width * 24 + 16); #endif }
/* * Constructor for the sensor. It remembers the pin number and the * type of sensor, and initializes internal variables. */ DHT_nonblocking::DHT_nonblocking( uint8_t pin, uint8_t type ) : _pin( pin ), _type( type ), _bit( digitalPinToBitMask( pin ) ), _port( digitalPinToPort( pin ) ), _maxcycles( microsecondsToClockCycles( 1000 ) ) { dht_state = DHT_IDLE; pinMode( _pin, INPUT ); digitalWrite( _pin, HIGH ); }
uint32_t DHT11::pulse(uint32_t state, uint32_t timeout) { uint32_t maxloops = microsecondsToClockCycles(timeout) / 16; uint32_t numloops = 0; while (digitalRead(_pin) == state) { if (numloops++ == maxloops) return 0; } return numloops; }
DHT::DHT(uint8_t pin) : _sensorID(-1) { _pin = pin; #ifdef __AVR _bit = digitalPinToBitMask(pin); _port = digitalPinToPort(pin); #endif // 1 millisecond timeout for reading pulses from DHT sensor. // The DHT reading algorithm adjusts itself based on the speed of the processor. _maxcycles = microsecondsToClockCycles(1000); }
// max timeout is 27 seconds at 160MHz clock and 54 seconds at 80MHz clock unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) { const uint32_t max_timeout_us = clockCyclesToMicroseconds(UINT_MAX); if (timeout > max_timeout_us) { timeout = max_timeout_us; } const uint32_t timeout_cycles = microsecondsToClockCycles(timeout); const uint32_t start_cycle_count = xthal_get_ccount(); WAIT_FOR_PIN_STATE(!state); WAIT_FOR_PIN_STATE(state); const uint32_t pulse_start_cycle_count = xthal_get_ccount(); WAIT_FOR_PIN_STATE(!state); return clockCyclesToMicroseconds(xthal_get_ccount() - pulse_start_cycle_count); }
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) { uint8_t volatile& pinreg = pinno2pinreg(pin); uint8_t msk = 1 << pinno2bit(pin); uint8_t stm = state? msk : 0; unsigned long w = 0; unsigned long n = 0; unsigned long m = microsecondsToClockCycles(timeout) / 16; while ((pinreg & msk) == stm) if (n++ == m) return 0; while ((pinreg & msk) != stm) if (n++ == m) return 0; while ((pinreg & msk) == stm) w++; return clockCyclesToMicroseconds(w * 10 + 16); }
void DHT::begin(uint8_t pin, uint8_t type) { _pin = pin; _type = type; #ifdef __AVR _bit = digitalPinToBitMask(pin); _port = digitalPinToPort(pin); #endif _maxcycles = microsecondsToClockCycles(1000); // 1 millisecond timeout for // reading pulses from DHT sensor. // Note that count is now ignored as the DHT reading algorithm adjusts itself // based on the speed of the processor. // set up the pins! pinMode(_pin, INPUT_PULLUP); // Using this value makes sure that millis() - lastreadtime will be // >= MIN_INTERVAL right away. Note that this assignment wraps around, // but so will the subtraction. _lastreadtime = -MIN_INTERVAL; DEBUG_PRINT("Max clock cycles: "); DEBUG_PRINTLN(_maxcycles, DEC); }
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds * to 3 minutes in length, but must be called at least a few dozen microseconds * before the start of the pulse. */ unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) { // cache the port and bit of the pin in order to speed up the // pulse width measuring loop and achieve finer resolution. calling // digitalRead() instead yields much coarser resolution. uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); uint32_t portBase = (uint32_t) portBASERegister(port); uint8_t stateMask = (state ? bit : 0); // convert the timeout from microseconds to a number of times through // the initial loop; it takes 11 clock cycles per iteration. unsigned long numloops = 0; unsigned long maxloops = microsecondsToClockCycles(timeout) / 11; // wait for any previous pulse to end while (MAP_GPIOPinRead(portBase, bit) == stateMask) if (numloops++ == maxloops) return 0; // wait for the pulse to start while (MAP_GPIOPinRead(portBase, bit) != stateMask) if (numloops++ == maxloops) return 0; // wait for the pulse to stop unsigned long start = micros(); while (MAP_GPIOPinRead(portBase, bit) == stateMask) { if (numloops++ == maxloops) return 0; } unsigned long end = micros(); unsigned long result = end - start; return(result); // convert the reading to microseconds. The loop has been determined // to be 13 clock cycles long and have about 11 clocks between the edge // and the start of the loop. There will be some error introduced by // the interrupt handlers. //return clockCyclesToMicroseconds(width * 13 + 11); }
// Same as pulseIn, but tweaked for range 1000 - 2000 usec, and reading only HIGH phase. // Must be compiled in .cpp file, with -Os compiler switch. unsigned long PulseIn(uint8_t pin, unsigned long timeout){ const uint8_t bit = digitalPinToBitMask(pin), port = digitalPinToPort(pin); unsigned long width = 1; unsigned long numloops = 0; const unsigned long maxloops = microsecondsToClockCycles(timeout) / 16; noInterrupts(); //wait for the pulse to start while((*portInputRegister(port) & bit) != bit){ if(++numloops == maxloops){ interrupts(); return 0; } } //wait for the pulse to stop while((*portInputRegister(port) & bit) == bit) width++; interrupts(); return clockCyclesToMicroseconds((width*0xd00L+0x800L)/256L); }
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds * to 3 minutes in length, but must be called at least a few dozen microseconds * before the start of the pulse. * * This function performs better with short pulses in noInterrupt() context */ unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout) { // cache the port and bit of the pin in order to speed up the // pulse width measuring loop and achieve finer resolution. calling // digitalRead() instead yields much coarser resolution. uint8_t bit = digitalPinToBitMask(pin); uint8_t port = digitalPinToPort(pin); uint8_t stateMask = (state ? bit : 0); // convert the timeout from microseconds to a number of times through // the initial loop; it takes approximately 16 clock cycles per iteration unsigned long maxloops = microsecondsToClockCycles(timeout)/16; unsigned long width = countPulseASM(portInputRegister(port), bit, stateMask, maxloops); // prevent clockCyclesToMicroseconds to return bogus values if countPulseASM timed out if (width) return clockCyclesToMicroseconds(width * 16 + 16); else return 0; }
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds * to 3 minutes in length, but must be called at least a few dozen microseconds * before the start of the pulse. */ extern uint32_t pulseIn( uint32_t pin, uint32_t state, uint32_t timeout ) { //TODO Correct clock cycle constants. // cache the port and bit of the pin in order to speed up the // pulse width measuring loop and achieve finer resolution. calling // digitalRead() instead yields much coarser resolution. //PinDescription p = g_APinDescription[pin]; uint32_t width = 0; // keep initialization out of time critical area // convert the timeout from microseconds to a number of times through // the initial loop; it takes 22 clock cycles per iteration. uint32_t numloops = 0; uint32_t maxloops = microsecondsToClockCycles(timeout) / 22; // wait for any previous pulse to end while ( ((u32AHI_DioReadInput()>>pin) & 0x1) == state) if (numloops++ == maxloops) return 0; // wait for the pulse to start while ( ((u32AHI_DioReadInput()>>pin) & 0x1) != state) if (numloops++ == maxloops) return 0; // wait for the pulse to stop while ( ((u32AHI_DioReadInput()>>pin) & 0x1) == state) { if (numloops++ == maxloops) return 0; width++; } // convert the reading to microseconds. The loop has been determined // to be 52 clock cycles long and have about 16 clocks between the edge // and the start of the loop. There will be some error introduced by // the interrupt handlers. return clockCyclesToMicroseconds(width * 52 + 16); }
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH * or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds * to 3 minutes in length, but must be called at least a few dozen microseconds * before the start of the pulse. */ extern uint32_t pulseIn( uint32_t pin, uint32_t state, uint32_t timeout ) { uint32_t width = 0; // keep initialization out of time critical area if(pin > 7) pin = pin + 4; // convert the timeout from microseconds to a number of times through // the initial loop; it takes 2 clock cycles per iteration. uint32_t numloops = 0; uint32_t maxloops = microsecondsToClockCycles(timeout) / 2; // wait for any previous pulse to end while (((NRF_GPIO->IN >> pin) & 1UL) == state) if (numloops++ == maxloops) return 0; // wait for the pulse to start while (((NRF_GPIO->IN >> pin) & 1UL) != state) if (numloops++ == maxloops) return 0; // wait for the pulse to stop while (((NRF_GPIO->IN >> pin) & 1UL) == state) { if (numloops++ == maxloops) return 0; width++; } // convert the reading to microseconds. The loop has been determined // to be 17 clock cycles long and have about 16 clocks between the edge // and the start of the loop. There will be some error introduced by // the interrupt handlers. return clockCyclesToMicroseconds(width * 17 + 16); }