calib_32kHz.c

Go to the documentation of this file.
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
00025 #include "calib_values.h"
00026 #include "device_specific.h"
00027 #include <inavr.h>
00028 #include <ioavr.h>
00029 
00031 unsigned char neighborsSearched;
00033 unsigned char calStep;
00035 unsigned char bestCountDiff = 0xFF;
00037 unsigned char bestCountDiff_first;
00039 unsigned char bestOSCCAL;
00041 unsigned char bestOSCCAL_first;
00043 unsigned int countVal;
00045 unsigned int calibration;
00047 signed char sign;
00048 
00049 //Functions used
00050 void CalibrationInit(void);
00051 void CalibrateInternalRc(void);
00052 unsigned int Counter(void);
00053 void BinarySearch(unsigned int ct);
00054 void NeighborSearch(void);
00055 
00064 void main(void){
00065   CalibrationInit();                                            // Initiates calibration
00066   PREPARE_CALIBRATION();                                        // Sets initial stepsize and sets calibration state to "running"
00067   CalibrateInternalRc();                                        // Calibrates to selected frequency
00068 
00069 #ifndef CALIBRATION_METHOD_SIMPLE                               // If simple search method is chosen, there is no need to do two calibrations.
00070 #ifdef TWO_RANGES                                               // For devices with splitted OSCCAL register.
00071   if (bestCountDiff != 0x00)                                    // Do not do a second search if perfect match
00072   {
00073     OSCCAL = DEFAULT_OSCCAL_HIGH;                               // Sets search range to upper part of OSCCAL
00074     NOP();
00075     bestOSCCAL_first = bestOSCCAL;                              // Save OSCCAL value and count difference achieved in first calibration
00076     bestCountDiff_first = bestCountDiff;
00077     PREPARE_CALIBRATION();                                      // Search performed in lower OSCCAL range, perform search in upper OSCCAl range
00078     CalibrateInternalRc();                                      // Perform a second search in upper part of OSCCAL
00079 
00080     if (bestCountDiff > bestCountDiff_first)                    // Check which search gave the best calibration
00081     {
00082       OSCCAL = bestOSCCAL_first;                                // First calibration is more accurate and OSCCAL is written accordingly
00083       NOP();
00084     }
00085   }
00086 #endif
00087 #endif
00088 
00089   for(;;)
00090   {
00091   }
00092 }
00093 
00094 
00101 void CalibrationInit(void){
00102 
00103   COMPUTE_COUNT_VALUE();                                        // Computes countVal for use in the calibration
00104   OSCCAL = DEFAULT_OSCCAL;
00105   NOP();
00106 
00107   SETUP_ASYNC_TIMER();                                          // Asynchronous timer setup
00108 }
00109 
00116 void CalibrateInternalRc(void){
00117   unsigned int count;
00118 
00119 #ifdef CALIBRATION_METHOD_SIMPLE                                // Simple search method
00120   unsigned char cycles = 0x80;
00121 
00122   do{
00123     count = Counter();
00124     if (count > countVal)
00125       OSCCAL--;                                                 // If count is more than count value corresponding to the given frequency:
00126     NOP();                                                      // - decrease speed
00127     if (count < countVal)
00128       OSCCAL++;
00129     NOP();                                                      // If count is less: - increase speed
00130     if (count == countVal)
00131       cycles=1;                 
00132   } while(--cycles);                                            // Calibrate using 128(0x80) calibration cycles
00133 
00134 #else                                                           // Binary search with or without neighbor search
00135   unsigned char countDiff;
00136   unsigned char neighborSearchStatus = FINISHED;
00137 
00138   while(calibration == RUNNING){
00139     count = Counter();                                          // Counter returns the count value after external ticks on XTAL
00140     if (calStep != 0)
00141     {
00142       BinarySearch(count);                                      // Do binary search until stepsize is zero
00143     }
00144     else
00145     {
00146       if(neighborSearchStatus == RUNNING)
00147       {
00148         countDiff = ABS((signed int)count-(signed int)countVal);
00149         if (countDiff < bestCountDiff)                          // Store OSCCAL if higher accuracy is achieved
00150         {
00151           bestCountDiff = countDiff;
00152           bestOSCCAL = OSCCAL;
00153         }
00154         NeighborSearch();                                       // Do neighbor search
00155       }
00156       else                                                      // Prepare and start neighbor search
00157       {
00158 #ifdef CALIBRATION_METHOD_BINARY_WITHOUT_NEIGHBOR               // No neighbor search if deselected
00159         calibration = FINISHED;
00160         countDiff = ABS((signed int)count-(signed int)countVal);
00161         bestCountDiff = countDiff;
00162         bestOSCCAL = OSCCAL;
00163 #else
00164         neighborSearchStatus = RUNNING;                         // Do neighbor search by default
00165         neighborsSearched = 0;
00166         countDiff = ABS((signed int)count-(signed int)countVal);
00167         bestCountDiff = countDiff;
00168         bestOSCCAL = OSCCAL;
00169 #endif
00170       }
00171     }
00172   }
00173 #endif
00174 }
00175 
00182 unsigned int Counter(void){
00183   unsigned int cnt;
00184 
00185   cnt = 0;                                                      // Reset counter
00186   TIMER = 0x00;                                                 // Reset async timer/counter
00187   while (ASSR & ((1<<OUTPUT_COMPARE_UPDATE_BUSY)|(1<<TIMER_UPDATE_BUSY)|(1<<ASYNC_TIMER_CONTROL_UPDATE_BUSY))); // Wait until async timer is updated  (Async Status reg. busy flags).
00188   do{                                                           // cnt++: Increment counter - the add immediate to word (ADIW) takes 2 cycles of code.
00189     cnt++;                                                      // Devices with async TCNT in I/0 space use 1 cycle reading, 2 for devices with async TCNT in extended I/O space
00190   } while (TIMER < EXTERNAL_TICKS);                             // CPI takes 1 cycle, BRCS takes 2 cycles, resulting in: 2+1(or 2)+1+2=6(or 7) CPU cycles
00191   return cnt;                                                   // NB! Different compilers may give different CPU cycles!
00192 }                                                               // Until 32.7KHz (XTAL FREQUENCY) * EXTERNAL TICKS
00193 
00200 void BinarySearch(unsigned int ct){
00201 
00202   if (ct > countVal)                                            // Check if count is larger than desired value
00203   {
00204     sign = -1;                                                  // Saves the direction
00205     OSCCAL -= calStep;                                          // Decrease OSCCAL if count is too high
00206     NOP();
00207   }
00208   else if (ct < countVal)                                       // Opposite procedure for lower value
00209   {
00210     sign = 1;
00211     OSCCAL += calStep;
00212     NOP();
00213   }
00214   else                                                          // Perfect match, OSCCAL stays unchanged
00215   {
00216     calibration = FINISHED;
00217   }
00218   calStep >>= 1;
00219 }
00220 
00228 void NeighborSearch(void){
00229 
00230   neighborsSearched++;
00231   if (neighborsSearched == 4)                                   // Finish if 3 neighbors searched
00232   {
00233     OSCCAL = bestOSCCAL;
00234     calibration = FINISHED;
00235   }
00236   else
00237   {
00238     OSCCAL+=sign;
00239     NOP();
00240   }
00241 }
00242 
00243 

Generated on Fri Feb 17 13:50:24 2006 for AVR055 - Using a 32 kHz crystal to calibrate the internal RC oscillatore by  doxygen 1.4.5