332 lines
11 KiB
C++
332 lines
11 KiB
C++
/******************************************************************************
|
||
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 "common/pimoroni_common.hpp"
|
||
#include "common/pimoroni_i2c.hpp"
|
||
|
||
#include <stdio.h>
|
||
#include <stdlib.h>
|
||
#include <math.h>
|
||
#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_INT_PIN = 22;
|
||
static const uint8_t PIN_UNUSED = UINT8_MAX;
|
||
|
||
|
||
//--------------------------------------------------
|
||
// Variables
|
||
//--------------------------------------------------
|
||
private:
|
||
I2C *i2c;
|
||
|
||
// interface pins with our standard defaults where appropriate
|
||
const int8_t address = DEFAULT_I2C_ADDRESS;
|
||
uint interrupt = DEFAULT_INT_PIN;
|
||
|
||
uint8_t times[TIME_ARRAY_LENGTH];
|
||
|
||
|
||
//--------------------------------------------------
|
||
// Constructors/Destructor
|
||
//--------------------------------------------------
|
||
public:
|
||
RV3028() : RV3028(new I2C()) {}
|
||
|
||
RV3028(I2C *i2c, uint interrupt = DEFAULT_INT_PIN) :
|
||
i2c(i2c), 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);
|
||
};
|
||
|
||
// POSSIBLE ENHANCEMENTS :
|
||
// ENHANCEMENT: Battery Interrupt / check battery voltage
|
||
// ENHANCEMENT: External Event Interrupt
|
||
|
||
}
|