PageRenderTime 52ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/platform/srf06-cc26xx/sensortag/bmp-280-sensor.c

https://gitlab.com/rdeterre/contiki
C | 392 lines | 242 code | 27 blank | 123 comment | 25 complexity | d6a4c473bae4ec7380053bb82513b6ef MD5 | raw file
  1. /*
  2. * Copyright (c) 2014, Texas Instruments Incorporated - http://www.ti.com/
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. Neither the name of the copyright holder nor the names of its
  14. * contributors may be used to endorse or promote products derived
  15. * from this software without specific prior written permission.
  16. *
  17. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  18. * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  19. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
  20. * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
  21. * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
  22. * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  24. * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  25. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  26. * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  27. * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  28. * OF THE POSSIBILITY OF SUCH DAMAGE.
  29. */
  30. /*---------------------------------------------------------------------------*/
  31. /**
  32. * \addtogroup sensortag-cc26xx-bmp-sensor
  33. * @{
  34. *
  35. * \file
  36. * Driver for the Sensortag BMP280 Altimeter / Pressure Sensor
  37. */
  38. /*---------------------------------------------------------------------------*/
  39. #include "contiki-conf.h"
  40. #include "lib/sensors.h"
  41. #include "bmp-280-sensor.h"
  42. #include "sys/ctimer.h"
  43. #include "sensor-common.h"
  44. #include "board-i2c.h"
  45. #include "ti-lib.h"
  46. #include <stdint.h>
  47. #include <string.h>
  48. #include <stdio.h>
  49. /*---------------------------------------------------------------------------*/
  50. #define DEBUG 0
  51. #if DEBUG
  52. #define PRINTF(...) printf(__VA_ARGS__)
  53. #else
  54. #define PRINTF(...)
  55. #endif
  56. /*---------------------------------------------------------------------------*/
  57. #define BMP280_I2C_ADDRESS 0x77
  58. /*---------------------------------------------------------------------------*/
  59. /* Registers */
  60. #define ADDR_CALIB 0x88
  61. #define ADDR_PROD_ID 0xD0
  62. #define ADDR_RESET 0xE0
  63. #define ADDR_STATUS 0xF3
  64. #define ADDR_CTRL_MEAS 0xF4
  65. #define ADDR_CONFIG 0xF5
  66. #define ADDR_PRESS_MSB 0xF7
  67. #define ADDR_PRESS_LSB 0xF8
  68. #define ADDR_PRESS_XLSB 0xF9
  69. #define ADDR_TEMP_MSB 0xFA
  70. #define ADDR_TEMP_LSB 0xFB
  71. #define ADDR_TEMP_XLSB 0xFC
  72. /*---------------------------------------------------------------------------*/
  73. /* Reset values */
  74. #define VAL_PROD_ID 0x58
  75. #define VAL_RESET 0x00
  76. #define VAL_STATUS 0x00
  77. #define VAL_CTRL_MEAS 0x00
  78. #define VAL_CONFIG 0x00
  79. #define VAL_PRESS_MSB 0x80
  80. #define VAL_PRESS_LSB 0x00
  81. #define VAL_TEMP_MSB 0x80
  82. #define VAL_TEMP_LSB 0x00
  83. /*---------------------------------------------------------------------------*/
  84. /* Test values */
  85. #define VAL_RESET_EXECUTE 0xB6
  86. #define VAL_CTRL_MEAS_TEST 0x55
  87. /*---------------------------------------------------------------------------*/
  88. /* Misc. */
  89. #define MEAS_DATA_SIZE 6
  90. /*---------------------------------------------------------------------------*/
  91. #define RES_OFF 0
  92. #define RES_ULTRA_LOW_POWER 1
  93. #define RES_LOW_POWER 2
  94. #define RES_STANDARD 3
  95. #define RES_HIGH 5
  96. #define RES_ULTRA_HIGH 6
  97. /*---------------------------------------------------------------------------*/
  98. /* Bit fields in CTRL_MEAS register */
  99. #define PM_OFF 0
  100. #define PM_FORCED 1
  101. #define PM_NORMAL 3
  102. /*---------------------------------------------------------------------------*/
  103. #define OSRST(v) ((v) << 5)
  104. #define OSRSP(v) ((v) << 2)
  105. /*---------------------------------------------------------------------------*/
  106. typedef struct bmp_280_calibration {
  107. uint16_t dig_t1;
  108. int16_t dig_t2;
  109. int16_t dig_t3;
  110. uint16_t dig_p1;
  111. int16_t dig_p2;
  112. int16_t dig_p3;
  113. int16_t dig_p4;
  114. int16_t dig_p5;
  115. int16_t dig_p6;
  116. int16_t dig_p7;
  117. int16_t dig_p8;
  118. int16_t dig_p9;
  119. int32_t t_fine;
  120. } bmp_280_calibration_t;
  121. /*---------------------------------------------------------------------------*/
  122. #define CALIB_DATA_SIZE (sizeof(bmp_280_calibration_t))
  123. static uint8_t calibration_data[CALIB_DATA_SIZE];
  124. /*---------------------------------------------------------------------------*/
  125. #define SENSOR_STATUS_DISABLED 0
  126. #define SENSOR_STATUS_INITIALISED 1
  127. #define SENSOR_STATUS_NOT_READY 2
  128. #define SENSOR_STATUS_READY 3
  129. static int enabled = SENSOR_STATUS_DISABLED;
  130. /*---------------------------------------------------------------------------*/
  131. /* A buffer for the raw reading from the sensor */
  132. #define SENSOR_DATA_BUF_SIZE 6
  133. static uint8_t sensor_value[SENSOR_DATA_BUF_SIZE];
  134. /*---------------------------------------------------------------------------*/
  135. /* Wait SENSOR_STARTUP_DELAY clock ticks for the sensor to be ready - ~80ms */
  136. #define SENSOR_STARTUP_DELAY 3
  137. static struct ctimer startup_timer;
  138. /*---------------------------------------------------------------------------*/
  139. static void
  140. notify_ready(void *not_used)
  141. {
  142. enabled = SENSOR_STATUS_READY;
  143. sensors_changed(&bmp_280_sensor);
  144. }
  145. /*---------------------------------------------------------------------------*/
  146. static void
  147. select_on_bus(void)
  148. {
  149. /* Set up I2C */
  150. board_i2c_select(BOARD_I2C_INTERFACE_0, BMP280_I2C_ADDRESS);
  151. }
  152. /*---------------------------------------------------------------------------*/
  153. /**
  154. * \brief Initalise the sensor
  155. */
  156. static void
  157. init(void)
  158. {
  159. uint8_t val;
  160. select_on_bus();
  161. /* Read and store calibration data */
  162. sensor_common_read_reg(ADDR_CALIB, calibration_data, CALIB_DATA_SIZE);
  163. /* Reset the sensor */
  164. val = VAL_RESET_EXECUTE;
  165. sensor_common_write_reg(ADDR_RESET, &val, sizeof(val));
  166. }
  167. /*---------------------------------------------------------------------------*/
  168. /**
  169. * \brief Enable/disable measurements
  170. * \param enable 0: disable, enable otherwise
  171. *
  172. * @return none
  173. */
  174. static void
  175. enable_sensor(bool enable)
  176. {
  177. uint8_t val;
  178. select_on_bus();
  179. if(enable) {
  180. /* Enable forced mode */
  181. val = PM_FORCED | OSRSP(1) | OSRST(1);
  182. } else {
  183. val = PM_OFF;
  184. }
  185. sensor_common_write_reg(ADDR_CTRL_MEAS, &val, sizeof(val));
  186. }
  187. /*---------------------------------------------------------------------------*/
  188. /**
  189. * \brief Read temperature and pressure data
  190. * \param data Pointer to a buffer where temperature and pressure will be
  191. * written (6 bytes)
  192. * \return True if valid data could be retrieved
  193. */
  194. static bool
  195. read_data(uint8_t *data)
  196. {
  197. bool success;
  198. select_on_bus();
  199. success = sensor_common_read_reg(ADDR_PRESS_MSB, data, MEAS_DATA_SIZE);
  200. if(!success) {
  201. sensor_common_set_error_data(data, MEAS_DATA_SIZE);
  202. }
  203. return success;
  204. }
  205. /*---------------------------------------------------------------------------*/
  206. /**
  207. * \brief Convert raw data to values in degrees C (temp) and Pascal (pressure)
  208. * \param data Pointer to a buffer that holds raw sensor data
  209. * \param temp Pointer to a variable where the converted temperature will be
  210. * written
  211. * \param press Pointer to a variable where the converted pressure will be
  212. * written
  213. */
  214. static void
  215. convert(uint8_t *data, int32_t *temp, uint32_t *press)
  216. {
  217. int32_t utemp, upress;
  218. bmp_280_calibration_t *p = (bmp_280_calibration_t *)calibration_data;
  219. int32_t v_x1_u32r;
  220. int32_t v_x2_u32r;
  221. int32_t temperature;
  222. uint32_t pressure;
  223. /* Pressure */
  224. upress = (int32_t)((((uint32_t)(data[0])) << 12)
  225. | (((uint32_t)(data[1])) << 4) | ((uint32_t)data[2] >> 4));
  226. /* Temperature */
  227. utemp = (int32_t)((((uint32_t)(data[3])) << 12) | (((uint32_t)(data[4])) << 4)
  228. | ((uint32_t)data[5] >> 4));
  229. /* Compensate temperature */
  230. v_x1_u32r = ((((utemp >> 3) - ((int32_t)p->dig_t1 << 1)))
  231. * ((int32_t)p->dig_t2)) >> 11;
  232. v_x2_u32r = (((((utemp >> 4) - ((int32_t)p->dig_t1))
  233. * ((utemp >> 4) - ((int32_t)p->dig_t1))) >> 12)
  234. * ((int32_t)p->dig_t3))
  235. >> 14;
  236. p->t_fine = v_x1_u32r + v_x2_u32r;
  237. temperature = (p->t_fine * 5 + 128) >> 8;
  238. *temp = temperature;
  239. /* Compensate pressure */
  240. v_x1_u32r = (((int32_t)p->t_fine) >> 1) - (int32_t)64000;
  241. v_x2_u32r = (((v_x1_u32r >> 2) * (v_x1_u32r >> 2)) >> 11)
  242. * ((int32_t)p->dig_p6);
  243. v_x2_u32r = v_x2_u32r + ((v_x1_u32r * ((int32_t)p->dig_p5)) << 1);
  244. v_x2_u32r = (v_x2_u32r >> 2) + (((int32_t)p->dig_p4) << 16);
  245. v_x1_u32r =
  246. (((p->dig_p3 * (((v_x1_u32r >> 2) * (v_x1_u32r >> 2)) >> 13)) >> 3)
  247. + ((((int32_t)p->dig_p2) * v_x1_u32r) >> 1)) >> 18;
  248. v_x1_u32r = ((((32768 + v_x1_u32r)) * ((int32_t)p->dig_p1)) >> 15);
  249. if(v_x1_u32r == 0) {
  250. return; /* Avoid exception caused by division by zero */
  251. }
  252. pressure = (((uint32_t)(((int32_t)1048576) - upress) - (v_x2_u32r >> 12)))
  253. * 3125;
  254. if(pressure < 0x80000000) {
  255. pressure = (pressure << 1) / ((uint32_t)v_x1_u32r);
  256. } else {
  257. pressure = (pressure / (uint32_t)v_x1_u32r) * 2;
  258. }
  259. v_x1_u32r = (((int32_t)p->dig_p9)
  260. * ((int32_t)(((pressure >> 3) * (pressure >> 3)) >> 13))) >> 12;
  261. v_x2_u32r = (((int32_t)(pressure >> 2)) * ((int32_t)p->dig_p8)) >> 13;
  262. pressure = (uint32_t)((int32_t)pressure
  263. + ((v_x1_u32r + v_x2_u32r + p->dig_p7) >> 4));
  264. *press = pressure;
  265. }
  266. /*---------------------------------------------------------------------------*/
  267. /**
  268. * \brief Returns a reading from the sensor
  269. * \param type BMP_280_SENSOR_TYPE_TEMP or BMP_280_SENSOR_TYPE_PRESS
  270. * \return Temperature (centi degrees C) or Pressure (Pascal).
  271. */
  272. static int
  273. value(int type)
  274. {
  275. int rv;
  276. int32_t temp = 0;
  277. uint32_t pres = 0;
  278. if(enabled != SENSOR_STATUS_READY) {
  279. PRINTF("Sensor disabled or starting up (%d)\n", enabled);
  280. return CC26XX_SENSOR_READING_ERROR;
  281. }
  282. if((type != BMP_280_SENSOR_TYPE_TEMP) && type != BMP_280_SENSOR_TYPE_PRESS) {
  283. PRINTF("Invalid type\n");
  284. return CC26XX_SENSOR_READING_ERROR;
  285. } else {
  286. memset(sensor_value, 0, SENSOR_DATA_BUF_SIZE);
  287. rv = read_data(sensor_value);
  288. if(rv == 0) {
  289. return CC26XX_SENSOR_READING_ERROR;
  290. }
  291. PRINTF("val: %02x%02x%02x %02x%02x%02x\n",
  292. sensor_value[0], sensor_value[1], sensor_value[2],
  293. sensor_value[3], sensor_value[4], sensor_value[5]);
  294. convert(sensor_value, &temp, &pres);
  295. if(type == BMP_280_SENSOR_TYPE_TEMP) {
  296. rv = (int)temp;
  297. } else if(type == BMP_280_SENSOR_TYPE_PRESS) {
  298. rv = (int)pres;
  299. }
  300. }
  301. return rv;
  302. }
  303. /*---------------------------------------------------------------------------*/
  304. /**
  305. * \brief Configuration function for the BMP280 sensor.
  306. *
  307. * \param type Activate, enable or disable the sensor. See below
  308. * \param enable
  309. *
  310. * When type == SENSORS_HW_INIT we turn on the hardware
  311. * When type == SENSORS_ACTIVE and enable==1 we enable the sensor
  312. * When type == SENSORS_ACTIVE and enable==0 we disable the sensor
  313. */
  314. static int
  315. configure(int type, int enable)
  316. {
  317. switch(type) {
  318. case SENSORS_HW_INIT:
  319. enabled = SENSOR_STATUS_INITIALISED;
  320. init();
  321. enable_sensor(0);
  322. break;
  323. case SENSORS_ACTIVE:
  324. /* Must be initialised first */
  325. if(enabled == SENSOR_STATUS_DISABLED) {
  326. return SENSOR_STATUS_DISABLED;
  327. }
  328. if(enable) {
  329. enable_sensor(1);
  330. ctimer_set(&startup_timer, SENSOR_STARTUP_DELAY, notify_ready, NULL);
  331. enabled = SENSOR_STATUS_NOT_READY;
  332. } else {
  333. ctimer_stop(&startup_timer);
  334. enable_sensor(0);
  335. enabled = SENSOR_STATUS_INITIALISED;
  336. }
  337. break;
  338. default:
  339. break;
  340. }
  341. return enabled;
  342. }
  343. /*---------------------------------------------------------------------------*/
  344. /**
  345. * \brief Returns the status of the sensor
  346. * \param type SENSORS_ACTIVE or SENSORS_READY
  347. * \return 1 if the sensor is enabled
  348. */
  349. static int
  350. status(int type)
  351. {
  352. switch(type) {
  353. case SENSORS_ACTIVE:
  354. case SENSORS_READY:
  355. return enabled;
  356. break;
  357. default:
  358. break;
  359. }
  360. return SENSOR_STATUS_DISABLED;
  361. }
  362. /*---------------------------------------------------------------------------*/
  363. SENSORS_SENSOR(bmp_280_sensor, "BMP280", value, configure, status);
  364. /*---------------------------------------------------------------------------*/
  365. /** @} */