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
1.4.5