Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 13 additions & 10 deletions examples/Example3-Trickle_Charging/Example3-Trickle_Charging.ino
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,23 @@ void setup() {
}
else
Serial.println("RTC online!");
Serial.println();
Serial.println();

//Trickle Charger
Serial.print("Config EEPROM 0x37 before: ");
Serial.println(rtc.readConfigEEPROM_RAMmirror(0x37));

rtc.enableTrickleCharge(TCR_3K); //series resistor 3kOhm
//rtc.enableTrickleCharge(TCR_5K); //series resistor 5kOhm
//rtc.enableTrickleCharge(TCR_9K); //series resistor 9kOhm
rtc.disableTrickleCharge(); // disable trickle charger
Serial.print("Config EEPROM 0x37 before:\t0b");
Serial.println(rtc.readConfigEEPROM_RAMmirror(0x37), BIN);


rtc.enableTrickleCharge(TCR_3K); //series resistor 3kOhm
//rtc.enableTrickleCharge(TCR_5K); //series resistor 5kOhm
//rtc.enableTrickleCharge(TCR_9K); //series resistor 9kOhm
//rtc.enableTrickleCharge(TCR_15K); //series resistor 15kOhm
//rtc.disableTrickleCharge(); //Trickle Charger disabled
//rtc.disableTrickleCharge(); //Trickle Charger disabled

Serial.print("Config EEPROM 0x37 after: ");
Serial.println(rtc.readConfigEEPROM_RAMmirror(0x37));
Serial.print("Config EEPROM 0x37 after:\t0b");
Serial.println(rtc.readConfigEEPROM_RAMmirror(0x37), BIN);
Serial.println("\t\t(1 = ON) TCE_bit ^\t^^ TCR_bits (00 = 3k series resistor)");

//For more information see https://www.microcrystal.com/fileadmin/Media/Products/RTC/App.Manual/RV-3028-C7_App-Manual.pdf#page=48
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
/*
Battery Backup Interrupt Time Stamp Configuration of RV-3028-C7 Real Time Clock
By: Paolo Salvagione
Date: 6/15/2020
License: This code is public domain.

This example shows how to set the Battery Backup Interrupt Time Stamp
Configuration of RTC RV-3028-C7. Open the serial monitor at 115200 baud.

For more information see
https://www.microcrystal.com/fileadmin/Media/Products/RTC/App.Manual/RV-3028-C7_App-Manual.pdf

Assumptions,
1) You've already set the RTC time. See the SetPrint_Time example.
2) You have a backup battery, or capacitor, attached to the RTC's Vbackup pin. See datasheet.
3) You're keeping the backup battery, or capacitor, topped off with the trickle charge feature
of the RTC. See Trickle_Charging example.
4) The Vbackup supply, a battery or a capacitor, has enougth power to keep the RTC alive during
interrupt event.
5) That you will unplug/plug the USB cable powering your microcontroller/Arduino to simulate
loss of power.

Known Issues,
1) Unplugging/plugging the RTC directly will bounce and the time stamp counter will count
each bounce as an event.
2) Default call to rtc.begin disables trick charge settings.
*/

#include <RV-3028-C7.h>

RV3028 rtc;

void setup() {

Serial.begin(115200);
while (!Serial);
Serial.println("Backup Battery Interrupt Time Stamp - RTC Example");

Wire.begin();
if (rtc.begin() == false) {
Serial.println("Something went wrong, check wiring");
while (1);
} else {
Serial.println("RTC online!");
}

// Enable Trickle Charger, see Trickle Charging example for complete list of settings.
rtc.enableTrickleCharge(TCR_3K); //series resistor 3kOhm

// Time Stamp Interrupt settings
if (rtc.isInterruptTimeStampEnabled() == false) // allows settings to persist through reboot.
{
rtc.enableInterruptTimeStamp(backupBattery, lastEvent, clockOff);
//rtc.enableInterruptTimeStamp(backupBattery, firstEvent, clockOff);
}

Serial.println("Unplug/plug the USB cable to simulate loss of power.\n");

} // end setup()

