Skip to content

Commit cce6f71

Browse files
refactor: increase modularity of the firmware (#5)
* refactor: isolate weekday names to ui components * chore: change tabs to spaces * refactor: rename display library to userinterface * chore: remove unused imports * refactor: expose display in its own subsystem * refactor: hide lvgl implementation in the subsystem * refactor: move ui functions to userinterface subsystem * fix: remove unix_time for all * feat: use dt aliases for devices
1 parent f669df6 commit cce6f71

File tree

16 files changed

+391
-276
lines changed

16 files changed

+391
-276
lines changed

boards/esp32.overlay

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
&timer0 {
2-
status = "okay";
1+
/ {
2+
aliases {
3+
rtccounterdevice = &rtc_timer;
4+
lcddisplaydevice = &gc9a01;
5+
lcdpwmdevice = &pwm_lcd0;
6+
};
37
};
48

59
&rtc_timer {

src/bluetooth/infrastructure.c

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -12,75 +12,75 @@
1212
LOG_MODULE_REGISTER(ZephyrWatch_BLE, LOG_LEVEL_INF);
1313

1414
static const struct bt_data m_ad[] = {
15-
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
16-
BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_CTS_VAL)),
15+
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
16+
BT_DATA_BYTES(BT_DATA_UUID16_ALL, BT_UUID_16_ENCODE(BT_UUID_CTS_VAL)),
1717
};
1818

1919
static const struct bt_data m_sd[] = {
20-
BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
20+
BT_DATA(BT_DATA_NAME_COMPLETE, CONFIG_BT_DEVICE_NAME, sizeof(CONFIG_BT_DEVICE_NAME) - 1),
2121
};
2222

2323
static void m_connected_callback(struct bt_conn *conn, uint8_t err) {
24-
if (err) LOG_ERR("Connection failed (err %u).", err);
25-
else {
26-
char addr[BT_ADDR_LE_STR_LEN];
27-
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
28-
LOG_INF("Connection established to %s.", addr);
29-
}
24+
if (err) LOG_ERR("Connection failed (err %u).", err);
25+
else {
26+
char addr[BT_ADDR_LE_STR_LEN];
27+
bt_addr_le_to_str(bt_conn_get_dst(conn), addr, sizeof(addr));
28+
LOG_INF("Connection established to %s.", addr);
29+
}
3030
}
3131

3232
static void m_disconnected_callback(struct bt_conn *conn, uint8_t reason) {
33-
LOG_INF("Disconnected (reason 0x%02x).", reason);
33+
LOG_INF("Disconnected (reason 0x%02x).", reason);
3434
}
3535

3636
BT_CONN_CB_DEFINE(conn_callbacks) = {
37-
.connected = m_connected_callback,
38-
.disconnected = m_disconnected_callback,
37+
.connected = m_connected_callback,
38+
.disconnected = m_disconnected_callback,
3939
};
4040

4141
/* The API function to enable Bluetooth and start advertisement. */
4242
uint8_t enable_bluetooth_subsystem() {
43-
int err;
44-
43+
int err;
44+
4545
err = bt_enable(NULL);
46-
if (err) {
47-
LOG_ERR("Bluetooth init failed (err %d).", err);
48-
return err;
49-
}
46+
if (err) {
47+
LOG_ERR("Bluetooth init failed (err %d).", err);
48+
return err;
49+
}
5050

51-
LOG_DBG("Bluetooth initialized.");
51+
LOG_DBG("Bluetooth initialized.");
5252

53-
if (IS_ENABLED(CONFIG_SETTINGS)) {
54-
settings_load();
55-
}
53+
if (IS_ENABLED(CONFIG_SETTINGS)) {
54+
settings_load();
55+
}
5656

57-
err = bt_le_adv_start(BT_LE_ADV_CONN, m_ad, ARRAY_SIZE(m_ad), m_sd, ARRAY_SIZE(m_sd));
58-
if (err) {
59-
LOG_ERR("Advertising failed to start (err %d).", err);
60-
return err;
61-
}
57+
err = bt_le_adv_start(BT_LE_ADV_CONN, m_ad, ARRAY_SIZE(m_ad), m_sd, ARRAY_SIZE(m_sd));
58+
if (err) {
59+
LOG_ERR("Advertising failed to start (err %d).", err);
60+
return err;
61+
}
6262

63-
LOG_DBG("Advertising successfully started.");
63+
LOG_DBG("Advertising successfully started.");
6464
return 0;
6565
}
6666

6767
uint8_t disable_bluetooth_subsystem() {
68-
int err;
68+
int err;
6969

70-
err = bt_le_adv_stop();
71-
if (err) {
72-
LOG_ERR("Advertising failed to stop (err %d).", err);
73-
return err;
74-
}
70+
err = bt_le_adv_stop();
71+
if (err) {
72+
LOG_ERR("Advertising failed to stop (err %d).", err);
73+
return err;
74+
}
7575

76-
LOG_DBG("Advertising successfully stopped.");
76+
LOG_DBG("Advertising successfully stopped.");
7777

78-
err = bt_disable();
79-
if (err) {
80-
LOG_ERR("Bluetooth failed to disable (err %d).", err);
81-
return err;
82-
}
78+
err = bt_disable();
79+
if (err) {
80+
LOG_ERR("Bluetooth failed to disable (err %d).", err);
81+
return err;
82+
}
8383

84-
LOG_DBG("Bluetooth disabled.");
85-
return 0;
84+
LOG_DBG("Bluetooth disabled.");
85+
return 0;
8686
}

src/bluetooth/services/current_time_service.c

Lines changed: 32 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -18,51 +18,51 @@ LOG_MODULE_REGISTER(ZephyrWatch_BLE_CTS, LOG_LEVEL_INF);
1818

1919
/* Current Time Service Write Callback */
2020
static ssize_t m_time_write_callback(
21-
struct bt_conn *conn,
22-
const struct bt_gatt_attr *attr,
23-
const void *buf,
24-
uint16_t len,
25-
uint16_t offset,
26-
uint8_t flags) {
21+
struct bt_conn *conn,
22+
const struct bt_gatt_attr *attr,
23+
const void *buf,
24+
uint16_t len,
25+
uint16_t offset,
26+
uint8_t flags) {
2727

28-
// Check if we received exactly 4 bytes for UNIX timestamp
29-
if (len != 4 || offset != 0) {
30-
LOG_ERR("Invalid write length or offset. Expected 4 bytes at offset 0, got %d bytes at offset %d", len, offset);
31-
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
32-
}
28+
// Check if we received exactly 4 bytes for UNIX timestamp
29+
if (len != 4 || offset != 0) {
30+
LOG_ERR("Invalid write length or offset. Expected 4 bytes at offset 0, got %d bytes at offset %d", len, offset);
31+
return BT_GATT_ERR(BT_ATT_ERR_INVALID_OFFSET);
32+
}
3333

34-
// Extract the UNIX timestamp from the buffer (assuming little-endian)
35-
uint32_t unix_timestamp = sys_le32_to_cpu(*(uint32_t *)buf);
36-
LOG_DBG("Received UNIX timestamp: %u", unix_timestamp);
34+
// Extract the UNIX timestamp from the buffer (assuming little-endian)
35+
uint32_t unix_timestamp = sys_le32_to_cpu(*(uint32_t *)buf);
36+
LOG_DBG("Received UNIX timestamp: %u", unix_timestamp);
3737

38-
// Get the device twin instance to get the UTC zone
39-
device_twin_t *device_twin = get_device_twin_instance();
40-
if (device_twin == NULL) {
41-
LOG_ERR("Failed to get device twin instance.");
42-
return BT_GATT_ERR(BT_ATT_ERR_UNLIKELY);
43-
}
38+
// Get the device twin instance to get the UTC zone
39+
device_twin_t *device_twin = get_device_twin_instance();
40+
if (device_twin == NULL) {
41+
LOG_ERR("Failed to get device twin instance.");
42+
return BT_GATT_ERR(BT_ATT_ERR_UNLIKELY);
43+
}
4444
device_twin->unix_time = unix_timestamp;
4545
trigger_ui_update();
4646

4747
// Convert UNIX timestamp to local time using the device's UTC zone to print.
48-
datetime_t local_time = unix_to_localtime(unix_timestamp, device_twin->utc_zone);
49-
LOG_INF("Current time updated to local time: %04d-%02d-%02d %02d:%02d:%02d (UTC%+d)",
50-
local_time.year, local_time.month, local_time.day,
51-
local_time.hour, local_time.minute, local_time.second,
52-
device_twin->utc_zone);
48+
datetime_t local_time = unix_to_localtime(unix_timestamp, device_twin->utc_zone);
49+
LOG_INF("Current time updated to local time: %04d-%02d-%02d %02d:%02d:%02d (UTC%+d)",
50+
local_time.year, local_time.month, local_time.day,
51+
local_time.hour, local_time.minute, local_time.second,
52+
device_twin->utc_zone);
5353

54-
return len;
54+
return len;
5555
}
5656

5757
/* Dummy data for GATT characteristic - not used for actual data storage */
5858
static uint8_t dummy_data[4] = {0};
5959

6060
/* Current Time Service Declaration */
6161
BT_GATT_SERVICE_DEFINE(cts_cvs,
62-
BT_GATT_PRIMARY_SERVICE(BT_UUID_CTS),
63-
BT_GATT_CHARACTERISTIC(
64-
BT_UUID_CTS_CURRENT_TIME,
65-
BT_GATT_CHRC_WRITE,
66-
BT_GATT_PERM_WRITE,
67-
NULL, m_time_write_callback, dummy_data),
62+
BT_GATT_PRIMARY_SERVICE(BT_UUID_CTS),
63+
BT_GATT_CHARACTERISTIC(
64+
BT_UUID_CTS_CURRENT_TIME,
65+
BT_GATT_CHRC_WRITE,
66+
BT_GATT_PERM_WRITE,
67+
NULL, m_time_write_callback, dummy_data),
6868
);

src/datetime/datetime.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,16 @@
1313
#include "devicetwin/devicetwin.h"
1414
#include "datetime/datetime.h"
1515

16+
// Get devices from the device tree.
17+
#define RTC_COUNTER_DEVICE DT_ALIAS(rtccounterdevice)
18+
1619
// Configuration for counter alarm.
1720
#define ALARM_INTERVAL_US 1000000
1821
#define ALARM_CHANNEL_ID 0
1922

2023
/* Register a logger for this library. */
2124
LOG_MODULE_REGISTER(ZephyrWatch_Datetime, LOG_LEVEL_INF);
2225

23-
/* Global unix_time variable to store datetime. */
24-
uint32_t unix_time = 1748554674;
25-
2626
/* Disable flag to not set alarm again in ISR.
2727
* 0: Set alarm again.
2828
* !: Do not set alarm again.
@@ -57,8 +57,7 @@ void rtc_isr(const struct device *dev, uint8_t channel_id, uint32_t ticks, void
5757
}
5858

5959
// Update device's current time.
60-
device_twin_t *device_twin = get_device_twin_instance();
61-
device_twin->unix_time = device_twin->unix_time + 1;
60+
set_current_unix_time(get_current_unix_time() + 1);
6261
}
6362

6463
/* ENABLE_DATETIME_SUBSYSTEM
@@ -69,7 +68,7 @@ int enable_datetime_subsystem() {
6968
int ret;
7069

7170
// Set the real time counter to trigger an callback every second.
72-
const struct device *real_time_counter = DEVICE_DT_GET(DT_NODELABEL(rtc_timer));
71+
const struct device *real_time_counter = DEVICE_DT_GET(RTC_COUNTER_DEVICE);
7372
if (!device_is_ready(real_time_counter)) {
7473
LOG_ERR("Real time counter device is not ready.");
7574
return -ENODEV;
@@ -107,7 +106,7 @@ int disable_datetime_subsystem() {
107106
int ret;
108107

109108
// Set the real time counter to trigger an callback every second.
110-
const struct device *real_time_counter = DEVICE_DT_GET(DT_NODELABEL(rtc_timer));
109+
const struct device *real_time_counter = DEVICE_DT_GET(RTC_COUNTER_DEVICE);
111110
if (!device_is_ready(real_time_counter)) {
112111
LOG_ERR("Real time counter device is not ready.");
113112
return -ENODEV;
@@ -133,22 +132,24 @@ int disable_datetime_subsystem() {
133132
* Return the UNIX epochs of the current time.
134133
*/
135134
uint32_t get_current_unix_time() {
136-
return unix_time;
135+
device_twin_t *device_twin = get_device_twin_instance();
136+
return device_twin->unix_time;
137137
}
138138

139139
/* SET_CURRENT_UNIX_TIME
140140
* Set the current time with UNIX epoch.
141141
*/
142142
int set_current_unix_time(uint32_t new_time) {
143-
unix_time = new_time;
143+
device_twin_t *device_twin = get_device_twin_instance();
144+
device_twin->unix_time = new_time;
144145
return 0;
145146
}
146147

147148
/* GET_CURRENT_LOCAL_TIME
148149
* Return the current time in datetime_t object in local time zone.
149150
*/
150151
datetime_t get_current_local_time(int8_t utc_offset_hours) {
151-
return unix_to_localtime(unix_time, utc_offset_hours);
152+
return unix_to_localtime(get_current_unix_time(), utc_offset_hours);
152153
}
153154

154155
/* UNIX_TO_LOCALTIME

src/display/display.c

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,74 @@
1-
/** Display initialization implementation for LVGL-based UI setup.
2-
* Implements display system initialization, theme configuration, and home screen loading for the smartwatch interface.
1+
/** Display Subsystem for ZephyrWatch.
2+
* Provides functions to initialize the display system.
33
*
44
* @license GNU v3
55
* @maintainer electricalgorithm @ github
66
*/
77

8-
#include "lvgl.h"
98
#include "display/display.h"
9+
#include <zephyr/drivers/display.h>
10+
#include <zephyr/drivers/pwm.h>
11+
#include <zephyr/logging/log.h>
1012

13+
// Get a logger for the display subsystem.
14+
LOG_MODULE_REGISTER(ZephyrWatch_Display, LOG_LEVEL_INF);
1115

12-
void display_init() {
13-
lv_disp_t *display = lv_disp_get_default();
14-
lv_theme_t *theme = lv_theme_default_init(
15-
display,
16-
lv_palette_main(LV_PALETTE_BLUE),
17-
lv_palette_main(LV_PALETTE_RED),
18-
true,
19-
LV_FONT_DEFAULT
20-
);
21-
lv_disp_set_theme(display, theme);
22-
home_screen_init();
23-
lv_disp_load_scr(home_screen);
16+
// Get devices from the device tree.
17+
#define DISPLAY_DEVICE DT_ALIAS(lcddisplaydevice)
18+
#define DISPLAY_PWM_DEVICE DT_ALIAS(lcdpwmdevice)
19+
20+
/* ENABLE_DISPLAY_SUBSYSTEM
21+
* Set the Zephyr display device and set backlight.
22+
*/
23+
int enable_display_subsystem() {
24+
int ret;
25+
26+
const struct device *display_dev = DEVICE_DT_GET(DISPLAY_DEVICE);
27+
ret = device_is_ready(display_dev);
28+
if (!ret) {
29+
LOG_ERR("Display device is not ready, exiting... (RET: %d)", ret);
30+
return 1;
31+
}
32+
LOG_DBG("Display device is ready.");
33+
34+
const struct pwm_dt_spec backlight = PWM_DT_SPEC_GET_BY_IDX(DISPLAY_PWM_DEVICE, 0);
35+
ret = pwm_is_ready_dt(&backlight);
36+
if (!ret) {
37+
LOG_ERR("PWM device is not ready, exiting... (RET: %d)", ret);
38+
return 1;
39+
}
40+
LOG_DBG("PWM device is ready.");
41+
42+
ret = pwm_set_dt(&backlight, 500, 250);
43+
if (ret) {
44+
LOG_ERR("Failed to set PWM pulse, exiting... (RET: %d)", ret);
45+
return ret;
46+
}
47+
LOG_DBG("PWM pulse for LCD backlight set.");
48+
49+
ret = display_blanking_off(display_dev);
50+
if (ret) {
51+
LOG_ERR("Failed to set blanking off, exiting... (RET: %d)", ret);
52+
return ret;
53+
}
54+
LOG_DBG("Set the blanking off.");
55+
56+
return 0;
2457
}
58+
59+
60+
/* ENABLE_DISPLAY_SUBSYSTEM
61+
* Disable the Zephyr display device and set backlight to 0.
62+
*/
63+
int disable_display_subsystem() {
64+
LOG_DBG("Not implemented yet.");
65+
return 0;
66+
}
67+
68+
/* CHANGE_BRIGHTNESS
69+
* Change the brightness based on a percentage.
70+
*/
71+
int change_brightness(uint8_t perc) {
72+
LOG_DBG("Not implemented yet.");
73+
return 0;
74+
}

0 commit comments

Comments
 (0)