Skip to content

Commit 16d75d6

Browse files
committed
pulseIn: modify function to use ASM implementation
1 parent fcdb8a7 commit 16d75d6

File tree

2 files changed

+12
-27
lines changed

2 files changed

+12
-27
lines changed

hardware/arduino/avr/cores/arduino/wiring_private.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ extern "C"{
4343
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
4444
#endif
4545

46+
uint32_t countPulseASM(volatile uint8_t *port, uint8_t bit, uint8_t stateMask, unsigned long maxloops);
47+
4648
#define EXTERNAL_INT_0 0
4749
#define EXTERNAL_INT_1 1
4850
#define EXTERNAL_INT_2 2

hardware/arduino/avr/cores/arduino/wiring_pulse.c

Lines changed: 10 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@
2828
/* Measures the length (in microseconds) of a pulse on the pin; state is HIGH
2929
* or LOW, the type of pulse to measure. Works on pulses from 2-3 microseconds
3030
* to 3 minutes in length, but must be called at least a few dozen microseconds
31-
* before the start of the pulse. */
31+
* before the start of the pulse.
32+
*
33+
* This function performs better with short pulses in noInterrupt() context
34+
*/
3235
unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
3336
{
3437
// cache the port and bit of the pin in order to speed up the
@@ -38,32 +41,12 @@ unsigned long pulseIn(uint8_t pin, uint8_t state, unsigned long timeout)
3841
uint8_t port = digitalPinToPort(pin);
3942
uint8_t stateMask = (state ? bit : 0);
4043
unsigned long width = 0; // keep initialization out of time critical area
41-
44+
4245
// convert the timeout from microseconds to a number of times through
43-
// the initial loop; it takes 16 clock cycles per iteration.
46+
// the initial loop; it takes approximately 16 clock cycles per iteration
4447
unsigned long numloops = 0;
45-
unsigned long maxloops = microsecondsToClockCycles(timeout) / 16;
46-
47-
// wait for any previous pulse to end
48-
while ((*portInputRegister(port) & bit) == stateMask)
49-
if (numloops++ == maxloops)
50-
return 0;
51-
52-
// wait for the pulse to start
53-
while ((*portInputRegister(port) & bit) != stateMask)
54-
if (numloops++ == maxloops)
55-
return 0;
56-
57-
// wait for the pulse to stop
58-
while ((*portInputRegister(port) & bit) == stateMask) {
59-
if (numloops++ == maxloops)
60-
return 0;
61-
width++;
62-
}
48+
unsigned long maxloops = microsecondsToClockCycles(timeout)/16;
6349

64-
// convert the reading to microseconds. The loop has been determined
65-
// to be 20 clock cycles long and have about 16 clocks between the edge
66-
// and the start of the loop. There will be some error introduced by
67-
// the interrupt handlers.
68-
return clockCyclesToMicroseconds(width * 21 + 16);
69-
}
50+
width = countPulseASM(portInputRegister(port), bit, stateMask, maxloops);
51+
return clockCyclesToMicroseconds(width * 16 + 16);
52+
}

0 commit comments

Comments
 (0)