|
3 | 3 |
|
4 | 4 | #include <Arduino.h> |
5 | 5 | #include <util/delay.h> |
| 6 | +#include "as_common.h" |
6 | 7 |
|
7 | | -// lightweight custom function call abi |
8 | | -extern void delay_impl(); |
9 | | -void delay(uint32_t msec) |
| 8 | +// delays a specified number of microseconds - modified from picoCore |
| 9 | +// works for clock frequencies of 4Mhz and up |
| 10 | +void delayMicroseconds(uint16_t us) |
10 | 11 | { |
11 | | - register uint32_t ms asm ("r24") = msec; |
12 | | - asm ( ".equ T0CNT_PER_MS, %0\n" |
13 | | - ".global T0CNT_PER_MS\n" |
14 | | - // T0 prescaler is 64 |
15 | | - :: "i" (F_CPU / 1000 / 64) ); |
16 | | - asm volatile ( |
17 | | - "rcall %x1\n" |
18 | | - : "+r"(ms) |
19 | | - : "i"(delay_impl) |
20 | | - : "r18", "r19", "r20", "r21" |
21 | | - ); |
22 | | -} |
| 12 | + // if us is a compile-time constant result is accurate to 1 cycle |
| 13 | + if (__builtin_constant_p(us)) { |
| 14 | + _delay_us(us); |
| 15 | + return; |
| 16 | + } |
23 | 17 |
|
24 | | -// avr-libc math.h does not declare gcc log2 builtin |
25 | | -double log2(double); |
| 18 | + // code below runs when us is not known at compile time |
| 19 | + // uses inline asm to guarantee exact cycle counts |
| 20 | + const float fMHz = (F_CPU/1000000.0); |
| 21 | + delay1us: |
| 22 | + // delay 1us per loop, less 4 cycles for overhead |
| 23 | + _delay_us(1.0 - (4.0 / fMHz)); |
| 24 | + asm volatile ("sbiw %[us], 1" : [us]"+d"(us)); |
| 25 | + asm goto( "brne %l[delay1us]" :::: delay1us); |
| 26 | +} |
26 | 27 |
|
27 | | -void init() |
| 28 | +void init(void) |
28 | 29 | { |
29 | | - asm("sei"); |
| 30 | + // T0CNT_PER_MS needed for delay_impl |
| 31 | + asm ( ".equ T0CNT_PER_MS, %0\n" |
| 32 | + ".global T0CNT_PER_MS\n" |
| 33 | + :: "i" (F_CPU / 1000 / T0_PRESCALE) ); |
30 | 34 |
|
31 | 35 | // setup ADC with 250-500kHz clock |
32 | 36 | uint8_t prescaler = log2(F_CPU/500000); |
33 | 37 | ADCSRA = prescaler | (1 << ADEN); |
| 38 | + |
| 39 | + TCCR0B = _BV(CS01) | _BV(CS00); // enable T0, div64 prescale |
| 40 | + |
| 41 | + asm("sei"); // enable interrupts |
| 42 | +} |
| 43 | + |
| 44 | +// replace main() from Arduino core |
| 45 | +int main(void) |
| 46 | +{ |
| 47 | + init(); |
| 48 | + setup(); |
| 49 | + while(1) loop(); |
34 | 50 | } |
35 | 51 |
|
0 commit comments