/********************************************************************* * Function: void RtccReadTime(rtccTime* pTm) * * PreCondition: pTm a valid pointer * Input: pTm - pointer to a rtccTime union to store the current time * Output: None * Side Effects: None * Overview: The function updates the user supplied union/structure with * the current time of the RTCC device. * Note: The function makes sure that the read value is valid. * It avoids waiting for the RTCSYNC to be clear by * performing successive reads. ********************************************************************/ void RtccReadTime(rtccTime* pTm) { rtccTimeDate rTD0, rTD1; do { mRtccClearRtcPtr(); mRtccSetRtcPtr(RTCCPTR_MASK_HRSWEEK); rTD0.w[2]=RTCVAL; rTD0.w[3]=RTCVAL; // read the device value mRtccClearRtcPtr(); mRtccSetRtcPtr(RTCCPTR_MASK_HRSWEEK); rTD1.w[2]=RTCVAL; rTD1.w[3]=RTCVAL; // read the device value }while(rTD0.f.sec!=rTD1.f.sec); // make sure you have the same sec pTm->f.hour=rTD0.f.hour; pTm->f.min=rTD0.f.min; pTm->f.sec=rTD0.f.sec; // update user's data }
/********************************************************************* Function: void RtccReadTimeDate(rtccTimeDate* pTD) PreCondition: None Input: pTD - pointer to a rtccTimeDate union to store the current time and date Output: None Side Effects: None Overview: The function updates the user supplied union/structure with the current time and date of the RTCC device. Note: This firmware solution would consist of reading each register twice and then comparing the two values. If the two values match, then a rollover did not occur. ********************************************************************/ void RtccReadTimeDate(rtccTimeDate* pTD) { rtccTimeDate currTD; do { mRtccClearRtcPtr(); mRtccSetRtcPtr(RTCCPTR_MASK_YEAR); pTD->b[0]=RTCVALL; pTD->b[1]=RTCVALH; pTD->b[2]=RTCVALL; pTD->b[3]=RTCVALH; pTD->b[4]=RTCVALL; pTD->b[5]=RTCVALH; pTD->b[6]=RTCVALL; pTD->b[7]=RTCVALH; // read the user value mRtccClearRtcPtr(); mRtccSetRtcPtr(RTCCPTR_MASK_YEAR); currTD.b[0]=RTCVALL; currTD.b[1]=RTCVALH; currTD.b[2]=RTCVALL; currTD.b[3]=RTCVALH; currTD.b[4]=RTCVALL; currTD.b[5]=RTCVALH; currTD.b[6]=RTCVALL; currTD.b[7]=RTCVALH; // read the user value }while(pTD->f.sec!=currTD.f.sec); // make sure you have the same sec }
void _ISRFAST _INT2Interrupt(void) #endif { //LED1 = ~LED1; if (SA02_VIBRA_INTPIN_IF) { uint8_t rtc_min; uint16_t rtc_sec; // get current time from RTC mRtccClearRtcPtr(); rtc_sec = BCDToDecimal(RTCVALL); rtc_min = BCDToDecimal(RTCVALH); rtc_sec += rtc_min*SEC_IN_MIN; //printf("int_cnt: %lu time: %d start_time: %d\n", int_cnt, rtc_sec, sec_start); if (isInInterval(sec_start, rtc_sec)) { // we have enough interrupts in given shaking interval if (int_cnt++ >= INTERRUPTS_FOR_ONE_SHAKE) { accel_int = TRUE; int_cnt = 0; //printf("=== Vibra interrupt ===\n"); } delay_ms(25); } else { sec_start = rtc_sec; // save new starting time int_cnt = 0; } SA02_VIBRA_INTPIN_IF = 0; } // RTC interrupt if ((PIR3bits.RTCCIF) && (PIE3bits.RTCCIE)) { PIR3bits.RTCCIF = 0; PIE3bits.RTCCIE = 0; RtccWrOn(); mRtccOff(); mRtccWrOff(); //printf("RTC INT\n"); } if (HW_isIRQ0Active()) { HW_irq0occurred(); HW_clearIRQ0(); } if (HW_isIRQ1Active()) { HW_irq1occurred(); HW_clearIRQ1(); } //LED1 = ~LED1; }
/********************************************************************************************** Function: void RtccSetCalibration(int drift) PreCondition: drift has to fit into signed 8 bits representation Input: drift - value to be added/subtracted to perform calibration Output: None Side Effects: None Overview: The function updates the value that the RTCC uses in the auto-adjust feature, once every minute. The drift value acts as a signed value, [-128*4, +127*4], 0 not having any effect. Note: Writes to the RTCCAL[7:0] register should only occur when the timer is turned off or immediately or after the edge of the seconds pulse (except when SECONDS=00 - due to the possibility of the auto-adjust event). In order to speed-up the process, the API function performs the reading of the HALFSEC field. The function may block for half a second, worst case, when called at the start of the minute. Interrupts can not be disabled for such a long period. However, long interrupt routines can interfere with the proper functioning of the device.Care must be taken. ***********************************************************************************************/ void RtccSetCalibration(int drift) { if(mRtccIsOn()) { unsigned int currSec; mRtccClearRtcPtr(); // make sure you read seconds if((currSec=RTCVALL)&0xff==00) { // we're at second 00, wait auto-adjust to be performed while(!mRtccIs2ndHalfSecond()); // wait until second half... } } // update the CAL value RTCCAL=drift; }
/********************************************************************* * Function: BOOL RtccWriteTime(const rtccTime* pTm, BOOL di) * * PreCondition: pTm pointing to a valid rtccTime structure having proper values: * - sec: BCD codification, 00-59 * - min: BCD codification, 00-59 * - hour: BCD codification, 00-24 * Input: pTm - pointer to a constant rtccTime union * di - if interrupts need to be disabled * Output: TRUE '1' : If all the values are within range * FALSE '0' : If any value is out of above mentioned range. * Side Effects: None * Overview: The function sets the current time of the RTCC device. * Note: - The write is successful only if Wr Enable is set. * The function will enable the write itself, if needed. * Also, the Alarm will be temporarily disabled and the * device will be stopped (On set to 0) in order * to safely perform the update of the RTC time register. * However, the device status will be restored. * - Usually the disabling of the interrupts is desired, if the user has to have more * precise control over the actual moment of the time setting. ********************************************************************/ BOOL RtccWriteTime(const rtccTime* pTm , BOOL di) { WORD_VAL tempHourWDay ; WORD_VAL tempMinSec ; UINT8 CPU_IPL; BOOL wasWrEn; BOOL wasOn; BOOL wasAlrm=FALSE; if((MAX_MIN < pTm->f.min )|| (MAX_SEC < pTm->f.sec) || (MAX_HOUR < pTm->f.hour)) { return(FALSE); } tempMinSec.byte.HB = pTm->f.min; tempMinSec.byte.LB =pTm->f.sec; // update the desired fields if(di) { /* Disable Global Interrupt */ mSET_AND_SAVE_CPU_IP(CPU_IPL,7); } if(!(wasWrEn= mRtccIsWrEn())) { RtccWrOn(); // have to allow the WRTEN in order to write the new value } if((wasOn=mRtccIsOn())) { wasAlrm= mRtccIsAlrmEnabled(); mRtccOff(); // turn module off before updating the time } mRtccClearRtcPtr(); mRtccSetRtcPtr(RTCCPTR_MASK_HRSWEEK); tempHourWDay.Val = RTCVAL; tempHourWDay.byte.LB = pTm->f.hour; mRtccClearRtcPtr(); mRtccSetRtcPtr(RTCCPTR_MASK_HRSWEEK); RTCVAL = tempHourWDay.Val; // update device value RTCVAL = tempMinSec.Val; if(wasOn) { mRtccOn(); if(wasAlrm) { mRtccAlrmEnable(); } if(wasWrEn) { RtccWrOn(); } } else { if(!wasWrEn) { mRtccWrOff(); } } if(di) { /* Enable Global Interrupt */ mRESTORE_CPU_IP(CPU_IPL); } return(TRUE); }