1- /**
2- * @file src/main.c
3- *
4- * @brief Main file for the application.
5- */
6-
71#include <stdio.h>
82#include <string.h>
93
1913#include <zephyr/drivers/gpio.h>
2014#include <zephyr/drivers/pwm.h>
2115#include <zephyr/bluetooth/bluetooth.h>
16+ #include <zephyr/drivers/counter.h>
2217
2318#include "display/display.h"
2419#include "display/screens/home/home.h"
2823#include "bluetooth/services/current_time_service.h"
2924
3025// Define the logger.
31- LOG_MODULE_REGISTER (ZephyrWatch , LOG_LEVEL_DBG );
26+ LOG_MODULE_REGISTER (ZephyrWatch , LOG_LEVEL_INF );
3227
3328// Global values to hold time.
3429uint32_t unix_time = 1748554674 ;
3530int8_t utc_zone = +2 ;
3631const char * weekdays [] = { "SUN" , "MON" , "TUE" , "WED" , "THU" , "FRI" , "SAT" };
3732
3833// Define the timer callbacks' prototypes.
39- void update_unix_time_callback (struct k_timer * timer );
4034void update_clock_view_callback (struct k_timer * timer );
41- void update_date_day_view_callback (struct k_timer * timer );
4235// Define the work queues' prototypes.
4336void clock_update_worker (struct k_work * work );
4437void date_day_update_worker (struct k_work * work );
@@ -51,9 +44,30 @@ static struct k_work clock_update_work;
5144static struct k_work date_day_update_work ;
5245
5346// Define timers.
54- K_TIMER_DEFINE (unix_time_timer , update_unix_time_callback , NULL );
47+ // K_TIMER_DEFINE(unix_time_timer, update_unix_time_callback, NULL);
5548K_TIMER_DEFINE (clock_view_timer , update_clock_view_callback , NULL );
56- K_TIMER_DEFINE (date_day_view_timer , update_date_day_view_callback , NULL );
49+
50+ // Create an alarm for 1 second.
51+ #define ALARM_INTERVAL_US 1000000
52+ #define ALARM_CHANNEL_ID 0
53+
54+
55+ void rtc_counter_isr (
56+ const struct device * dev ,
57+ uint8_t channel_id ,
58+ uint32_t ticks ,
59+ void * user_data )
60+ {
61+ // Cast alarm config from user data.
62+ struct counter_alarm_cfg * alarm_cfg = user_data ;
63+
64+ // Reset alarm
65+ alarm_cfg -> ticks = counter_us_to_ticks (dev , ALARM_INTERVAL_US );
66+ counter_set_channel_alarm (dev , ALARM_CHANNEL_ID , alarm_cfg );
67+
68+ // Update the second.
69+ unix_time ++ ;
70+ }
5771
5872
5973int main (void ) {
@@ -65,61 +79,54 @@ int main(void) {
6579 LOG_ERR ("Cannot create device twin instance." );
6680 return 0 ;
6781 }
68- LOG_INF ("Device twin instance created successfully." );
69-
70- // Start the timer to track the real time.
71- k_timer_start (& unix_time_timer , K_MSEC (60 ), K_SECONDS (1 ));
72- k_timer_start (& clock_view_timer , K_MSEC (60 ), K_SECONDS (30 ));
73- k_timer_start (& date_day_view_timer , K_MSEC (60 ), K_MINUTES (1 ));
74- LOG_INF ("Timers started successfully." );
82+ LOG_DBG ("Device twin instance created successfully." );
7583
7684 // Check if the display device is ready.
7785 const struct device * display_dev = DEVICE_DT_GET (DT_CHOSEN (zephyr_display ));
7886 if (!device_is_ready (display_dev )) {
7987 LOG_ERR ("Display device is not ready, exiting..." );
8088 return 0 ;
8189 }
82- LOG_INF ("Display device is ready." );
90+ LOG_DBG ("Display device is ready." );
8391
8492 const struct pwm_dt_spec backlight = PWM_DT_SPEC_GET_BY_IDX (DT_NODELABEL (pwm_lcd0 ), 0 );
8593 if (!pwm_is_ready_dt (& backlight )) {
8694 LOG_ERR ("PWM device is not ready, exiting..." );
8795 return 0 ;
8896 }
89- LOG_INF ("PWM device is ready." );
97+ LOG_DBG ("PWM device is ready." );
9098
9199 // Initialize the PWM device.
92100 ret = pwm_set_dt (& backlight , 500 , 250 );
93101 if (ret < 0 ) {
94102 LOG_ERR ("Failed to set PWM pulse, exiting..." );
95103 return 0 ;
96104 }
97- LOG_INF ("PWM pulse for LCD backlight set." );
105+ LOG_DBG ("PWM pulse for LCD backlight set." );
98106
99107 // Initialize the display device with initial GUI.
100108 display_init ();
101- LOG_INF ("UI initialized." );
109+ LOG_DBG ("UI initialized." );
102110
103111 // Start the UI work queue.
104112 k_work_queue_start (& ui_work_q , ui_stack_area , K_THREAD_STACK_SIZEOF (ui_stack_area ),
105113 K_PRIO_PREEMPT (5 ), NULL );
106- LOG_INF ("UI work queue started." );
114+ LOG_DBG ("UI work queue started." );
107115
108116 // Initialize the work items.
109117 k_work_init (& clock_update_work , clock_update_worker );
110118 k_work_init (& date_day_update_work , date_day_update_worker );
111119
112- // Start timers after work queue is ready - reduced frequency to prevent queue overflow
113- k_timer_start (& unix_time_timer , K_MSEC (1000 ), K_SECONDS (1 ));
114- k_timer_start (& clock_view_timer , K_MSEC (2000 ), K_SECONDS (30 ));
115- k_timer_start (& date_day_view_timer , K_MSEC (3000 ), K_MINUTES (1 ));
116- LOG_INF ("Timers are set." );
120+ // Start timers after work queue is ready - reduced frequency to prevent queue overflow.
121+ k_timer_start (& clock_view_timer , K_MSEC (2000 ), K_SECONDS (10 ));
122+ k_work_submit_to_queue (& ui_work_q , & date_day_update_work );
123+ LOG_DBG ("Timers are set." );
117124
118125 // Initialize LVGL first and let UI stabilize
119126 lv_task_handler ();
120127 display_blanking_off (display_dev );
121128
122- // Give the system more time to stabilize before initializing Bluetooth
129+ // Give the system more time to stabilize before initializing Bluetooth.
123130 k_sleep (K_SECONDS (2 ));
124131
125132 // Initialize the Bluetooth stack.
@@ -128,7 +135,36 @@ int main(void) {
128135 LOG_ERR ("Bluetooth init failed (ret %d)." , ret );
129136 return ret ;
130137 }
131- LOG_INF ("Bluetooth subsytem is initialized." );
138+ LOG_INF ("Started to advertise with Bluetooth." );
139+
140+ // Set the real time counter to trigger an callback every second.
141+ const struct device * real_time_counter = DEVICE_DT_GET (DT_NODELABEL (rtc_timer ));
142+ if (!device_is_ready (real_time_counter )) {
143+ LOG_ERR ("Real time counter device is not ready." );
144+ return - ENODEV ;
145+ }
146+ LOG_DBG ("Real time counter device is ready." );
147+
148+ // Configure real time counter to track tine.
149+ ret = counter_start (real_time_counter );
150+ if (ret ) {
151+ LOG_ERR ("Failed to start real time counter (ret %d)." , ret );
152+ return ret ;
153+ }
154+ LOG_DBG ("Real time counter started successfully." );
155+
156+ struct counter_alarm_cfg alarm_cfg = {
157+ .flags = 0 ,
158+ .ticks = counter_us_to_ticks (real_time_counter , ALARM_INTERVAL_US ),
159+ .callback = rtc_counter_isr ,
160+ .user_data = & alarm_cfg ,
161+ };
162+ ret = counter_set_channel_alarm (real_time_counter , ALARM_CHANNEL_ID , & alarm_cfg );
163+ if (ret ) {
164+ LOG_ERR ("Failed to set channel alarm (ret %d)." , ret );
165+ return ret ;
166+ }
167+ LOG_DBG ("Channel alarm set successfully." );
132168
133169 while (1 ) {
134170 lv_task_handler ();
@@ -141,35 +177,18 @@ int main(void) {
141177 * It sends an event to the UI work queue to update the clock view.
142178 */
143179void update_clock_view_callback (struct k_timer * timer ) {
180+ LOG_DBG ("Pushing clock_update_work work to ui_work_q." );
144181 k_work_submit_to_queue (& ui_work_q , & clock_update_work );
145182}
146183
147- /* UPDATE_DATE_DAY_VIEW_CALLBACK
148- * This function is called by the timer to update the date and day views.
149- * It sends an event to the UI work queue to update the date and day views.
150- */
151- void update_date_day_view_callback (struct k_timer * timer ) {
152- k_work_submit_to_queue (& ui_work_q , & date_day_update_work );
153- }
154-
155- /* UPDATE_UNIX_TIME_CALLBACK
156- * This timer callback function runs every second to update
157- * the value inside the unix_time to track the real time.
158- * It is neccessary to use timers instead of configuring the
159- * RTC because the PoC board does not have RTC support in Zephyr.
160- */
161- void update_unix_time_callback (struct k_timer * timer ) {
162- unix_time += 1 ;
163- }
164-
165184/* UPDATE_GLOBAL_UNIX_TIME
166185 * Function to update the global unix time from external sources
167186 * (like Bluetooth CTS). This function will be called by the external
168187 * sources.
169188 */
170189void update_global_unix_time (uint32_t unix_timestamp ) {
171190 unix_time = unix_timestamp ;
172- LOG_INF ("Global UNIX time updated to: %u" , unix_time );
191+ LOG_INF ("unix_time is updated to: %u" , unix_time );
173192
174193 // Only submit if not already pending.
175194 if (!k_work_is_pending (& clock_update_work )) {
@@ -187,6 +206,7 @@ void update_global_unix_time(uint32_t unix_timestamp) {
187206 * calls the home screen set clock function.
188207 */
189208void clock_update_worker (struct k_work * work ) {
209+ LOG_DBG ("unix_time=%u" , unix_time );
190210 // Get the device twin to find UTC zone.
191211 device_twin_t * device_twin = get_device_twin_instance ();
192212
@@ -199,6 +219,12 @@ void clock_update_worker(struct k_work *work) {
199219 if (ret != 0 ) {
200220 LOG_ERR ("Failed to update the clock view." );
201221 }
222+
223+ // Send a date day update worker if 00:00.
224+ if (device_twin -> current_time .hour == 0 && device_twin -> current_time .minute == 0 ) {
225+ k_work_submit_to_queue (& ui_work_q , & date_day_update_work );
226+ LOG_DBG ("Date and day update worker submitted to queue." );
227+ }
202228}
203229
204230/* DATE_DAY_UPDATE_WORKER
0 commit comments