Firmware SDK
twr_opt3001.c
1 #include <twr_opt3001.h>
2 
3 #define _TWR_OPT3001_DELAY_RUN 50
4 #define _TWR_OPT3001_DELAY_INITIALIZATION 50
5 #define _TWR_OPT3001_DELAY_MEASUREMENT 1000
6 
7 static void _twr_opt3001_task_interval(void *param);
8 
9 static void _twr_opt3001_task_measure(void *param);
10 
11 void twr_opt3001_init(twr_opt3001_t *self, twr_i2c_channel_t i2c_channel, uint8_t i2c_address)
12 {
13  memset(self, 0, sizeof(*self));
14 
15  self->_i2c_channel = i2c_channel;
16  self->_i2c_address = i2c_address;
17 
18  self->_task_id_interval = twr_scheduler_register(_twr_opt3001_task_interval, self, TWR_TICK_INFINITY);
19  self->_task_id_measure = twr_scheduler_register(_twr_opt3001_task_measure, self, _TWR_OPT3001_DELAY_RUN);
20 
21  self->_tick_ready = _TWR_OPT3001_DELAY_RUN;
22 
23  twr_i2c_init(self->_i2c_channel, TWR_I2C_SPEED_400_KHZ);
24 }
25 
27 {
28  twr_i2c_memory_write_16b(self->_i2c_channel, self->_i2c_address, 0x01, 0xc810);
29 
30  twr_scheduler_unregister(self->_task_id_interval);
31 
32  twr_scheduler_unregister(self->_task_id_measure);
33 }
34 
35 void twr_opt3001_set_event_handler(twr_opt3001_t *self, void (*event_handler)(twr_opt3001_t *, twr_opt3001_event_t, void *), void *event_param)
36 {
37  self->_event_handler = event_handler;
38  self->_event_param = event_param;
39 }
40 
42 {
43  self->_update_interval = interval;
44 
45  if (self->_update_interval == TWR_TICK_INFINITY)
46  {
47  twr_scheduler_plan_absolute(self->_task_id_interval, TWR_TICK_INFINITY);
48  }
49  else
50  {
51  twr_scheduler_plan_relative(self->_task_id_interval, self->_update_interval);
52 
53  twr_opt3001_measure(self);
54  }
55 }
56 
58 {
59  if (self->_measurement_active)
60  {
61  return false;
62  }
63 
64  self->_measurement_active = true;
65 
66  twr_scheduler_plan_absolute(self->_task_id_measure, self->_tick_ready);
67 
68  return true;
69 }
70 
72 {
73  if (!self->_illuminance_valid)
74  {
75  return false;
76  }
77 
78  *raw = self->_reg_result;
79 
80  return true;
81 }
82 
84 {
85  uint16_t raw;
86 
87  if (!twr_opt3001_get_illuminance_raw(self, &raw))
88  {
89  return false;
90  }
91 
92  *lux = 0.01f * (float) (1 << (raw >> 12)) * (float) (raw & 0xfff);
93 
94  return true;
95 }
96 
97 static void _twr_opt3001_task_interval(void *param)
98 {
99  twr_opt3001_t *self = param;
100 
101  twr_opt3001_measure(self);
102 
103  twr_scheduler_plan_current_relative(self->_update_interval);
104 }
105 
106 static void _twr_opt3001_task_measure(void *param)
107 {
108  twr_opt3001_t *self = param;
109 
110 start:
111 
112  switch (self->_state)
113  {
114  case TWR_OPT3001_STATE_ERROR:
115  {
116  self->_illuminance_valid = false;
117 
118  self->_measurement_active = false;
119 
120  if (self->_event_handler != NULL)
121  {
122  self->_event_handler(self, TWR_OPT3001_EVENT_ERROR, self->_event_param);
123  }
124 
125  self->_state = TWR_OPT3001_STATE_INITIALIZE;
126 
127  return;
128  }
129  case TWR_OPT3001_STATE_INITIALIZE:
130  {
131  self->_state = TWR_OPT3001_STATE_ERROR;
132 
133  if (!twr_i2c_memory_write_16b(self->_i2c_channel, self->_i2c_address, 0x01, 0xc810))
134  {
135  goto start;
136  }
137 
138  self->_state = TWR_OPT3001_STATE_MEASURE;
139 
140  self->_tick_ready = twr_tick_get() + _TWR_OPT3001_DELAY_INITIALIZATION;
141 
142  if (self->_measurement_active)
143  {
144  twr_scheduler_plan_current_absolute(self->_tick_ready);
145  }
146 
147  return;
148  }
149  case TWR_OPT3001_STATE_MEASURE:
150  {
151  self->_state = TWR_OPT3001_STATE_ERROR;
152 
153  if (!twr_i2c_memory_write_16b(self->_i2c_channel, self->_i2c_address, 0x01, 0xca10))
154  {
155  goto start;
156  }
157 
158  self->_state = TWR_OPT3001_STATE_READ;
159 
160  twr_scheduler_plan_current_from_now(_TWR_OPT3001_DELAY_MEASUREMENT);
161 
162  return;
163  }
164  case TWR_OPT3001_STATE_READ:
165  {
166  self->_state = TWR_OPT3001_STATE_ERROR;
167 
168  uint16_t reg_configuration;
169 
170  if (!twr_i2c_memory_read_16b(self->_i2c_channel, self->_i2c_address, 0x01, &reg_configuration))
171  {
172  goto start;
173  }
174 
175  if ((reg_configuration & 0x0680) != 0x0080)
176  {
177  goto start;
178  }
179 
180  if (!twr_i2c_memory_read_16b(self->_i2c_channel, self->_i2c_address, 0x00, &self->_reg_result))
181  {
182  goto start;
183  }
184 
185  self->_illuminance_valid = true;
186 
187  self->_state = TWR_OPT3001_STATE_UPDATE;
188 
189  goto start;
190  }
191  case TWR_OPT3001_STATE_UPDATE:
192  {
193  self->_measurement_active = false;
194 
195  if (self->_event_handler != NULL)
196  {
197  self->_event_handler(self, TWR_OPT3001_EVENT_UPDATE, self->_event_param);
198  }
199 
200  self->_state = TWR_OPT3001_STATE_MEASURE;
201 
202  return;
203  }
204  default:
205  {
206  self->_state = TWR_OPT3001_STATE_ERROR;
207 
208  goto start;
209  }
210  }
211 }
bool twr_opt3001_get_illuminance_lux(twr_opt3001_t *self, float *lux)
Get measured illuminance in lux.
Definition: twr_opt3001.c:83
void twr_scheduler_plan_relative(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to tick relative from current spin.
bool twr_i2c_memory_write_16b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint16_t data)
Memory write 2 bytes to I2C channel.
Definition: twr_i2c.c:420
void twr_scheduler_plan_current_relative(twr_tick_t tick)
Schedule current task to tick relative from current spin.
twr_scheduler_task_id_t twr_scheduler_register(void(*task)(void *), void *param, twr_tick_t tick)
Register task in scheduler.
Definition: twr_scheduler.c:53
void twr_scheduler_plan_current_absolute(twr_tick_t tick)
Schedule current task to absolute tick.
twr_opt3001_event_t
Callback events.
Definition: twr_opt3001.h:13
struct twr_opt3001_t twr_opt3001_t
OPT3001 instance.
Definition: twr_opt3001.h:25
void twr_opt3001_set_update_interval(twr_opt3001_t *self, twr_tick_t interval)
Set measurement interval.
Definition: twr_opt3001.c:41
void twr_scheduler_plan_current_from_now(twr_tick_t tick)
Schedule current task to tick relative from now.
void twr_opt3001_set_event_handler(twr_opt3001_t *self, void(*event_handler)(twr_opt3001_t *, twr_opt3001_event_t, void *), void *event_param)
Set callback function.
Definition: twr_opt3001.c:35
void twr_opt3001_init(twr_opt3001_t *self, twr_i2c_channel_t i2c_channel, uint8_t i2c_address)
Initialize OPT3001 driver.
Definition: twr_opt3001.c:11
void twr_i2c_init(twr_i2c_channel_t channel, twr_i2c_speed_t speed)
Initialize I2C channel.
Definition: twr_i2c.c:57
void twr_opt3001_deinit(twr_opt3001_t *self)
Deinitialize OPT3001 driver.
Definition: twr_opt3001.c:26
bool twr_opt3001_measure(twr_opt3001_t *self)
Start measurement manually.
Definition: twr_opt3001.c:57
bool twr_i2c_memory_read_16b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint16_t *data)
Memory read 2 bytes from I2C channel.
Definition: twr_i2c.c:449
uint64_t twr_tick_t
Timestamp data type.
Definition: twr_tick.h:16
bool twr_opt3001_get_illuminance_raw(twr_opt3001_t *self, uint16_t *raw)
Get measured illuminance as raw value.
Definition: twr_opt3001.c:71
twr_tick_t twr_tick_get(void)
Get absolute timestamp since start of program.
Definition: twr_tick.c:7
twr_i2c_channel_t
I2C channels.
Definition: twr_i2c.h:15
void twr_scheduler_unregister(twr_scheduler_task_id_t task_id)
Unregister specified task.
Definition: twr_scheduler.c:77
#define TWR_TICK_INFINITY
Maximum timestamp value.
Definition: twr_tick.h:12
void twr_scheduler_plan_absolute(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to absolute tick.
I2C communication speed is 400 kHz.
Definition: twr_i2c.h:36