55#include "mfg_als_app.h"
66
77#include "applib/app.h"
8- #include "applib/tick_timer_service.h"
98#include "applib/ui/app_window_stack.h"
109#include "applib/ui/text_layer.h"
1110#include "applib/ui/window_private.h"
11+ #include "drivers/rtc.h"
1212#include "kernel/pbl_malloc.h"
1313#include "process_management/pebble_process_md.h"
1414#include "process_state/app_state/app_state.h"
15+ #include "services/common/evented_timer.h"
1516#include "services/common/light.h"
1617#include "system/logging.h"
1718
3233#endif
3334
3435// Test parameters
35- #define COUNTDOWN_SECONDS 5
36- #define SAMPLE_DURATION_SECONDS 5
36+ #define COUNTDOWN_MS 5000
37+ #define SAMPLE_DURATION_MS 5000
38+ #define SAMPLE_INTERVAL_MS 100
3739
3840typedef enum {
3941 ALSStateWaitForStart = 0 ,
@@ -44,6 +46,9 @@ typedef enum {
4446} ALSTestState ;
4547
4648#define AMBIENT_READING_STR_LEN 64
49+
50+ static EventedTimerID s_timer ;
51+
4752typedef struct {
4853 Window * window ;
4954 TextLayer * status_text_layer ;
@@ -52,14 +57,16 @@ typedef struct {
5257 char ambient_reading [AMBIENT_READING_STR_LEN ];
5358
5459 ALSTestState test_state ;
55- uint32_t countdown_remaining ;
56- uint32_t samples_remaining ;
60+ RtcTicks state_start_time ;
5761 uint64_t als_sum ;
5862 uint32_t als_sample_count ;
5963 uint32_t als_average ;
6064} AmbientLightAppData ;
6165
62- static void prv_update_display (AmbientLightAppData * data ) {
66+ static void prv_update_display (void * context ) {
67+ AmbientLightAppData * data = context ;
68+ uint32_t elapsed = (uint32_t )(rtc_get_ticks () - data -> state_start_time );
69+
6370 switch (data -> test_state ) {
6471 case ALSStateWaitForStart :
6572 snprintf (data -> status_text , AMBIENT_READING_STR_LEN , "ALS Test\nPress CENTER\nto start" );
@@ -69,15 +76,44 @@ static void prv_update_display(AmbientLightAppData *data) {
6976 case ALSStateCountdown :
7077 snprintf (data -> status_text , AMBIENT_READING_STR_LEN , "Place in\nlight box" );
7178 snprintf (data -> ambient_reading , AMBIENT_READING_STR_LEN , "Starting in: %" PRIu32 "s" ,
72- data -> countdown_remaining );
79+ (COUNTDOWN_MS - elapsed ) / 1000 + 1 );
80+ if (elapsed >= COUNTDOWN_MS ) {
81+ // Start sampling
82+ data -> test_state = ALSStateSampling ;
83+ data -> state_start_time = rtc_get_ticks ();
84+ data -> als_sum = 0 ;
85+ data -> als_sample_count = 0 ;
86+ PBL_LOG (LOG_LEVEL_INFO , "ALS sampling started" );
87+ }
7388 break ;
7489
7590 case ALSStateSampling : {
76- uint32_t current_level = ambient_light_get_light_level ();
91+ // Take a sample
92+ uint32_t level = ambient_light_get_light_level ();
93+ data -> als_sum += level ;
94+ data -> als_sample_count ++ ;
95+
7796 snprintf (data -> status_text , AMBIENT_READING_STR_LEN , "Sampling..." );
7897 snprintf (data -> ambient_reading , AMBIENT_READING_STR_LEN ,
7998 "Time: %" PRIu32 "s\nCurrent: %" PRIu32 "\nSamples: %" PRIu32 ,
80- data -> samples_remaining , current_level , data -> als_sample_count );
99+ (SAMPLE_DURATION_MS - elapsed ) / 1000 + 1 , level , data -> als_sample_count );
100+
101+ if (elapsed >= SAMPLE_DURATION_MS ) {
102+ // Calculate average and determine pass/fail
103+ data -> als_average = (uint32_t )(data -> als_sum / data -> als_sample_count );
104+
105+ PBL_LOG (LOG_LEVEL_INFO , "ALS test complete - Average: %" PRIu32 " (samples: %" PRIu32 ")" ,
106+ data -> als_average , data -> als_sample_count );
107+
108+ if (data -> als_average >= ALS_MIN_VALUE && data -> als_average <= ALS_MAX_VALUE ) {
109+ data -> test_state = ALSStatePass ;
110+ PBL_LOG (LOG_LEVEL_INFO , "ALS test PASSED" );
111+ } else {
112+ data -> test_state = ALSStateFail ;
113+ PBL_LOG (LOG_LEVEL_ERROR , "ALS test FAILED - Average %" PRIu32 " outside range %d-%d" ,
114+ data -> als_average , ALS_MIN_VALUE , ALS_MAX_VALUE );
115+ }
116+ }
81117 break ;
82118 }
83119
@@ -100,64 +136,6 @@ static void prv_update_display(AmbientLightAppData *data) {
100136 text_layer_set_text (data -> reading_text_layer , data -> ambient_reading );
101137}
102138
103- static void prv_handle_second_tick (struct tm * tick_time , TimeUnits units_changed ) {
104- AmbientLightAppData * data = app_state_get_user_data ();
105-
106- switch (data -> test_state ) {
107- case ALSStateCountdown :
108- if (data -> countdown_remaining > 0 ) {
109- data -> countdown_remaining -- ;
110- if (data -> countdown_remaining == 0 ) {
111- // Start sampling
112- data -> test_state = ALSStateSampling ;
113- data -> samples_remaining = SAMPLE_DURATION_SECONDS ;
114- data -> als_sum = 0 ;
115- data -> als_sample_count = 0 ;
116- PBL_LOG (LOG_LEVEL_INFO , "ALS sampling started" );
117- }
118- }
119- break ;
120-
121- case ALSStateSampling : {
122- // Take a sample
123- uint32_t level = ambient_light_get_light_level ();
124- data -> als_sum += level ;
125- data -> als_sample_count ++ ;
126- PBL_LOG (LOG_LEVEL_INFO , "ALS sample %" PRIu32 ": %" PRIu32 ,
127- data -> als_sample_count , level );
128-
129- if (data -> samples_remaining > 0 ) {
130- data -> samples_remaining -- ;
131- if (data -> samples_remaining == 0 ) {
132- // Calculate average and determine pass/fail
133- data -> als_average = (uint32_t )(data -> als_sum / data -> als_sample_count );
134-
135- PBL_LOG (LOG_LEVEL_INFO , "ALS test complete - Average: %" PRIu32 " (samples: %" PRIu32 ")" ,
136- data -> als_average , data -> als_sample_count );
137-
138- if (data -> als_average >= ALS_MIN_VALUE && data -> als_average <= ALS_MAX_VALUE ) {
139- data -> test_state = ALSStatePass ;
140- PBL_LOG (LOG_LEVEL_INFO , "ALS test PASSED" );
141- } else {
142- data -> test_state = ALSStateFail ;
143- PBL_LOG (LOG_LEVEL_ERROR , "ALS test FAILED - Average %" PRIu32 " outside range %d-%d" ,
144- data -> als_average , ALS_MIN_VALUE , ALS_MAX_VALUE );
145- }
146- }
147- }
148- break ;
149- }
150-
151- case ALSStateWaitForStart :
152- case ALSStatePass :
153- case ALSStateFail :
154- default :
155- // No action needed
156- break ;
157- }
158-
159- prv_update_display (data );
160- }
161139
162140static void prv_select_click_handler (ClickRecognizerRef recognizer , void * context ) {
163141 AmbientLightAppData * data = app_state_get_user_data ();
@@ -168,10 +146,9 @@ static void prv_select_click_handler(ClickRecognizerRef recognizer, void *contex
168146
169147 // Start countdown
170148 data -> test_state = ALSStateCountdown ;
171- data -> countdown_remaining = COUNTDOWN_SECONDS ;
149+ data -> state_start_time = rtc_get_ticks () ;
172150
173- PBL_LOG (LOG_LEVEL_INFO , "ALS test started - countdown %d seconds" , COUNTDOWN_SECONDS );
174- prv_update_display (data );
151+ PBL_LOG (LOG_LEVEL_INFO , "ALS test started - countdown %d ms" , COUNTDOWN_MS );
175152 } else if (data -> test_state == ALSStatePass || data -> test_state == ALSStateFail ) {
176153 // Exit app on second press
177154 app_window_stack_pop (true);
@@ -210,31 +187,28 @@ static void prv_handle_init(void) {
210187
211188 // Initialize state
212189 data -> test_state = ALSStateWaitForStart ;
213- data -> countdown_remaining = 0 ;
214- data -> samples_remaining = 0 ;
190+ data -> state_start_time = rtc_get_ticks ();
215191 data -> als_sum = 0 ;
216192 data -> als_sample_count = 0 ;
217193 data -> als_average = 0 ;
218194
219- prv_update_display (data );
220-
221195 // Set up click handlers
222196 window_set_click_config_provider (data -> window , prv_config_provider );
223197
224198 app_state_set_user_data (data );
225199 app_window_stack_push (data -> window , true);
226200
227- // Subscribe to second tick for timing
228- tick_timer_service_subscribe ( SECOND_UNIT , prv_handle_second_tick );
201+ // Register evented timer for 100ms updates
202+ s_timer = evented_timer_register ( SAMPLE_INTERVAL_MS , true /* repeating */ , prv_update_display , data );
229203
230204 PBL_LOG (LOG_LEVEL_INFO , "ALS test initialized - range: %d-%d" , ALS_MIN_VALUE , ALS_MAX_VALUE );
231205}
232206
233207static void prv_handle_deinit (void ) {
234208 AmbientLightAppData * data = app_state_get_user_data ();
235209
236- // Unsubscribe from tick timer
237- tick_timer_service_unsubscribe ( );
210+ // Cancel evented timer
211+ evented_timer_cancel ( s_timer );
238212
239213 text_layer_destroy (data -> status_text_layer );
240214 text_layer_destroy (data -> reading_text_layer );
0 commit comments