ccs811.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. /**
  2. * Copyright (c) 2017 - 2018, Nordic Semiconductor ASA
  3. *
  4. * All rights reserved.
  5. *
  6. * Redistribution and use in source and binary forms, with or without modification,
  7. * are permitted provided that the following conditions are met:
  8. *
  9. * 1. Redistributions of source code must retain the above copyright notice, this
  10. * list of conditions and the following disclaimer.
  11. *
  12. * 2. Redistributions in binary form, except as embedded into a Nordic
  13. * Semiconductor ASA integrated circuit in a product or a software update for
  14. * such product, must reproduce the above copyright notice, this list of
  15. * conditions and the following disclaimer in the documentation and/or other
  16. * materials provided with the distribution.
  17. *
  18. * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * 4. This software, with or without modification, must only be used with a
  23. * Nordic Semiconductor ASA integrated circuit.
  24. *
  25. * 5. Any software provided in binary form under this license must not be reverse
  26. * engineered, decompiled, modified and/or disassembled.
  27. *
  28. * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
  29. * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  30. * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
  31. * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
  32. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  33. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
  34. * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  35. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  36. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  37. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  38. *
  39. */
  40. #include "ccs811.h"
  41. #define SWAP_16(arg) ((arg) = (MSB_16(arg) | (LSB_16(arg) << 8)))
  42. ret_code_t ccs811_init(ccs811_instance_t const * p_instance)
  43. {
  44. ASSERT(p_instance != NULL);
  45. if (p_instance->p_sensor_data->p_twi_mngr->p_queue->size < CCS811_MIN_QUEUE_SIZE)
  46. {
  47. return NRF_ERROR_INVALID_LENGTH;
  48. }
  49. static uint8_t const send_msg[] = {
  50. CCS811_REG_APP_START
  51. };
  52. ret_code_t err = nrf_twi_sensor_write(p_instance->p_sensor_data,
  53. p_instance->sensor_addr,
  54. send_msg,
  55. ARRAY_SIZE(send_msg),
  56. true);
  57. err = ccs811_drive_mode_set(p_instance, CCS811_MODE_0, false, false);
  58. if (err != NRF_SUCCESS)
  59. {
  60. return err;
  61. }
  62. err = ccs811_env_set(p_instance, CCS811_DEFAULT_TEMPERATURE, 0, CCS811_DEFAULT_HUMIDITY, 0);
  63. if (err != NRF_SUCCESS)
  64. {
  65. return err;
  66. }
  67. return ccs811_thr_cfg(p_instance,
  68. CCS811_DEFAULT_LOW_THR,
  69. CCS811_DEFAULT_HIGH_THR,
  70. CCS811_DEFAULT_HYSTERESIS);
  71. }
  72. ret_code_t ccs811_drive_mode_set(ccs811_instance_t const * p_instance,
  73. ccs811_drive_mode_t mode,
  74. bool drdy_en,
  75. bool thr_en)
  76. {
  77. ASSERT(p_instance != NULL);
  78. uint8_t reg = 0;
  79. NRF_TWI_SENSOR_REG_SET(reg, CCS811_DRIVE_MODE_MASK, CCS811_DRIVE_MODE_POS, mode);
  80. NRF_TWI_SENSOR_REG_SET(reg, CCS811_DATA_READY_MASK, CCS811_DATA_READY_POS, drdy_en);
  81. NRF_TWI_SENSOR_REG_SET(reg, CCS811_THRESH_MASK, CCS811_THRESH_POS, thr_en);
  82. uint8_t send_msg[] = {
  83. CCS811_REG_MEAS_MODE,
  84. reg
  85. };
  86. return nrf_twi_sensor_write(p_instance->p_sensor_data,
  87. p_instance->sensor_addr,
  88. send_msg,
  89. ARRAY_SIZE(send_msg),
  90. true);
  91. }
  92. ret_code_t ccs811_alg_data_read(ccs811_instance_t const * p_instance,
  93. ccs811_data_callback_t user_cb,
  94. ccs811_alg_data_t * p_alg_data,
  95. ccs811_last_data_byte_t last)
  96. {
  97. ASSERT(p_instance != NULL);
  98. ASSERT(p_alg_data != NULL);
  99. return nrf_twi_sensor_reg_read(p_instance->p_sensor_data,
  100. p_instance->sensor_addr,
  101. CCS811_REG_ALG_RESULT_DATA,
  102. (nrf_twi_sensor_reg_cb_t) user_cb,
  103. (uint8_t *) p_alg_data,
  104. last);
  105. }
  106. void ccs811_alg_data_process(ccs811_alg_data_t * p_alg_data)
  107. {
  108. ASSERT(p_alg_data != NULL);
  109. SWAP_16(p_alg_data->eco2);
  110. SWAP_16(p_alg_data->tvoc);
  111. SWAP_16(p_alg_data->raw);
  112. }
  113. ret_code_t ccs811_env_set(ccs811_instance_t const * p_instance,
  114. int8_t temp_value,
  115. uint16_t temp_fraction,
  116. uint8_t hum_percent,
  117. uint16_t hum_fraction)
  118. {
  119. ASSERT(p_instance != NULL);
  120. temp_value += CCS811_TEMPERATURE_OFFSET;
  121. if(temp_value < 0)
  122. {
  123. temp_value = 0;
  124. }
  125. uint16_t env_temp = ( *((uint16_t *) &temp_value) << CCS811_ENV_TEMP_VALUE_POS)
  126. | (temp_fraction & CCS811_ENV_TEMP_FRACTION_MASK);
  127. uint16_t env_hum = ( *((uint16_t *) &hum_percent) << CCS811_ENV_HUM_PERCENT_POS)
  128. | (hum_fraction & CCS811_ENV_HUM_FRACTION_MASK);
  129. uint8_t send_msg[] = {
  130. CCS811_REG_ENV_DATA,
  131. MSB_16(env_temp),
  132. LSB_16(env_temp),
  133. MSB_16(env_hum),
  134. LSB_16(env_hum)
  135. };
  136. return nrf_twi_sensor_write(p_instance->p_sensor_data,
  137. p_instance->sensor_addr,
  138. send_msg,
  139. ARRAY_SIZE(send_msg),
  140. true);
  141. }
  142. ret_code_t ccs811_thr_cfg(ccs811_instance_t const * p_instance,
  143. uint16_t l_to_m,
  144. uint16_t m_to_h,
  145. uint8_t hysteresis)
  146. {
  147. ASSERT(p_instance != NULL);
  148. uint8_t send_msg[] = {
  149. CCS811_REG_THRESHOLDS,
  150. MSB_16(l_to_m),
  151. LSB_16(l_to_m),
  152. MSB_16(m_to_h),
  153. LSB_16(m_to_h),
  154. hysteresis
  155. };
  156. return nrf_twi_sensor_write(p_instance->p_sensor_data,
  157. p_instance->sensor_addr,
  158. send_msg,
  159. ARRAY_SIZE(send_msg),
  160. true);
  161. }
  162. ret_code_t ccs811_baseline_read(ccs811_instance_t const * p_instance,
  163. nrf_twi_sensor_reg_cb_t user_cb,
  164. uint16_t * p_baseline)
  165. {
  166. ASSERT(p_instance != NULL);
  167. ASSERT(p_baseline != NULL);
  168. return nrf_twi_sensor_reg_read(p_instance->p_sensor_data,
  169. p_instance->sensor_addr,
  170. CCS811_REG_BASELINE,
  171. user_cb,
  172. (uint8_t *) p_baseline,
  173. 2);
  174. }
  175. ret_code_t ccs811_baseline_set(ccs811_instance_t const * p_instance, uint16_t baseline)
  176. {
  177. ASSERT(p_instance != NULL);
  178. uint8_t * p_base = (uint8_t *) &baseline;
  179. uint8_t send_msg[] = {
  180. CCS811_REG_BASELINE,
  181. p_base[0],
  182. p_base[1]
  183. };
  184. return nrf_twi_sensor_write(p_instance->p_sensor_data,
  185. p_instance->sensor_addr,
  186. send_msg,
  187. ARRAY_SIZE(send_msg),
  188. true);
  189. }
  190. ret_code_t ccs811_sw_reset(ccs811_instance_t const * p_instance)
  191. {
  192. ASSERT(p_instance != NULL);
  193. static uint8_t const send_msg[] = {
  194. CCS811_REG_SW_RESET,
  195. CCS811_SW_RESET_BYTE0,
  196. CCS811_SW_RESET_BYTE1,
  197. CCS811_SW_RESET_BYTE2,
  198. CCS811_SW_RESET_BYTE3
  199. };
  200. return nrf_twi_sensor_write(p_instance->p_sensor_data,
  201. p_instance->sensor_addr,
  202. send_msg,
  203. ARRAY_SIZE(send_msg),
  204. true);
  205. }