00001
00046
00047 #include "avr_compiler.h"
00048 #include "clksys_driver.h"
00049 #include "TC_driver.h"
00050 #include "event_system_driver.h"
00051 #include "eeprom_driver.h"
00052
00053
00054 #define SYS_CLOCK (32000000)
00055 #define CAL_REF_CLOCK_FREQ (32768)
00056 #define CAL_REF_NUM (32000000/32768)
00057
00058
00059
00060 #define OSC_Stable_Cycle (4032)
00061
00062 #define JTAG_TDI (PIN5_bm)
00063 #define JTAG_TDO (PIN7_bm)
00064
00065 #define Handshake_Cycle (8)
00066
00067 #define EEPROM_PAGE_ADDR_32M (0x0)
00068 #define EEPROM_BYTE_ADDR_32M_1 (0x0)
00069 #define EEPROM_BYTE_ADDR_32M_2 (0x1)
00070
00071 #define EEPROM_PAGE_ADDR_2M (0x0)
00072 #define EEPROM_BYTE_ADDR_2M_1 (0x2)
00073 #define EEPROM_BYTE_ADDR_2M_2 (0x3)
00074
00075 #define EEPROM_PAGE_ADDR_32k (0x0)
00076 #define EEPROM_BYTE_ADDR_32k (0x4)
00077
00078
00080 typedef enum cal_status_enum {
00081 FREQ_ADJ,
00082 FREQ_MEASURE,
00083 } cal_status_t;
00084
00085
00086
00088 static volatile bool flag = false;
00090 static volatile bool state_change = false;
00092 static volatile bool Calibration_flag = false;
00094 static volatile uint16_t cca = 0;
00096 static uint8_t step_size = 0x80;
00097
00098
00110 static void TC0_ConfigCapture( volatile TC0_t * tc, TC_EVSEL_t eventSource, TC_EVACT_t eventAction );
00112 static void tcc0_init(void);
00114 static void port_init(void);
00115
00116
00117 int main( void )
00118 {
00119
00120 cal_status_t cal_status = FREQ_ADJ;
00121
00122 uint16_t cnt = 0;
00123
00124 uint16_t i;
00125
00126
00127 CCPWrite( &MCU.MCUCR, 1 );
00128
00129 OSC.RC32KCAL = step_size;
00130
00131
00132
00133
00134 CLKSYS_Enable( OSC_RC32MEN_bm | OSC_RC32KEN_bm );
00135 while ( CLKSYS_IsReady( OSC_RC32KEN_bm ) == 0 );
00136 CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc );
00137 while ( CLKSYS_IsReady( OSC_RC32MRDY_bm ) == 0 );
00138 CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_RC32M_gc );
00139
00140
00141 CLKSYS_AutoCalibration_Enable( OSC_RC32MCREF_bm, false );
00142 CLKSYS_AutoCalibration_Enable( OSC_RC2MCREF_bm, false );
00143
00144
00145 tcc0_init();
00146 port_init();
00147
00148 PMIC.CTRL |= PMIC_LOLVLEX_bm;
00149 sei();
00150
00151
00152 while ( !flag ) {
00153 if (state_change == true) {
00154 state_change = false;
00155 if (cal_status == FREQ_ADJ) {
00156 if( cnt > OSC_Stable_Cycle ) {
00157 cnt = 0;
00158 cal_status = FREQ_MEASURE;
00159 } else {
00160 cnt ++;
00161 }
00162 } else {
00163 if (step_size == 1) {
00164 if ((cca > CAL_REF_NUM*0.99) && (cca <CAL_REF_NUM*1.01)) {
00165 flag = true;
00166 Calibration_flag = true;
00167
00168 } else {
00169 Calibration_flag = false;
00170 flag = true;
00171 }
00172 } else {
00173 step_size = step_size / 2;
00174 if (cca > CAL_REF_NUM) {
00175 OSC.RC32KCAL -= step_size;
00176 } else {
00177 OSC.RC32KCAL += step_size;
00178 }
00179 }
00180 cal_status = FREQ_ADJ;
00181 }
00182 }
00183 }
00184
00185
00186
00187
00188 if ( Calibration_flag )
00189 for (i = 0; i < Handshake_Cycle ;i++){
00190 while (PORTB.IN & JTAG_TDI){
00191 }
00192 PORTB.OUTTGL |= JTAG_TDO;
00193 while (!(PORTB.IN & JTAG_TDI)){
00194 }
00195 }
00196 else
00197 for (i = 0; i < Handshake_Cycle ;i++){
00198 while (PORTB.IN & JTAG_TDI){
00199 }
00200 PORTB.OUT &= ~JTAG_TDO;
00201 while (!(PORTB.IN & JTAG_TDI)){
00202 }
00203 }
00204
00205
00206 if ( Calibration_flag ){
00207
00208 EEPROM_DisableMapping();
00209
00210 EEPROM_WriteByte(EEPROM_PAGE_ADDR_32k, EEPROM_BYTE_ADDR_32k, OSC.RC32KCAL);
00211
00212 EEPROM_WriteByte(EEPROM_PAGE_ADDR_32M, EEPROM_BYTE_ADDR_32M_1, DFLLRC32M.CALA);
00213 EEPROM_WriteByte(EEPROM_PAGE_ADDR_32M, EEPROM_BYTE_ADDR_32M_2, DFLLRC32M.CALB);
00214
00215 EEPROM_WriteByte(EEPROM_PAGE_ADDR_2M, EEPROM_BYTE_ADDR_2M_1, DFLLRC2M.CALA);
00216 EEPROM_WriteByte(EEPROM_PAGE_ADDR_2M, EEPROM_BYTE_ADDR_2M_2, DFLLRC2M.CALB);
00217 }
00218
00219
00220
00221 CCPWrite( &MCU.MCUCR, 0 );
00222
00223 while(true){
00224 }
00225 }
00226
00227 static void tcc0_init(void)
00228 {
00229 TC0_ConfigWGM( &TCC0, TC_WGMODE_NORMAL_gc);
00230 TC0_EnableCCChannels( &TCC0, TC0_CCAEN_bm);
00231 TC0_ConfigCapture( &TCC0, TC_EVSEL_CH0_gc, TC_EVACT_FRW_gc);
00232 TC0_SetCCAIntLevel( &TCC0, TC_CCAINTLVL_LO_gc);
00233 TC0_ConfigClockSource( &TCC0, TC_CLKSEL_DIV1_gc);
00234 }
00235
00236 static void port_init(void)
00237 {
00238 PORTB.DIR |= JTAG_TDO;
00239 PORTB.OUT |= JTAG_TDO;
00240 PORTB.PIN7CTRL = (uint8_t) PORT_OPC_PULLUP_gc;
00241 PORTB.PIN5CTRL = (uint8_t) PORT_OPC_PULLUP_gc | PORT_ISC_RISING_gc;
00242 EVSYS_SetEventSource( 0, EVSYS_CHMUX_PORTB_PIN5_gc);
00243 }
00244
00245 static void TC0_ConfigCapture( volatile TC0_t * tc, TC_EVSEL_t eventSource, TC_EVACT_t eventAction )
00246 {
00247 tc->CTRLD = ( tc->CTRLD & ~( TC0_EVSEL_gm | TC0_EVACT_gm ) ) |
00248 eventSource |
00249 eventAction;
00250 }
00251
00252
00257 ISR(TCC0_CCA_vect)
00258 {
00259 cca = TCC0.CCA;
00260 state_change = true;
00261 }