Skip to content

Commit 2cb0da6

Browse files
authored
feat(rx8130ce): Add RX8130CE Real-Time Clock (RTC) component (#540)
* feat(rx8130ce): Add `RX8130CE` Real-Time Clock (RTC) component * address comments and improve api
1 parent 89f173f commit 2cb0da6

File tree

18 files changed

+993
-12
lines changed

18 files changed

+993
-12
lines changed

.github/workflows/build.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ jobs:
165165
target: esp32
166166
- path: 'components/runqueue/example'
167167
target: esp32
168+
- path: 'components/rx8130ce/example'
169+
target: esp32s3
168170
- path: 'components/seeed-studio-round-display/example'
169171
target: esp32s3
170172
- path: 'components/serialization/example'

.github/workflows/upload_components.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ jobs:
103103
components/rmt
104104
components/rtsp
105105
components/runqueue
106+
components/rx8130ce
106107
components/seeed-studio-round-display
107108
components/serialization
108109
components/socket

components/bm8563/include/bm8563.hpp

Lines changed: 77 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#pragma once
22

3+
#include <ctime>
34
#include <functional>
45

56
#include "base_peripheral.hpp"
@@ -96,13 +97,79 @@ class Bm8563 : public BasePeripheral<> {
9697
}
9798
}
9899

