00001
00055
00056 #include "RC_calib_oscsampleif.h"
00057 #include "ATmega8HVA_16HVA_signature.h"
00058 #include <ioavr.h>
00059 #include <inavr.h>
00060
00061
00062 #define SUCCESS 0
00063 #define FAILED -1
00064
00065
00066 uint16_t OSIsampleClockPeriod(uint8_t clock_source);
00067
00068
00081 uint16_t CalculateSlowRCperiod(int16_t temperature)
00082 {
00083 uint16_t slow_RC_period;
00084 int16_t slow_RC_temperature_coeff;
00085 uint16_t calib_temperature;
00086
00087
00088
00089
00090
00091 slow_RC_period = READ_SIGNATUREBYTE(SIG_SLOW_RC_L);
00092
00093
00094 __delay_cycles(2);
00095
00096 slow_RC_period |= READ_SIGNATUREBYTE(SIG_SLOW_RC_H) << 8;
00097
00098
00099 __delay_cycles(2);
00100
00101 slow_RC_temperature_coeff = READ_SIGNATUREBYTE(SIG_SLOW_RC_PRED_L);
00102
00103
00104 __delay_cycles(2);
00105
00106 slow_RC_temperature_coeff |= READ_SIGNATUREBYTE(SIG_SLOW_RC_PRED_H) << 8;
00107
00108
00109 __delay_cycles(2);
00110
00111 calib_temperature = READ_SIGNATUREBYTE(SIG_TEMPERATURE_HOT) + ZERO_C_IN_KELVIN;
00112
00113 return (uint16_t)(slow_RC_period - ((temperature - calib_temperature)*slow_RC_temperature_coeff)/64);
00114 }
00115
00116
00117
00143 int8_t CalibrateFastRCruntime(uint16_t cal_RC_period)
00144 {
00145 uint16_t target_period;
00146 int16_t error;
00147 int16_t last_error;
00148 uint8_t fosccal_saved;
00149
00150
00151
00152
00153
00154 uint8_t fosccal_default = READ_SIGNATUREBYTE(SIG_FOSCCAL_DEFAULT);
00155
00156
00157 __delay_cycles(2);
00158
00159 uint8_t fosccal_segment = READ_SIGNATUREBYTE(SIG_FOSC_SEGMENT);
00160
00161 uint8_t bottom_limit = fosccal_segment & 0xE0;
00162 uint8_t top_limit = (fosccal_default & 0xE0) + 0x1F;
00163
00164
00165 target_period = cal_RC_period * FAST_RC_TARGET_MHZ;
00166
00167
00168 uint8_t check_value;
00169 error = OSIsampleClockPeriod(SLOW_RC) - target_period;
00170
00171 if(error > 0){
00172
00173 check_value = bottom_limit + 0x1F;
00174 do {
00175 last_error = error;
00176 fosccal_saved = FOSCCAL;
00177 if ( FOSCCAL-- == check_value ){
00178
00179 FOSCCAL = fosccal_segment;
00180 } else if (FOSCCAL < bottom_limit){
00181
00182 FOSCCAL = fosccal_default;
00183 return FAILED;
00184 }
00185 error = OSIsampleClockPeriod(SLOW_RC) - target_period;
00186 } while (error > 0);
00187 }else{
00188
00189 check_value = fosccal_segment + 0x01;
00190 do {
00191 last_error = error;
00192 fosccal_saved = FOSCCAL;
00193 if ( FOSCCAL++ == check_value ){
00194
00195 FOSCCAL = fosccal_default & 0xE0;
00196 } else if ( FOSCCAL > top_limit ){
00197
00198 FOSCCAL = fosccal_default;
00199 return FAILED;
00200 }
00201 error = OSIsampleClockPeriod(SLOW_RC) - target_period;
00202 }while ( error < 0 );
00203 }
00204
00205
00206
00207
00208
00209 if(error < 0){
00210
00211 if (last_error < -error){
00212 FOSCCAL = fosccal_saved;
00213 }
00214 }else{
00215
00216 if (-last_error < error){
00217 FOSCCAL = fosccal_saved;
00218 }
00219 }
00220
00221 return SUCCESS;
00222 }
00223
00224
00225
00236 uint16_t MeasureULPRCperiod(uint16_t cal_RC_period)
00237 {
00238 uint16_t slow_RC_measurement, ULP_RC_measurement;
00239 uint32_t result;
00240
00241 slow_RC_measurement = OSIsampleClockPeriod(SLOW_RC);
00242 ULP_RC_measurement = OSIsampleClockPeriod(ULP_RC);
00243
00244 result = (uint32_t)cal_RC_period * ULP_RC_measurement / slow_RC_measurement;
00245 return (uint16_t)result;
00246 }
00247
00248
00262 uint16_t OSIsampleClockPeriod(uint8_t clock_source)
00263 {
00264 uint16_t initial_capture, final_capture, result;
00265
00266
00267 OSICSR = clock_source | (1 << OSIEN);
00268
00269
00270 TCCR0A = (1 << TCW0) | (1 << ICEN0) | (0 << ICS0);
00271
00272
00273 TCCR0B = T0_PRESCALER;
00274
00275
00276 TIFR0 |= (1 << ICF0);
00277
00278
00279 do {} while(!(TIFR0 & (1 << ICF0)));
00280 initial_capture = OCR0A;
00281 initial_capture |= OCR0B << 8;
00282
00283
00284 TIFR0 |= (1 << ICF0);
00285
00286 for(uint8_t i = 0 ; i < RC_CALIB_CYCLES ; i++) {
00287
00288 do {} while(!(TIFR0 & (1 << ICF0)));
00289 TIFR0 |= (1 << ICF0);
00290 }
00291 final_capture = OCR0A;
00292 final_capture |= OCR0B << 8;
00293
00294
00295 result = final_capture - initial_capture;
00296
00297 return result;
00298 }
00299
00300
00301