diff --git a/RTClib.cpp b/RTClib.cpp index 8b034182..415ed2d4 100644 --- a/RTClib.cpp +++ b/RTClib.cpp @@ -1451,6 +1451,90 @@ DateTime RTC_PCF8563::now() { return DateTime(y, m, d, hh, mm, ss); } +/**************************************************************************/ +/*! + @brief Enable the Countdown Timer Interrupt on the PCF8563. +*/ +/**************************************************************************/ +void RTC_PCF8563::enableCountdownTimer(PCF8563TimerClockFreq clkFreq, uint8_t numPeriods) { + // Set the countdown value (TIMER[7:0]) in the timer register + write_i2c_register(PCF8563_ADDRESS, PCF8563_TIMER, numPeriods); + + uint8_t timer_ctlreg = read_i2c_register(PCF8563_ADDRESS, PCF8563_TIMER_CONTROL); + //write_i2c_register(PCF8563_ADDRESS, PCF8563_TIMER_CONTROL, timer_ctlreg & ~0x03 | clkFreq); + + // Sets the enable bit TE and the clock source bits TD[1:0] in the timer control register + write_i2c_register(PCF8563_ADDRESS, PCF8563_TIMER_CONTROL, (timer_ctlreg & ~PCF8563_TimerControl_TD) | clkFreq | PCF8563_TimerControl_TE); + + // uint8_t timer_ctlreg = read_i2c_register(PCF8563_ADDRESS, PCF8563_TIMER_CONTROL); + // //if (timer_ctlreg & (1 << 5)) { + // write_i2c_register(PCF8563_ADDRESS, PCF8563_TIMER_CONTROL, timer_ctlreg | (1 << 7)); + // //} +} + +/**************************************************************************/ +/*! + @brief Disable the Countdown Timer on the PCF8563. + @details +*/ +/**************************************************************************/ +void RTC_PCF8563::disableCountdownTimer() { + // Leave compatible settings intact + uint8_t timer_ctlreg = read_i2c_register(PCF8563_ADDRESS, PCF8563_TIMER_CONTROL); + + // Reset the enable bit TE in the timer control register leaving the clock source bits TD[1:0] unchanged + write_i2c_register(PCF8563_ADDRESS, PCF8563_TIMER_CONTROL, timer_ctlreg & ~PCF8563_TimerControl_TE); +} + +/**************************************************************************/ +/*! + @brief Enable the interrupt for the countdown timer on the PCF8563. + @details +*/ +/**************************************************************************/ +void RTC_PCF8563::enableCountdownTimerInt(bool pulse) { + // Leave compatible settings intact + uint8_t ctlreg = read_i2c_register(PCF8563_ADDRESS, PCF8563_CONTROL_2); + + // Set the counter interrupt enable bit TIE in the control status 2. Additionally clear any interrupt flags. + // Because the alarm and timer interrupt are tied to the interrupt signal both flags have to be cleared. + if(pulse) { + // sets the TI_TP bit in control status 2 register so that the generated interrupt is a pulse + ctlreg = (ctlreg | (PCF8563_CONTROL2_TI_TP | PCF8563_CONTROL2_TIE)) & ~(PCF8563_CONTROL2_AF | PCF8563_CONTROL2_TF); + } else { + // clear the TI_TP bit in control status 2 register. The value of INT is equal to the value + // of the timer interrupt flag TF + ctlreg = (ctlreg | PCF8563_CONTROL2_TIE) & ~(PCF8563_CONTROL2_TI_TP | PCF8563_CONTROL2_AF | PCF8563_CONTROL2_TF); + } + + write_i2c_register(PCF8563_ADDRESS, PCF8563_CONTROL_2, ctlreg); +} + +/**************************************************************************/ +/*! + @brief Disable the interrupt for the countdown timer on the PCF8563. + @details +*/ +/**************************************************************************/ +void RTC_PCF8563::disableCountdownTimerInt(void) { + // Leave compatible settings intact + uint8_t ctlreg = read_i2c_register(PCF8563_ADDRESS, PCF8563_CONTROL_2); + + // Reset the enable bit TIE in the control status 2 register leaving other bits unchanged + write_i2c_register(PCF8563_ADDRESS, PCF8563_CONTROL_2, ctlreg & ~PCF8563_CONTROL2_TIE); +} + +uint8_t RTC_PCF8563::getAndClearIntFlags(void) { + // Read control status register 2 which contains the interrupt flags + uint8_t ctlreg = read_i2c_register(PCF8563_ADDRESS, PCF8563_CONTROL_2); + + // Clear the AF and TF interrupt flags in control status register 2 + write_i2c_register(PCF8563_ADDRESS, PCF8563_CONTROL_2, ctlreg & ~12); + + // Return the value of the control status 2 register masking out all bits except the TF and AF interrupt flags + return(ctlreg & (PCF8563_CONTROL2_AF | PCF8563_CONTROL2_TF)); +} + /**************************************************************************/ /*! @brief Resets the STOP bit in register Control_1 diff --git a/RTClib.h b/RTClib.h index e48960ee..63527ab7 100644 --- a/RTClib.h +++ b/RTClib.h @@ -38,6 +38,8 @@ class TimeSpan; #define PCF8563_ADDRESS 0x51 ///< I2C address for PCF8563 #define PCF8563_CLKOUTCONTROL 0x0D ///< CLKOUT control register +#define PCF8563_TIMER_CONTROL 0x0E ///< Timer control register +#define PCF8563_TIMER 0x0F ///< Timer register #define PCF8563_CONTROL_1 0x00 ///< Control and status register 1 #define PCF8563_CONTROL_2 0x01 ///< Control and status register 2 #define PCF8563_VL_SECONDS 0x02 ///< register address for VL_SECONDS @@ -410,6 +412,29 @@ class RTC_PCF8523 { void calibrate(Pcf8523OffsetMode mode, int8_t offset); }; +/** PCF8563 timer control register settings */ +enum PCF8563TimerControl { + PCF8563_TimerControl_TE = 128, + PCF8563_TimerControl_TD = 3 +}; + +/** PCF8563 Timer clock source settings */ +enum PCF8563TimerClockFreq { + PCF8563_TimerClk4096kHz = 0x00, /**< 4096 kHz */ + PCF8563_TimerClk64Hz = 0x01, /**< 64 Hz */ + PCF8563_TimerClk1Hz = 0x02, /**< 1 Hz */ + PCF8563_TimerClk1_60Hz = 0x03 /**< 1/60 Hz */ +}; + +/** PCF8563 control status 2 register settings */ +enum PCF8563Control2 { + PCF8563_CONTROL2_TI_TP = 16, + PCF8563_CONTROL2_AF = 8, + PCF8563_CONTROL2_TF = 4, + PCF8563_CONTROL2_AIE = 2, + PCF8563_CONTROL2_TIE = 1 +}; + /** PCF8563 CLKOUT pin mode settings */ enum Pcf8563SqwPinMode { PCF8563_SquareWaveOFF = 0x00, /**< Off */ @@ -431,6 +456,11 @@ class RTC_PCF8563 { boolean lostPower(void); void adjust(const DateTime &dt); static DateTime now(); + void enableCountdownTimer(PCF8563TimerClockFreq clkFreq, uint8_t numPeriods); + void disableCountdownTimer(void); + void enableCountdownTimerInt(bool pulse); + void disableCountdownTimerInt(void); + uint8_t getAndClearIntFlags(void); void start(void); void stop(void); uint8_t isrunning();