/****************************************************************************** RV-3028-C7.hpp bBased on the RV-3028-C7 Arduino Library by Constantin Koch, July 25, 2019 https://github.com/constiko/RV-3028_C7-Arduino_Library This code is released under the [MIT License](http://opensource.org/licenses/MIT). Please review the LICENSE file included with this example. Distributed as-is; no warranty is given. ******************************************************************************/ #pragma once #include "hardware/i2c.h" #include "hardware/gpio.h" #include #include #include #include "pico/stdlib.h" //The 7-bit I2C ADDRESS of the RV3028 #define RV3028_ADDR 0x52 //REGISTERS //Clock registers #define RV3028_SECONDS 0x00 #define RV3028_MINUTES 0x01 #define RV3028_HOURS 0x02 //Calendar registers #define RV3028_WEEKDAY 0x03 #define RV3028_DATE 0x04 #define RV3028_MONTHS 0x05 #define RV3028_YEARS 0x06 //Alarm registers #define RV3028_MINUTES_ALM 0x07 #define RV3028_HOURS_ALM 0x08 #define RV3028_DATE_ALM 0x09 //Periodic Countdown Timer registers #define RV3028_TIMERVAL_0 0x0A #define RV3028_TIMERVAL_1 0x0B #define RV3028_TIMERSTAT_0 0x0C #define RV3028_TIMERSTAT_1 0x0D //Configuration registers #define RV3028_STATUS 0x0E #define RV3028_CTRL1 0x0F #define RV3028_CTRL2 0x10 #define RV3028_GPBITS 0x11 #define RV3028_INT_MASK 0x12 //Eventcontrol/Timestamp registers #define RV3028_EVENTCTRL 0x13 #define RV3028_COUNT_TS 0x14 #define RV3028_SECONDS_TS 0x15 #define RV3028_MINUTES_TS 0x16 #define RV3028_HOURS_TS 0x17 #define RV3028_DATE_TS 0x18 #define RV3028_MONTH_TS 0x19 #define RV3028_YEAR_TS 0x1A //Unix Time registers #define RV3028_UNIX_TIME0 0x1B #define RV3028_UNIX_TIME1 0x1C #define RV3028_UNIX_TIME2 0x1D #define RV3028_UNIX_TIME3 0x1E //RAM registers #define RV3028_USER_RAM1 0x1F #define RV3028_USER_RAM2 0x20 //Password registers #define RV3028_PASSWORD0 0x21 #define RV3028_PASSWORD1 0x22 #define RV3028_PASSWORD2 0x23 #define RV3028_PASSWORD3 0x24 //EEPROM Memory Control registers #define RV3028_EEPROM_ADDR 0x25 #define RV3028_EEPROM_DATA 0x26 #define RV3028_EEPROM_CMD 0x27 //ID register #define RV3028_ID 0x28 #define RV3028_CHIP_ID 0x30 #define RV3028_VERSION 0x03 //EEPROM Registers #define EEPROM_Clkout_Register 0x35 #define RV3028_EEOffset_8_1 0x36 //bits 8 to 1 of EEOffset. Bit 0 is bit 7 of register 0x37 #define EEPROM_Backup_Register 0x37 //BITS IN IMPORTANT REGISTERS //Bits in Status Register #define STATUS_EEBUSY 7 #define STATUS_CLKF 6 #define STATUS_BSF 5 #define STATUS_UF 4 #define STATUS_TF 3 #define STATUS_AF 2 #define STATUS_EVF 1 #define STATUS_PORF 0 //Bits in Control1 Register #define CTRL1_TRPT 7 #define CTRL1_WADA 5//Bit 6 not implemented #define CTRL1_USEL 4 #define CTRL1_EERD 3 #define CTRL1_TE 2 #define CTRL1_TD1 1 #define CTRL1_TD0 0 //Bits in Control2 Register #define CTRL2_TSE 7 #define CTRL2_CLKIE 6 #define CTRL2_UIE 5 #define CTRL2_TIE 4 #define CTRL2_AIE 3 #define CTRL2_EIE 2 #define CTRL2_12_24 1 #define CTRL2_RESET 0 //Bits in Hours register #define HOURS_AM_PM 5 //Bits in Alarm registers #define MINUTESALM_AE_M 7 #define HOURSALM_AE_H 7 #define DATE_AE_WD 7 //Commands for EEPROM Command Register (0x27) #define EEPROMCMD_First 0x00 #define EEPROMCMD_Update 0x11 #define EEPROMCMD_Refresh 0x12 #define EEPROMCMD_WriteSingle 0x21 #define EEPROMCMD_ReadSingle 0x22 //Bits in EEPROM Backup Register #define EEPROMBackup_TCE_BIT 5 //Trickle Charge Enable Bit #define EEPROMBackup_FEDE_BIT 4 //Fast Edge Detection Enable Bit (for Backup Switchover Mode) #define EEPROMBackup_BSM_SHIFT 2 //Backup Switchover Mode shift #define EEPROMBackup_TCR_SHIFT 0 //Trickle Charge Resistor shift #define EEPROMBackup_BSM_CLEAR 0b11110011 //Backup Switchover Mode clear #define EEPROMBackup_TCR_CLEAR 0b11111100 //Trickle Charge Resistor clear #define TCR_3K 0b00 //Trickle Charge Resistor 3kOhm #define TCR_5K 0b01 //Trickle Charge Resistor 5kOhm #define TCR_9K 0b10 //Trickle Charge Resistor 9kOhm #define TCR_15K 0b11 //Trickle Charge Resistor 15kOhm // Clock output register (0x35) #define EEPROMClkout_CLKOE_BIT 7 //1 = CLKOUT pin is enabled. – Default value on delivery #define EEPROMClkout_CLKSY_BIT 6 // Bits 5 and 4 not implemented #define EEPROMClkout_PORIE 3 //0 = No interrupt, or canceled, signal on INT pin at POR. – Default value on delivery //1 = An interrupt signal on INT pin at POR. Retained until the PORF flag is cleared to 0 (no automatic cancellation). #define EEPROMClkout_FREQ_SHIFT 0 //frequency shift #define FD_CLKOUT_32k 0b000 //32.768 kHz – Default value on delivery #define FD_CLKOUT_8192 0b001 //8192 Hz #define FD_CLKOUT_1024 0b010 //1024 Hz #define FD_CLKOUT_64 0b011 //64 Hz #define FD_CLKOUT_32 0b100 //32 Hz #define FD_CLKOUT_1 0b101 //1 Hz #define FD_CLKOUT_TIMER 0b110 //Predefined periodic countdown timer interrupt #define FD_CLKOUT_LOW 0b111 //CLKOUT = LOW #define IMT_MASK_CEIE 3 //Clock output when Event Interrupt bit. #define IMT_MASK_CAIE 2 //Clock output when Alarm Interrupt bit. #define IMT_MASK_CTIE 1 //Clock output when Periodic Countdown Timer Interrupt bit. #define IMT_MASK_CUIE 0 //Clock output when Periodic Time Update Interrupt bit. #define TIME_ARRAY_LENGTH 7 // Total number of writable values in device namespace pimoroni { enum time_order { TIME_SECONDS, // 0 TIME_MINUTES, // 1 TIME_HOURS, // 2 TIME_WEEKDAY, // 3 TIME_DATE, // 4 TIME_MONTH, // 5 TIME_YEAR, // 6 }; class RV3028 { //-------------------------------------------------- // Constants //-------------------------------------------------- public: static const uint8_t DEFAULT_I2C_ADDRESS = RV3028_ADDR; static const uint8_t DEFAULT_SDA_PIN = 20; static const uint8_t DEFAULT_SCL_PIN = 21; static const uint8_t DEFAULT_INT_PIN = 22; static const uint8_t PIN_UNUSED = UINT8_MAX; //-------------------------------------------------- // Variables //-------------------------------------------------- private: i2c_inst_t *i2c = i2c0; // interface pins with our standard defaults where appropriate int8_t address = DEFAULT_I2C_ADDRESS; int8_t sda = DEFAULT_SDA_PIN; int8_t scl = DEFAULT_SCL_PIN; int8_t interrupt = DEFAULT_INT_PIN; uint8_t times[TIME_ARRAY_LENGTH]; //-------------------------------------------------- // Constructors/Destructor //-------------------------------------------------- public: RV3028() {} RV3028(i2c_inst_t *i2c, uint8_t sda, uint8_t scl, uint8_t interrupt = PIN_UNUSED) : i2c(i2c), sda(sda), scl(scl), interrupt(interrupt) {} //-------------------------------------------------- // Methods //-------------------------------------------------- public: bool init(); void reset(); i2c_inst_t* get_i2c() const; int get_sda() const; int get_scl() const; int get_int() const; bool setup(bool set_24Hour = true, bool disable_TrickleCharge = true, bool set_LevelSwitchingMode = true); bool set_time(uint8_t sec, uint8_t min, uint8_t hour, uint8_t weekday, uint8_t date, uint8_t month, uint16_t year); bool set_time(uint8_t *time, uint8_t len); bool set_seconds(uint8_t value); bool set_minutes(uint8_t value); bool set_hours(uint8_t value); bool set_weekday(uint8_t value); bool set_date(uint8_t value); bool set_month(uint8_t value); bool set_year(uint16_t value); bool set_to_compiler_time(); //Uses the hours, mins, etc from compile time to set RTC bool update_time(); //Update the local array with the RTC registers char* string_date_usa(); //Return date in mm-dd-yyyy char* string_date(); //Return date in dd-mm-yyyy char* string_time(); //Return time hh:mm:ss with AM/PM if in 12 hour mode char* string_time_stamp(); //Return timeStamp in ISO 8601 format yyyy-mm-ddThh:mm:ss uint8_t get_seconds(); uint8_t get_minutes(); uint8_t get_hours(); uint8_t get_weekday(); uint8_t get_date(); uint8_t get_month(); uint16_t get_year(); bool is_12_hour(); //Returns true if 12hour bit is set bool is_pm(); //Returns true if is12Hour and PM bit is set void set_12_hour(); void set_24_hour(); bool set_unix(uint32_t value); //Set the UNIX Time (Real Time and UNIX Time are INDEPENDENT!) uint32_t get_unix(); void enable_alarm_interrupt(uint8_t min, uint8_t hour, uint8_t date_or_weekday, bool set_weekday_alarm_not_date, uint8_t mode, bool enable_clock_output = false); void enable_alarm_interrupt(); void disable_alarm_interrupt(); bool read_alarm_interrupt_flag(); void clear_alarm_interrupt_flag(); void set_timer(bool timer_repeat, uint16_t timer_frequency, uint16_t timer_value, bool set_interrupt, bool start_timer, bool enable_clock_output = false); uint16_t get_timer_count(); void enable_timer(); void disable_timer(); void enable_timer_interrupt(); void disable_timer_interrupt(); bool read_timer_interrupt_flag(); void clear_timer_interrupt_flag(); void enable_periodic_update_interrupt(bool every_second, bool enable_clock_output = false); void disable_periodic_update_interrupt(); bool read_periodic_update_interrupt_flag(); void clear_periodic_update_interrupt_flag(); void enable_trickle_charge(uint8_t tcr = TCR_15K); //Trickle Charge Resistor default 15k void disable_trickle_charge(); bool set_backup_switchover_mode(uint8_t val); void enable_clock_out(uint8_t freq); void enable_interrupt_controlled_clockout(uint8_t freq); void disable_clock_out(); bool read_clock_output_interrupt_flag(); void clear_clock_output_interrupt_flag(); uint8_t status(); //Returns the status byte void clear_interrupts(); private: //Values in RTC are stored in Binary Coded Decimal. These functions convert to/from Decimal uint8_t bcd_to_dec(uint8_t val); uint8_t dec_to_bcd(uint8_t val); uint8_t read_register(uint8_t addr); bool write_register(uint8_t addr, uint8_t val); bool read_multiple_registers(uint8_t addr, uint8_t *dest, uint8_t len); bool write_multiple_registers(uint8_t addr, uint8_t *values, uint8_t len); bool write_config_eeprom_ram_mirror(uint8_t eepromaddr, uint8_t val); uint8_t read_config_eeprom_ram_mirror(uint8_t eepromaddr); bool wait_for_eeprom(); void set_bit(uint8_t reg_addr, uint8_t bit_num); void clear_bit(uint8_t reg_addr, uint8_t bit_num); bool read_bit(uint8_t reg_addr, uint8_t bit_num); // From i2cdevice int write_bytes(uint8_t reg, uint8_t *buf, int len); int read_bytes(uint8_t reg, uint8_t *buf, int len); uint8_t get_bits(uint8_t reg, uint8_t shift, uint8_t mask = 0b1); void set_bits(uint8_t reg, uint8_t shift, uint8_t mask = 0b1); void clear_bits(uint8_t reg, uint8_t shift, uint8_t mask = 0b1); }; //POSSIBLE ENHANCEMENTS : //ENHANCEMENT: Battery Interrupt / check battery voltage //ENHANCEMENT: External Event Interrupt }