int SoftwareSerial::read() { int val = 0; int bitDelay = _bitPeriod - clockCyclesToMicroseconds(50); // one byte of serial data (LSB first) // ...--\ /--\/--\/--\/--\/--\/--\/--\/--\/--... // \--/\--/\--/\--/\--/\--/\--/\--/\--/ // start 0 1 2 3 4 5 6 7 stop while (digitalRead(_receivePin)); // confirm that this is a real start bit, not line noise if (digitalRead(_receivePin) == LOW) { // frame start indicated by a falling edge and low start bit // jump to the middle of the low start bit delayMicroseconds(bitDelay / 2 - clockCyclesToMicroseconds(50)); // offset of the bit in the byte: from 0 (LSB) to 7 (MSB) for (int offset = 0; offset < 8; offset++) { // jump to middle of next bit delayMicroseconds(bitDelay); // read bit val |= digitalRead(_receivePin) << offset; } delayMicroseconds(_bitPeriod); return val; } return -1; }
/* 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 }
// 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 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); }
/* 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 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); }
/* || @override Print.write || || @description || | Set the cursor at cooridnate x,y of the display || # */ void SoftwareSerial::write(uint8_t b) { if (baudRate == 0) return; int bitDelay = bitPeriod - clockCyclesToMicroseconds(50); // a digitalWrite is about 50 cycles byte mask; digitalWrite(transmitPin, LOW); delayMicroseconds(bitDelay); for (mask = 0x01; mask; mask <<= 1) { if (b & mask) // choose bit { digitalWrite(transmitPin,HIGH); // send 1 } else { digitalWrite(transmitPin,LOW); // send 1 } delayMicroseconds(bitDelay); } digitalWrite(transmitPin, HIGH); delayMicroseconds(bitDelay); }
/** * \par Function * poll * \par Description * If we used the serial as software serial port, and set the _polling mask true. * we beed use this function to read the serial data. * \par Output * None * \return * The character read, or -1 if none is available * \par Others * None */ int16_t MeSerial::poll(void) { int16_t val = 0; int16_t bitDelay = _bitPeriod - clockCyclesToMicroseconds(50); if (digitalRead(_RxPin) == LOW) { for (int16_t offset = 0; offset < 8; offset++) { delayMicroseconds(bitDelay); val |= digitalRead(_RxPin) << offset; } delayMicroseconds(bitDelay); return (val & 0xff); } return (-1); }
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); }
// 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); }
numvar setBaud(numvar pin, unumvar baud) { chkpin(pin); //#ifndef SOFTWARE_SERIAL_TX if (pin == DEFAULT_OUTPIN) { beginSerial(baud); return 0; } //#endif #ifdef ALTERNATE_OUTPIN else if (pin == ALTERNATE_OUTPIN) { Serial1.begin(baud); return 0; } #endif bittime[pin] = (1000000/baud) - clockCyclesToMicroseconds(50); pinMode(pin, OUTPUT); // make it an output digitalWrite(pin, HIGH); // set idle delayMicroseconds(bittime[pin]); // let it quiesce return bittime[pin]; }
void SWSerLCDpa::print(uint8_t b) { if (_baudRate == 0) return; int bitDelay = _bitPeriod - clockCyclesToMicroseconds(50); // a digitalWrite is about 50 cycles byte mask; digitalWrite(_transmitPin, LOW); delayMicroseconds(bitDelay); for (mask = 0x01; mask; mask <<= 1) { if (b & mask) { // choose bit digitalWrite(_transmitPin,HIGH); // send 1 } else { digitalWrite(_transmitPin,LOW); // send 1 } delayMicroseconds(bitDelay); } digitalWrite(_transmitPin, HIGH); delayMicroseconds(bitDelay); }
/* 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); }