Skip to content

Commit f4b1ecf

Browse files
WestfWladyada
authored andcommitted
Fix pulseIn() on SAMD51 by writing it in plain C, so that (arduino#76)
the CM0+-specific pulse_asm won't need to be linked. The SAMD51 is fast enough that we can time pulses with micros() Tested with a bunch of pulse lengths from <1us to >1s
1 parent 166b43b commit f4b1ecf

File tree

1 file changed

+31
-0
lines changed

1 file changed

+31
-0
lines changed

cores/arduino/pulse.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,36 @@ uint32_t pulseIn(uint32_t pin, uint32_t state, uint32_t timeout)
3434
uint32_t bit = 1 << p.ulPin;
3535
uint32_t stateMask = state ? bit : 0;
3636

37+
#if defined(__SAMD51__)
38+
/*
39+
* The SAMD51 is fast enough to use really obvious code (similar to
40+
* what was used to produce pulse_asm.S, but using micros() for timing.
41+
* No assembly required, no conversion of loop counts to times (which is
42+
* worrisome in the presence of cache.)
43+
*/
44+
volatile uint32_t *port = &(PORT->Group[p.ulPort].IN.reg);
45+
uint32_t usCallStart; // microseconds at start of call, for timeout.
46+
uint32_t usPulseStart; // microseconds at start of measured pulse.
47+
usCallStart = micros();
48+
// wait for any previous pulse to end
49+
while ((*port & bit) == stateMask) {
50+
if (micros() - usCallStart > timeout)
51+
return -1;
52+
}
53+
// wait for the pulse to start
54+
while ((*port & bit) != stateMask) {
55+
usPulseStart = micros();
56+
if (usPulseStart - usCallStart > timeout)
57+
return -2;
58+
}
59+
60+
// wait for the pulse to stop
61+
while ((*port & bit) == stateMask) {
62+
if (micros() - usCallStart > timeout)
63+
return -3;
64+
}
65+
return micros() - usPulseStart;
66+
#else
3767
// convert the timeout from microseconds to a number of times through
3868
// the initial loop; it takes (roughly) 13 clock cycles per iteration.
3969
uint32_t maxloops = microsecondsToClockCycles(timeout) / 13;
@@ -48,5 +78,6 @@ uint32_t pulseIn(uint32_t pin, uint32_t state, uint32_t timeout)
4878
return clockCyclesToMicroseconds(width * 13 + 16);
4979
else
5080
return 0;
81+
#endif // SAMD51
5182
}
5283

0 commit comments

Comments
 (0)