c1bff3210f2f35ced23279f58966c61be4e569ff
[riso-kagaku-clone.git] / libs-device / osccal.c
1 /* Name: osccal.c
2  * Author: Christian Starkjohann
3  * Creation Date: 2008-04-10
4  * Tabsize: 4
5  * Copyright: (c) 2008 by OBJECTIVE DEVELOPMENT Software GmbH
6  * License: GNU GPL v2 (see License.txt), GNU GPL v3 or proprietary (CommercialLicense.txt)
7  */
8
9 #include <avr/io.h>
10
11 #ifndef uchar
12 #define uchar   unsigned char
13 #endif
14
15 /* ------------------------------------------------------------------------- */
16 /* ------------------------ Oscillator Calibration ------------------------- */
17 /* ------------------------------------------------------------------------- */
18
19 /* Calibrate the RC oscillator. Our timing reference is the Start Of Frame
20  * signal (a single SE0 bit) repeating every millisecond immediately after
21  * a USB RESET. We first do a binary search for the OSCCAL value and then
22  * optimize this value with a neighboorhod search.
23  */
24 void    calibrateOscillator(void)
25 {
26 uchar       step = 128;
27 uchar       trialValue = 0, optimumValue;
28 int         x, optimumDev, targetValue = (unsigned)(1499 * (double)F_CPU / 10.5e6 + 0.5);
29
30     /* do a binary search: */
31     do{
32         OSCCAL = trialValue + step;
33         x = usbMeasureFrameLength();    /* proportional to current real frequency */
34         if(x < targetValue)             /* frequency still too low */
35             trialValue += step;
36         step >>= 1;
37     }while(step > 0);
38     /* We have a precision of +/- 1 for optimum OSCCAL here */
39     /* now do a neighborhood search for optimum value */
40     optimumValue = trialValue;
41     optimumDev = x; /* this is certainly far away from optimum */
42     for(OSCCAL = trialValue - 1; OSCCAL <= trialValue + 1; OSCCAL++){
43         x = usbMeasureFrameLength() - targetValue;
44         if(x < 0)
45             x = -x;
46         if(x < optimumDev){
47             optimumDev = x;
48             optimumValue = OSCCAL;
49         }
50     }
51     OSCCAL = optimumValue;
52 }
53 /*
54 Note: This calibration algorithm may try OSCCAL values of up to 192 even if
55 the optimum value is far below 192. It may therefore exceed the allowed clock
56 frequency of the CPU in low voltage designs!
57 You may replace this search algorithm with any other algorithm you like if
58 you have additional constraints such as a maximum CPU clock.
59 For version 5.x RC oscillators (those with a split range of 2x128 steps, e.g.
60 ATTiny25, ATTiny45, ATTiny85), it may be useful to search for the optimum in
61 both regions.
62 */