void loop() {
// Print time stamp register
if (rtc.readInterruptTimeStamp() == false)
{
Serial.println("RTC failed to update.");
while (rtc.readInterruptTimeStamp() == false);
}
else if (rtc.readNumberOfInterrupts() !=0)
{
static String lastInterruptTime = "";
String currentInterruptTime = rtc.stringTimeStamp();
if (currentInterruptTime != lastInterruptTime)
{
Serial.print(currentInterruptTime);
Serial.print(" <<< interrupt time stamp, interrupted ");
Serial.print(rtc.readNumberOfInterrupts());
Serial.println(" times.");
lastInterruptTime = currentInterruptTime;
}
}

// Print time
if (rtc.updateTime() == false) //Updates the time variables from RTC.
{
Serial.println("RTC failed to update.");
while (rtc.updateTime() == false);
}
else
{
static String lastTime = "";
String currentTime = rtc.stringTimeStamp();
if (currentTime != lastTime) {
Serial.println(currentTime);
lastTime = currentTime;
}
}

// Change time stamp register settings
if (Serial.available()) {
switch (Serial.read()) {
case 'c':
rtc.clearTimeStampRegister();
Serial.println("Time stamp register cleared.");
break;
case 'f':
rtc.enableInterruptTimeStamp(backupBattery, firstEvent, clockOff);
Serial.println("Time stamp register cleared and set to store first interrupt time stamp.");
break;
case 'l':
rtc.enableInterruptTimeStamp(backupBattery, lastEvent, clockOff);
Serial.println("Time stamp register cleared and set to store last interrupt time stamp.");
break;
case '\n':
// trap returns
break;
default:
Serial.println("---------------------------------------------");
Serial.println("c - Clears the Time Stamp Register");
Serial.println("f - Stores first event in time stamp register");
Serial.println("l - Stores last event in time stamp register");
Serial.println("---------------------------------------------");
break;
}
}
} // end loop()
73 changes: 69 additions & 4 deletions src/RV-3028-C7.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,6 @@ BUILD_MONTH_OCT | BUILD_MONTH_NOV | BUILD_MONTH_DEC

RV3028::RV3028(void)
{

}

bool RV3028::begin(TwoWire &wirePort, bool set_24Hour, bool disable_TrickleCharge, bool set_LevelSwitchingMode)
Expand Down Expand Up @@ -523,7 +522,6 @@ void RV3028::setTimer(bool timer_repeat, uint16_t timer_frequency, uint16_t time
case 60000: // 1/60Hz // up to 7.813ms error on first time
ctrl1_val |= 3; // Set both bits
break;

}

if (set_interrupt)
Expand Down Expand Up @@ -637,7 +635,7 @@ void RV3028::enableTrickleCharge(uint8_t tcr)
writeConfigEEPROM_RAMmirror(EEPROM_Backup_Register, EEPROMBackup);
}

void RV3028::disableTrickleCharge()
void RV3028::disableTrickleCharge() // does not clear trickle charge resistor setting
{
//Read EEPROM Backup Register (0x37)
uint8_t EEPROMBackup = readConfigEEPROM_RAMmirror(EEPROM_Backup_Register);
Expand All @@ -647,6 +645,10 @@ void RV3028::disableTrickleCharge()
writeConfigEEPROM_RAMmirror(EEPROM_Backup_Register, EEPROMBackup);
}

bool RV3028::isTrickleChargeEnabled ()
{
return readBit(EEPROM_Backup_Register, EEPROMBackup_TCE_BIT);
}

