Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_mpl3115a2.c
1 #include <bc_mpl3115a2.h>
2 
3 #define _BC_MPL3115A2_DELAY_RUN 1500
4 #define _BC_MPL3115A2_DELAY_INITIALIZATION 1500
5 #define _BC_MPL3115A2_DELAY_MEASUREMENT 1500
6 
7 static void _bc_mpl3115a2_task_interval(void *param);
8 
9 static void _bc_mpl3115a2_task_measure(void *param);
10 
11 void bc_mpl3115a2_init(bc_mpl3115a2_t *self, bc_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 = bc_scheduler_register(_bc_mpl3115a2_task_interval, self, BC_TICK_INFINITY);
19  self->_task_id_measure = bc_scheduler_register(_bc_mpl3115a2_task_measure, self, _BC_MPL3115A2_DELAY_RUN);
20 
21  self->_tick_ready = _BC_MPL3115A2_DELAY_RUN;
22 
23  bc_i2c_init(self->_i2c_channel, BC_I2C_SPEED_400_KHZ);
24 }
25 
26 void bc_mpl3115a2_set_event_handler(bc_mpl3115a2_t *self, void (*event_handler)(bc_mpl3115a2_t *, bc_mpl3115a2_event_t, void *), void *event_param)
27 {
28  self->_event_handler = event_handler;
29  self->_event_param = event_param;
30 }
31 
33 {
34  self->_update_interval = interval;
35 
36  if (self->_update_interval == BC_TICK_INFINITY)
37  {
38  bc_scheduler_plan_absolute(self->_task_id_interval, BC_TICK_INFINITY);
39  }
40  else
41  {
42  bc_scheduler_plan_relative(self->_task_id_interval, self->_update_interval);
43 
45  }
46 }
47 
49 {
50  if (self->_measurement_active)
51  {
52  return false;
53  }
54 
55  self->_measurement_active = true;
56 
57  bc_scheduler_plan_absolute(self->_task_id_measure, self->_tick_ready);
58 
59  return true;
60 }
61 
63 {
64  if (!self->_altitude_valid)
65  {
66  return false;
67  }
68 
69  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;
70 
71  *meter = ((float) out_pa) / 65536.f;
72 
73  return true;
74 }
75 
77 {
78  if (!self->_pressure_valid)
79  {
80  return false;
81  }
82 
83  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;
84 
85  *pascal = ((float) out_p) / 64.f;
86 
87  return true;
88 }
89 
90 static void _bc_mpl3115a2_task_interval(void *param)
91 {
92  bc_mpl3115a2_t *self = param;
93 
95 
96  bc_scheduler_plan_current_relative(self->_update_interval);
97 }
98 
99 static void _bc_mpl3115a2_task_measure(void *param)
100 {
101  bc_mpl3115a2_t *self = param;
102 
103 start:
104 
105  switch (self->_state)
106  {
107  case BC_MPL3115A2_STATE_ERROR:
108  {
109  self->_altitude_valid = false;
110  self->_pressure_valid = false;
111 
112  self->_measurement_active = false;
113 
114  if (self->_event_handler != NULL)
115  {
116  self->_event_handler(self, BC_MPL3115A2_EVENT_ERROR, self->_event_param);
117  }
118 
119  self->_state = BC_MPL3115A2_STATE_INITIALIZE;
120 
121  return;
122  }
123  case BC_MPL3115A2_STATE_INITIALIZE:
124  {
125  bc_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x26, 0x04);
126 
127  self->_state = BC_MPL3115A2_STATE_MEASURE_ALTITUDE;
128 
129  self->_tick_ready = bc_tick_get() + _BC_MPL3115A2_DELAY_INITIALIZATION;
130 
131  if (self->_measurement_active)
132  {
133  bc_scheduler_plan_current_absolute(self->_tick_ready);
134  }
135 
136  return;
137  }
138  case BC_MPL3115A2_STATE_MEASURE_ALTITUDE:
139  {
140  self->_state = BC_MPL3115A2_STATE_ERROR;
141 
142  if (!bc_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x26, 0xb8))
143  {
144  goto start;
145  }
146 
147  if (!bc_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x13, 0x07))
148  {
149  goto start;
150  }
151 
152  if (!bc_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x26, 0xba))
153  {
154  goto start;
155  }
156 
157  self->_state = BC_MPL3115A2_STATE_READ_ALTITUDE;
158 
159  bc_scheduler_plan_current_from_now(_BC_MPL3115A2_DELAY_MEASUREMENT);
160 
161  return;
162  }
163  case BC_MPL3115A2_STATE_READ_ALTITUDE:
164  {
165  self->_state = BC_MPL3115A2_STATE_ERROR;
166 
167  uint8_t reg_status;
168 
169  if (!bc_i2c_memory_read_8b(self->_i2c_channel, self->_i2c_address, 0x00, &reg_status))
170  {
171  goto start;
172  }
173 
174  if (reg_status != 0x0e)
175  {
176  goto start;
177  }
178 
179  uint8_t buffer[5];
180 
181  bc_i2c_memory_transfer_t transfer;
182 
183  transfer.device_address = self->_i2c_address;
184  transfer.memory_address = 0x01;
185  transfer.buffer = buffer;
186  transfer.length = 5;
187 
188  if (!bc_i2c_memory_read(self->_i2c_channel, &transfer))
189  {
190  goto start;
191  }
192 
193  self->_reg_out_p_msb_altitude = buffer[0];
194  self->_reg_out_p_csb_altitude = buffer[1];
195  self->_reg_out_p_lsb_altitude = buffer[2];
196  self->_reg_out_t_msb_altitude = buffer[3];
197  self->_reg_out_t_lsb_altitude = buffer[4];
198 
199  self->_altitude_valid = true;
200 
201  self->_state = BC_MPL3115A2_STATE_MEASURE_PRESSURE;
202 
203  goto start;
204  }
205  case BC_MPL3115A2_STATE_MEASURE_PRESSURE:
206  {
207  self->_state = BC_MPL3115A2_STATE_ERROR;
208 
209  if (!bc_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x26, 0x38))
210  {
211  goto start;
212  }
213 
214  if (!bc_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x13, 0x07))
215  {
216  goto start;
217  }
218 
219  if (!bc_i2c_memory_write_8b(self->_i2c_channel, self->_i2c_address, 0x26, 0x3a))
220  {
221  goto start;
222  }
223 
224  self->_state = BC_MPL3115A2_STATE_READ_PRESSURE;
225 
226  bc_scheduler_plan_current_from_now(_BC_MPL3115A2_DELAY_MEASUREMENT);
227 
228  return;
229  }
230  case BC_MPL3115A2_STATE_READ_PRESSURE:
231  {
232  self->_state = BC_MPL3115A2_STATE_ERROR;
233 
234  uint8_t reg_status;
235 
236  if (!bc_i2c_memory_read_8b(self->_i2c_channel, self->_i2c_address, 0x00, &reg_status))
237  {
238  goto start;
239  }
240 
241  if (reg_status != 0x0e)
242  {
243  goto start;
244  }
245 
246  uint8_t buffer[5];
247 
248  bc_i2c_memory_transfer_t transfer;
249 
250  transfer.device_address = self->_i2c_address;
251  transfer.memory_address = 0x01;
252  transfer.buffer = buffer;
253  transfer.length = 5;
254 
255  if (!bc_i2c_memory_read(self->_i2c_channel, &transfer))
256  {
257  goto start;
258  }
259 
260  self->_reg_out_p_msb_pressure = buffer[0];
261  self->_reg_out_p_csb_pressure = buffer[1];
262  self->_reg_out_p_lsb_pressure = buffer[2];
263  self->_reg_out_t_msb_pressure = buffer[3];
264  self->_reg_out_t_lsb_pressure = buffer[4];
265 
266  self->_pressure_valid = true;
267 
268  self->_state = BC_MPL3115A2_STATE_UPDATE;
269 
270  goto start;
271  }
272  case BC_MPL3115A2_STATE_UPDATE:
273  {
274  self->_measurement_active = false;
275 
276  if (self->_event_handler != NULL)
277  {
278  self->_event_handler(self, BC_MPL3115A2_EVENT_UPDATE, self->_event_param);
279  }
280 
281  self->_state = BC_MPL3115A2_STATE_MEASURE_ALTITUDE;
282 
283  return;
284  }
285  default:
286  {
287  self->_state = BC_MPL3115A2_STATE_ERROR;
288 
289  goto start;
290  }
291  }
292 }
void * buffer
Pointer to buffer which is being written or read.
Definition: bc_i2c.h:66
uint64_t bc_tick_t
Timestamp data type.
Definition: bc_tick.h:16
I2C communication speed is 400 kHz.
Definition: bc_i2c.h:36
void bc_scheduler_plan_absolute(bc_scheduler_task_id_t task_id, bc_tick_t tick)
Schedule specified task to absolute tick.
Definition: bc_scheduler.c:124
struct bc_mpl3115a2_t bc_mpl3115a2_t
MPL3115A2 instance.
Definition: bc_mpl3115a2.h:25
bool bc_mpl3115a2_get_pressure_pascal(bc_mpl3115a2_t *self, float *pascal)
Get measured pressured in Pascal.
Definition: bc_mpl3115a2.c:76
bool bc_i2c_memory_read(bc_i2c_channel_t channel, const bc_i2c_memory_transfer_t *transfer)
Memory read from I2C channel.
Definition: bc_i2c.c:365
bc_scheduler_task_id_t bc_scheduler_register(void(*task)(void *), void *param, bc_tick_t tick)
Register task in scheduler.
Definition: bc_scheduler.c:56
bool bc_i2c_memory_read_8b(bc_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t *data)
Memory read 1 byte from I2C channel.
Definition: bc_i2c.c:431
void bc_scheduler_plan_current_absolute(bc_tick_t tick)
Schedule current task to absolute tick.
Definition: bc_scheduler.c:144
void bc_i2c_init(bc_i2c_channel_t channel, bc_i2c_speed_t speed)
Initialize I2C channel.
Definition: bc_i2c.c:54
bc_tick_t bc_tick_get(void)
Get absolute timestamp since start of program.
Definition: bc_tick.c:7
void bc_scheduler_plan_current_relative(bc_tick_t tick)
Schedule current task to tick relative from current spin.
Definition: bc_scheduler.c:149
bc_mpl3115a2_event_t
Callback events.
Definition: bc_mpl3115a2.h:13
void bc_mpl3115a2_init(bc_mpl3115a2_t *self, bc_i2c_channel_t i2c_channel, uint8_t i2c_address)
Initialize MPL3115A2.
Definition: bc_mpl3115a2.c:11
uint32_t memory_address
8-bit I2C memory address (it can be extended to 16-bit format if OR-ed with BC_I2C_MEMORY_ADDRESS_16_...
Definition: bc_i2c.h:63
uint8_t device_address
7-bit I2C device address
Definition: bc_i2c.h:60
I2C memory transfer parameters.
Definition: bc_i2c.h:57
void bc_scheduler_plan_relative(bc_scheduler_task_id_t task_id, bc_tick_t tick)
Schedule specified task to tick relative from current spin.
Definition: bc_scheduler.c:129
bool bc_mpl3115a2_get_altitude_meter(bc_mpl3115a2_t *self, float *meter)
Get measured altitude in meters.
Definition: bc_mpl3115a2.c:62
bc_i2c_channel_t
I2C channels.
Definition: bc_i2c.h:15
void bc_mpl3115a2_set_event_handler(bc_mpl3115a2_t *self, void(*event_handler)(bc_mpl3115a2_t *, bc_mpl3115a2_event_t, void *), void *event_param)
Set callback function.
Definition: bc_mpl3115a2.c:26
void bc_scheduler_plan_current_from_now(bc_tick_t tick)
Schedule current task to tick relative from now.
Definition: bc_scheduler.c:154
#define BC_TICK_INFINITY
Maximum timestamp value.
Definition: bc_tick.h:12
size_t length
Length of buffer which is being written or read.
Definition: bc_i2c.h:69
bool bc_mpl3115a2_measure(bc_mpl3115a2_t *self)
Start measurement manually.
Definition: bc_mpl3115a2.c:48
void bc_mpl3115a2_set_update_interval(bc_mpl3115a2_t *self, bc_tick_t interval)
Set measurement interval.
Definition: bc_mpl3115a2.c:32
bool bc_i2c_memory_write_8b(bc_i2c_channel_t channel, uint8_t device_address, uint32_t memory_address, uint8_t data)
Memory write 1 byte to I2C channel.
Definition: bc_i2c.c:402