df220.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. /**\mainpage
  2. * Copyright (C) 2012 - 2019 MiraMEMS
  3. *
  4. * Redistribution and use in source and binary forms, with or without
  5. * modification, are permitted provided that the following conditions are met:
  6. *
  7. * Redistributions of source code must retain the above copyright
  8. * notice, this list of conditions and the following disclaimer.
  9. *
  10. * 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. *
  14. * Neither the name of the copyright holder nor the names of the
  15. * contributors may be used to endorse or promote products derived from
  16. * this software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  19. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
  20. * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  21. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDER
  23. * OR CONTRIBUTORS BE LIABLE FOR ANY
  24. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
  25. * OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO,
  26. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  27. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  29. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
  31. * ANY WAY OUT OF THE USE OF THIS
  32. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE
  33. *
  34. * The information provided is believed to be accurate and reliable.
  35. * The copyright holder assumes no responsibility
  36. * for the consequences of use
  37. * of such information nor for any infringement of patents or
  38. * other rights of third parties which may result from its use.
  39. * No license is granted by implication or otherwise under any patent or
  40. * patent rights of the copyright holder.
  41. *
  42. * File df220.c
  43. * Date 17 Apr 2019
  44. * Version 0.0.1
  45. *
  46. */
  47. /*! @file df220.c
  48. * @brief Sensor driver for df270 sensor
  49. */
  50. #include "df220.h"
  51. /************************** Internal macros *******************************/
  52. /********************** Static function declarations ************************/
  53. /*!
  54. * @brief This internal API is used to validate the device pointer for
  55. * null conditions.
  56. *
  57. * @param[in] dev : Structure instance of df220_dev.
  58. *
  59. * @return Result of API execution status
  60. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
  61. */
  62. static int8_t null_ptr_check(const struct df220_dev *dev);
  63. /*!
  64. * @brief This internal API is used to set the force configurations in sensor
  65. *
  66. * @param[in] force_conf : Structure instance with force configurations
  67. * @param[in] dev : Structure instance of df220_dev
  68. *
  69. * @return Result of API execution status
  70. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
  71. */
  72. static int8_t set_force_conf(const struct df220_force_conf *force_conf, const struct df220_dev *dev);
  73. /*!
  74. * @brief This API reads force data along with sensor time
  75. *
  76. * @param[in,out] force : Structure instance to store the force data
  77. * @param[in] dev : Structure instance of df220_dev
  78. *
  79. * @return Result of API execution status
  80. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
  81. */
  82. static int8_t get_force_data(struct df220_sensor_data *force, const struct df220_dev *dev);
  83. /*!
  84. * @brief This internal API is used to get the force configurations in sensor
  85. *
  86. * @param[in,out] force_conf : Structure instance of basic
  87. * forceerometer configuration
  88. * @param[in] dev : Structure instance of df220_dev
  89. *
  90. * @return Result of API execution status
  91. * @retval zero -> Success / +ve value -> Warning / -ve value -> Error
  92. */
  93. static int8_t get_force_conf(struct df220_force_conf *force_conf, const struct df220_dev *dev);
  94. /********************** Global function definitions ************************/
  95. /*!
  96. * @brief This API is the entry point, Call this API before using other APIs.
  97. * This API reads the chip-id of the sensor which is the first step to
  98. * verify the sensor and updates the trim parameters of the sensor.
  99. */
  100. int8_t df220_init(struct df220_dev *dev)
  101. {
  102. int8_t rslt;
  103. uint8_t chip_id = 0;
  104. /* Check for null pointer in the device structure*/
  105. rslt = null_ptr_check(dev);
  106. /* Proceed if null check is fine */
  107. if (rslt == DF220_OK) {
  108. /* Initial power-up time */
  109. dev->delay_ms(5);
  110. /* Assigning dummy byte value, TODO */
  111. if (dev->intf == DF220_SPI_INTF) {
  112. /* Dummy Byte availability */
  113. dev->dummy_byte = 1;
  114. /* Dummy read of Chip-ID in SPI mode */
  115. rslt = df220_get_regs(DF220_CHIP_ID_ADDR, &chip_id, 1, dev);
  116. } else {
  117. dev->dummy_byte = 0;
  118. }
  119. if (rslt == DF220_OK) {
  120. /* Chip ID of the sensor is read */
  121. rslt = df220_get_regs(DF220_CHIP_ID_ADDR, &chip_id, 1, dev);
  122. /* Proceed if everything is fine until now */
  123. if (rslt == DF220_OK) {
  124. /* Check for chip id validity */
  125. if (chip_id == DF220_CHIP_ID) {
  126. /* Store the chip ID in dev structure */
  127. dev->chip_id = chip_id;
  128. } else {
  129. rslt = DF220_E_DEV_NOT_FOUND;
  130. }
  131. }
  132. }
  133. }
  134. return rslt;
  135. }
  136. /*!
  137. * @brief This API writes the given data to the register address
  138. * of the sensor.
  139. */
  140. int8_t df220_set_regs(uint8_t reg_addr, uint8_t *reg_data, uint8_t len, const struct df220_dev *dev)
  141. {
  142. int8_t rslt;
  143. uint8_t count;
  144. /* Check for null pointer in the device structure */
  145. rslt = null_ptr_check(dev);
  146. /* Proceed if null check is fine */
  147. if ((rslt == DF220_OK) && (reg_data != NULL)) {
  148. /* Write the data to the reg_addr */
  149. /* SPI write requires to set The MSB of reg_addr as 0
  150. but in default the MSB is always 0 */
  151. if (len == 1) {
  152. rslt = dev->write(dev->intf_ptr, dev->dev_id, reg_addr, reg_data, len);
  153. if (rslt != DF220_OK) {
  154. /* Failure case */
  155. rslt = DF220_E_COM_FAIL;
  156. }
  157. }
  158. /* Burst write is not allowed thus we split burst case write
  159. * into single byte writes Thus user can write multiple bytes
  160. * with ease */
  161. if (len > 1) {
  162. for (count = 0; count < len; count++) {
  163. rslt = dev->write(dev->intf_ptr, dev->dev_id, reg_addr, &reg_data[count], 1);
  164. reg_addr++;
  165. }
  166. }
  167. } else {
  168. rslt = DF220_E_NULL_PTR;
  169. }
  170. return rslt;
  171. }
  172. /*!
  173. * @brief This API reads the data from the given register address of the sensor.
  174. */
  175. int8_t df220_get_regs(uint8_t reg_addr, uint8_t *reg_data, uint8_t len, const struct df220_dev *dev)
  176. {
  177. int8_t rslt;
  178. uint16_t index;
  179. uint16_t temp_len = len;
  180. uint8_t temp_buff[temp_len];
  181. /* Check for null pointer in the device structure */
  182. rslt = null_ptr_check(dev);
  183. /* Proceed if null check is fine */
  184. if ((rslt == DF220_OK) && (reg_data != NULL)) {
  185. if (dev->intf != DF220_I2C_INTF) {
  186. /* If interface selected is SPI */
  187. reg_addr = reg_addr | DF220_SPI_RD_MASK;
  188. }
  189. /* Read the data from the reg_addr */
  190. rslt = dev->read(dev->intf_ptr, dev->dev_id, reg_addr, temp_buff, temp_len);
  191. if (rslt == DF220_OK) {
  192. for (index = 0; index < len; index++) {
  193. /* Parse the data read and store in "reg_data"
  194. * buffer so that the dummy byte is removed
  195. * and user will get only valid data
  196. */
  197. reg_data[index] = temp_buff[index];
  198. }
  199. }
  200. if (rslt != DF220_OK) {
  201. /* Failure case */
  202. rslt = DF220_E_COM_FAIL;
  203. }
  204. } else {
  205. rslt = DF220_E_NULL_PTR;
  206. }
  207. return rslt;
  208. }
  209. /*!
  210. * @brief This API is used to perform soft-reset of the sensor
  211. * where all the registers are reset to their default values.
  212. */
  213. int8_t df220_soft_reset(const struct df220_dev *dev)
  214. {
  215. int8_t rslt;
  216. uint8_t data = DF220_SOFT_RESET_CMD;
  217. /* Null-pointer check */
  218. rslt = null_ptr_check(dev);
  219. if (rslt == DF220_OK) {
  220. /* Reset the device */
  221. rslt = df220_get_regs(0x00, &data, 1, dev);
  222. data = DF220_SET_BITS_POS_0(data, DF220_SOFT_RESET_CMD, DF220_SOFT_RESET_CMD);
  223. rslt = df220_set_regs(DF220_SPI_CONFIG, &data, 1, dev);
  224. dev->delay_ms(DF220_SOFT_RESET_DELAY_MS);
  225. if ((rslt == DF220_OK) && (dev->intf == DF220_SPI_INTF)) {
  226. /* Dummy read of 0x7F register to enable SPI Interface
  227. * if SPI is used
  228. */
  229. rslt = df220_get_regs(0x7F, &data, 1, dev);
  230. }
  231. }
  232. return rslt;
  233. }
  234. /*!
  235. * @brief This API is used to set the power mode of the sensor.
  236. */
  237. int8_t df220_set_power_mode(uint8_t power_mode, const struct df220_dev *dev)
  238. {
  239. int8_t rslt;
  240. uint8_t reg_data = 0;
  241. rslt = null_ptr_check(dev);
  242. if (rslt == DF220_OK) {
  243. rslt = df220_get_regs(DF220_FORCE_MODE_BW, &reg_data, 1, dev);
  244. }
  245. if (rslt == DF220_OK) {
  246. reg_data = DF220_SET_BITS(reg_data, DF220_POWER_MODE, power_mode);
  247. /* Set the power mode of sensor */
  248. rslt = df220_set_regs(DF220_FORCE_MODE_BW, &reg_data, 1, dev);
  249. if (power_mode == DF220_LOW_POWER_MODE) {
  250. /* A delay of 1/ODR is required to switch power modes*/
  251. dev->delay_ms(100);
  252. } else {
  253. dev->delay_ms(100);
  254. }
  255. }
  256. return rslt;
  257. }
  258. /*!
  259. * @brief This API is used to get the force data along with the sensor-time
  260. */
  261. int8_t df220_get_force_data(struct df220_sensor_data *force, const struct df220_dev *dev)
  262. {
  263. int8_t rslt;
  264. /* Check for null pointer in the device structure*/
  265. rslt = null_ptr_check(dev);
  266. /* Proceed if null check is fine */
  267. if ((rslt == DF220_OK) && (force != NULL)) {
  268. /* Read and store the force data */
  269. rslt = get_force_data(force, dev);
  270. } else {
  271. rslt = DF220_E_NULL_PTR;
  272. }
  273. return rslt;
  274. }
  275. /*!
  276. * @brief This API is used to set the sensor settings like sensor
  277. * configurations and interrupt configurations
  278. */
  279. int8_t df220_set_sensor_conf(const struct df220_sensor_conf *conf, uint16_t n_sett, const struct df220_dev *dev)
  280. {
  281. int8_t rslt;
  282. uint16_t idx = 0;
  283. /* Check for null pointer in the device structure*/
  284. rslt = null_ptr_check(dev);
  285. if (rslt == DF220_OK) {
  286. for (idx = 0; idx < n_sett; idx++) {
  287. switch (conf[idx].type) {
  288. case DF220_FORCE:
  289. /* Setting Force configurations */
  290. rslt = set_force_conf(&conf[idx].param.force, dev);
  291. if (rslt == DF220_OK) {
  292. /* Set the INT pin mapping */
  293. }
  294. break;
  295. default:
  296. rslt = DF220_E_INVALID_CONFIG;
  297. }
  298. }
  299. }
  300. return rslt;
  301. }
  302. /*!
  303. * @brief This API is used to get the sensor settings like sensor
  304. * configurations and interrupt configurations and store
  305. * them in the corresponding structure instance
  306. */
  307. int8_t df220_get_sensor_conf(struct df220_sensor_conf *conf, uint16_t n_sett, const struct df220_dev *dev)
  308. {
  309. int8_t rslt = DF220_OK;
  310. uint16_t idx = 0;
  311. if (conf == NULL) {
  312. rslt = DF220_E_NULL_PTR;
  313. }
  314. for (idx = 0; (idx < n_sett) && (rslt == DF220_OK); idx++) {
  315. switch (conf[idx].type) {
  316. case DF220_FORCE:
  317. /* Force configuration settings */
  318. rslt = get_force_conf(&conf[idx].param.force, dev);
  319. if (rslt == DF220_OK) {
  320. /* Get the INT pin mapping */
  321. }
  322. break;
  323. default:
  324. rslt = DF220_E_INVALID_CONFIG;
  325. }
  326. }
  327. return rslt;
  328. }
  329. /****************************************************************************/
  330. /**\name INTERNAL APIs */
  331. /*!
  332. * @brief This internal API is used to validate the device structure pointer for
  333. * null conditions.
  334. */
  335. static int8_t null_ptr_check(const struct df220_dev *dev)
  336. {
  337. int8_t rslt;
  338. if ((dev == NULL) || (dev->read == NULL) || (dev->write == NULL) || (dev->delay_ms == NULL)) {
  339. /* Device structure pointer is not valid */
  340. rslt = DF220_E_NULL_PTR;
  341. } else {
  342. /* Device structure is fine */
  343. rslt = DF220_OK;
  344. }
  345. return rslt;
  346. }
  347. /*!
  348. * @brief This internal API is used to set the force configurations in sensor
  349. */
  350. static int8_t set_force_conf(const struct df220_force_conf *force_conf, const struct df220_dev *dev)
  351. {
  352. int8_t rslt;
  353. uint8_t data_array[3] = { 0, 0, 0 };
  354. /* Update the force configurations from the user structure
  355. * force_conf */
  356. rslt = df220_get_regs(DF220_FORCE_LSB_RANGE, data_array, 3, dev);
  357. if (rslt == DF220_OK) {
  358. data_array[0] = DF220_SET_BITS(data_array[0], DF220_FORCE_RANGE, force_conf->range);
  359. data_array[1] = DF220_SET_BITS_POS_0(data_array[1], DF220_FORCEL_ODR, force_conf->odr);
  360. data_array[2] = DF220_SET_BITS(data_array[2], DF220_BW, force_conf->bw);
  361. /* Set the force configurations in the sensor */
  362. rslt = df220_set_regs(DF220_FORCE_LSB_RANGE, data_array, 3, dev);
  363. }
  364. return rslt;
  365. }
  366. /*!
  367. * @brief This internal API is used to set the force configurations in sensor
  368. */
  369. static int8_t get_force_conf(struct df220_force_conf *force_conf, const struct df220_dev *dev)
  370. {
  371. int8_t rslt;
  372. uint8_t data_array[3];
  373. rslt = df220_get_regs(DF220_FORCE_LSB_RANGE, data_array, 3, dev);
  374. if (rslt == DF220_OK) {
  375. force_conf->range = DF220_GET_BITS(data_array[0], DF220_FORCE_RANGE);
  376. force_conf->odr = DF220_GET_BITS_POS_0(data_array[1], DF220_FORCEL_ODR);
  377. force_conf->bw = DF220_GET_BITS(data_array[2], DF220_BW);
  378. }
  379. return rslt;
  380. }
  381. /*!
  382. * @brief This API reads force data along with sensor time
  383. */
  384. static int8_t get_force_data(struct df220_sensor_data *force, const struct df220_dev *dev)
  385. {
  386. int8_t rslt;
  387. uint8_t data_array[2] = { 0 };
  388. /* Read the sensor data registers only */
  389. rslt = df220_get_regs(DF220_FORCE_DATA_ADDR, data_array, 2, dev);
  390. if (rslt == DF220_OK) {
  391. force->f = ((int16_t)(data_array[1] << 8 | data_array[0]))>> 2;
  392. force->f = 10000*(force->f+8192)/16384;
  393. }
  394. return rslt;
  395. }