Skip to content

Commit 62e666c

Browse files
committed
improved delayMicroseconds() works from 1MHz and up
1 parent cfc46eb commit 62e666c

File tree

1 file changed

+15
-5
lines changed

1 file changed

+15
-5
lines changed

avr/cores/picocore/Arduino.h

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,26 @@ inline void check_valid_digital_pin(uint8_t pin)
6363
}
6464

6565
// delays a specified number of microseconds
66-
// minimum F_CPU = 4M
67-
// todo: add support for 1-3.9M, dividing us by 4
66+
// works for clock frequencies of 1Mhz and up
6867
__attribute((always_inline))
6968
static inline void delayMicroseconds(uint16_t us)
7069
{
70+
// if us is a compile-time constant result is accurate to 1 cycle
71+
if (__builtin_constant_p(us)) {
72+
_delay_us(us);
73+
return;
74+
}
7175

76+
// when us is not known at compile time, delay is accurate to +/- 2us
77+
// plus an overhead of 3 CPU cycles
7278
const float fMHz = (F_CPU/1000000.0);
73-
do {
74-
_delay_us(1.0 - (4.0 / fMHz)); // correct for 4c loop overhead
75-
} while (--us);
79+
// subtract two for rounding before dividing by 4
80+
us -= 2;
81+
delay4us:
82+
// delay 4us per loop, less 4 cycles for overhead
83+
_delay_us(4.0 - (4.0 / fMHz));
84+
asm volatile ("sbiw %[us], 4" : [us]"+d"(us));
85+
asm goto( "brpl %l[delay4us]" :::: delay4us);
7686
}
7787

7888
void delay(uint16_t count);

0 commit comments

Comments
 (0)