Firmware SDK
twr_mpl3115a2.c
1 #include <twr_mpl3115a2.h>
2 
3 #define _TWR_MPL3115A2_DELAY_RUN 1500
4 #define _TWR_MPL3115A2_DELAY_INITIALIZATION 1500
5 #define _TWR_MPL3115A2_DELAY_MEASUREMENT 1500
6 
7 static void _twr_mpl3115a2_task_interval(void *param);
8 
9 static void _twr_mpl3115a2_task_measure(void *param);
10 
11 void twr_mpl3115a2_init(twr_mpl3115a2_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_mpl3115a2_task_interval, self, TWR_TICK_INFINITY);
19  self->_task_id_measure = twr_scheduler_register(_twr_mpl3115a2_task_measure, self, _TWR_MPL3115A2_DELAY_RUN);
20 
21  self->_tick_ready = twr_tick_get() + _TWR_MPL3115A2_DELAY_RUN;
22 
23  twr_i2c_init(self->_i2c_channel, TWR_I2C_SPEED_400_KHZ);
24 }
25 
27 {
28  twr_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x26, 0x04);
29 
30  twr_scheduler_unregister(self->_task_id_interval);
31 
32  twr_scheduler_unregister(self->_task_id_measure);
33 }
34 
35 void twr_mpl3115a2_set_event_handler(twr_mpl3115a2_t *self, void (*event_handler)(twr_mpl3115a2_t *, twr_mpl3115a2_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 
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->_altitude_valid)
74  {
75  return false;
76  }
77 
78  int32_t out_pa = (uint32_t) self->_reg_out_p_msb_altitude << 24 | (uint32_t) self->_reg_out_p_csb_altitude << 16 | (uint32_t) (self->_reg_out_p_lsb_altitude & 0xf0) << 8;
79 
80  *meter = ((float) out_pa) / 65536.f;
81 
82  return true;
83 }
84 
86 {
87  if (!self->_pressure_valid)
88  {
89  return false;
90  }
91 
92  uint32_t out_p = (uint32_t) self->_reg_out_p_msb_pressure << 16 | (uint32_t) self->_reg_out_p_csb_pressure << 8 | (uint32_t) self->_reg_out_p_lsb_pressure;
93 
94  *pascal = ((float) out_p) / 64.f;
95 
96  return true;
97 }
98 
99 static void _twr_mpl3115a2_task_interval(void *param)
100 {
101  twr_mpl3115a2_t *self = param;
102 
103  twr_mpl3115a2_measure(self);
104 
105  twr_scheduler_plan_current_relative(self->_update_interval);
106 }
107 
108 static void _twr_mpl3115a2_task_measure(void *param)
109 {
110  twr_mpl3115a2_t *self = param;
111 
112 start:
113 
114  switch (self->_state)
115  {
116  case TWR_MPL3115A2_STATE_ERROR:
117  {
118  self->_altitude_valid = false;
119  self->_pressure_valid = false;
120 
121  self->_measurement_active = false;
122 
123  if (self->_event_handler != NULL)
124  {
125  self->_event_handler(self, TWR_MPL3115A2_EVENT_ERROR, self->_event_param);
126  }
127 
128  self->_state = TWR_MPL3115A2_STATE_INITIALIZE;
129 
130  return;
131  }
132  case TWR_MPL3115A2_STATE_INITIALIZE:
133  {
134  twr_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x26, 0x04);
135 
136  self->_state = TWR_MPL3115A2_STATE_MEASURE_ALTITUDE;
137 
138  self->_tick_ready = twr_tick_get() + _TWR_MPL3115A2_DELAY_INITIALIZATION;
139 
140  if (self->_measurement_active)
141  {
142  twr_scheduler_plan_current_absolute(self->_tick_ready);
143  }
144 
145  return;
146  }
147  case TWR_MPL3115A2_STATE_MEASURE_ALTITUDE:
148  {
149  self->_state = TWR_MPL3115A2_STATE_ERROR;
150 
151  if (!twr_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x26, 0xb8))
152  {
153  goto start;
154  }
155 
156  if (!twr_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x13, 0x07))
157  {
158  goto start;
159  }
160 
161  if (!twr_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x26, 0xba))
162  {
163  goto start;
164  }
165 
166  self->_state = TWR_MPL3115A2_STATE_READ_ALTITUDE;
167 
168  twr_scheduler_plan_current_from_now(_TWR_MPL3115A2_DELAY_MEASUREMENT);
169 
170  return;
171  }
172  case TWR_MPL3115A2_STATE_READ_ALTITUDE:
173  {
174  self->_state = TWR_MPL3115A2_STATE_ERROR;
175 
176  uint8_t reg_status;
177 
178  if (!twr_i2c_memory_read_8b(self->_i2c_channel, self->_i2c_address, 0x00, &reg_status))
179  {
180  goto start;
181  }
182 
183  if ((reg_status & 0x04) == 0)
184  {
185  goto start;
186  }
187 
188  uint8_t buffer[5];
189 
190  twr_i2c_memory_transfer_t transfer;
191 
192  transfer.device_address = self->_i2c_address;
193  transfer.memory_address = 0x01;
194  transfer.buffer = buffer;
195  transfer.length = 5;
196 
197  if (!twr_i2c_memory_read(self->_i2c_channel, &transfer))
198  {
199  goto start;
200  }
201 
202  self->_reg_out_p_msb_altitude = buffer[0];
203  self->_reg_out_p_csb_altitude = buffer[1];
204  self->_reg_out_p_lsb_altitude = buffer[2];
205  self->_reg_out_t_msb_altitude = buffer[3];
206  self->_reg_out_t_lsb_altitude = buffer[4];
207 
208  self->_altitude_valid = true;
209 
210  self->_state = TWR_MPL3115A2_STATE_MEASURE_PRESSURE;
211 
212  goto start;
213  }
214  case TWR_MPL3115A2_STATE_MEASURE_PRESSURE:
215  {
216  self->_state = TWR_MPL3115A2_STATE_ERROR;
217 
218  if (!twr_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x26, 0x38))
219  {
220  goto start;
221  }
222 
223  if (!twr_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x13, 0x07))
224  {
225  goto start;
226  }
227 
228  if (!twr_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x26, 0x3a))
229  {
230  goto start;
231  }
232 
233  self->_state = TWR_MPL3115A2_STATE_READ_PRESSURE;
234 
235  twr_scheduler_plan_current_from_now(_TWR_MPL3115A2_DELAY_MEASUREMENT);
236 
237  return;
238  }
239  case TWR_MPL3115A2_STATE_READ_PRESSURE:
240  {
241  self->_state = TWR_MPL3115A2_STATE_ERROR;
242 
243  uint8_t reg_status;
244 
245  if (!twr_i2c_memory_read_8b(self->_i2c_channel, self->_i2c_address, 0x00, &reg_status))
246  {
247  goto start;
248  }
249 
250  if ((reg_status & 0x04) == 0)
251  {
252  goto start;
253  }
254 
255  uint8_t buffer[5];
256 
257  twr_i2c_memory_transfer_t transfer;
258 
259  transfer.device_address = self->_i2c_address;
260  transfer.memory_address = 0x01;
261  transfer.buffer = buffer;
262  transfer.length = 5;
263 
264  if (!twr_i2c_memory_read(self->_i2c_channel, &transfer))
265  {
266  goto start;
267  }
268 
269  self->_reg_out_p_msb_pressure = buffer[0];
270  self->_reg_out_p_csb_pressure = buffer[1];
271  self->_reg_out_p_lsb_pressure = buffer[2];
272  self->_reg_out_t_msb_pressure = buffer[3];
273  self->_reg_out_t_lsb_pressure = buffer[4];
274 
275  self->_pressure_valid = true;
276 
277  self->_state = TWR_MPL3115A2_STATE_UPDATE;
278 
279  goto start;
280  }
281  case TWR_MPL3115A2_STATE_UPDATE:
282  {
283  self->_measurement_active = false;
284 
285  if (self->_event_handler != NULL)
286  {
287  self->_event_handler(self, TWR_MPL3115A2_EVENT_UPDATE, self->_event_param);
288  }
289 
290  self->_state = TWR_MPL3115A2_STATE_MEASURE_ALTITUDE;
291 
292  return;
293  }
294  default:
295  {
296  self->_state = TWR_MPL3115A2_STATE_ERROR;
297 
298  goto start;
299  }
300  }
301 }
void twr_i2c_init(twr_i2c_channel_t channel, twr_i2c_speed_t speed)
Initialize I2C channel.
Definition: twr_i2c.c:57
bool twr_i2c_memory_read(twr_i2c_channel_t channel, const twr_i2c_memory_transfer_t *transfer)
Memory read from I2C channel.
Definition: twr_i2c.c:371
bool twr_i2c_memory_write_8b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t data)
Memory write 1 byte to I2C channel.
Definition: twr_i2c.c:408
bool twr_i2c_memory_read_8b(twr_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t *data)
Memory read 1 byte from I2C channel.
Definition: twr_i2c.c:437
twr_i2c_channel_t
I2C channels.
Definition: twr_i2c.h:16
@ TWR_I2C_SPEED_400_KHZ
I2C communication speed is 400 kHz.
Definition: twr_i2c.h:36
void twr_mpl3115a2_init(twr_mpl3115a2_t *self, twr_i2c_channel_t i2c_channel, uint8_t i2c_address)
Initialize MPL3115A2.
Definition: twr_mpl3115a2.c:11
bool twr_mpl3115a2_get_pressure_pascal(twr_mpl3115a2_t *self, float *pascal)
Get measured pressured in Pascal.
Definition: twr_mpl3115a2.c:85
bool twr_mpl3115a2_measure(twr_mpl3115a2_t *self)
Start measurement manually.
Definition: twr_mpl3115a2.c:57
void twr_mpl3115a2_set_event_handler(twr_mpl3115a2_t *self, void(*event_handler)(twr_mpl3115a2_t *, twr_mpl3115a2_event_t, void *), void *event_param)
Set callback function.
Definition: twr_mpl3115a2.c:35
struct twr_mpl3115a2_t twr_mpl3115a2_t
MPL3115A2 instance.
Definition: twr_mpl3115a2.h:25
twr_mpl3115a2_event_t
Callback events.
Definition: twr_mpl3115a2.h:14
void twr_mpl3115a2_set_update_interval(twr_mpl3115a2_t *self, twr_tick_t interval)
Set measurement interval.
Definition: twr_mpl3115a2.c:41
void twr_mpl3115a2_deinit(twr_mpl3115a2_t *self)
Deinitialize MPL3115A2.
Definition: twr_mpl3115a2.c:26
bool twr_mpl3115a2_get_altitude_meter(twr_mpl3115a2_t *self, float *meter)
Get measured altitude in meters.
Definition: twr_mpl3115a2.c:71
@ TWR_MPL3115A2_EVENT_ERROR
Error event.
Definition: twr_mpl3115a2.h:16
@ TWR_MPL3115A2_EVENT_UPDATE
Update event.
Definition: twr_mpl3115a2.h:19
void twr_scheduler_plan_current_from_now(twr_tick_t tick)
Schedule current task to tick relative from now.
void twr_scheduler_plan_current_relative(twr_tick_t tick)
Schedule current task to tick relative from current spin.
void twr_scheduler_plan_current_absolute(twr_tick_t tick)
Schedule current task to absolute tick.
void twr_scheduler_plan_absolute(twr_scheduler_task_id_t task_id, twr_tick_t tick)
Schedule specified task to absolute tick.
void twr_scheduler_unregister(twr_scheduler_task_id_t task_id)
Unregister specified task.
Definition: twr_scheduler.c:77
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.
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
#define TWR_TICK_INFINITY
Maximum timestamp value.
Definition: twr_tick.h:12
twr_tick_t twr_tick_get(void)
Get absolute timestamp since start of program.
Definition: twr_tick.c:7
uint64_t twr_tick_t
Timestamp data type.
Definition: twr_tick.h:16
I2C memory transfer parameters.
Definition: twr_i2c.h:58
uint32_t memory_address
8-bit I2C memory address (it can be extended to 16-bit format if OR-ed with TWR_I2C_MEMORY_ADDRESS_16...
Definition: twr_i2c.h:63
uint8_t device_address
7-bit I2C device address
Definition: twr_i2c.h:60
size_t length
Length of buffer which is being written or read.
Definition: twr_i2c.h:69
void * buffer
Pointer to buffer which is being written or read.
Definition: twr_i2c.h:66