/*********************************
0 = Switchover disabled
Expand Down Expand Up @@ -727,6 +729,70 @@ void RV3028::clearClockOutputInterruptFlag()
clearBit(RV3028_STATUS, STATUS_CLKF);
}

// interrupt time stamp functions
// step by step as described in data sheet
// https://www.microcrystal.com/fileadmin/Media/Products/RTC/App.Manual/RV-3028-C7_App-Manual.pdf#page=76
void RV3028::enableInterruptTimeStamp(timeStampSource TSS, timeStampStore TSOW, clockOutputOnEvent CEIE) {
clearBit(RV3028_CTRL2, CTRL2_TSE); // clear Time Stamp Enable bit
clearBit(EEPROM_Backup_Register,
EEPROMBackup_BSIE_BIT); // clear Backup Switchover Interrupt Enable bit
clearBit(RV3028_STATUS, STATUS_BSF); // clear Backup Switch Flag

if (TSS == backupBattery) {
setBit(RV3028_EVENTCTRL, ECR_TSS); // select battery switch over as Time Stamp Source
} else if (TSS == externalPin) {
clearBit(RV3028_EVENTCTRL, ECR_TSS); // select external pin as Time Stamp Source
}

if (TSOW == lastEvent) {
setBit(RV3028_EVENTCTRL, ECR_TSOW); // stores time stamp of last event
} else if (TSOW == firstEvent) {
clearBit(RV3028_EVENTCTRL, ECR_TSOW); // stores time stamp of first event
}

setBit(RV3028_EVENTCTRL, ECR_TSR); // reset Time Stamp Register

if (CEIE == clockOn) {
setBit(RV3028_INT_MASK, IMT_MASK_CEIE); // Clock output on when Event Interrupt bit
} else if (CEIE == clockOff) {
clearBit(RV3028_INT_MASK, IMT_MASK_CEIE); // Clock output off when Event Interrupt bit
}

setBit(RV3028_CTRL2, CTRL2_TSE); // set Time Stamp Enable bit
setBit(EEPROM_Backup_Register,
EEPROMBackup_BSIE_BIT); // set Backup Switchover Interrupt Enable bit
}

bool RV3028::isInterruptTimeStampEnabled() {
return readBit(RV3028_CTRL2, CTRL2_TSE);
}

void RV3028::disableInterruptTimeStamp () {
clearBit(RV3028_CTRL2, CTRL2_TSE); // clear Time Stamp Enable bit
}

bool RV3028::readInterruptTimeStamp() { // reusing updateTime() function
if (readMultipleRegisters(RV3028_SECONDS_TS, _time, TIME_ARRAY_LENGTH) == false)
return(false); //Something went wrong

if (is12Hour()) _time[TIME_HOURS] &= ~(1 << HOURS_AM_PM); //Remove this bit from value

//shift values in array to account for the missing weekday register.
_time[6] = _time[5];
_time[5] = _time[4];
_time[4] = _time[3];
_time[3] = 99;
return true;
}

uint8_t RV3028::readNumberOfInterrupts(void) {
return(readRegister(RV3028_COUNT_TS));
}

void RV3028::clearTimeStampRegister()
{
setBit(RV3028_EVENTCTRL, ECR_TSR);
}

//Returns the status byte
uint8_t RV3028::status(void)
Expand Down Expand Up @@ -895,6 +961,5 @@ bool RV3028::readBit(uint8_t reg_addr, uint8_t bit_num)
uint8_t value = readRegister(reg_addr);
value &= (1 << bit_num);
return value;

}

57 changes: 45 additions & 12 deletions src/RV-3028-C7.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,12 +106,12 @@ Distributed as-is; no warranty is given.

//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_CLKF 6 // clock output interrupt flag
#define STATUS_BSF 5 // backup switch flag
#define STATUS_UF 4 // periodic time update flag
#define STATUS_TF 3 // periodic countdown timer flag
#define STATUS_AF 2 // alarm flag
#define STATUS_EVF 1 // event flag
#define STATUS_PORF 0

//Bits in Control1 Register
Expand All @@ -124,7 +124,7 @@ Distributed as-is; no warranty is given.
#define CTRL1_TD0 0

//Bits in Control2 Register
#define CTRL2_TSE 7
#define CTRL2_TSE 7 // Time Stamp Enable bit
#define CTRL2_CLKIE 6
#define CTRL2_UIE 5
#define CTRL2_TIE 4
Expand All @@ -149,6 +149,7 @@ Distributed as-is; no warranty is given.
#define EEPROMCMD_ReadSingle 0x22

//Bits in EEPROM Backup Register
#define EEPROMBackup_BSIE_BIT 6 //Backup Switchover Interrupt Enable bit
#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
Expand Down Expand Up @@ -179,11 +180,18 @@ Distributed as-is; no warranty is given.
#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 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

// Event control register (0x13)
// bit 7 not implimented
#define ECR_EHL 6 //Event High/Low Level
// bit 3 not implimented
#define ECR_TSR 2 //Time Stamp Reset bit
#define ECR_TSOW 1 //Time Stamp Overwrite bit, 0 = first event, 1 = last event
#define ECR_TSS 0 //Time Stamp Source Selection bit

#define TIME_ARRAY_LENGTH 7 // Total number of writable values in device

Expand All @@ -197,13 +205,28 @@ enum time_order {
TIME_YEAR, // 6
};

enum timeStampSource {
externalPin = 0,
backupBattery = 1
};

enum timeStampStore {
firstEvent = 0,
lastEvent = 1,
};

enum clockOutputOnEvent {
clockOff = 0,
clockOn = 1,
};

class RV3028
{
public:

RV3028(void);

bool begin(TwoWire &wirePort = Wire, bool set_24Hour = true, bool disable_TrickleCharge = true, bool set_LevelSwitchingMode = true);
bool begin(TwoWire &wirePort = Wire, bool set_24Hour = true, bool disable_TrickleCharge = false, bool set_LevelSwitchingMode = true);

bool setTime(uint8_t sec, uint8_t min, uint8_t hour, uint8_t weekday, uint8_t date, uint8_t month, uint16_t year);
bool setTime(uint8_t * time, uint8_t len);
Expand Down Expand Up @@ -261,6 +284,8 @@ class RV3028

void enableTrickleCharge(uint8_t tcr = TCR_15K); //Trickle Charge Resistor default 15k
void disableTrickleCharge();
bool isTrickleChargeEnabled ();

bool setBackupSwitchoverMode(uint8_t val);

void enableClockOut(uint8_t freq);
Expand All @@ -269,6 +294,14 @@ class RV3028
bool readClockOutputInterruptFlag();
void clearClockOutputInterruptFlag();

// Interrupt Time Stamp Functions
void enableInterruptTimeStamp(timeStampSource TSS, timeStampStore TSOW, clockOutputOnEvent CEIE);
void disableInterruptTimeStamp();
bool isInterruptTimeStampEnabled();
bool readInterruptTimeStamp();
uint8_t readNumberOfInterrupts();
void clearTimeStampRegister();

uint8_t status(); //Returns the status byte
void clearInterrupts();

Expand Down