Skip to content
Open
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
491 changes: 491 additions & 0 deletions libraries/RTC/RTC.cpp

Large diffs are not rendered by default.

87 changes: 87 additions & 0 deletions libraries/RTC/RTC.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// RTC.h
#pragma once

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/counter.h>
#include <zephyr/drivers/rtc.h>
#include <time.h>

// Alarm callback types
typedef void (*RTCAlarmCallback)(void *user_data);
typedef void (*RTCUpdateCallback)(void *user_data);

class ArduinoRTC {
public:
ArduinoRTC();
bool begin();
~ArduinoRTC();

/* setters */
bool setDayOfMonth(int day);
bool setMonthOfYear(int m);
bool setYear(int year);
bool setHour(int hour);
bool setMinute(int minute);
bool setSecond(int second);

/* Getters */
int getDayOfMonth();
int getMonth();
int getYear();
int getHour();
int getMinutes();
int getSeconds();

int setTime(int year, int month, int day, int hour, int minute, int second);
int getTime(int &year, int &month, int &day, int &hour, int &minute, int &second);
#if defined(ARDUINO_GIGA) || defined(ARDUINO_PORTENTA_H7) || defined(ARDUINO_OPTA)
int setAlarm(int year, int month, int day, int hour, int minute, int second,
RTCAlarmCallback cb = nullptr, void *user_data = nullptr);
int cancelAlarm();
#elif defined(ARDUINO_NANO33BLE) || defined(ARDUINO_NICLA_SENSE_ME)
int setAlarm(int year, int month, int day, int hour, int minute, int second,
void (*callback)(const struct device *dev, uint8_t chan_id, uint32_t ticks, void *user_data),
void *cb_user_data);
void cancelAlarm();
#endif

#if defined(ARDUINO_GIGA) || defined(ARDUINO_PORTENTA_H7) || defined(ARDUINO_OPTA)
// Optional APIs (only if supported)
int getAlarm(int &year, int &month, int &day, int &hour, int &minute, int &second);
bool isAlarmPending();
int setUpdateCallback(RTCUpdateCallback cb, void *user_data);
int setCalibration(int32_t calibration);
int getCalibration(int32_t &calibration);
#endif


private:
#if defined(ARDUINO_GIGA) || defined(ARDUINO_PORTENTA_H7) || defined(ARDUINO_OPTA)
const struct device *rtc_dev;

static void alarmCallbackWrapper(const struct device *dev, uint16_t id, void *user_data);
static void updateCallbackWrapper(const struct device *dev, void *user_data);

RTCAlarmCallback userAlarmCallback = nullptr;
void *userAlarmCallbackData = nullptr;

RTCUpdateCallback userUpdateCallback = nullptr;
void *userUpdateCallbackData = nullptr;

uint16_t alarmId = 0; // default to alarm ID 0
#elif defined(ARDUINO_NANO33BLE) || defined(ARDUINO_NICLA_SENSE_ME)
const struct device *counter_dev;
time_t timeOffset;

// Alarm members
struct counter_alarm_cfg alarm_cfg;
void (*user_callback)(const struct device *dev, uint8_t chan_id, uint32_t ticks, void *user_data);
void *user_data;

static void alarmHandler(const struct device *dev, uint8_t chan_id, uint32_t ticks, void *user_data);

time_t datetimeToEpoch(int year, int month, int day, int hour, int minute, int second);
void epochToDatetime(time_t t, int &year, int &month, int &day, int &hour, int &minute, int &second);
#endif
};
76 changes: 76 additions & 0 deletions libraries/RTC/examples/AlarmRTC/AlarmRTC.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/*
* This sketch sets an alarm 10 seconds in the future and handles it via a callback.
*/

#include "RTC.h"
#include <stdio.h>

ArduinoRTC rtc;

char printBuffer[30]; // declare a buffer of large enough size for the message we want to display
int year, month, day, hour, minute, second;

#if defined(ARDUINO_NICLA_SENSE_ME) || defined(ARDUINO_NANO33BLE)
void onAlarm(const struct device *dev, uint8_t chan_id, uint32_t ticks, void *user_data) {
char printBuffer[40];
// Assuming user_data is a string or message you want to print
sprintf(printBuffer, "Alarm went off! Message: %s\n", (char *)user_data);
Serial.println(printBuffer);
}
#elif
void onAlarm(void *user_data) {
char printBuffer[40];
sprintf(printBuffer, "Alarm went off! Message: %s\n", (char *)user_data);
Serial.println(printBuffer);
}
#endif

