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