add Rf link quality checks
[openXsensor.git] / openXsensor / oXs_general.cpp
blobff42061f7c7af5b3ba495fc09cf244afd1ca5dd4
1 // Author: Mike Blandford
3 #include "oXs_general.h"
5 #ifdef DEBUG
6 //#define xxxxxxxxxx
7 #endif
9 uint16_t MillisPrecount ;
10 uint16_t lastTimerValue ;
11 uint32_t TotalMicros ;
12 uint32_t TotalMillis ;
13 uint8_t Correction ;
16 uint32_t lastEventTime ;
17 uint8_t RpmCounter ;
20 // RPM code
21 #ifdef MEASURE_RPM
22 ISR( TIMER1_CAPT_vect, ISR_NOBLOCK )
24 uint16_t elapsed ;
25 uint32_t eventTime ;
26 uint32_t difference ;
28 if ( ++RpmCounter > 3 )
30 uint8_t oReg = SREG ; // save status register
31 cli() ;
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 ) ;
41 #else
42 #error Unsupported clock speed
43 #endif
45 RpmCounter = 0 ;
46 difference = eventTime - lastEventTime ;
47 lastEventTime = eventTime ;
48 if ( difference > 200 ) {
49 RpmValue = 4000000 / difference ;
50 } else {
51 RpmValue = 0 ;
53 RpmSet = true ;
57 #endif // MEASURE_RPM
59 uint32_t micros()
61 uint16_t elapsed ;
62 uint8_t millisToAdd ;
63 uint8_t oldSREG = SREG ;
64 cli() ;
65 uint16_t time = TCNT1 ; // Read timer 1
66 SREG = oldSREG ;
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 ;
76 elapsed >>= 4 ;
77 #elif F_CPU == 8000000L // 8MHz clock
78 Correction = elapsed & 0x07 ;
79 elapsed >>= 3 ;
80 #else
81 #error Unsupported clock speed
82 #endif
84 //elapsed >>= 4 ;
86 uint32_t ltime = TotalMicros ;
87 ltime += elapsed ;
88 cli() ;
89 TotalMicros = ltime ; // Done this way for RPM to work correctly
90 lastTimerValue = time ;
91 SREG = oldSREG ; // Still valid from above
93 elapsed += MillisPrecount;
94 millisToAdd = 0 ;
95 if ( elapsed > 3999 )
97 millisToAdd = 4 ;
98 elapsed -= 4000 ;
100 else if ( elapsed > 2999 )
102 millisToAdd = 3 ;
103 elapsed -= 3000 ;
105 else if ( elapsed > 1999 )
107 millisToAdd = 2 ;
108 elapsed -= 2000 ;
110 else if ( elapsed > 999 )
112 millisToAdd = 1 ;
113 elapsed -= 1000 ;
115 TotalMillis += millisToAdd ;
116 MillisPrecount = elapsed ;
117 return TotalMicros ;
120 // retrun the number of milli second
121 uint32_t millis()
123 micros() ;
124 return TotalMillis ;
128 void init()
130 // Timer1
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
136 #if defined(ADCSRA)
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.
150 sbi(ADCSRA, ADPS2);
151 sbi(ADCSRA, ADPS1);
152 sbi(ADCSRA, ADPS0);
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.
156 sbi(ADCSRA, ADPS2);
157 sbi(ADCSRA, ADPS1);
158 cbi(ADCSRA, ADPS0);
159 #else
160 #error Unsupported clock speed
161 #endif
166 // enable a2d conversions
167 sbi(ADCSRA, ADEN);
168 #endif
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()
173 #if defined(UCSRB)
174 UCSRB = 0;
175 #elif defined(UCSR0B)
176 UCSR0B = 0;
177 #endif
179 #ifdef MEASURE_RPM
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)
191 sbi(TCCR2, CS22);
192 #elif defined(TCCR2B) && defined(CS22)
193 sbi(TCCR2B, CS22);
194 #else
195 #warning Timer 2 not finished (may not be present on this CPU)
196 #endif
198 // configure timer 2 for phase correct pwm (8-bit)
199 #if defined(TCCR2) && defined(WGM20)
200 sbi(TCCR2, WGM20);
201 #elif defined(TCCR2A) && defined(WGM20)
202 sbi(TCCR2A, WGM20);
203 #else
204 #warning Timer 2 not finished (may not be present on this CPU)
205 #endif
210 void delay(unsigned long ms)
212 uint16_t start = (uint16_t)micros();
213 uint16_t lms = ms ;
215 while (lms > 0) {
216 if (((uint16_t)micros() - start) >= 1000) {
217 lms--;
218 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.
228 // delay_us(us);
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__ (
235 "nop" "\n\t"
236 "nop"); //just waiting 2 cycle
237 if (--us == 0)
238 return;
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
242 // delay requested.
243 us = (us<<2) + us; // x5 us
245 // account for the time taken in the preceeding commands.
246 us -= 2;
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.
253 if (--us == 0)
254 return;
256 // the following loop takes a quarter of a microsecond (4 cycles)
257 // per iteration, so execute it four times for each microsecond of
258 // delay requested.
259 us <<= 2;
261 // account for the time taken in the preceeding commands.
262 us -= 2;
263 #else
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.
269 if (--us == 0)
270 return;
271 if (--us == 0)
272 return;
274 // the following loop takes half of a microsecond (4 cycles)
275 // per iteration, so execute it twice for each microsecond of
276 // delay requested.
277 us <<= 1;
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.
281 us--;
282 #endif
284 // busy wait
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)
296 #ifdef DEBUG_BLINK
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 ) ;
304 } else {
305 digitalWrite( PIN_LED , HIGH ) ;
307 nextMillisBlink += (unsigned long) blinkDelay * 100 ;
310 #endif