void setup() {
int ret = 0xDEADBEEFu; // Starting with a custom value for the return which will definitely lead to failure if not changed to zero (i.e. success) by the functions below
char printBuffer[60];
Serial.begin(115200);
delay(1000);

if (!rtc.begin()) {
Serial.println("RTC not ready\n");
return;
}

int year, month, day, hour, minute, second;
ret = rtc.getTime(year, month, day, hour, minute, second);
if(ret != 0)
{
rtc.setTime(2025, 10, 21, 12, 0, 0);
}

sprintf(printBuffer, "Current Time: %04d-%02d-%02d %02d:%02d:%02d\n", year, month, day, hour, minute, second);
Serial.println(printBuffer);

// Set alarm 10 seconds into the future
second += 5;
// Correct for minute rollover if necessary
if (second >= 60) {
second -= 60;
minute += 1;
}

// The method also allows for registering a function callback which will be called when the alarm sets off and a display message which will be shown in the console
ret = rtc.setAlarm(year, month, day, hour, minute, second, onAlarm, (void *)"Wake up!!!");
if (ret == 0) {
sprintf(printBuffer, "Alarm set for: %02d:%02d:%02d\n", hour, minute, second);
Serial.println(printBuffer);
} else {
sprintf(printBuffer, "Failed to set alarm (%d)\n", ret);
Serial.println(printBuffer);
}
}

void loop() {
char printBuffer[30]; // declare a buffer of large enough size for the message we want to display
int y, m, d, h, min, s;
int status = rtc.getTime(y, m, d, h, min, s);
// Because the print() and println() functions do not support formatted output directly, we can use this trick to prepare a buffer with the string we want to show
sprintf(printBuffer, "Time is: %04d-%02d-%02d %02d:%02d:%02d", y, m, d, h, min, s);
Serial.println(printBuffer);
delay(1000);
}
40 changes: 40 additions & 0 deletions libraries/RTC/examples/CalibrationRTC/CalibrationRTC.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "RTC.h"
#include <stdio.h>

// Doesn't work on the Opta for some reason.


ArduinoRTC rtc;

void setup() {
char printBuffer[30];
delay(1000);
Serial.begin(115200);
if (!rtc.begin()) {
printf("RTC not ready\n");
return;
}

int calib = 0;
if (rtc.getCalibration(calib) == 0) {
sprintf(printBuffer, "Current calibration: %d\n", calib);
Serial.println(printBuffer);
} else {
Serial.println("Failed to get calibration");
}

// Apply a small positive calibration (e.g., +1)
// This value is hardware-dependent, in a real application you should check the microcontroller's datasheet for the correct amount.
int32_t new_calib = calib + 1;

if (rtc.setCalibration(new_calib) == 0) {
sprintf(printBuffer, "Calibration updated to: %d\n", new_calib);
Serial.println(printBuffer);
} else {
Serial.println("Failed to set calibration");
}
}

void loop() {
delay(5000);
}
72 changes: 72 additions & 0 deletions libraries/RTC/examples/EnhancedRTC/EnhancedRTC.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
#include "RTC.h"

ArduinoRTC rtc;

// 7-segment style representation for digits 0–9 and colon ":"
const char* bigDigits[11][3] = {
{" _ ", "| |", "|_|"}, // 0
{" ", " |", " |"}, // 1
{" _ ", " _|", "|_ "}, // 2
{" _ ", " _|", " _|"}, // 3
{" ", "|_|", " |"}, // 4
{" _ ", "|_ ", " _|"}, // 5
{" _ ", "|_ ", "|_|"}, // 6
{" _ ", " |", " |"}, // 7
{" _ ", "|_|", "|_|"}, // 8
{" _ ", "|_|", " _|"}, // 9
{" ", " . ", " . "} // colon ":"
};

void printBigTime(int h, int m, int s) {
// Format time as HH:MM:SS string
char timeStr[9];
memset(timeStr, 0, sizeof(timeStr));
char bigDigitsPrint[40];
memset(bigDigitsPrint, 0, sizeof(bigDigitsPrint));
snprintf(timeStr, sizeof(timeStr), "%02d:%02d:%02d", h, m, s); // This (and further such manipulations) is necessary because Serial.print() does not support formatted output like printf()
Serial.println(timeStr);


// Print each of the 3 lines row by row
for (int row = 0; row < 3; row++) {
for (int i = 0; timeStr[i] != '\0'; i++) {
char c = timeStr[i];
if (c >= '0' && c <= '9') {
sprintf(bigDigitsPrint, "%s ", bigDigits[c - '0'][row]);
Serial.print(bigDigitsPrint);
} else if (c == ':') {
sprintf(bigDigitsPrint, "%s ", bigDigits[10][row]);
Serial.print(bigDigitsPrint);
} else {
Serial.print(" "); // Space or unknown
}
}
Serial.println();
}
Serial.println();
}

