EDF - OnePIC MCU
v1.1.0
|
00001 /***************************************************************************** 00002 * 00003 * Real Time Clock Calender 00004 * 00005 ***************************************************************************** 00006 * 00007 * Author Date Comment 00008 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 00009 * Chris Valenti 05-26-05 ... 00010 * Ross Fosler 06-06-2005 Several changes 00011 * Anton Alkhimenok 10-21-2005 Get/Set functions 00012 * Anton Alkhimenok 02-07-2008 PIC32 support 00013 *****************************************************************************/ 00036 #include "OnePIC_rtcc.h" 00037 #include "Compiler.h" 00038 #include "OnePIC_i2c.h" 00039 #include <string.h> 00040 00041 /* 00042 * @brief These structures contain the time and date. 00043 * RTCCProcessEvents updates them. _time_chk is used as input/output for 00044 * get/set operations. 00045 */ 00046 00047 00048 RTCC _time; 00049 RTCC _time_chk; 00050 RTCC _pwr_off; 00051 RTCC _pwr_on; 00053 unsigned char temp[10]; 00054 /***************************************************************************** 00055 * RTCCProcessEvents updates these. 00056 *****************************************************************************/ 00057 char _day_time_str[16] = " "; 00058 char _date_str[16] = " "; 00059 // XXX 10/4/2011 8:39:40 AM: Changed original _time_str to _day_time_str 00060 char _time_str[9] = " "; 00061 // . 00062 unsigned char _rtcc_flag; 00063 unsigned char rtccBuf[32]; 00064 unsigned char rtccWriteBuf[10]; 00070 struct trb rtcStart = { 00071 0x6f, // Addr 00072 5, // 5 write bytes 00073 0, // 0 bytes to read 00074 (unsigned char*) "\000\200\000\000\010", // Set the Start bit 00075 rtccBuf, 00076 0, // no retries 00077 0, // status is 0 00078 (void *) 0 // no next pointer 00079 }; 00080 00085 struct trb rtcClearVbat = { 00086 0x6f, // Addr 00087 2, // 2 write bytes 00088 0, // 0 bytes to read 00089 (unsigned char*) "\003\011", // Clear Vbat bit 00090 rtccBuf, 00091 0, // no retries 00092 0, // status is 0 00093 (void *) 0 // no next pointer 00094 }; 00095 00100 struct trb rtcRead = { 00101 0x6f, // Addr 00102 1, // 1 write byte 00103 0x20, // 0x20 bytes to read 00104 rtccWriteBuf, // Register address 00105 rtccBuf, 00106 0, // no retries 00107 0, // status is 0 00108 (void *) 0 // no next pointer 00109 }; 00110 00115 struct trb rtcWrite = { 00116 0x6f, // Addr 00117 1, // 1 write byte 00118 0, // bytes to read 00119 rtccWriteBuf, 00120 rtccBuf, 00121 0, // no retries 00122 0, // status is 0 00123 (void *) 0 // no next pointer 00124 }; 00125 00130 struct trb rtcSaveInRAM = { 00131 0x6f, // Addr 00132 4, // 4 write byte 00133 0, // bytes to read 00134 rtccWriteBuf, 00135 rtccBuf, 00136 0, // no retries 00137 0, // status is 0 00138 (void *) 0 // no next pointer 00139 }; 00140 00141 00147 void RTCCReadTime(RTCC *t) { 00148 static unsigned char prevSec = 0; 00149 rtccWriteBuf[0] = 0; // register address 00150 rtcRead.rxBuf = (unsigned char *) t; 00151 rtcRead.rxLen = sizeof (*t); 00152 trbEnQ(&bus1, &rtcRead); 00153 while ((rtcRead.status & 0x80) == 0) // wait until done 00154 ; 00155 if (t->sec != prevSec) { 00156 prevSec = t->sec; 00157 rtccWriteBuf[0] = 0x22; 00158 rtccWriteBuf[1] = ((unsigned char *) t)[0]; 00159 rtccWriteBuf[2] = ((unsigned char *) t)[1]; 00160 rtccWriteBuf[3] = ((unsigned char *) t)[2]; 00161 trbEnQ(&bus1, &rtcSaveInRAM); 00162 while ((rtcSaveInRAM.status & 0x80) == 0) // wait until done 00163 ; 00164 } 00165 } 00166 00171 void RTCCReadOffTime(RTCC *t) { 00172 // Unused warning: static unsigned char prevSec=0; 00173 rtccWriteBuf[0] = 0x22; // register address 00174 rtcRead.rxBuf = (unsigned char *) t; 00175 rtcRead.rxLen = sizeof (*t); 00176 trbEnQ(&bus1, &rtcRead); 00177 while ((rtcRead.status & 0x80) == 0) // wait until done 00178 ; 00179 } 00180 00181 00188 void RTCCWriteTime(RTCC *t) { 00189 rtccWriteBuf[0] = 0; // register address 00190 memcpy(rtccWriteBuf + 1, t, sizeof (*t)); 00191 rtcWrite.txLen = sizeof (*t) + 1; 00192 trbEnQ(&bus1, &rtcWrite); 00193 while ((rtcWrite.status & 0x80) == 0) // wait until done 00194 ; 00195 } 00196 00208 void RTCCProcessEvents(void) { 00209 00210 00211 // Process time object only if time is not being set 00212 while (!_rtcc_flag) { 00213 // Grab the time 00214 RTCCReadTime(&_time); 00215 00216 // Grab the time again 00217 RTCCReadTime(&_time_chk); 00218 00219 // Verify there is no roll-over 00220 if (!memcmp(&_time, &_time_chk, sizeof (_time))) { 00221 switch (_time.mth) { 00222 default: 00223 00224 case 0x01: 00225 _date_str[0] = 'J'; 00226 _date_str[1] = 'a'; 00227 _date_str[2] = 'n'; 00228 break; 00229 00230 case 0x02: 00231 _date_str[0] = 'F'; 00232 _date_str[1] = 'e'; 00233 _date_str[2] = 'b'; 00234 break; 00235 00236 case 0x03: 00237 _date_str[0] = 'M'; 00238 _date_str[1] = 'a'; 00239 _date_str[2] = 'r'; 00240 break; 00241 00242 case 0x04: 00243 _date_str[0] = 'A'; 00244 _date_str[1] = 'p'; 00245 _date_str[2] = 'r'; 00246 break; 00247 00248 case 0x05: 00249 _date_str[0] = 'M'; 00250 _date_str[1] = 'a'; 00251 _date_str[2] = 'y'; 00252 break; 00253 00254 case 0x06: 00255 _date_str[0] = 'J'; 00256 _date_str[1] = 'u'; 00257 _date_str[2] = 'n'; 00258 break; 00259 00260 case 0x07: 00261 _date_str[0] = 'J'; 00262 _date_str[1] = 'u'; 00263 _date_str[2] = 'l'; 00264 break; 00265 00266 case 0x08: 00267 _date_str[0] = 'A'; 00268 _date_str[1] = 'u'; 00269 _date_str[2] = 'g'; 00270 break; 00271 00272 case 0x09: 00273 _date_str[0] = 'S'; 00274 _date_str[1] = 'e'; 00275 _date_str[2] = 'p'; 00276 break; 00277 00278 case 0x10: 00279 _date_str[0] = 'O'; 00280 _date_str[1] = 'c'; 00281 _date_str[2] = 't'; 00282 break; 00283 00284 case 0x11: 00285 _date_str[0] = 'N'; 00286 _date_str[1] = 'o'; 00287 _date_str[2] = 'v'; 00288 break; 00289 00290 case 0x12: 00291 _date_str[0] = 'D'; 00292 _date_str[1] = 'e'; 00293 _date_str[2] = 'c'; 00294 break; 00295 } 00296 00297 _date_str[3] = ' '; 00298 _date_str[6] = ','; 00299 _date_str[7] = ' '; 00300 _date_str[8] = '2'; 00301 _date_str[9] = '0'; 00302 00303 _date_str[4] = (_time.day >> 4) + '0'; 00304 _date_str[5] = (_time.day & 0xF) + '0'; 00305 00306 _date_str[10] = (_time.yr >> 4) + '0'; 00307 _date_str[11] = (_time.yr & 0xF) + '0'; 00308 00309 switch (_time.wkd) { 00310 default: 00311 00312 case 0x00: 00313 _day_time_str[0] = 'S'; 00314 _day_time_str[1] = 'u'; 00315 _day_time_str[2] = 'n'; 00316 break; 00317 00318 case 0x01: 00319 _day_time_str[0] = 'M'; 00320 _day_time_str[1] = 'o'; 00321 _day_time_str[2] = 'n'; 00322 break; 00323 00324 case 0x02: 00325 _day_time_str[0] = 'T'; 00326 _day_time_str[1] = 'u'; 00327 _day_time_str[2] = 'e'; 00328 break; 00329 00330 case 0x03: 00331 _day_time_str[0] = 'W'; 00332 _day_time_str[1] = 'e'; 00333 _day_time_str[2] = 'd'; 00334 break; 00335 00336 case 0x04: 00337 _day_time_str[0] = 'T'; 00338 _day_time_str[1] = 'h'; 00339 _day_time_str[2] = 'u'; 00340 break; 00341 00342 case 0x05: 00343 _day_time_str[0] = 'F'; 00344 _day_time_str[1] = 'r'; 00345 _day_time_str[2] = 'i'; 00346 break; 00347 00348 case 0x06: 00349 _day_time_str[0] = 'S'; 00350 _day_time_str[1] = 'a'; 00351 _day_time_str[2] = 't'; 00352 break; 00353 } 00354 00355 _day_time_str[3] = ' '; 00356 _day_time_str[6] = ':'; 00357 _day_time_str[9] = ':'; 00358 00359 _day_time_str[4] = (_time.hr >> 4) + '0'; 00360 _day_time_str[5] = (_time.hr & 0xF) + '0'; 00361 00362 _day_time_str[7] = (_time.min >> 4) + '0'; 00363 _day_time_str[8] = (_time.min & 0xF) + '0'; 00364 00365 _day_time_str[10] = (_time.sec >> 4) + '0'; 00366 _day_time_str[11] = (_time.sec & 0xF) + '0'; 00367 00368 _time_str[0] = _day_time_str[4]; 00369 _time_str[1] = _day_time_str[5]; 00370 _time_str[2] = _day_time_str[6]; 00371 _time_str[3] = _day_time_str[7]; 00372 _time_str[4] = _day_time_str[8]; 00373 _time_str[5] = _day_time_str[9]; 00374 _time_str[6] = _day_time_str[10]; 00375 _time_str[7] = _day_time_str[11]; 00376 _time_str[8] = '\0'; 00377 00378 00379 break; 00380 } 00381 } 00382 } 00383 00384 00389 void RTCCInit(void) { 00390 00391 RTCCReadOffTime(&_pwr_off); 00392 RTCCReadTime(&_pwr_on); 00393 RTCCReadTime(&_time); 00394 _time.vbatEn = 0; 00395 if (_time.start == 0 || _time.vbatEn == 0) { 00396 _time.start = 0; // Stop Oscillator 00397 RTCCWriteTime(&_time); 00398 00399 // EXTOSC ON 00400 /* rtccWriteBuf[0] = 0x07; // register address 00401 rtccWriteBuf[1] = 0x4B; 00402 rtcWrite.txLen = 2; 00403 trbEnQ(&bus1, &rtcWrite); 00404 while ((rtcWrite.status & 0x80) == 0) // wait until done 00405 */ 00406 _time.time12 = 0; 00407 _time.start = 1; 00408 _time.vbatEn = 1; 00409 _time.sec = 0x00; 00410 _time.min = 0x00; 00411 _time.hr = 0x12; 00412 _time.wkd = 3; 00413 _time.day = 0x14; 00414 _time.mth = 0x09; 00415 _time.yr = 0x11; 00416 RTCCWriteTime(&_time); 00417 00418 rtccWriteBuf[0] = 0x07; // register address 00419 rtcRead.rxBuf = temp; 00420 rtcRead.rxLen = 1; 00421 trbEnQ(&bus1, &rtcRead); 00422 while ((rtcRead.status & 0x80) == 0) // wait until done 00423 ; 00424 } 00425 } 00426 00430 void RTCCClear() { 00431 _time.start = 0; // Stop Oscillator 00432 RTCCWriteTime(&_time); 00433 RTCCInit(); 00434 } 00435 00441 void RTCCSet(void) { 00442 // Set the time 00443 RTCCWriteTime(&_time_chk); 00444 _rtcc_flag = 0; // Release the lock on the time 00445 } 00446 00447 00451 void RTCCUnlock(void) { 00452 #ifdef __PIC32MX__ 00453 SYSKEY = 0xaa996655; // write first unlock key to SYSKEY 00454 SYSKEY = 0x556699aa; // write second unlock key to SYSKEY 00455 RTCCONSET = 0x8; // set RTCWREN in RTCCONSET 00456 #endif 00457 // XXX 10/5/2011 4:42:26 PM: Added ifdef for PIC24/16 00458 #ifdef __PIC24FJ256GA106 00459 asm volatile("disi #5"); 00460 asm volatile("mov #0x55, w7"); 00461 asm volatile("mov w7, _NVMKEY"); 00462 asm volatile("mov #0xAA, w8"); 00463 asm volatile("mov w8, _NVMKEY"); 00464 00465 // asm volatile("bset _NVMCON, #15"); 00466 asm volatile("bset _RCFGCAL, #13"); 00467 asm volatile("nop"); 00468 asm volatile("nop"); 00469 #endif 00470 00471 #ifdef _16F1939 00472 // XXX 10/6/2011 8:35:28 AM: not sure what needs to happen for the PIC16F, the following code was here commented out already. 00473 // XXX 12/15/2011 10:15:28 AM: this writes to the EEPROM - shown below is the required sequence 00474 // EECON2 = 0x55; 00475 // EECON2 = 0xAA; 00476 // RCFGCALbits.RTCWREN = 1; 00477 #endif 00478 } 00479 00480 00481 00490 void RTCCSetBinSec(unsigned char Sec) { 00491 if (Sec == 0xff) 00492 Sec = 59; 00493 if (Sec == 60) 00494 Sec = 0; 00495 mRTCCSetSec(mRTCCBin2Dec(Sec)); 00496 } 00497 00506 void RTCCSetBinMin(unsigned char Min) { 00507 if (Min == 0xff) 00508 Min = 59; 00509 if (Min == 60) 00510 Min = 0; 00511 mRTCCSetMin(mRTCCBin2Dec(Min)); 00512 } 00513 00522 void RTCCSetBinHour(unsigned char Hour) { 00523 if (Hour == 0xff) 00524 Hour = 23; 00525 if (Hour == 24) 00526 Hour = 0; 00527 mRTCCSetHour(mRTCCBin2Dec(Hour)); 00528 } 00529 00530 00543 void RTCCCalculateWeekDay(void) { 00544 const char MonthOffset[] = 00545 00546 //jan feb mar apr may jun jul aug sep oct nov dec 00547 {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5}; 00548 unsigned Year; 00549 unsigned Month; 00550 unsigned Day; 00551 unsigned Offset; 00552 00553 // calculate week day 00554 Year = mRTCCGetBinYear(); 00555 Month = mRTCCGetBinMonth(); 00556 Day = mRTCCGetBinDay(); 00557 00558 // 2000s century offset = 6 + 00559 // every year 365%7 = 1 day shift + 00560 // every leap year adds 1 day 00561 Offset = 6 + Year + Year / 4; 00562 00563 // Add month offset from table 00564 Offset += MonthOffset[Month - 1]; 00565 00566 // Add day 00567 Offset += Day; 00568 00569 // If it's a leap year and before March there's no additional day yet 00570 if ((Year % 4) == 0) 00571 if (Month < 3) 00572 Offset -= 1; 00573 00574 // Week day is 00575 Offset %= 7; 00576 00577 mRTCCSetWkDay(Offset); 00578 } 00579 00580 00589 void RTCCSetBinDay(unsigned char Day) { 00590 const char MonthDaymax[] = 00591 00592 //jan feb mar apr may jun jul aug sep oct nov dec 00593 {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; 00594 unsigned Daymax; 00595 unsigned Month; 00596 unsigned Year; 00597 00598 Month = mRTCCGetBinMonth(); 00599 Year = mRTCCGetBinYear(); 00600 00601 Daymax = MonthDaymax[Month - 1]; 00602 00603 // February has one day more for a leap year 00604 if (Month == 2) 00605 if ((Year % 4) == 0) 00606 Daymax++; 00607 00608 if (Day == 0) 00609 Day = Daymax; 00610 if (Day > Daymax) 00611 Day = 1; 00612 mRTCCSetDay(mRTCCBin2Dec(Day)); 00613 } 00614 00623 void RTCCSetBinMonth(unsigned char Month) { 00624 if (Month < 1) 00625 Month = 12; 00626 if (Month > 12) 00627 Month = 1; 00628 mRTCCSetMonth(mRTCCBin2Dec(Month)); 00629 } 00630 00631 00639 void RTCCSetBinYear(unsigned char Year) { 00640 if (Year == 0xff) 00641 Year = 99; 00642 if (Year == 100) 00643 Year = 0; 00644 mRTCCSetYear(mRTCCBin2Dec(Year)); 00645 00646 // Recheck day. Leap year influences to Feb 28/29. 00647 RTCCSetBinDay(mRTCCGetBinDay()); 00648 } 00650 /***************************************************************************** 00651 * EOF 00652 *****************************************************************************/