Library for Real Time Clock module MCP97410 based on Library for DS1307
Fork of RTC-DS1307 by
Rtc_Mcp97410.h
- Committer:
- charly
- Date:
- 2015-01-16
- Revision:
- 11:ef48dcb888c9
- Parent:
- 10:780027029afe
- Child:
- 12:88f82e47b6a1
File content as of revision 11:ef48dcb888c9:
/* Rtc_Mcp97410.h */ /* Support for Michrochip RTC MCP97410 Should work for MCP97410, MCP97411, MCP97412 - see datasheet Based on Library for DS1307 Chips are similar but not equal! Ported for MCP97410 by Karl Zweimueller Original Copyright (c) 2013 Henry Leinen (henry[dot]leinen [at] online [dot] de) Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #ifndef __RTC_MCP97410_H__ #define __RTC_MCP97410_H__ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // GLOBAL CONSTANTS RTCC - ADDRESSES //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ #define ADDR_EEPROM 0xaf // DEVICE ADDR for EEPROM #define ADDR_RTCC 0xdf // DEVICE ADDR for RTCC MCHP //................................................................................. #define SRAM_PTR 0x20 // pointer of the SRAM area (RTCC) #define ADDR_EEPROM_SR 0xff // STATUS REGISTER in the EEPROM //................................................................................. #define ADDR_SEC 0x00 // address of SECONDS register #define ADDR_MIN 0x01 // address of MINUTES register #define ADDR_HOUR 0x02 // address of HOURS register #define ADDR_DAY 0x03 // address of DAY OF WK register #define ADDR_STAT 0x03 // address of STATUS register #define ADDR_DATE 0x04 // address of DATE register #define ADDR_MNTH 0x05 // address of MONTH register #define ADDR_YEAR 0x06 // address of YEAR register #define ADDR_CTRL 0x07 // address of CONTROL register #define ADDR_CAL 0x08 // address of CALIB register #define ADDR_ULID 0x09 // address of UNLOCK ID register //................................................................................. #define ADDR_ALM0SEC 0x0a // address of ALARMO SEC register #define ADDR_ALM0MIN 0x0b // address of ALARMO MIN register #define ADDR_ALM0HR 0x0c // address of ALARMO HOUR register #define ADDR_ALM0CTL 0x0d // address of ALARM0 CONTR register #define ADDR_ALM0DAT 0x0e // address of ALARMO DATE register #define ADDR_ALM0MTH 0x0f // address of ALARMO MONTH register //................................................................................. #define ADDR_ALM1SEC 0x11 // address of ALARM1 SEC register #define ADDR_ALM1MIN 0x12 // address of ALARM1 MIN register #define ADDR_ALM1HR 0x13 // address of ALARM1 HOUR register #define ADDR_ALM1CTL 0x14 // address of ALARM1 CONTR register #define ADDR_ALM1DAT 0x15 // address of ALARM1 DATE register #define ADDR_ALM1MTH 0x16 // address of ALARM1 MONTH register //................................................................................. #define ADDR_SAVtoBAT_MIN 0x18 // address of T_SAVER MIN(VDD->BAT) #define ADDR_SAVtoBAT_HR 0x19 // address of T_SAVER HR (VDD->BAT) #define ADDR_SAVtoBAT_DAT 0x1a // address of T_SAVER DAT(VDD->BAT) #define ADDR_SAVtoBAT_MTH 0x1b // address of T_SAVER MTH(VDD->BAT) //.................................................................................. #define ADDR_SAVtoVDD_MIN 0x1c // address of T_SAVER MIN(BAT->VDD) #define ADDR_SAVtoVDD_HR 0x1d // address of T_SAVER HR (BAT->VDD) #define ADDR_SAVtoVDD_DAT 0x1e // address of T_SAVER DAT(BAT->VDD) #define ADDR_SAVtoVDD_MTH 0x1f // address of T_SAVER MTH(BAT->VDD) //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // GLOBAL CONSTANTS RTCC - INITIALIZATION //.................................................................................. #define START_32KHZ 0x80 // start crystal: ST = b7 (ADDR_SEC) #define LP 0x20 // mask for the leap year bit(MONTH REG) #define HOUR_12 0x40 // 12 hours format (ADDR_HOUR) #define PM 0x20 // post-meridian bit (ADDR_HOUR) #define OUT_PIN 0x80 // = b7 (ADDR_CTRL) #define SQWE 0x40 // SQWE = b6 (ADDR_CTRL) #define ALM_NO 0x00 // no alarm activated (ADDR_CTRL) #define ALM_0 0x10 // ALARM0 is activated (ADDR_CTRL) #define ALM_1 0x20 // ALARM1 is activated (ADDR_CTRL) #define ALM_01 0x30 // both alarms are activated (ADDR_CTRL) #define MFP_01H 0x00 // MFP = SQVAW(01 HERZ) (ADDR_CTRL) #define MFP_04K 0x01 // MFP = SQVAW(04 KHZ) (ADDR_CTRL) #define MFP_08K 0x02 // MFP = SQVAW(08 KHZ) (ADDR_CTRL) #define MFP_32K 0x03 // MFP = SQVAW(32 KHZ) (ADDR_CTRL) #define MFP_64H 0x04 // MFP = SQVAW(64 HERZ) (ADDR_CTRL) #define ALMx_POL 0x80 // polarity of MFP on alarm (ADDR_ALMxCTL) #define ALMxC_SEC 0x00 // ALARM compare on SEC (ADDR_ALMxCTL) #define ALMxC_MIN 0x10 // ALARM compare on MIN (ADDR_ALMxCTL) #define ALMxC_HR 0x20 // ALARM compare on HOUR (ADDR_ALMxCTL) #define ALMxC_DAY 0x30 // ALARM compare on DAY (ADDR_ALMxCTL) #define ALMxC_DAT 0x40 // ALARM compare on DATE (ADDR_ALMxCTL) #define ALMxC_ALL 0x70 // ALARM compare on all param(ADDR_ALMxCTL) #define ALMx_IF 0x08 // MASK of the ALARM_IF (ADDR_ALMxCTL) #define OSCON 0x20 // state of the oscillator(running or not) #define VBATEN 0x08 // enable battery for back-up /** Class Rtc_Mcp97410 implements the real time clock module MCP97410 * * You can read the clock and set a new time and date. * It is also possible to start and stop the clock. * Rtc_Mcp97410 allows you to display the time in a 12h or 24h format. * Based on Library for DS1307 by Henry Leinen. * Ported for MC97410 by Karl Zweimueller. */ class Rtc_Mcp97410 { public: /** Structure which is used to exchange the time and date */ typedef struct { int sec; /*!< seconds [0..59] */ int min; /*!< minutes {0..59] */ int hour; /*!< hours [0..23] */ int wday; /*!< weekday [1..7, where 1 = sunday, 2 = monday, ... */ int date; /*!< day of month [0..31] */ int mon; /*!< month of year [1..12] */ int year; /*!< year [2000..2255] */ } Time_rtc; /** RateSelect specifies the valid frequency values for the square wave output */ typedef enum { RS1Hz = 0, RS4kHz = 1, RS8kHz = 2, RS32kHz = 3 } SqwRateSelect_t; protected: I2C* _i2c; static const char *m_weekDays[]; public: /** public constructor which creates the real time clock object * * @param i2c : Pointer to I2C-Object for I2C-Interface. * */ Rtc_Mcp97410(I2C* i2c); ~Rtc_Mcp97410(); /** Read the current time from RTC chip * * @param time : reference to a struct tm which will be filled with the time from rtc * * @returns true if successful, otherwise an acknowledge error occured */ virtual bool getTime(Time_rtc& time); /** Write the given time onto the RTC chip (and enable Battery-Backup) * * @param time : refereence to a struct which contains valid date and time information * * @param start : contains true if the clock shall start (or keep on running). * * @param thm : 12-hour-mode if set to true, otherwise 24-hour-mode will be set. * * @returns true if successful, otherwise an acknowledge error occured */ virtual bool setTime(Time_rtc& time, bool start, bool thm); /** Start the clock. Please note that the seconds register need to be read and * written in order to start or stop the clock. This can lead to an error * in the time value. The recommended way of starting and stoping the clock is * to write the actual date and time and set the start bit accordingly. * * @returns true if the clock was started, false if a communication error occured */ bool startClock(); /** Stop the clock. Please note that the seconds register need to be read and * written in order to start or stop the clock. This can lead to an error * in the time value. The recommended way of starting and stoping the clock is * to write the actual date and time and set the start bit accordingly. * * @returns true if the clock was stopped, false if a communication error occured */ bool stopClock(); /** Service function to convert a weekday into a string representation * * @param wday : day of week to convert (starting with sunday = 1, monday = 2, ..., saturday = 7 * * @returns the corresponding string representation */ const char* weekdayToString( int wday ) { return m_weekDays[wday%7]; } /** Enable Square Wave output. The function enables or disables the square wave output * of the module and sets the desired frequency. * * @param ena : if set to true, the square wave output is enabled. * * @param rs : rate select, can be either one of the four values defined by type /c RateSelect_t * * @return true if the operation was successful or false otherwise */ bool setSquareWaveOutput(bool ena, SqwRateSelect_t rs); /** enable write-Operations to EEPROM * * */ bool enableEEPROMWrite(); /** disable write-Operations to EEPROM * * */ bool disableEEPROMWrite(); /** read from EEPROM * address from 0x00 to 0x7F * all 128 Bytes can be read in one chunk * * @param address : start address to read from * * @param *buffer : buffer of char to write the result to. Be sure to have enough storage * * @param len : number of bytes to read **/ bool readEEPROM(int address, char* buffer, int len); /** write to EEPROM * address from 0x00 to 0x7F * only maximum 8 Bytes can be written in one chunk * * @param address : start address to write * * @param *buffer : buffer of chars to write * * @param len : number of bytes to write **/ bool writeEEPROM(int address, char* buffer, int len); /** read 6Byte EUI-48 address from EEPROM * * @param eui48 : array to hold 6 Bytes of EUI48 * */ bool readEUI48(uint8_t* eui48); /** write 6Byte EUI-48 address to EEPROM * * be sure to enable EUI-write-Operation (UNLOCK) before * @param eui48 : array with 6 Bytes of EUI48 * */ bool writeEUI48(uint8_t* eui48); /** unlock the EUI area in the EEPROM * * write operation must immediatly follow the unlock procedure * after a write the EEPROM is automatically locked again * */ bool unlockEUI(); private: // read from a memory area RTC/SRAM or EEPROM. specify correct control_byte bool read(int control_byte, int address, char* buffer, int len); // write to a memory area RTC/SRAM or EEPROM. specify correct control_byte bool write(int control_byte, int address, char* buffer, int len); // read from RTC/SRAM bool readRTC(int address, char* buffer, int len); //wrtie to RTC/SRAM bool writeRTC(int address, char* buffer, int len); static int bcdToDecimal(int bcd) { return ((bcd&0xF0)>>4)*10 + (bcd&0x0F); } static int decimalToBcd(int dec) { return (dec%10) + ((dec/10)<<4); } }; typedef void (*RtcCallback_t) (void); class RtcCls : public Rtc_Mcp97410 { protected: InterruptIn m_sqw; bool m_bUseSqw; time_t m_time; // Only used in case SQW is used bool m_bAlarmEnabled; RtcCallback_t m_alarmfunc; time_t m_alarmTime; public: RtcCls(I2C* i2c, PinName sqw, bool bUseSqw); protected: void _callback(void); public: time_t getTime(); virtual bool getTime(Time_rtc& time) { return Rtc_Mcp97410::getTime(time); } void setTime(time_t time); virtual bool setTime(Time_rtc& time, bool start, bool thm) { return Rtc_Mcp97410::setTime(time, start, thm); } public: void setAlarm(int nSeconds, RtcCallback_t alarmfunc) { m_alarmfunc = alarmfunc; m_alarmTime = m_time + nSeconds; m_bAlarmEnabled = (alarmfunc == NULL) ? false : true; } }; #endif // __RTC_MCP97410_H__