66#include "drivers/ambient_light.h"
77#include "drivers/i2c.h"
88#include "drivers/periph_config.h"
9- #include "drivers/rtc.h"
109#include "kernel/util/sleep.h"
1110#include "mfg/mfg_info.h"
12- #include "os/mutex.h"
1311#include "system/logging.h"
1412#include "system/passert.h"
1513
5957#define W1160_ALSCTRL_DATA_FORMAT12 (0<<2) /* 1:12bit 0:16bit */
6058#define W1160_DATA_GC_LVL (15<<4) /* gc lelvel 15 */
6159#define W1160_SAT_GC_CONFIG (0x0A)
62- #define W1160_SLOW_IT_CONFIG1 (0x03 ) /* 99ms ((0x3E7+1) * 99us) */
63- #define W1160_SLOW_IT_CONFIG2 (0xE7 )
64- #define W1160_SLOW_ST_CONFIG1 (0x07 ) /* 200ms ((0x7CF+1) * 100us) */
65- #define W1160_SLOW_ST_CONFIG2 (0xCF )
60+ #define W1160_SLOW_IT_CONFIG1 (0x00 ) /* 16.830ms */
61+ #define W1160_SLOW_IT_CONFIG2 (0xA9 )
62+ #define W1160_SLOW_ST_CONFIG1 (0x03 ) /* 480ms */
63+ #define W1160_SLOW_ST_CONFIG2 (0xFF )
6664#define W1160_SAMPLING_EN (1<<1) /* 1:en 0:dis */
6765#define W1160_SAMPLING_DIS (0<<1) /* 1:en 0:dis */
6866#define W1160_CHIP_ID (0xE5)
7876static bool s_initialized ;
7977static uint32_t s_sensor_light_dark_threshold ;
8078
81- // DATA_ALS reads zero while SAMPLING_EN=0, so we cache the last known-good
82- // value. Cache is served during suspend windows and invalidated when the
83- // active window drops (so the next unprimed read does a fresh one-shot
84- // instead of returning a stale value from an earlier primed window).
85- #define W1160_SETTLE_AFTER_ENABLE_MS (W1160_ALS_POLL_TIMEOUT_MS)
86- static PebbleMutex * s_state_mutex ;
87- static bool s_active ;
88- static bool s_sampling_active ;
89- static RtcTicks s_sampling_started_ticks ;
90- static uint16_t s_cached_value ;
91- static bool s_cache_valid ;
92-
9379static bool prv_read_register (uint8_t register_address , uint8_t * result ) {
9480 i2c_use (I2C_W1160 );
9581 bool rv = i2c_read_register_block (I2C_W1160 , register_address , 1 , result );
@@ -104,23 +90,10 @@ static bool prv_write_register(uint8_t register_address, uint8_t datum) {
10490 return rv ;
10591}
10692
107- static bool prv_read_data_register (uint16_t * als_out ) {
108- uint8_t hi , lo ;
109- if (!prv_read_register (W1160_DATA1_ALS_REG , & hi )) {
110- return false;
111- }
112- if (!prv_read_register (W1160_DATA2_ALS_REG , & lo )) {
113- return false;
114- }
115- * als_out = (((uint16_t )hi ) << 8 ) | lo ;
116- return true;
117- }
118-
11993void ambient_light_init (void ) {
12094 uint8_t chip_id ;
12195 bool rv ;
12296
123- s_state_mutex = mutex_create ();
12497 s_sensor_light_dark_threshold = BOARD_CONFIG .ambient_light_dark_threshold ;
12598
12699 psleep (W1160_POR_WAIT_TIME );
@@ -149,125 +122,61 @@ void ambient_light_init(void) {
149122
150123 PBL_ASSERT (rv , "Failed to initialize W1160" );
151124
152- ambient_light_common_init ();
153125 s_initialized = true;
154126}
155127
156- // Block-poll FLG_ALS_DR, then read DATA_ALS. Caller must have SAMPLING_EN=1.
157- static bool prv_read_data_polled (uint16_t * als_out ) {
158- uint8_t flag ;
159- uint32_t elapsed = 0 ;
160- while (true) {
161- if (!prv_read_register (W1160_FLAG1_REG , & flag )) {
162- PBL_LOG_ERR ("Could not read W1160 FLAG1" );
163- return false;
164- }
165- if (flag & W1160_FLG_ALS_DR ) {
166- break ;
167- }
168- if (elapsed >= W1160_ALS_POLL_TIMEOUT_MS ) {
169- PBL_LOG_ERR ("W1160 ALS data-ready timeout" );
170- return false;
171- }
172- psleep (W1160_ALS_POLL_DELAY_MS );
173- elapsed += W1160_ALS_POLL_DELAY_MS ;
174- }
175- return prv_read_data_register (als_out );
176- }
177-
178- // True if SAMPLING_EN has been on long enough for DATA_ALS to hold a real
179- // sample. Caller holds s_state_mutex and has checked s_sampling_active.
180- static bool prv_sampling_has_settled_locked (void ) {
181- const RtcTicks now = rtc_get_ticks ();
182- const RtcTicks elapsed = now - s_sampling_started_ticks ;
183- return elapsed >= ((RtcTicks )W1160_SETTLE_AFTER_ENABLE_MS * RTC_TICKS_HZ / 1000U );
184- }
185-
186128uint32_t ambient_light_get_light_level (void ) {
129+ uint8_t result [2 ] = {0 };
130+ uint16_t als ;
131+ bool rv ;
132+
187133 if (!s_initialized ) {
188134 return 0UL ;
189135 }
190136
191- mutex_lock (s_state_mutex );
192-
193- if (s_active ) {
194- if (s_sampling_active && prv_sampling_has_settled_locked ()) {
195- uint16_t als = 0 ;
196- bool ok = prv_read_data_register (& als );
197- if (ok ) {
198- s_cached_value = als ;
199- s_cache_valid = true;
200- }
201- mutex_unlock (s_state_mutex );
202- return ok ? als : 0UL ;
203- }
204-
205- if (s_cache_valid ) {
206- uint16_t cached = s_cached_value ;
207- mutex_unlock (s_state_mutex );
208- return cached ;
209- }
210-
211- if (!s_sampling_active ) {
212- mutex_unlock (s_state_mutex );
213- return 0UL ;
214- }
215- uint16_t als = 0 ;
216- bool ok = prv_read_data_polled (& als );
217- if (ok ) {
218- s_cached_value = als ;
219- s_cache_valid = true;
220- }
221- mutex_unlock (s_state_mutex );
222- return ok ? als : 0UL ;
223- }
224-
225- // Unprimed one-shot: enable, poll, read, disable.
226- if (!prv_write_register (W1160_STATE_REG , W1160_SAMPLING_EN )) {
137+ rv = prv_write_register (W1160_STATE_REG , W1160_SAMPLING_EN );
138+ if (!rv ) {
227139 PBL_LOG_ERR ("Could not enable W1160 sampling" );
228- mutex_unlock (s_state_mutex );
229140 return 0UL ;
230141 }
231142
232- uint16_t als = 0 ;
233- bool ok = prv_read_data_polled (& als );
234- if (ok ) {
235- s_cached_value = als ;
236- s_cache_valid = true;
143+ uint32_t elapsed = 0 ;
144+ do {
145+ rv = prv_read_register (W1160_FLAG1_REG , & result [0 ]);
146+ if (!rv ) {
147+ PBL_LOG_ERR ("Could not read W1160 FLAG1" );
148+ goto disable_and_fail ;
149+ }
150+ if ((result [0 ] & W1160_FLG_ALS_DR ) == 0U ) {
151+ if (elapsed >= W1160_ALS_POLL_TIMEOUT_MS ) {
152+ PBL_LOG_ERR ("W1160 ALS data-ready timeout" );
153+ goto disable_and_fail ;
154+ }
155+ psleep (W1160_ALS_POLL_DELAY_MS );
156+ elapsed += W1160_ALS_POLL_DELAY_MS ;
157+ }
158+ } while ((result [0 ] & W1160_FLG_ALS_DR ) == 0U );
159+
160+ rv = prv_read_register (W1160_DATA1_ALS_REG , & result [1 ]);
161+ rv &= prv_read_register (W1160_DATA2_ALS_REG , & result [0 ]);
162+ if (!rv ) {
163+ PBL_LOG_ERR ("Could not obtain W1160 data" );
164+ goto disable_and_fail ;
237165 }
238166
239- if (!prv_write_register (W1160_STATE_REG , W1160_SAMPLING_DIS )) {
167+ rv = prv_write_register (W1160_STATE_REG , W1160_SAMPLING_DIS );
168+ if (!rv ) {
240169 PBL_LOG_ERR ("Could not disable W1160 sampling" );
241- mutex_unlock (s_state_mutex );
242170 return 0UL ;
243171 }
244172
245- mutex_unlock (s_state_mutex );
246- return ok ? als : 0UL ;
247- }
173+ als = (((uint16_t )(result [1 ])) << 8 ) | result [0 ];
248174
249- void ambient_light_driver_set_state (bool active , bool sampling ) {
250- if (!s_initialized ) {
251- return ;
252- }
253- mutex_lock (s_state_mutex );
254- if (sampling != s_sampling_active ) {
255- const uint8_t reg = sampling ? W1160_SAMPLING_EN : W1160_SAMPLING_DIS ;
256- if (prv_write_register (W1160_STATE_REG , reg )) {
257- s_sampling_active = sampling ;
258- if (sampling ) {
259- s_sampling_started_ticks = rtc_get_ticks ();
260- }
261- } else {
262- PBL_LOG_ERR ("Could not write W1160 STATE_REG" );
263- }
264- }
265- if (s_active && !active ) {
266- // Window closed: drop the cache so the next unprimed read is fresh.
267- s_cache_valid = false;
268- }
269- s_active = active ;
270- mutex_unlock (s_state_mutex );
175+ return als ;
176+
177+ disable_and_fail :
178+ (void )prv_write_register (W1160_STATE_REG , W1160_SAMPLING_DIS );
179+ return 0UL ;
271180}
272181
273182void command_als_read (void ) {
0 commit comments