void setup() {
Serial.begin(115200);
rtc.begin();
bool status = rtc.setTime(2025, 9, 25, 7, 46, 0); // Initial time
}

void loop() {
int y, m, d, h, min, s;
char printBuffer[60];
int status = rtc.getTime(y, m, d, h, min, s);

// Clear screen (optional line, works on many terminals, tested on Tera Term. Does not take effect in Arduino IDE console unfortunately)
Serial.println("\033[2J\033[H");

// Print date and time in plain format
sprintf(printBuffer, "Date: %04d-%02d-%02d\n", y, m, d);
Serial.println(printBuffer);
Serial.println("Time:");

// Print time in big digits
printBigTime(h, min, s);

delay(1000);
}
23 changes: 23 additions & 0 deletions libraries/RTC/examples/SimpleRTC/SimpleRTC.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#include "RTC.h"

ArduinoRTC rtc;

int year, month, day, hour, minute, second;
int previousSecond = 0;
char printBuffer[30]; // Allocate large enough buffer to hold the 28 characters of the output format "Time is: 2025-09-25 11:49:26"

void setup() {
Serial.begin(115200);
if (!rtc.begin()) {
Serial.println("RTC not ready\n");
return;
}
rtc.setTime(2025, 10, 21, 12, 0, 0);
}

void loop() {
rtc.getTime(year, month, day, hour, minute, second); // Read back time from hardware
sprintf(printBuffer, "Time is: %04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second);
Serial.println(printBuffer);
delay(1000);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ CONFIG_DAC=y
CONFIG_PWM=y
CONFIG_I2C_TARGET=y

CONFIG_CLOCK_CONTROL=y
CONFIG_RTC=y
CONFIG_RTC_ALARM=y
CONFIG_RTC_UPDATE=y
CONFIG_RTC_CALIBRATION=y

CONFIG_ICACHE=y
CONFIG_DCACHE=y
CONFIG_CACHE_MANAGEMENT=y
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,17 @@
status = "okay";
};

&rtc {
status = "okay";
label = "RTC_0";

clocks = <&rcc STM32_CLOCK_BUS_APB1 0x10000000>, /* RTCAPB */
<&rcc STM32_SRC_LSE RTC_SEL(1)>; /* Use LSI instead of LSE */

alarms-count = <2>;
alrm-exti-line = <17>;
};

&i2c4 {
status = "okay";
gc2145: gc2145@3c {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ CONFIG_CDC_ACM_DTE_RATE_CALLBACK_SUPPORT=y

CONFIG_ADC=y
CONFIG_PWM=y
CONFIG_COUNTER=y

CONFIG_LLEXT_STORAGE_WRITABLE=n
CONFIG_SHELL_STACK_SIZE=2048
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,3 +273,8 @@
clock-frequency = <I2C_BITRATE_FAST>;
};

&rtc2 {
status = "okay";
clock-frequency = <32768>;
prescaler = <1>; // Optional: sets the RTC tick to ~30.5 µs
};
Original file line number Diff line number Diff line change
Expand Up @@ -196,3 +196,8 @@
pinctrl-1 = <&pwm2_sleep>;
pinctrl-names = "default", "sleep";
};

&rtc2 {
status = "okay";
prescaler = <1>; // Optional: sets the RTC tick to ~30.5 µs
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ CONFIG_BT_BUF_CMD_TX_COUNT=10

#CONFIG_ADC=y
#CONFIG_PWM=y
CONFIG_COUNTER=y

CONFIG_LLEXT_STORAGE_WRITABLE=n
CONFIG_SHELL_STACK_SIZE=1024
CONFIG_HEAP_MEM_POOL_SIZE=1024
CONFIG_LLEXT_HEAP_SIZE=15
CONFIG_MAIN_STACK_SIZE=1024
CONFIG_MAIN_STACK_SIZE=2048

CONFIG_BT_RX_STACK_SIZE=1024
CONFIG_BT_HCI_TX_STACK_SIZE=1024
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@
};
};

&rtc2 {
status = "okay";
clock-frequency = <32768>;
prescaler = <1>; // Optional: sets the RTC tick to ~30.5 µs
};

/ {
zephyr,user {
digital-pin-gpios = <&gpio0 10 0>, // 0: GPIO3
Expand Down Expand Up @@ -34,4 +40,4 @@
i2cs = <&i2c1>;
spis = <&spi1>;
};
};
};
Loading
Loading