rtc.c
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include <mc1322x.h>
00037 #include <stdlib.h>
00038 #include "rtc.h"
00039
00040
00041
00042
00043 int rtc_freq = 0;
00044 static int __use_32khz = 0;
00045
00046
00047 void rtc_init_osc(int use_32khz)
00048 {
00049 __use_32khz = use_32khz;
00050
00051 if (use_32khz)
00052 {
00053 uint32_t old;
00054
00055
00056
00057
00058
00059
00060 CRM->RINGOSC_CNTLbits.ROSC_EN = 0;
00061
00062
00063 CRM->XTAL32_CNTLbits.XTAL32_EN = 1;
00064
00065
00066
00067
00068 CRM->SYS_CNTLbits.XTAL32_EXISTS = 1;
00069
00070 old = CRM->RTC_COUNT;
00071 while (CRM->RTC_COUNT == old)
00072 continue;
00073
00074
00075 rtc_freq = 32000;
00076 }
00077 else
00078 {
00079
00080 CRM->RINGOSC_CNTLbits.ROSC_EN = 1;
00081 CRM->XTAL32_CNTLbits.XTAL32_EN = 0;
00082
00083
00084 CRM->RINGOSC_CNTLbits.ROSC_CTUNE = 0x6;
00085 CRM->RINGOSC_CNTLbits.ROSC_FTUNE = 0x17;
00086
00087
00088 rtc_calibrate();
00089 }
00090 }
00091
00092 uint32_t __rtc_try(int loading, int timeout)
00093 {
00094
00095
00096
00097
00098
00099
00100
00101 #define RTC_LOADING_MIN 0
00102 #define RTC_LOADING_MAX 19960
00103
00104
00105
00106
00107 #define CTUNE_MAX 15
00108 #define FTUNE_MAX 31
00109 #define CSTEP 1000
00110 #define FSTEP 160
00111 #define MAX_F (FSTEP*FTUNE_MAX)
00112
00113 int ctune;
00114 int ftune;
00115 int ctune_start = (loading - MAX_F) / CSTEP;
00116 int ctune_end = loading / CSTEP;
00117 int best_err = loading, best_ctune = 0, best_ftune = 0;
00118
00119 uint32_t count;
00120
00121 if (ctune_start < 0) ctune_start = 0;
00122 if (ctune_end > CTUNE_MAX) ctune_end = CTUNE_MAX;
00123
00124 for (ctune = ctune_start; ctune <= ctune_end; ctune++)
00125 {
00126 int this_loading, this_err;
00127
00128 ftune = ((loading - (ctune * CSTEP)) + (FSTEP / 2)) / FSTEP;
00129 if (ftune < 0) ftune = 0;
00130 if (ftune > FTUNE_MAX) ftune = FTUNE_MAX;
00131
00132 this_loading = ctune * CSTEP + ftune * FSTEP;
00133 this_err = abs(this_loading - loading);
00134 if (this_err < best_err) {
00135 best_err = this_err;
00136 best_ctune = ctune;
00137 best_ftune = ftune;
00138 }
00139 }
00140
00141
00142
00143
00144
00145 CRM->RINGOSC_CNTLbits.ROSC_CTUNE = best_ctune;
00146 CRM->RINGOSC_CNTLbits.ROSC_FTUNE = best_ftune;
00147 CRM->CAL_CNTLbits.CAL_TIMEOUT = timeout;
00148 CRM->STATUSbits.CAL_DONE = 1;
00149 CRM->CAL_CNTLbits.CAL_EN = 1;
00150 while (CRM->STATUSbits.CAL_DONE == 0)
00151 continue;
00152
00153
00154 count = CRM->CAL_COUNT;
00155 if (count == 0) count = 1;
00156 return count;
00157 }
00158
00159
00160 void rtc_calibrate(void)
00161 {
00162
00163
00164
00165 int i;
00166 int low = RTC_LOADING_MIN, high = RTC_LOADING_MAX;
00167 int mid;
00168 uint32_t count;
00169
00170 if (__use_32khz) {
00171 rtc_freq = 32000;
00172 return;
00173 }
00174
00175 #define TIMEOUT 100
00176
00177 for (i = 0; i < 9; i++)
00178 {
00179 mid = (low + high) / 2;
00180 count = __rtc_try(mid, TIMEOUT);
00181
00182 rtc_freq = REF_OSC / ((count + TIMEOUT/2) / TIMEOUT);
00183
00184 if (rtc_freq > 2000)
00185 low = mid;
00186 else
00187 high = mid;
00188 }
00189
00190
00191 }
00192
00193
00194
00195 void rtc_delay_ms(uint32_t msec)
00196 {
00197 uint32_t start;
00198
00199 start = CRM->RTC_COUNT;
00200 while ((CRM->RTC_COUNT - start) < ((msec * rtc_freq) / 1000))
00201 continue;
00202 }