Library for Real Time Clock module MCP97410 based on Library for DS1307

Fork of RTC-DS1307 by Henry Leinen

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Rtc_Mcp97410.h Source File

Rtc_Mcp97410.h

00001 /* Rtc_Mcp97410.h */
00002 /*
00003 Support for Michrochip RTC MCP97410
00004 Should work for MCP97410, MCP97411, MCP97412 - see datasheet
00005 Based on Library for DS1307
00006 Chips are similar but not equal!
00007 Ported for MCP97410 by Karl Zweimueller
00008 
00009 Original Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de)
00010 
00011 Permission is hereby granted, free of charge, to any person obtaining a copy
00012 of this software and associated documentation files (the "Software"), to deal
00013 in the Software without restriction, including without limitation the rights
00014 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00015 copies of the Software, and to permit persons to whom the Software is
00016 furnished to do so, subject to the following conditions:
00017 
00018 The above copyright notice and this permission notice shall be included in
00019 all copies or substantial portions of the Software.
00020 
00021 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00022 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00023 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00024 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00025 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00026 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00027 THE SOFTWARE.
00028 */
00029 #ifndef __RTC_MCP97410_H__
00030 #define __RTC_MCP97410_H__
00031 
00032 
00033 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00034 //                    GLOBAL CONSTANTS RTCC - ADDRESSES
00035 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00036 #define  ADDR_EEPROM       0xaf       //  DEVICE ADDR for EEPROM 
00037 #define  ADDR_RTCC         0xdf       //  DEVICE ADDR for RTCC MCHP
00038 //.................................................................................
00039 #define  SRAM_PTR          0x20       //  pointer of the SRAM area (RTCC) 
00040 #define  ADDR_EEPROM_SR    0xff       //  STATUS REGISTER in the  EEPROM
00041 //.................................................................................
00042 #define  ADDR_SEC          0x00       //  address of SECONDS      register 
00043 #define  ADDR_MIN          0x01       //  address of MINUTES      register 
00044 #define  ADDR_HOUR         0x02       //  address of HOURS        register 
00045 #define  ADDR_DAY          0x03       //  address of DAY OF WK    register 
00046 #define  ADDR_STAT         0x03       //  address of STATUS       register 
00047 #define  ADDR_DATE         0x04       //  address of DATE         register  
00048 #define  ADDR_MNTH         0x05       //  address of MONTH        register 
00049 #define  ADDR_YEAR         0x06       //  address of YEAR         register 
00050 #define  ADDR_CTRL         0x07       //  address of CONTROL      register 
00051 #define  ADDR_CAL          0x08       //  address of CALIB        register 
00052 #define  ADDR_ULID         0x09       //  address of UNLOCK ID    register
00053 //.................................................................................
00054 #define  ADDR_ALM0SEC      0x0a       //  address of ALARMO SEC   register 
00055 #define  ADDR_ALM0MIN      0x0b       //  address of ALARMO MIN   register 
00056 #define  ADDR_ALM0HR       0x0c       //  address of ALARMO HOUR  register 
00057 #define  ADDR_ALM0CTL      0x0d       //  address of ALARM0 CONTR register
00058 #define  ADDR_ALM0DAT      0x0e       //  address of ALARMO DATE  register 
00059 #define  ADDR_ALM0MTH      0x0f       //  address of ALARMO MONTH register 
00060 //.................................................................................
00061 #define  ADDR_ALM1SEC      0x11       //  address of ALARM1 SEC   register 
00062 #define  ADDR_ALM1MIN      0x12       //  address of ALARM1 MIN   register 
00063 #define  ADDR_ALM1HR       0x13       //  address of ALARM1 HOUR  register 
00064 #define  ADDR_ALM1CTL      0x14       //  address of ALARM1 CONTR register
00065 #define  ADDR_ALM1DAT      0x15       //  address of ALARM1 DATE  register 
00066 #define  ADDR_ALM1MTH      0x16       //  address of ALARM1 MONTH register 
00067 //.................................................................................
00068 #define  ADDR_SAVtoBAT_MIN 0x18       //  address of T_SAVER MIN(VDD->BAT)
00069 #define  ADDR_SAVtoBAT_HR  0x19       //  address of T_SAVER HR (VDD->BAT) 
00070 #define  ADDR_SAVtoBAT_DAT 0x1a       //  address of T_SAVER DAT(VDD->BAT) 
00071 #define  ADDR_SAVtoBAT_MTH 0x1b       //  address of T_SAVER MTH(VDD->BAT) 
00072 //..................................................................................
00073 #define  ADDR_SAVtoVDD_MIN 0x1c       //  address of T_SAVER MIN(BAT->VDD)
00074 #define  ADDR_SAVtoVDD_HR  0x1d       //  address of T_SAVER HR (BAT->VDD) 
00075 #define  ADDR_SAVtoVDD_DAT 0x1e       //  address of T_SAVER DAT(BAT->VDD) 
00076 #define  ADDR_SAVtoVDD_MTH 0x1f       //  address of T_SAVER MTH(BAT->VDD)        
00077 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00078 //                  GLOBAL CONSTANTS RTCC - INITIALIZATION
00079 //..................................................................................
00080 #define  START_32KHZ  0x80            //  start crystal: ST = b7    (ADDR_SEC)
00081 #define  LP           0x20            //  mask for the leap year bit(MONTH REG)   
00082 #define  HOUR_12      0x40            //  12 hours format           (ADDR_HOUR)   
00083 #define  PM           0x20            //  post-meridian bit         (ADDR_HOUR) 
00084 #define  OUT_PIN      0x80            //  = b7                      (ADDR_CTRL) 
00085 #define  SQWE         0x40            //  SQWE = b6                 (ADDR_CTRL) 
00086 #define  ALM_NO       0x00            //  no alarm activated        (ADDR_CTRL) 
00087 #define  ALM_0        0x10            //  ALARM0 is       activated (ADDR_CTRL)
00088 #define  ALM_1        0x20            //  ALARM1 is       activated (ADDR_CTRL)
00089 #define  ALM_01       0x30            //  both alarms are activated (ADDR_CTRL)
00090 #define  MFP_01H      0x00            //  MFP = SQVAW(01 HERZ)      (ADDR_CTRL)  
00091 #define  MFP_04K      0x01            //  MFP = SQVAW(04 KHZ)       (ADDR_CTRL)  
00092 #define  MFP_08K      0x02            //  MFP = SQVAW(08 KHZ)       (ADDR_CTRL)  
00093 #define  MFP_32K      0x03            //  MFP = SQVAW(32 KHZ)       (ADDR_CTRL)  
00094 #define  MFP_64H      0x04            //  MFP = SQVAW(64 HERZ)      (ADDR_CTRL)
00095 #define  ALMx_POL     0x80            //  polarity of MFP on alarm  (ADDR_ALMxCTL)   
00096 #define  ALMxC_SEC    0x00            //  ALARM compare on SEC      (ADDR_ALMxCTL)              
00097 #define  ALMxC_MIN    0x10            //  ALARM compare on MIN      (ADDR_ALMxCTL)   
00098 #define  ALMxC_HR     0x20            //  ALARM compare on HOUR     (ADDR_ALMxCTL)   
00099 #define  ALMxC_DAY    0x30            //  ALARM compare on DAY      (ADDR_ALMxCTL)   
00100 #define  ALMxC_DAT    0x40            //  ALARM compare on DATE     (ADDR_ALMxCTL)   
00101 #define  ALMxC_ALL    0x70            //  ALARM compare on all param(ADDR_ALMxCTL)    
00102 #define  ALMx_IF      0x08            //  MASK of the ALARM_IF      (ADDR_ALMxCTL)
00103 #define  OSCON        0x20            //  state of the oscillator(running or not)
00104 #define  VBATEN       0x08            //  enable battery for back-up         
00105 
00106 /** Class Rtc_Mcp97410 implements the real time clock module MCP97410
00107  *
00108  * You can read the clock and set a new time and date.
00109  * It is also possible to start and stop the clock.
00110  * Rtc_Mcp97410 allows you to display the time in a 12h or 24h format.
00111  * Based on Library for DS1307 by Henry Leinen.
00112  * Ported for MC97410 by Karl Zweimueller.
00113  */
00114 class Rtc_Mcp97410
00115 {
00116 public:
00117     /** Structure which is used to exchange the time and date
00118      */
00119     typedef struct {
00120         int sec ;        /*!< seconds [0..59] */
00121         int min ;        /*!< minutes {0..59] */
00122         int hour ;       /*!< hours [0..23] */
00123         int wday ;       /*!< weekday [1..7, where 1 = sunday, 2 = monday, ... */
00124         int date ;       /*!< day of month [0..31] */
00125         int mon ;        /*!< month of year [1..12] */
00126         int year ;       /*!< year [2000..2255] */
00127     } Time_rtc;
00128 
00129 
00130     /** RateSelect specifies the valid frequency values for the square wave output
00131      */
00132     typedef enum {
00133         RS1Hz = 0,
00134         RS4kHz = 1,
00135         RS8kHz = 2,
00136         RS32kHz = 3
00137     } SqwRateSelect_t;
00138     
00139 
00140 protected:
00141     I2C*    _i2c;
00142 
00143     static const char *m_weekDays[];
00144 
00145 public:
00146     /** public constructor which creates the real time clock object
00147      *
00148      * @param i2c : Pointer to I2C-Object for I2C-Interface.
00149      *
00150      */
00151     Rtc_Mcp97410(I2C* i2c);
00152 
00153     ~Rtc_Mcp97410();
00154 
00155     /** Read the current time from RTC chip
00156      *
00157      * @param time : reference to a struct tm which will be filled with the time from rtc
00158      *
00159      * @returns true if successful, otherwise an acknowledge error occured
00160      */
00161     virtual bool getTime(Time_rtc& time);
00162 
00163     /** Write the given time onto the RTC chip (and enable Battery-Backup)
00164      *
00165      * @param time : refereence to a struct which contains valid date and time information
00166      *
00167      * @param start : contains true if the clock shall start (or keep on running).
00168      *
00169      * @param thm : 12-hour-mode if set to true, otherwise 24-hour-mode will be set.
00170      *
00171      * @returns true if successful, otherwise an acknowledge error occured
00172      */
00173     virtual bool setTime(Time_rtc& time, bool start, bool thm);
00174 
00175     /** Start the clock. Please note that the seconds register need to be read and
00176      * written in order to start or stop the clock. This can lead to an error
00177      * in the time value. The recommended way of starting and stoping the clock is
00178      * to write the actual date and time and set the start bit accordingly.
00179      *
00180      * @returns true if the clock was started, false if a communication error occured
00181      */
00182     bool startClock();
00183 
00184     /** Stop the clock. Please note that the seconds register need to be read and
00185      * written in order to start or stop the clock. This can lead to an error
00186      * in the time value. The recommended way of starting and stoping the clock is
00187      * to write the actual date and time and set the start bit accordingly.
00188      *
00189      * @returns true if the clock was stopped, false if a communication error occured
00190      */
00191     bool stopClock();
00192 
00193     /** Service function to convert a weekday into a string representation
00194      *
00195      * @param wday : day of week to convert (starting with sunday = 1, monday = 2, ..., saturday = 7
00196      *
00197      * @returns the corresponding string representation
00198      */
00199     const char* weekdayToString( int wday ) {
00200         return m_weekDays[wday%7];
00201     }
00202 
00203     /** Enable Square Wave output. The function enables or disables the square wave output
00204      * of the module and sets the desired frequency.
00205      *
00206      * @param ena : if set to true, the square wave output is enabled.
00207      *
00208      * @param rs : rate select, can be either one of the four values defined by type /c RateSelect_t
00209      *
00210      * @return true if the operation was successful or false otherwise
00211      */
00212     bool setSquareWaveOutput(bool ena, SqwRateSelect_t rs);
00213     
00214     /** enable write-Operations to EEPROM
00215     *
00216     *
00217     */
00218     bool enableEEPROMWrite();
00219 
00220     /** disable write-Operations to EEPROM
00221     *
00222     *
00223     */
00224     bool disableEEPROMWrite();    
00225 
00226     /** read the OSCTRIM-Register (0x08)
00227     *
00228     * -127 .. +127
00229     * bit 7 is Sign
00230     * bit 0:6 Trim-Value
00231     */
00232     uint8_t readTrim();
00233     
00234     /** Increment TRIM-Value
00235     *
00236     * Increment TRIM-Value by one 
00237     */
00238     bool incTrim();
00239     
00240     /** Derement TRIM-Value
00241     *
00242     * Decrement TRIM-Value by one 
00243     */
00244     bool decTrim();
00245     
00246        
00247     /** read from EEPROM
00248     *
00249     * address from 0x00 to 0x7F
00250     * all 128 Bytes can be read in one chunk
00251     *
00252     * @param address : start address to read from
00253     *
00254     * @param *buffer : buffer of char to write the result to. Be sure to have enough storage
00255     *
00256     * @param len : number of bytes to read
00257     **/
00258     bool readEEPROM(int address, char* buffer, int len);
00259     
00260     /** write to EEPROM
00261     *
00262     * address from 0x00 to 0x7F
00263     * only maximum 8 Bytes can be written in one chunk
00264     *
00265     * @param address : start address to write
00266     *
00267     * @param *buffer : buffer of chars to write 
00268     *
00269     * @param len : number of bytes to write
00270     **/
00271     bool writeEEPROM(int address, char* buffer, int len);
00272 
00273 
00274 
00275     /** read 6Byte EUI-48 address from EEPROM
00276     *
00277     * @param eui48 : array to hold 6 Bytes of EUI48
00278     *
00279     */
00280     bool readEUI48(uint8_t* eui48);
00281 
00282     /** write 6Byte EUI-48 address to EEPROM
00283     *
00284     * be sure to enable EUI-write-Operation (UNLOCK) before
00285     * @param eui48 : array with 6 Bytes of EUI48
00286     *
00287     */
00288     bool writeEUI48(uint8_t* eui48);    
00289 
00290     /** read 8Byte EUI-64 address from EEPROM
00291     *
00292     * @param eui64 : array to hold 8 Bytes of EUI64
00293     *
00294     */
00295     bool readEUI64(uint8_t* eui64);
00296 
00297     /** write 8Byte EUI-64 address to EEPROM
00298     *
00299     * be sure to enable EUI-write-Operation (UNLOCK) before
00300     * @param eui64 : array with 8 Bytes of EUI64
00301     *
00302     */
00303     bool writeEUI64(uint8_t* eui64);    
00304 
00305     /** unlock the EUI area in the EEPROM
00306     *
00307     * write operation must immediatly follow the unlock procedure
00308     * after a write the EEPROM is automatically locked again
00309     *
00310     */
00311     bool unlockEUI();        
00312 
00313 private:
00314     // read from a memory area RTC/SRAM or EEPROM. specify correct control_byte
00315     bool read(int control_byte, int address, char* buffer, int len);
00316     // write to a memory area RTC/SRAM or EEPROM. specify correct control_byte
00317     bool write(int control_byte, int address, char* buffer, int len);
00318     // read from RTC/SRAM
00319     bool readRTC(int address, char* buffer, int len);
00320     //wrtie to RTC/SRAM
00321     bool writeRTC(int address, char* buffer, int len);
00322 
00323 
00324     static int bcdToDecimal(int bcd) {
00325         return ((bcd&0xF0)>>4)*10 + (bcd&0x0F);
00326     }
00327 
00328     static int decimalToBcd(int dec) {
00329         return (dec%10) + ((dec/10)<<4);
00330     }
00331 };
00332 
00333 
00334 
00335 typedef void (*RtcCallback_t) (void);
00336 
00337 
00338 class RtcCls : public Rtc_Mcp97410
00339 {
00340 protected:
00341     InterruptIn                 m_sqw;
00342     bool                        m_bUseSqw;
00343     time_t                      m_time;             //  Only used in case SQW is used
00344     
00345     bool                        m_bAlarmEnabled;
00346     RtcCallback_t               m_alarmfunc;
00347     time_t                      m_alarmTime;
00348     
00349 public:
00350     RtcCls(I2C* i2c, PinName sqw, bool bUseSqw);
00351     
00352 protected:
00353     void _callback(void);
00354     
00355 public:
00356     time_t                      getTime();
00357     virtual bool                getTime(Time_rtc& time)                         { return Rtc_Mcp97410::getTime(time); }
00358     void                        setTime(time_t time);
00359     virtual bool                setTime(Time_rtc& time, bool start, bool thm)   { return Rtc_Mcp97410::setTime(time, start, thm); }
00360 public:
00361     void                        setAlarm(int nSeconds, RtcCallback_t alarmfunc) {
00362         m_alarmfunc = alarmfunc;
00363         m_alarmTime = m_time + nSeconds;
00364         m_bAlarmEnabled = (alarmfunc == NULL) ? false : true;
00365     }
00366 };
00367 
00368 #endif // __RTC_MCP97410_H__