EDF - OnePIC MCU  v1.1.0
source/base/OnePIC_rtcc.c
Go to the documentation of this file.
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  *****************************************************************************/