99-
/// @brief Get the date and time.
100+
/////////////////////////////////////////////////////////////////////////////
101+
// std::tm based APIs (recommended for portability)
102+
/////////////////////////////////////////////////////////////////////////////
103+
104+
/// @brief Set the time using std::tm structure
105+
/// @param time The time to set
106+
/// @param ec The error code to set if an error occurs
107+
/// @return True if the time was set successfully, false otherwise
108+
bool set_time(const std::tm &time, std::error_code &ec) {
109+
std::lock_guard<std::recursive_mutex> lock(base_mutex_);
110+
111+
// Validate time values
112+
if (time.tm_year < 0 || time.tm_year > 199 || // Years 1900-2099
113+
time.tm_mon < 0 || time.tm_mon > 11 || time.tm_mday < 1 || time.tm_mday > 31 ||
114+
time.tm_hour < 0 || time.tm_hour > 23 || time.tm_min < 0 || time.tm_min > 59 ||
115+
time.tm_sec < 0 || time.tm_sec > 59) {
116+
ec = std::make_error_code(std::errc::invalid_argument);
117+
return false;
118+
}
119+
120+
// Convert std::tm to device-specific format and set
121+
DateTime dt;
122+
dt.date.year = time.tm_year + 1900;
123+
dt.date.month = time.tm_mon + 1;
124+
dt.date.weekday = time.tm_wday;
125+
dt.date.day = time.tm_mday;
126+
dt.time.hour = time.tm_hour;
127+
dt.time.minute = time.tm_min;
128+
dt.time.second = time.tm_sec;
129+
130+
set_date_time(dt, ec);
131+
return !ec;
132+
}
133+
134+
/// @brief Get the time using std::tm structure
135+
/// @param ec The error code to set if an error occurs
136+
/// @return The time from the device
137+
std::tm get_time(std::error_code &ec) {
138+
std::lock_guard<std::recursive_mutex> lock(base_mutex_);
139+
140+
auto dt = get_date_time(ec);
141+
if (ec) {
142+
return {};
143+
}
144+
145+
std::tm time = {};
146+
time.tm_sec = dt.time.second;
147+
time.tm_min = dt.time.minute;
148+
time.tm_hour = dt.time.hour;
149+
time.tm_mday = dt.date.day;
150+
time.tm_mon = dt.date.month - 1;
151+
time.tm_year = dt.date.year - 1900;
152+
time.tm_wday = dt.date.weekday;
153+
time.tm_yday = -1; // Let mktime calculate it
154+
time.tm_isdst = -1; // Let system determine DST
155+
156+
// Normalize the time structure
157+
mktime(&time);
158+
159+
return time;
160+
}
161+
162+
/////////////////////////////////////////////////////////////////////////////
163+
// Device-specific APIs (for backward compatibility)
164+
/////////////////////////////////////////////////////////////////////////////
165+
166+
/// @brief Get the date and time (device-specific format).
100167
/// @param ec The error code.
101168
/// @return The date and time.
102169
DateTime get_date_time(std::error_code &ec) {
103170
std::lock_guard<std::recursive_mutex> lock(base_mutex_);
104171
DateTime dt;
105-
dt.time = get_time(ec);
172+
dt.time = get_time_device(ec);
106173
if (ec)
107174
return {};
108175
dt.date = get_date(ec);
@@ -111,18 +178,18 @@ class Bm8563 : public BasePeripheral<> {
111178
return dt;
112179
}
113180

114-
/// @brief Set the date and time.
181+
/// @brief Set the date and time (device-specific format).
115182
/// @param dt The date and time.
116183
/// @param ec The error code.
117184
void set_date_time(const DateTime &dt, std::error_code &ec) {
118185
std::lock_guard<std::recursive_mutex> lock(base_mutex_);
119186
set_date(dt.date, ec);
120187
if (ec)
121188
return;
122-
set_time(dt.time, ec);
189+
set_time_device(dt.time, ec);
123190
}
124191

125-
/// @brief Get the date.
192+
/// @brief Get the date (device-specific format).
126193
/// @param ec The error code.
127194
/// @return The date.
128195
Date get_date(std::error_code &ec) {
@@ -141,7 +208,7 @@ class Bm8563 : public BasePeripheral<> {
141208
return d;
142209
}
143210

144-
/// @brief Set the date.
211+
/// @brief Set the date (device-specific format).
145212
/// @param d The date.
146213
/// @param ec The error code.
147214
void set_date(const Date &d, std::error_code &ec) {
@@ -152,10 +219,10 @@ class Bm8563 : public BasePeripheral<> {
152219
write_many_to_register((uint8_t)Registers::DATE, data, 4, ec);
153220
}
154221

155-
/// @brief Get the time.
222+
/// @brief Get the time (device-specific format).
156223
/// @param ec The error code.
157224
/// @return The time.
158-
Time get_time(std::error_code &ec) {
225+
Time get_time_device(std::error_code &ec) {
159226
logger_.info("getting time");
160227
uint8_t data[3];
161228
read_many_from_register((uint8_t)Registers::TIME, data, 3, ec);
@@ -169,10 +236,10 @@ class Bm8563 : public BasePeripheral<> {
169236
return t;
170237
}
171238

172-
/// @brief Set the time.
239+
/// @brief Set the time (device-specific format).
173240
/// @param t The time.
174241
/// @param ec The error code.
175-
void set_time(const Time &t, std::error_code &ec) {
242+
void set_time_device(const Time &t, std::error_code &ec) {
176243
logger_.info("Setting time");
177244
const uint8_t data[] = {decimal_to_bcd(t.second), decimal_to_bcd(t.minute),
178245
decimal_to_bcd(t.hour)};

components/rx8130ce/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
idf_component_register(INCLUDE_DIRS "include"
2+
REQUIRES base_peripheral
3+
)

components/rx8130ce/README.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# RX8130CE Real-Time Clock (RTC)
2+
3+
[![Badge](https://components.espressif.com/components/espp/rx8130ce/badge.svg)](https://components.espressif.com/components/espp/rx8130ce)
4+
5+
This component provides a driver for the RX8130CE Real-Time Clock chip from EPSON.
6+
7+
## Features
8+
9+
- I2C interface (address 0x32)
10+
- Real-time clock with calendar (seconds, minutes, hours, day, month, year, weekday)
11+
- Automatic leap year correction
12+
- Temperature compensated crystal oscillator (TCXO)
13+
- Alarm functions with interrupt output
14+
- Timer functions (countdown timer)
15+
- Square wave output with selectable frequencies
16+
- Low power consumption
17+
- Wide operating voltage range (1.6V to 5.5V)
18+
- std::tm based time APIs
19+
- Device-specific time structures for advanced features
20+
21+
## Datasheet
22+
23+
- [RX8130CE Datasheet](https://support.epson.biz/td/api/doc_check.php?dl=brief_RX8130CE&lang=en)
24+
25+
## Example
26+
27+
The [example](./example) shows how to use the RX8130CE RTC driver to set and get
28+
the time.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# The following lines of boilerplate have to be in your project's CMakeLists
2+
# in this exact order for cmake to work correctly
3+
cmake_minimum_required(VERSION 3.20)
4+
5+
set(ENV{IDF_COMPONENT_MANAGER} "0")
6+
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
7+
8+
# add the component directories that we want to use
9+
set(EXTRA_COMPONENT_DIRS
10+
"../"
11+
"../../../components/base_component"
12+
"../../../components/cli"
13+
"../../../components/format"
14+
"../../../components/logger"
15+
"../../../components/i2c"
16+
"../../../components/task"
17+
"../../../components/base_peripheral"
18+
)
19+
20+
set(
21+
COMPONENTS
22+
"main esptool_py rx8130ce i2c"
23+
CACHE STRING
24+
"List of components to include"
25+
)
26+
27+
project(rx8130ce_example)
28+
29+
set(CMAKE_CXX_STANDARD 20)
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# RX8130CE Example
2+
3+
This example shows how to use the RX8130CE RTC driver to set and get the time.
4+
5+
## How to use example
6+
7+
### Hardware Required
8+
9+
This example can be run on any ESP32-based board, the RX8130CE is connected to
10+
the ESP32 via I2C.
11+
12+
You can use `menuconfig` to configure the I2C pins and frequency used by the example.
13+
14+
### Build and Flash
15+
16+
Build the project and flash it to the board, then run monitor tool to view serial output:
17+
18+
```
19+
idf.py -p PORT flash monitor
20+
```
21+
22+
(Replace PORT with the name of the serial port to use.)
23+
24+
(To exit the serial monitor, type ``Ctrl-]``.)
25+
26+
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
27+
28+
## Example Output
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
idf_component_register(SRC_DIRS "."
2+
INCLUDE_DIRS ".")
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
menu "Example Configuration"
2+
3+
choice EXAMPLE_HARDWARE
4+
prompt "Hardware"
5+
default EXAMPLE_HARDWARE_CUSTOM
6+
help
7+
Select the hardware to run this example on.
8+
9+
config EXAMPLE_HARDWARE_CUSTOM
10+
bool "Custom"
11+
endchoice
12+
13+
config EXAMPLE_I2C_SCL_GPIO
14+
int "SCL GPIO Num"
15+
range 0 50
16+
default 19
17+
help
18+
GPIO number for I2C Master clock line.
19+
20+
config EXAMPLE_I2C_SDA_GPIO
21+
int "SDA GPIO Num"
22+
range 0 50
23+
default 22
24+
help
25+
GPIO number for I2C Master data line.
26+
27+
config EXAMPLE_I2C_CLOCK_SPEED_HZ
28+
int "I2C Clock Speed"
29+
range 100 1000000
30+
default 400000
31+
help
32+
I2C clock speed in Hz.
33+
34+
endmenu

0 commit comments

Comments
 (0)