Skip to content

Commit d3ba34d

Browse files
Canocmaglie
Cano
authored andcommitted
delayMicroseconds(): added support for 1Mhz, 12Mhz and 24Mhz
1Mhz is a default clock speed on Atmega328, many users run it on the internal 1Mhz clock to save battery power. Up until now delayMicroseconds() function wasn't taking this frequencies into an account.
1 parent b40f171 commit d3ba34d

File tree

1 file changed

+68
-10
lines changed

1 file changed

+68
-10
lines changed

cores/arduino/wiring.c

+68-10
Original file line numberDiff line numberDiff line change
@@ -119,17 +119,41 @@ void delay(unsigned long ms)
119119
}
120120
}
121121

122-
/* Delay for the given number of microseconds. Assumes a 8 or 16 MHz clock. */
122+
/* Delay for the given number of microseconds. Assumes a 1, 8, 12, 16, 20 or 24 MHz clock. */
123123
void delayMicroseconds(unsigned int us)
124124
{
125+
// call = 4 cycles + 2 to 4 cycles to init us(2 for constant delay, 4 for variable)
125126
// calling avrlib's delay_us() function with low values (e.g. 1 or
126127
// 2 microseconds) gives delays longer than desired.
127128
//delay_us(us);
128-
#if F_CPU >= 20000000L
129+
#if F_CPU >= 24000000L
130+
// for the 24 MHz clock for the aventurous ones, trying to overclock
131+
132+
// for a one-microsecond delay, simply wait 6 cycles and return. The overhead
133+
// of the function call yields a delay of exactly one microsecond.
134+
__asm__ __volatile__ (
135+
"nop" "\n\t"
136+
"nop" "\n\t"
137+
"nop" "\n\t"
138+
"nop" "\n\t"
139+
"nop" "\n\t"
140+
"nop"); //just waiting 6 cycles
141+
if (--us == 0)
142+
return;
143+
144+
// the following loop takes a 1/6 of a microsecond (4 cycles)
145+
// per iteration, so execute it six times for each microsecond of
146+
// delay requested.
147+
us *= 6; // x6 us
148+
149+
// account for the time taken in the preceeding commands.
150+
us -= 2;
151+
152+
#elif F_CPU >= 20000000L
129153
// for the 20 MHz clock on rare Arduino boards
130154

131-
// for a one-microsecond delay, simply wait 2 cycle and return. The overhead
132-
// of the function call yields a delay of exactly a one microsecond.
155+
// for a one-microsecond delay, simply wait 2 cycles and return. The overhead
156+
// of the function call yields a delay of exactly one microsecond.
133157
__asm__ __volatile__ (
134158
"nop" "\n\t"
135159
"nop"); //just waiting 2 cycle
@@ -152,15 +176,31 @@ void delayMicroseconds(unsigned int us)
152176
if (--us == 0)
153177
return;
154178

155-
// the following loop takes a quarter of a microsecond (4 cycles)
179+
// the following loop takes 1/4 of a microsecond (4 cycles)
156180
// per iteration, so execute it four times for each microsecond of
157181
// delay requested.
158-
us <<= 2;
182+
us <<= 2; // x4 us
159183

160184
// account for the time taken in the preceeding commands.
161185
us -= 2;
162-
#else
163-
// for the 8 MHz internal clock on the ATmega168
186+
187+
#elif F_CPU >= 12000000L
188+
// for the 12 MHz clock if somebody is working with USB
189+
190+
// for a one-microsecond delay, simply return. the overhead
191+
// of the function call yields a delay of approximately 1.5 us.
192+
if (--us == 0)
193+
return;
194+
195+
// the following loop takes 1/3 of a microsecond (4 cycles)
196+
// per iteration, so execute it three times for each microsecond of
197+
// delay requested.
198+
us = (us << 1) + us; // x3 us
199+
200+
// account for the time taken in the preceeding commands.
201+
us -= 2;
202+
#elif F_CPU >= 8000000L
203+
// for the 8 MHz internal clock
164204

165205
// for a one- or two-microsecond delay, simply return. the overhead of
166206
// the function calls takes more than two microseconds. can't just
@@ -170,21 +210,39 @@ void delayMicroseconds(unsigned int us)
170210
if (--us == 0)
171211
return;
172212

173-
// the following loop takes half of a microsecond (4 cycles)
213+
// the following loop takes 1/2 of a microsecond (4 cycles)
174214
// per iteration, so execute it twice for each microsecond of
175215
// delay requested.
176-
us <<= 1;
216+
us <<= 1; //x2 us
177217

178218
// partially compensate for the time taken by the preceeding commands.
179219
// we can't subtract any more than this or we'd overflow w/ small delays.
180220
us--;
221+
222+
#else
223+
// for the 1 MHz internal clock (default settings for common Atmega microcontrollers)
224+
225+
// the overhead of the function calls takes about 16 microseconds.
226+
if (us <= 16) //4 cycles spent here
227+
return;
228+
if (us <= 22) { //4 cycles spent here
229+
return;
230+
}
231+
232+
// compensate for the time taken by the preceeding and next commands.
233+
us -= 22;
234+
235+
// the following loop takes 4 microseconds (4 cycles)
236+
// per iteration, so execute it us/4 times
237+
us >>= 2; // us div 4
181238
#endif
182239

183240
// busy wait
184241
__asm__ __volatile__ (
185242
"1: sbiw %0,1" "\n\t" // 2 cycles
186243
"brne 1b" : "=w" (us) : "0" (us) // 2 cycles
187244
);
245+
// return = 4 cycles
188246
}
189247

190248
void init()

0 commit comments

Comments
 (0)