dRonin  adbada4
dRonin firmware
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
pios_bmm150.c
Go to the documentation of this file.
1 
12 /*
13  * This program is free software; you can redistribute it and/or modify
14  * it under the terms of the GNU General Public License as published by
15  * the Free Software Foundation; either version 3 of the License, or
16  * (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful, but
19  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20  * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21  * for more details.
22  *
23  * You should have received a copy of the GNU General Public License along
24  * with this program; if not, see <http://www.gnu.org/licenses/>
25  *
26  * Additional note on redistribution: The copyright and license notices above
27  * must be maintained in each individual source file that is a derivative work
28  * of this source file; otherwise redistribution is prohibited.
29  */
30 
31 #include "openpilot.h"
32 #include "pios.h"
33 
34 #if defined(PIOS_INCLUDE_BMM150)
35 
36 #include "pios_semaphore.h"
37 #include "pios_thread.h"
38 #include "pios_queue.h"
39 #include "physical_constants.h"
40 #include "taskmonitor.h"
41 
42 #include "pios_bmm150_priv.h"
43 
44 #define PIOS_BMM_TASK_PRIORITY PIOS_THREAD_PRIO_HIGHEST
45 
46 #define PIOS_BMM_TASK_STACK 640
47 
48 #define PIOS_BMM_QUEUE_LEN 2
49 
50 #define PIOS_BMM_SPI_SPEED 10000000
51 
52 
57 enum pios_bmm150_dev_magic {
58  PIOS_BMM_DEV_MAGIC = 0x586e6f42
59 };
60 
64 struct pios_bmm150_dev {
65  enum pios_bmm150_dev_magic magic;
66  const struct pios_bmm150_cfg *cfg;
67  pios_spi_t spi_id;
68  uint32_t spi_slave_mag;
70  struct pios_queue *mag_queue;
71 
72  struct pios_thread *task_handle;
73 
74  int8_t dig_x1;
75  int8_t dig_y1;
77  int8_t dig_x2;
78  int8_t dig_y2;
80  uint16_t dig_z1;
81  int16_t dig_z2;
82  int16_t dig_z3;
83  int16_t dig_z4;
85  uint8_t dig_xy1;
86  int8_t dig_xy2;
88  uint16_t dig_xyz1;
89 };
90 
92 static struct pios_bmm150_dev *bmm_dev;
93 
95 
98 static struct pios_bmm150_dev *PIOS_BMM_Alloc(const struct pios_bmm150_cfg *cfg);
99 
104 static int32_t PIOS_BMM_Validate(struct pios_bmm150_dev *dev);
105 
106 static void PIOS_BMM_Task(void *parameters);
107 
108 static inline float bmm050_compensate_X_float(pios_bmm150_dev_t p_bmm050,
109  int16_t mag_data_x, uint16_t data_r);
110 static inline float bmm050_compensate_Y_float(pios_bmm150_dev_t p_bmm050,
111  int16_t mag_data_y, uint16_t data_r);
112 static inline float bmm050_compensate_Z_float(pios_bmm150_dev_t p_bmm050,
113  int16_t mag_data_z, uint16_t data_r);
118 static int32_t PIOS_BMM_ClaimBus();
119 
124 static int32_t PIOS_BMM_ReleaseBus();
125 
126 static int32_t PIOS_BMM_ReadReg(uint8_t address, uint8_t *buffer);
127 static int32_t PIOS_BMM_WriteReg(uint8_t address, uint8_t buffer);
128 
129 static struct pios_bmm150_dev *PIOS_BMM_Alloc(const struct pios_bmm150_cfg *cfg)
130 {
131  struct pios_bmm150_dev *dev;
132 
133  dev = (struct pios_bmm150_dev *)PIOS_malloc(sizeof(*bmm_dev));
134  if (!dev)
135  return NULL;
136 
137  dev->magic = PIOS_BMM_DEV_MAGIC;
138 
139  dev->mag_queue = PIOS_Queue_Create(PIOS_BMM_QUEUE_LEN, sizeof(struct pios_sensor_mag_data));
140  if (dev->mag_queue == NULL) {
141  PIOS_free(dev);
142  return NULL;
143  }
144 
145  return dev;
146 }
147 
148 static int32_t PIOS_BMM_Validate(struct pios_bmm150_dev *dev)
149 {
150  if (dev == NULL)
151  return -1;
152  if (dev->magic != PIOS_BMM_DEV_MAGIC)
153  return -2;
154  if (dev->spi_id == 0)
155  return -3;
156  return 0;
157 }
158 
159 static int32_t AssertReg(uint8_t address, uint8_t expect) {
160  uint8_t c;
161 
162  int32_t ret = PIOS_BMM_ReadReg(address, &c);
163 
164  if (ret) {
165  return ret;
166  }
167 
168  if (c != expect) {
169  DEBUG_PRINTF(2, "BMM: Assertion failed: *(%02x) == %02x (expect %02x)\n",
170  address, c, expect);
171  return -1;
172  }
173 
174  DEBUG_PRINTF(2, "BMM: Assertion passed: *(%02x) == %02x\n", address,
175  expect);
176 
177  return 0;
178 }
179 
180 static int32_t PIOS_BMM150_ReadTrims(pios_bmm150_dev_t dev)
181 {
182  int ret;
183 
184  ret = PIOS_BMM_ReadReg(BMM150_DIG_X1, (uint8_t *) &dev->dig_x1);
185  if (ret) return ret;
186 
187  ret = PIOS_BMM_ReadReg(BMM150_DIG_X2, (uint8_t *) &dev->dig_x2);
188  if (ret) return ret;
189 
190  ret = PIOS_BMM_ReadReg(BMM150_DIG_Y1, (uint8_t *) &dev->dig_y1);
191  if (ret) return ret;
192 
193  ret = PIOS_BMM_ReadReg(BMM150_DIG_Y2, (uint8_t *) &dev->dig_y2);
194  if (ret) return ret;
195 
196  ret = PIOS_BMM_ReadReg(BMM150_DIG_X1, &dev->dig_xy1);
197  if (ret) return ret;
198 
199  ret = PIOS_BMM_ReadReg(BMM150_DIG_X2, (uint8_t *) &dev->dig_xy2);
200  if (ret) return ret;
201 
202  /* Sensor is little endian; all supported platforms are little endian
203  * presently, but try to do the right thing anyways */
204 
205  uint8_t tmp[2];
206 
207  ret = PIOS_BMM_ReadReg(BMM150_DIG_Z1_LSB, tmp);
208  if (ret) return ret;
209  ret = PIOS_BMM_ReadReg(BMM150_DIG_Z1_MSB, tmp+1);
210  if (ret) return ret;
211  dev->dig_z1 = (tmp[1] << 8) | tmp[0];
212 
213  ret = PIOS_BMM_ReadReg(BMM150_DIG_Z2_LSB, tmp);
214  if (ret) return ret;
215  ret = PIOS_BMM_ReadReg(BMM150_DIG_Z2_MSB, tmp+1);
216  if (ret) return ret;
217  dev->dig_z2 = (tmp[1] << 8) | tmp[0];
218 
219  ret = PIOS_BMM_ReadReg(BMM150_DIG_Z3_LSB, tmp);
220  if (ret) return ret;
221  ret = PIOS_BMM_ReadReg(BMM150_DIG_Z3_MSB, tmp+1);
222  if (ret) return ret;
223  dev->dig_z3 = (tmp[1] << 8) | tmp[0];
224 
225  ret = PIOS_BMM_ReadReg(BMM150_DIG_Z4_LSB, tmp);
226  if (ret) return ret;
227  ret = PIOS_BMM_ReadReg(BMM150_DIG_Z4_MSB, tmp+1);
228  if (ret) return ret;
229  dev->dig_z4 = (tmp[1] << 8) | tmp[0];
230 
231  ret = PIOS_BMM_ReadReg(BMM150_DIG_XYZ1_LSB, tmp);
232  if (ret) return ret;
233  ret = PIOS_BMM_ReadReg(BMM150_DIG_XYZ1_MSB, tmp+1);
234  if (ret) return ret;
235  dev->dig_xyz1 = (tmp[1] << 8) | tmp[0];
236 
237  DEBUG_PRINTF(2, "BMM: x1=%d y1=%d x2=%d y2=%d xy1=%d xy2=%d\n",
238  dev->dig_x1, dev->dig_y1, dev->dig_x2, dev->dig_y2,
239  dev->dig_xy1, dev->dig_xy2);
240 
241  DEBUG_PRINTF(2, "BMM: z1=%d z2=%d z3=%d z4=%d xyz1=%d\n",
242  dev->dig_z1, dev->dig_z2, dev->dig_z3, dev->dig_z4,
243  dev->dig_xyz1);
244 
245  return 0;
246 }
247 
249  uint32_t slave_mag, const struct pios_bmm150_cfg *cfg)
250 {
251  bmm_dev = PIOS_BMM_Alloc(cfg);
252  if (bmm_dev == NULL)
253  return -1;
254  *dev = bmm_dev;
255 
256  bmm_dev->spi_id = spi_id;
257  bmm_dev->spi_slave_mag = slave_mag;
258  bmm_dev->cfg = cfg;
259 
260  int32_t ret;
261 
262  /* Unfortunately can't check mag right away, so proceed with
263  * init
264  */
265 
266  DEBUG_PRINTF(2, "BMM: Resetting sensor\n");
267 
268  ret = PIOS_BMM_WriteReg(BMM150_REG_MAG_POWER_CONTROL,
270 
271  if (ret) return ret;
272 
273  PIOS_DELAY_WaitmS(20);
274 
275  ret = PIOS_BMM_WriteReg(BMM150_REG_MAG_POWER_CONTROL,
277 
278  if (ret) return ret;
279 
280  PIOS_DELAY_WaitmS(30);
281 
282  /* Verify expected chip id. */
284 
285  if (ret) return ret;
286 
287  ret = PIOS_BMM150_ReadTrims(bmm_dev);
288 
289  if (ret) {
290  DEBUG_PRINTF(2, "BMM: Unable to read trims!\n");
291  return ret;
292  }
293 
294  /* We choose a point between "Enhanced Regular preset"
295  * nXy=15, nZ=27, max ODR=60 (calc by data sheet formula 60.04)
296  * and "High accuracy preset"
297  * nXY=47, nZ=83, max ODR=20. (calc by data sheet formula 20.29)
298  *
299  * nXy=29, nZ=54. yields ODR>31. Which makes ODR 30 safe.
300  * A little more data in exchange for a little more RMS noise,
301  * which we can smooth out somewhat anyways.
302  */
303 
304  /* 14 * 2 + 1 = 29, per above */
305  ret = PIOS_BMM_WriteReg(BMM150_REG_MAG_X_Y_AXIS_REP, 14);
306 
307  if (ret) {
308  return ret;
309  }
310 
311  /* 53 + 1 = 54, per above */
312  ret = PIOS_BMM_WriteReg(BMM150_REG_MAG_Z_AXIS_REP, 53);
313 
314  if (ret) {
315  return ret;
316  }
317 
318  /* Start the sensor in normal mode, ODR=30 */
319  ret = PIOS_BMM_WriteReg(BMM150_REG_MAG_OPERATION_MODE,
322 
323  if (ret) {
324  return ret;
325  }
326 
327  bmm_dev->task_handle = PIOS_Thread_Create(
328  PIOS_BMM_Task, "pios_bmm", PIOS_BMM_TASK_STACK,
329  NULL, PIOS_BMM_TASK_PRIORITY);
330 
331  PIOS_SENSORS_Register(PIOS_SENSOR_MAG, bmm_dev->mag_queue);
332 
333  return 0;
334 }
335 
336 static int32_t PIOS_BMM_ClaimBus()
337 {
338  if (PIOS_BMM_Validate(bmm_dev) != 0)
339  return -1;
340 
341  if (PIOS_SPI_ClaimBus(bmm_dev->spi_id) != 0)
342  return -2;
343 
344  PIOS_SPI_RC_PinSet(bmm_dev->spi_id, bmm_dev->spi_slave_mag, false);
345 
346  PIOS_SPI_SetClockSpeed(bmm_dev->spi_id, 10000000);
347 
348  return 0;
349 }
350 
351 static int32_t PIOS_BMM_ReleaseBus()
352 {
353  if (PIOS_BMM_Validate(bmm_dev) != 0)
354  return -1;
355 
356  PIOS_SPI_RC_PinSet(bmm_dev->spi_id, bmm_dev->spi_slave_mag, true);
357 
358  PIOS_SPI_ReleaseBus(bmm_dev->spi_id);
359 
360  return 0;
361 }
362 
363 static int32_t PIOS_BMM_ReadReg(uint8_t address, uint8_t *buffer)
364 {
365  if (PIOS_BMM_ClaimBus() != 0)
366  return -1;
367 
368  PIOS_SPI_TransferByte(bmm_dev->spi_id, 0x80 | address); // request byte
369  *buffer = PIOS_SPI_TransferByte(bmm_dev->spi_id, 0); // receive response
370 
371  PIOS_BMM_ReleaseBus();
372 
373  return 0;
374 }
375 
376 static int32_t PIOS_BMM_WriteReg(uint8_t address, uint8_t buffer)
377 {
378  if (PIOS_BMM_ClaimBus() != 0)
379  return -1;
380 
381  PIOS_SPI_TransferByte(bmm_dev->spi_id, 0x7f & address);
382  PIOS_SPI_TransferByte(bmm_dev->spi_id, buffer);
383 
384  PIOS_BMM_ReleaseBus();
385 
386  return 0;
387 }
388 
389 static void PIOS_BMM_Task(void *parameters)
390 {
391  (void)parameters;
392 
393  while (true) {
394  PIOS_Thread_Sleep(6); /* XXX */
395 
396  uint8_t drdy;
397 
398  if (PIOS_BMM_ReadReg(BMM150_REG_MAG_HALL_RESISTANCE_LSB,
399  &drdy))
400  continue;
401 
402  /* Check if there's any new data. If not.. wait 6 more ms
403  * (we expect it at 33ms intervals).
404  * At the end of this we sleep 24, which results in a first
405  * drdy check at 30ms [3ms early] and the next check at 36ms
406  * [3ms late]. Should keep us disciplined very close to
407  * measurements so they're not sitting around long.
408  */
410  continue;
411 
412  if (PIOS_BMM_ClaimBus() != 0)
413  continue;
414 
415  uint8_t sensor_buf[BMM150_REG_MAG_HALL_RESISTANCE_MSB -
417 
418  PIOS_SPI_TransferByte(bmm_dev->spi_id,
419  0x80 | BMM150_REG_MAG_X_LSB);
420 
421  if (PIOS_SPI_TransferBlock(bmm_dev->spi_id, NULL, sensor_buf,
422  sizeof(sensor_buf)) < 0) {
423  PIOS_BMM_ReleaseBus();
424  continue;
425  }
426 
427  PIOS_BMM_ReleaseBus();
428 
429  /* The Bosch compensation functions appear to expect this data
430  * right-aligned, signed. The unpacking functions in the
431  * library are rather obtuse, but they do sign extension
432  * on the right align operation.
433  *
434  * We form them into a 16 bit left aligned signed value,
435  * then shift them right to right align and sign extend.
436  * Hopefully this is clearer.
437  */
438 
439 #define PACK_REG13_ADDR_OFFSET(b, reg, off) ((int16_t) ( (b[reg-off] & 0xf8) | (b[reg-off+1] << 8) ))
440 #define PACK_REG14_ADDR_OFFSET(b, reg, off) ((int16_t) ( (b[reg-off] & 0xfc) | (b[reg-off+1] << 8) ))
441 #define PACK_REG15_ADDR_OFFSET(b, reg, off) ((int16_t) ( (b[reg-off] & 0xfe) | (b[reg-off+1] << 8) ))
442 
443  int16_t raw_x, raw_y, raw_z, raw_r;
444  raw_x = PACK_REG13_ADDR_OFFSET(sensor_buf, BMM150_REG_MAG_X_LSB,
446  raw_x >>= 3;
447  raw_y = PACK_REG13_ADDR_OFFSET(sensor_buf, BMM150_REG_MAG_Y_LSB,
449  raw_y >>= 3;
450  raw_z = PACK_REG15_ADDR_OFFSET(sensor_buf, BMM150_REG_MAG_Z_LSB,
452  raw_z >>= 1;
453  raw_r = PACK_REG14_ADDR_OFFSET(sensor_buf,
456  raw_r >>= 2;
457 
458  // Datasheet is typical res 0.3 uT. X/Y -4096 to 4095,
459  // Z -16384 to 16383. .3*4095 checks out with expected range
460  // (+/- 1228 uT vs datasheet +/- 1300uT)
461  // .3 * 16384 is off by a factor of 2 though
462  // (+/- 4915 uT vs datasheet +/- 2500uT)
463 
464  struct pios_sensor_mag_data mag_data;
465 
466  float mag_x = bmm050_compensate_X_float(bmm_dev,
467  raw_x, raw_r);
468  float mag_y = bmm050_compensate_Y_float(bmm_dev,
469  raw_y, raw_r);
470  float mag_z = bmm050_compensate_Z_float(bmm_dev,
471  raw_z, raw_r);
472 
473  switch (bmm_dev->cfg->orientation) {
474  case PIOS_BMM_TOP_0DEG:
475  mag_data.y = mag_x;
476  mag_data.x = mag_y;
477  mag_data.z = -mag_z;
478  break;
479  case PIOS_BMM_TOP_90DEG:
480  mag_data.y = -mag_y;
481  mag_data.x = mag_x;
482  mag_data.z = -mag_z;
483  break;
484  case PIOS_BMM_TOP_180DEG:
485  mag_data.y = -mag_x;
486  mag_data.x = -mag_y;
487  mag_data.z = -mag_z;
488  break;
489  case PIOS_BMM_TOP_270DEG:
490  mag_data.y = mag_y;
491  mag_data.x = -mag_x;
492  mag_data.z = -mag_z;
493  break;
495  mag_data.y = -mag_x;
496  mag_data.x = mag_y;
497  mag_data.z = mag_z;
498  break;
500  mag_data.y = mag_y;
501  mag_data.x = mag_x;
502  mag_data.z = mag_z;
503  break;
505  mag_data.y = mag_x;
506  mag_data.x = -mag_y;
507  mag_data.z = mag_z;
508  break;
510  mag_data.y = -mag_y;
511  mag_data.x = -mag_x;
512  mag_data.z = mag_z;
513  break;
514  }
515 
516  /* scale-- it reads in microtesla. we want milligauss */
517  float mag_scale = 10.0f;
518 
519  mag_data.x *= mag_scale;
520  mag_data.y *= mag_scale;
521  mag_data.z *= mag_scale;
522 
523  PIOS_Queue_Send(bmm_dev->mag_queue, &mag_data, 0);
524 
525  PIOS_Thread_Sleep(24);
526  }
527 }
528 
529 /* The following code originally comes from the Bosch SensorTec BMM050 driver:
530 * https://github.com/BoschSensortec/BMM050_driver/
531 *
532 ****************************************************************************
533 * Copyright (C) 2015 - 2016 Bosch Sensortec GmbH
534 * Copyright (C) 2016 dRonin
535 *
536 * bmm050.c
537 * Date: 2016/03/17
538 * Revision: 2.0.6 $
539 *
540 * Usage: Sensor Driver for BMM050 and BMM150 sensor
541 *
542 ****************************************************************************
543 * License:
544 *
545 * Redistribution and use in source and binary forms, with or without
546 * modification, are permitted provided that the following conditions are met:
547 *
548 * Redistributions of source code must retain the above copyright
549 * notice, this list of conditions and the following disclaimer.
550 *
551 * Redistributions in binary form must reproduce the above copyright
552 * notice, this list of conditions and the following disclaimer in the
553 * documentation and/or other materials provided with the distribution.
554 *
555 * Neither the name of the copyright holder nor the names of the
556 * contributors may be used to endorse or promote products derived from
557 * this software without specific prior written permission.
558 */
559 
572 static inline float bmm050_compensate_X_float(pios_bmm150_dev_t p_bmm050,
573  int16_t mag_data_x, uint16_t data_r)
574 {
575  float inter_retval;
576 
577  if (mag_data_x != BMM050_FLIP_OVERFLOW_ADCVAL /* no overflow */
578  ) {
579  if ((data_r != BMM050_INIT_VALUE)
580  && (p_bmm050->dig_xyz1 != BMM050_INIT_VALUE)) {
581  inter_retval = ((((float)p_bmm050->dig_xyz1)
582  * 16384.0f / data_r) - 16384.0f);
583  } else {
584  inter_retval = BMM050_OVERFLOW_OUTPUT_FLOAT;
585  return inter_retval;
586  }
587  inter_retval = (((mag_data_x * ((((((float)p_bmm050->dig_xy2) *
588  (inter_retval*inter_retval /
589  268435456.0f) +
590  inter_retval * ((float)p_bmm050->dig_xy1)
591  / 16384.0f)) + 256.0f) *
592  (((float)p_bmm050->dig_x2) + 160.0f)))
593  / 8192.0f)
594  + (((float)p_bmm050->dig_x1) *
595  8.0f)) / 16.0f;
596  } else {
597  inter_retval = BMM050_OVERFLOW_OUTPUT_FLOAT;
598  }
599  return inter_retval;
600 }
601 
614 static inline float bmm050_compensate_Y_float(pios_bmm150_dev_t p_bmm050,
615  int16_t mag_data_y, uint16_t data_r)
616 {
617  float inter_retval;
618 
619  if (mag_data_y != BMM050_FLIP_OVERFLOW_ADCVAL /* no overflow */
620  ) {
621  if ((data_r != BMM050_INIT_VALUE)
622  && (p_bmm050->dig_xyz1 != BMM050_INIT_VALUE)) {
623  inter_retval = ((((float)p_bmm050->dig_xyz1)
624  * 16384.0f
625  /data_r) - 16384.0f);
626  } else {
627  inter_retval = BMM050_OVERFLOW_OUTPUT_FLOAT;
628  return inter_retval;
629  }
630  inter_retval = (((mag_data_y * ((((((float)p_bmm050->dig_xy2) *
631  (inter_retval*inter_retval
632  / 268435456.0f) +
633  inter_retval * ((float)p_bmm050->dig_xy1)
634  / 16384.0f)) +
635  256.0f) *
636  (((float)p_bmm050->dig_y2) + 160.0f)))
637  / 8192.0f) +
638  (((float)p_bmm050->dig_y1) * 8.0f))
639  / 16.0f;
640  } else {
641  /* overflow, set output to 0.0f */
642  inter_retval = BMM050_OVERFLOW_OUTPUT_FLOAT;
643  }
644  return inter_retval;
645 }
646 
659 static inline float bmm050_compensate_Z_float(pios_bmm150_dev_t p_bmm050,
660  int16_t mag_data_z, uint16_t data_r)
661 {
662  float inter_retval = BMM050_OVERFLOW_OUTPUT_FLOAT;
663  /* no overflow */
664  if (mag_data_z != BMM050_HALL_OVERFLOW_ADCVAL) {
665  if ((p_bmm050->dig_z2 != BMM050_INIT_VALUE)
666  && (p_bmm050->dig_z1 != BMM050_INIT_VALUE)
667  && (p_bmm050->dig_xyz1 != BMM050_INIT_VALUE)
668  && (data_r != BMM050_INIT_VALUE)) {
669  inter_retval = ((((((float)mag_data_z)-
670  ((float)p_bmm050->dig_z4)) * 131072.0f)-
671  (((float)p_bmm050->dig_z3)*(((float)data_r)
672  -((float)p_bmm050->dig_xyz1))))
673  /((((float)p_bmm050->dig_z2)+
674  ((float)p_bmm050->dig_z1)*((float)data_r) /
675  32768.0f) * 4.0f)) / 16.0f;
676  }
677  }
678 
679  return inter_retval;
680 }
681 
682 #endif // PIOS_INCLUDE_BMM150
683 
#define BMM150_REG_MAG_OPERATION_MODE
struct pios_queue * PIOS_Queue_Create(size_t queue_length, size_t item_size)
Definition: pios_queue.c:47
Main PiOS header to include all the compiled in PiOS options.
int32_t PIOS_BMM150_SPI_Init(pios_bmm150_dev_t *dev, pios_spi_t spi_id, uint32_t slave_mag, const struct pios_bmm150_cfg *cfg)
Initialize the BMM-xxxx 6/9-axis sensor on SPI.
int32_t PIOS_SPI_RC_PinSet(pios_spi_t spi_dev, uint32_t slave_id, bool pin_value)
#define BMM050_FLIP_OVERFLOW_ADCVAL
#define BMM150_REG_MAG_X_LSB
int32_t PIOS_SPI_ClaimBus(pios_spi_t spi_dev)
#define BMM150_DIG_XYZ1_MSB
#define BMM150_DIG_Z4_MSB
void * PIOS_malloc(size_t size)
Definition: pios_heap.c:125
bool PIOS_Queue_Send(struct pios_queue *queuep, const void *itemp, uint32_t timeout_ms)
Definition: pios_queue.c:141
#define BMM150_DIG_Z1_MSB
#define BMM150_DIG_Z1_LSB
#define BMM050_INIT_VALUE
#define BMM150_DIG_Z3_LSB
#define DEBUG_PRINTF(level,...)
Definition: pios_board.h:39
Task monitoring library.
#define BMM150_DIG_X1
static struct flyingpicmd_cfg_fa cfg
Definition: main.c:49
#define BMM150_REG_MAG_Y_LSB
#define BMM150_REG_MAG_CHIPID
#define BMM150_DIG_X2
#define BMM150_DIG_Z2_MSB
#define BMM050_OVERFLOW_OUTPUT_FLOAT
uint8_t PIOS_SPI_TransferByte(pios_spi_t spi_dev, uint8_t b)
int32_t PIOS_SPI_SetClockSpeed(pios_spi_t spi_dev, uint32_t speed)
#define BMM150_DIG_Y2
int32_t PIOS_SPI_TransferBlock(pios_spi_t spi_dev, const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len)
struct pios_thread * PIOS_Thread_Create(void(*fp)(void *), const char *namep, size_t stack_bytes, void *argp, enum pios_thread_prio_e prio)
Definition: pios_thread.c:89
int32_t PIOS_SENSORS_Register(enum pios_sensor_type type, struct pios_queue *queue)
Register a queue-based sensor with the PIOS_SENSORS interface.
Definition: pios_sensors.c:82
static float mag_scale[3]
Definition: sensors.c:113
#define BMM150_VAL_MAG_CHIPID
#define BMM150_REG_MAG_Z_AXIS_REP
#define BMM150_DIG_Z4_LSB
#define BMM150_VAL_MAG_OPERATION_MODE_OPMODE_NORMAL
#define BMM050_HALL_OVERFLOW_ADCVAL
#define BMM150_VAL_MAG_POWER_CONTROL_POWEROFF
uint32_t magic
void PIOS_free(void *buf)
Definition: pios_heap.c:174
void PIOS_Thread_Sleep(uint32_t time_ms)
Definition: pios_thread.c:229
Pios sensor structure for generic mag data.
Definition: pios_sensors.h:54
tuple f
Definition: px_mkfw.py:81
struct pios_bmm150_dev * pios_bmm150_dev_t
Definition: pios_bmm150.h:48
#define BMM150_REG_MAG_POWER_CONTROL
#define BMM150_REG_MAG_HALL_RESISTANCE_LSB
#define BMM150_DIG_Z2_LSB
Includes PiOS and core architecture components.
#define BMM150_REG_MAG_Z_LSB
#define BMM150_REG_MAG_X_Y_AXIS_REP
int32_t PIOS_SPI_ReleaseBus(pios_spi_t spi_dev)
#define BMM150_VAL_MAG_POWER_CONTROL_POWERON
#define BMM150_REG_MAG_HALL_RESISTANCE_MSB
#define BMM150_VAL_MAG_OPERATION_MODE_ODR30
#define BMM150_VAL_MAG_HALL_RESISTANCE_LSB_DRDY
#define BMM150_DIG_Y1
int32_t PIOS_DELAY_WaitmS(uint32_t mS)
Definition: pios_delay.c:140
#define BMM150_DIG_Z3_MSB
#define BMM150_DIG_XYZ1_LSB