1 // Author: Mike Blandford
3 #include "oXs_general.h"
9 uint16_t MillisPrecount
;
10 uint16_t lastTimerValue
;
11 uint32_t TotalMicros
;
12 uint32_t TotalMillis
;
16 uint32_t lastEventTime
;
22 ISR( TIMER1_CAPT_vect
, ISR_NOBLOCK
)
28 if ( ++RpmCounter
> 3 )
30 uint8_t oReg
= SREG
; // save status register
32 uint16_t time
= ICR1
; // Read capture register on timer 1
33 SREG
= oReg
; // restore status register
34 elapsed
= time
- lastTimerValue
;
35 #if F_CPU == 20000000L // 20MHz clock
36 #error Unsupported clock speed
37 #elif F_CPU == 16000000L // 16MHz clock
38 eventTime
= TotalMicros
+ ( elapsed
>> 4 ) ;
39 #elif F_CPU == 8000000L // 8MHz clock
40 eventTime
= TotalMicros
+ ( elapsed
>> 3 ) ;
42 #error Unsupported clock speed
46 difference
= eventTime
- lastEventTime
;
47 lastEventTime
= eventTime
;
48 if ( difference
> 200 ) {
49 RpmValue
= 4000000 / difference
;
63 uint8_t oldSREG
= SREG
;
65 uint16_t time
= TCNT1
; // Read timer 1
68 elapsed
= time
- lastTimerValue
;
69 elapsed
+= Correction
;
72 #if F_CPU == 20000000L // 20MHz clock
73 #error Unsupported clock speed
74 #elif F_CPU == 16000000L // 16MHz clock
75 Correction
= elapsed
& 0x0F ;
77 #elif F_CPU == 8000000L // 8MHz clock
78 Correction
= elapsed
& 0x07 ;
81 #error Unsupported clock speed
86 uint32_t ltime
= TotalMicros
;
89 TotalMicros
= ltime
; // Done this way for RPM to work correctly
90 lastTimerValue
= time
;
91 SREG
= oldSREG
; // Still valid from above
93 elapsed
+= MillisPrecount
;
100 else if ( elapsed
> 2999 )
105 else if ( elapsed
> 1999 )
110 else if ( elapsed
> 999 )
115 TotalMillis
+= millisToAdd
;
116 MillisPrecount
= elapsed
;
120 // retrun the number of milli second
131 TIMSK1
&= ~( 1<< OCIE1A
) ; // Disable interupt on timer 1 for compA
132 TCCR1A
= 0x00 ; //Init.
133 TCCR1B
= 0xC1 ; // I/p noise cancel, rising edge, Clock/1 (so running at same speed as CPU)
135 // initialise le ADC converter
137 // set a2d prescale factor to 128
138 // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.
139 // XXX: this will not work properly for other clock speeds, and
140 // this code should use F_CPU to determine the prescale factor.
141 //sbi(ADCSRA, ADPS2);
142 //sbi(ADCSRA, ADPS1);
143 //sbi(ADCSRA, ADPS0);
144 #if ( F_CPU == 20000000L ) || ( F_CPU == 16000000L ) // 20 MHz or 16 MHz clock
145 // set a2d prescale factor to 128
146 // 20 MHz / 128 = 156.25 KHz
147 // 16 MHz / 128 = 125 KHz, inside the desired 50-200 KHz range.
148 // XXX: this will not work properly for other clock speeds, and
149 // this code should use F_CPU to determine the prescale factor.
153 #elif F_CPU == 8000000L // 8MHz clock
154 // set a2d prescale factor to 64
155 // 8 MHz / 64 = 125 KHz, inside the desired 50-200 KHz range.
160 #error Unsupported clock speed
166 // enable a2d conversions
170 // the bootloader connects pins 0 and 1 to the USART; disconnect them
171 // here so they can be used as normal digital i/o; they will be
172 // reconnected in Serial.begin()
175 #elif defined(UCSR0B)
180 DDRB
&= ~0x01 ; // Pin PB0 is input in order to allow PCINT0
181 PORTB
|= 1 ; // With pullup
182 sbi( TIMSK1
, ICIE1
) ; // allow change interrupt
183 #endif // MEASURE_RPM
186 sei(); //allow interrupt in general
188 // timer2 (used by analoWrite to generate PWM
189 // set timer 2 prescale factor to 64
190 #if defined(TCCR2) && defined(CS22)
192 #elif defined(TCCR2B) && defined(CS22)
195 #warning Timer 2 not finished (may not be present on this CPU)
198 // configure timer 2 for phase correct pwm (8-bit)
199 #if defined(TCCR2) && defined(WGM20)
201 #elif defined(TCCR2A) && defined(WGM20)
204 #warning Timer 2 not finished (may not be present on this CPU)
210 void delay(unsigned long ms
)
212 uint16_t start
= (uint16_t)micros();
216 if (((uint16_t)micros() - start
) >= 1000) {
223 // Delay for the given number of microseconds. Assumes a 8 or 16 MHz clock.
224 void delayMicroseconds(unsigned int us
)
226 // calling avrlib's delay_us() function with low values (e.g. 1 or
227 // 2 microseconds) gives delays longer than desired.
229 #if F_CPU >= 20000000L
230 // for the 20 MHz clock on rare Arduino boards
232 // for a one-microsecond delay, simply wait 2 cycle and return. The overhead
233 // of the function call yields a delay of exactly a one microsecond.
234 __asm__
__volatile__ (
236 "nop"); //just waiting 2 cycle
240 // the following loop takes a 1/5 of a microsecond (4 cycles)
241 // per iteration, so execute it five times for each microsecond of
243 us
= (us
<<2) + us
; // x5 us
245 // account for the time taken in the preceeding commands.
248 #elif F_CPU >= 16000000L
249 // for the 16 MHz clock on most Arduino boards
251 // for a one-microsecond delay, simply return. the overhead
252 // of the function call yields a delay of approximately 1 1/8 us.
256 // the following loop takes a quarter of a microsecond (4 cycles)
257 // per iteration, so execute it four times for each microsecond of
261 // account for the time taken in the preceeding commands.
264 // for the 8 MHz internal clock on the ATmega168
266 // for a one- or two-microsecond delay, simply return. the overhead of
267 // the function calls takes more than two microseconds. can't just
268 // subtract two, since us is unsigned; we'd overflow.
274 // the following loop takes half of a microsecond (4 cycles)
275 // per iteration, so execute it twice for each microsecond of
279 // partially compensate for the time taken by the preceeding commands.
280 // we can't subtract any more than this or we'd overflow w/ small delays.
285 __asm__
__volatile__ (
286 "1: sbiw %0,1" "\n\t" // 2 cycles
287 "brne 1b" : "=w" (us
) : "0" (us
) // 2 cycles
292 //#define delay_us(x) {unsigned char _dcnt; _dcnt = (x)/(24000000UL/FOSC)|1; while(--_dcnt !=0) continue;// }
295 //******************* toggle led every blinkDelay X 100 msec ; used in order to debug without using DEBUG option (which uses uart)
297 #define PIN_LED 13 // The Signal LED (default=13=onboard LED)
298 void blinkLed(uint8_t blinkDelay
) {
299 // static int16_t blinkDelay = 300 ;
300 static unsigned long nextMillisBlink
;
301 if (millis() > nextMillisBlink
) {
302 if ( digitalRead( PIN_LED
) ) {
303 digitalWrite( PIN_LED
, LOW
) ;
305 digitalWrite( PIN_LED
, HIGH
) ;
307 nextMillisBlink
+= (unsigned long) blinkDelay
* 100 ;