simple CCS811 driver

Dependencies:   AMS_ENS210_temp_humid_sensor

Dependents:   TBSense2_Sensor_Demo

Fork of AMS_CCS811_gas_sensor by Marcus Lee

Committer:
UHSLMarcus
Date:
Mon Jan 23 14:27:57 2017 +0000
Revision:
6:22c0a7f2ece2
Parent:
5:41e97348e9e7
Child:
7:5c95614a61ee
reading data via poll, interrupt in all active modes works

Who changed what in which revision?

UserRevisionLine numberNew contents of line
UHSLMarcus 0:5edbf3550350 1
UHSLMarcus 2:e394671ef5f6 2 #include "AMS_CCS811.h"
UHSLMarcus 0:5edbf3550350 3
UHSLMarcus 5:41e97348e9e7 4 const char *byte_to_binary(uint8_t in)
UHSLMarcus 5:41e97348e9e7 5 {
UHSLMarcus 5:41e97348e9e7 6 static char b[9];
UHSLMarcus 5:41e97348e9e7 7 b[0] = '\0';
UHSLMarcus 5:41e97348e9e7 8
UHSLMarcus 5:41e97348e9e7 9 int z;
UHSLMarcus 5:41e97348e9e7 10 for (z = 128; z > 0; z >>= 1)
UHSLMarcus 5:41e97348e9e7 11 {
UHSLMarcus 5:41e97348e9e7 12 strcat(b, ((in & z) == z) ? "1" : "0");
UHSLMarcus 5:41e97348e9e7 13 }
UHSLMarcus 5:41e97348e9e7 14
UHSLMarcus 5:41e97348e9e7 15 return b;
UHSLMarcus 5:41e97348e9e7 16 }
UHSLMarcus 0:5edbf3550350 17
UHSLMarcus 6:22c0a7f2ece2 18 const char *short_to_binary(uint16_t in)
UHSLMarcus 6:22c0a7f2ece2 19 {
UHSLMarcus 6:22c0a7f2ece2 20 static char b[17];
UHSLMarcus 6:22c0a7f2ece2 21 b[0] = '\0';
UHSLMarcus 6:22c0a7f2ece2 22
UHSLMarcus 6:22c0a7f2ece2 23 uint16_t z;
UHSLMarcus 6:22c0a7f2ece2 24 for (z = 32768; z > 0; z >>= 1)
UHSLMarcus 6:22c0a7f2ece2 25 {
UHSLMarcus 6:22c0a7f2ece2 26 strcat(b, ((in & z) == z) ? "1" : "0");
UHSLMarcus 6:22c0a7f2ece2 27 }
UHSLMarcus 6:22c0a7f2ece2 28
UHSLMarcus 6:22c0a7f2ece2 29 return b;
UHSLMarcus 6:22c0a7f2ece2 30 }
UHSLMarcus 6:22c0a7f2ece2 31
UHSLMarcus 0:5edbf3550350 32 AMS_CCS811::AMS_CCS811(I2C * i2c, PinName n_wake_pin) {
UHSLMarcus 5:41e97348e9e7 33 _n_wake_out = new (std::nothrow) DigitalOut(n_wake_pin, 1);
UHSLMarcus 4:a6b8881eae87 34 _i2c = i2c;
UHSLMarcus 0:5edbf3550350 35 }
UHSLMarcus 0:5edbf3550350 36
UHSLMarcus 0:5edbf3550350 37 AMS_CCS811::AMS_CCS811(I2C * i2c, PinName n_wake_pin, I2C * ens210_i2c) {
UHSLMarcus 5:41e97348e9e7 38 _n_wake_out = new (std::nothrow) DigitalOut(n_wake_pin, 1);
UHSLMarcus 0:5edbf3550350 39 _i2c = i2c;
UHSLMarcus 0:5edbf3550350 40 _ens210_i2c = ens210_i2c;
UHSLMarcus 0:5edbf3550350 41 }
UHSLMarcus 0:5edbf3550350 42
UHSLMarcus 1:acfca1d3256d 43 AMS_CCS811::~AMS_CCS811() {
UHSLMarcus 1:acfca1d3256d 44 delete _n_wake_out;
UHSLMarcus 1:acfca1d3256d 45 delete _addr_out;
UHSLMarcus 1:acfca1d3256d 46 delete _int_data;
UHSLMarcus 1:acfca1d3256d 47 }
UHSLMarcus 1:acfca1d3256d 48
UHSLMarcus 1:acfca1d3256d 49 bool AMS_CCS811::init() {
UHSLMarcus 5:41e97348e9e7 50
UHSLMarcus 5:41e97348e9e7 51 bool success = false;
UHSLMarcus 5:41e97348e9e7 52
UHSLMarcus 5:41e97348e9e7 53 _init_errors();
UHSLMarcus 5:41e97348e9e7 54 set_defaults();
UHSLMarcus 5:41e97348e9e7 55
UHSLMarcus 5:41e97348e9e7 56 if (_n_wake_out) {
UHSLMarcus 5:41e97348e9e7 57
UHSLMarcus 5:41e97348e9e7 58 int fw_mode = firmware_mode();
UHSLMarcus 5:41e97348e9e7 59
UHSLMarcus 5:41e97348e9e7 60 if (fw_mode == 1) {
UHSLMarcus 5:41e97348e9e7 61 enable_ens210(true);
UHSLMarcus 5:41e97348e9e7 62 success = write_config();
UHSLMarcus 5:41e97348e9e7 63
UHSLMarcus 5:41e97348e9e7 64 } else if (fw_mode == 0) { // is in boot mode, needs to be loaded into app mode
UHSLMarcus 5:41e97348e9e7 65 if (boot_app_start()) // if succesfully writes to app_start, retry init
UHSLMarcus 5:41e97348e9e7 66 init();
UHSLMarcus 5:41e97348e9e7 67 }
UHSLMarcus 5:41e97348e9e7 68 }
UHSLMarcus 5:41e97348e9e7 69 return success;
UHSLMarcus 4:a6b8881eae87 70 }
UHSLMarcus 4:a6b8881eae87 71
UHSLMarcus 4:a6b8881eae87 72 void AMS_CCS811::i2c_interface(I2C * i2c) {
UHSLMarcus 4:a6b8881eae87 73 _i2c = i2c;
UHSLMarcus 4:a6b8881eae87 74 }
UHSLMarcus 4:a6b8881eae87 75
UHSLMarcus 4:a6b8881eae87 76 void AMS_CCS811::ens210_i2c_interface(I2C * i2c) {
UHSLMarcus 4:a6b8881eae87 77 _ens210_i2c = i2c;
UHSLMarcus 4:a6b8881eae87 78 }
UHSLMarcus 4:a6b8881eae87 79
UHSLMarcus 4:a6b8881eae87 80 bool AMS_CCS811::enable_ens210(bool enable) {
UHSLMarcus 4:a6b8881eae87 81
UHSLMarcus 4:a6b8881eae87 82 _ens210_enabled = false;
UHSLMarcus 4:a6b8881eae87 83 if (_ens210_i2c != NULL) _ens210_enabled = enable;
UHSLMarcus 4:a6b8881eae87 84 update_ens210_timer();
UHSLMarcus 4:a6b8881eae87 85
UHSLMarcus 4:a6b8881eae87 86 return _ens210_enabled;
UHSLMarcus 4:a6b8881eae87 87 }
UHSLMarcus 4:a6b8881eae87 88
UHSLMarcus 4:a6b8881eae87 89 bool AMS_CCS811::ens210_is_enabled() {
UHSLMarcus 4:a6b8881eae87 90 return _ens210_enabled;
UHSLMarcus 4:a6b8881eae87 91 }
UHSLMarcus 4:a6b8881eae87 92
UHSLMarcus 4:a6b8881eae87 93 void AMS_CCS811::ens210_poll_interval(int poll_ms) {
UHSLMarcus 4:a6b8881eae87 94 _ens210_poll_split = poll_ms;
UHSLMarcus 4:a6b8881eae87 95 update_ens210_timer();
UHSLMarcus 4:a6b8881eae87 96 }
UHSLMarcus 4:a6b8881eae87 97
UHSLMarcus 4:a6b8881eae87 98 int AMS_CCS811::ens210_poll_interval() {
UHSLMarcus 4:a6b8881eae87 99 return _ens210_poll_split;
UHSLMarcus 1:acfca1d3256d 100 }
UHSLMarcus 1:acfca1d3256d 101
UHSLMarcus 5:41e97348e9e7 102 int AMS_CCS811::firmware_mode() {
UHSLMarcus 5:41e97348e9e7 103 int firmware_result = -1;
UHSLMarcus 5:41e97348e9e7 104
UHSLMarcus 6:22c0a7f2ece2 105 clear_errors();
UHSLMarcus 6:22c0a7f2ece2 106
UHSLMarcus 5:41e97348e9e7 107 read_byte_result read_result = read_status();
UHSLMarcus 5:41e97348e9e7 108 if (read_result.success) {
UHSLMarcus 5:41e97348e9e7 109 firmware_result = (read_result.byte >> 7) & 1;
UHSLMarcus 6:22c0a7f2ece2 110 }
UHSLMarcus 5:41e97348e9e7 111
UHSLMarcus 5:41e97348e9e7 112 return firmware_result;
UHSLMarcus 5:41e97348e9e7 113 }
UHSLMarcus 5:41e97348e9e7 114
UHSLMarcus 1:acfca1d3256d 115 bool AMS_CCS811::mode(OP_MODES mode) {
UHSLMarcus 6:22c0a7f2ece2 116 clear_errors();
UHSLMarcus 6:22c0a7f2ece2 117
UHSLMarcus 1:acfca1d3256d 118 OP_MODES old = _mode; // incase the write fails, to roll back
UHSLMarcus 1:acfca1d3256d 119 _mode = mode;
UHSLMarcus 1:acfca1d3256d 120
UHSLMarcus 1:acfca1d3256d 121 bool success = write_config();
UHSLMarcus 1:acfca1d3256d 122 if (!success)
UHSLMarcus 1:acfca1d3256d 123 _mode = old;
UHSLMarcus 1:acfca1d3256d 124
UHSLMarcus 1:acfca1d3256d 125 return success;
UHSLMarcus 1:acfca1d3256d 126 }
UHSLMarcus 1:acfca1d3256d 127
UHSLMarcus 1:acfca1d3256d 128 AMS_CCS811::OP_MODES AMS_CCS811::mode() {
UHSLMarcus 6:22c0a7f2ece2 129 clear_errors();
UHSLMarcus 6:22c0a7f2ece2 130
UHSLMarcus 5:41e97348e9e7 131 OP_MODES result = INVALID;
UHSLMarcus 1:acfca1d3256d 132
UHSLMarcus 5:41e97348e9e7 133 read_byte_result read_result = read_config();
UHSLMarcus 1:acfca1d3256d 134 if (read_result.success) {
UHSLMarcus 1:acfca1d3256d 135 int mode = (read_result.byte >> 4) & 0b111;
UHSLMarcus 2:e394671ef5f6 136 result = mode > 4 ? INVALID : (OP_MODES)mode;
UHSLMarcus 6:22c0a7f2ece2 137 }
UHSLMarcus 1:acfca1d3256d 138
UHSLMarcus 2:e394671ef5f6 139 return result;
UHSLMarcus 1:acfca1d3256d 140 }
UHSLMarcus 1:acfca1d3256d 141
UHSLMarcus 1:acfca1d3256d 142 bool AMS_CCS811::addr_mode(bool high) {
UHSLMarcus 1:acfca1d3256d 143 _addr_dir = high;
UHSLMarcus 5:41e97348e9e7 144 if (_addr_out != NULL) _addr_out->write(_addr_dir);
UHSLMarcus 1:acfca1d3256d 145
UHSLMarcus 2:e394671ef5f6 146 update_slave_addr();
UHSLMarcus 2:e394671ef5f6 147
UHSLMarcus 1:acfca1d3256d 148 return addr_mode() == high;
UHSLMarcus 1:acfca1d3256d 149 }
UHSLMarcus 1:acfca1d3256d 150
UHSLMarcus 1:acfca1d3256d 151 bool AMS_CCS811::addr_mode() {
UHSLMarcus 1:acfca1d3256d 152 if (_addr_out != NULL) {
UHSLMarcus 5:41e97348e9e7 153 _addr_dir = _addr_out->read();
UHSLMarcus 1:acfca1d3256d 154 }
UHSLMarcus 1:acfca1d3256d 155
UHSLMarcus 1:acfca1d3256d 156 return _addr_dir;
UHSLMarcus 1:acfca1d3256d 157 }
UHSLMarcus 1:acfca1d3256d 158
UHSLMarcus 1:acfca1d3256d 159 bool AMS_CCS811::addr_pin(PinName pin) {
UHSLMarcus 1:acfca1d3256d 160 _addr_out = _addr_out == NULL ? new (std::nothrow) DigitalOut(pin) : new (_addr_out) DigitalOut(pin);
UHSLMarcus 1:acfca1d3256d 161 addr_mode(_addr_dir);
UHSLMarcus 1:acfca1d3256d 162
UHSLMarcus 1:acfca1d3256d 163 return _addr_out != NULL;
UHSLMarcus 1:acfca1d3256d 164 }
UHSLMarcus 1:acfca1d3256d 165
UHSLMarcus 1:acfca1d3256d 166 bool AMS_CCS811::n_wake_pin(PinName pin) {
UHSLMarcus 1:acfca1d3256d 167 _n_wake_out = _n_wake_out == NULL ? new (std::nothrow) DigitalOut(pin) : new (_n_wake_out) DigitalOut(pin);
UHSLMarcus 1:acfca1d3256d 168 return _n_wake_out != NULL;
UHSLMarcus 1:acfca1d3256d 169 }
UHSLMarcus 1:acfca1d3256d 170
UHSLMarcus 2:e394671ef5f6 171 bool AMS_CCS811::env_data(float humid, float temp) {
UHSLMarcus 1:acfca1d3256d 172 return true;
UHSLMarcus 1:acfca1d3256d 173 }
UHSLMarcus 1:acfca1d3256d 174
UHSLMarcus 1:acfca1d3256d 175
UHSLMarcus 5:41e97348e9e7 176 int AMS_CCS811::has_new_data() {
UHSLMarcus 6:22c0a7f2ece2 177
UHSLMarcus 6:22c0a7f2ece2 178 clear_errors();
UHSLMarcus 6:22c0a7f2ece2 179
UHSLMarcus 5:41e97348e9e7 180 int result = -1;
UHSLMarcus 5:41e97348e9e7 181
UHSLMarcus 6:22c0a7f2ece2 182 char meas_mode[1];
UHSLMarcus 6:22c0a7f2ece2 183 if(i2c_read(MEAS_MODE, meas_mode, 1) == 1) { // one read here is quicker than calling read_config() twice
UHSLMarcus 6:22c0a7f2ece2 184
UHSLMarcus 6:22c0a7f2ece2 185 int curr_mode = (meas_mode[0] >> 4) & 0b111;
UHSLMarcus 6:22c0a7f2ece2 186 if (curr_mode < 5) {
UHSLMarcus 6:22c0a7f2ece2 187 if (curr_mode > 0) { // check for all valid modes other than idle
UHSLMarcus 6:22c0a7f2ece2 188 if (((meas_mode[0] >> 3) & 1) == 0) { // check if interrupts are disabled
UHSLMarcus 6:22c0a7f2ece2 189 char status[1];
UHSLMarcus 6:22c0a7f2ece2 190 if (i2c_read(STATUS, status, 1) == 1) // for some reason the status register in ALG_RESULT_DATA is not updated after reading data, however the STATUS register is
UHSLMarcus 6:22c0a7f2ece2 191 result = (status[0] >> 3) & 1;
UHSLMarcus 6:22c0a7f2ece2 192
UHSLMarcus 6:22c0a7f2ece2 193 } else result = 1;
UHSLMarcus 6:22c0a7f2ece2 194
UHSLMarcus 6:22c0a7f2ece2 195 if (result == 1)
UHSLMarcus 6:22c0a7f2ece2 196 if (i2c_read(ALG_RESULT_DATA, _alg_result_data, 8) != 8) result = -1;
UHSLMarcus 6:22c0a7f2ece2 197
UHSLMarcus 6:22c0a7f2ece2 198
UHSLMarcus 6:22c0a7f2ece2 199 } else result = 0; // return 0 when in idle
UHSLMarcus 6:22c0a7f2ece2 200 } else new_error(CCS811_LIB_INV_MODE_ID);
UHSLMarcus 5:41e97348e9e7 201 }
UHSLMarcus 5:41e97348e9e7 202
UHSLMarcus 5:41e97348e9e7 203 return result;
UHSLMarcus 1:acfca1d3256d 204 }
UHSLMarcus 1:acfca1d3256d 205
UHSLMarcus 1:acfca1d3256d 206 uint16_t AMS_CCS811::co2_read() {
UHSLMarcus 6:22c0a7f2ece2 207 return 0 | (_alg_result_data[0] << 8) | _alg_result_data[1];
UHSLMarcus 2:e394671ef5f6 208 }
UHSLMarcus 1:acfca1d3256d 209
UHSLMarcus 1:acfca1d3256d 210 uint16_t AMS_CCS811::tvoc_read() {
UHSLMarcus 6:22c0a7f2ece2 211 return 0 | (_alg_result_data[2] << 8) | _alg_result_data[3];
UHSLMarcus 1:acfca1d3256d 212 }
UHSLMarcus 1:acfca1d3256d 213
UHSLMarcus 1:acfca1d3256d 214 uint16_t AMS_CCS811::raw_read() {
UHSLMarcus 6:22c0a7f2ece2 215 return 0 | (_alg_result_data[6] << 8) | _alg_result_data[7];
UHSLMarcus 1:acfca1d3256d 216 }
UHSLMarcus 1:acfca1d3256d 217
UHSLMarcus 5:41e97348e9e7 218 bool AMS_CCS811::error_status() {
UHSLMarcus 5:41e97348e9e7 219 bool result = false;
UHSLMarcus 5:41e97348e9e7 220
UHSLMarcus 5:41e97348e9e7 221 read_byte_result read_result = read_status();
UHSLMarcus 5:41e97348e9e7 222 if (read_result.success) {
UHSLMarcus 5:41e97348e9e7 223 result = read_result.byte & 1;
UHSLMarcus 5:41e97348e9e7 224 }
UHSLMarcus 5:41e97348e9e7 225
UHSLMarcus 5:41e97348e9e7 226 result = result || (_error_count > 0);
UHSLMarcus 5:41e97348e9e7 227
UHSLMarcus 5:41e97348e9e7 228 return result;
UHSLMarcus 5:41e97348e9e7 229 }
UHSLMarcus 5:41e97348e9e7 230
UHSLMarcus 5:41e97348e9e7 231 AMS_CCS811::ccs811_errors AMS_CCS811::errors() {
UHSLMarcus 5:41e97348e9e7 232 ccs811_errors error_result;
UHSLMarcus 5:41e97348e9e7 233
UHSLMarcus 5:41e97348e9e7 234 char byte[1];
UHSLMarcus 5:41e97348e9e7 235 if (i2c_read(ERROR_ID, byte, 1) == 1) {
UHSLMarcus 5:41e97348e9e7 236 for(int i = 0; i < CCS811_ERR_NUM; i++) {
UHSLMarcus 5:41e97348e9e7 237 if ((byte[0] << i) & 1) {
UHSLMarcus 5:41e97348e9e7 238 error_result.codes[error_result.count++] = i;
UHSLMarcus 5:41e97348e9e7 239 }
UHSLMarcus 5:41e97348e9e7 240 }
UHSLMarcus 5:41e97348e9e7 241 }
UHSLMarcus 5:41e97348e9e7 242 for(int i = 0; i < CCS811_LIB_ERR_NUM; i++) {
UHSLMarcus 5:41e97348e9e7 243 if (_errors[i]) {
UHSLMarcus 5:41e97348e9e7 244 error_result.codes[error_result.count++] = i + CCS811_ERR_NUM;
UHSLMarcus 5:41e97348e9e7 245 }
UHSLMarcus 5:41e97348e9e7 246 }
UHSLMarcus 5:41e97348e9e7 247
UHSLMarcus 5:41e97348e9e7 248 return error_result;
UHSLMarcus 5:41e97348e9e7 249
UHSLMarcus 5:41e97348e9e7 250 }
UHSLMarcus 5:41e97348e9e7 251
UHSLMarcus 5:41e97348e9e7 252 const char * AMS_CCS811::error_string(int err_code){
UHSLMarcus 5:41e97348e9e7 253 static char result[255];
UHSLMarcus 5:41e97348e9e7 254 result[0] = 0;
UHSLMarcus 5:41e97348e9e7 255 if (err_code < CCS811_TOTAL_ERR_NUM && err_code > -1)
UHSLMarcus 5:41e97348e9e7 256 strcpy(result, _error_strings[err_code]);
UHSLMarcus 5:41e97348e9e7 257 else
UHSLMarcus 5:41e97348e9e7 258 sprintf(result, "Invalid Code: %d is out of range (0 - %d)", err_code, CCS811_TOTAL_ERR_NUM-1);
UHSLMarcus 5:41e97348e9e7 259
UHSLMarcus 5:41e97348e9e7 260 return result;
UHSLMarcus 1:acfca1d3256d 261 }
UHSLMarcus 1:acfca1d3256d 262
UHSLMarcus 1:acfca1d3256d 263 bool AMS_CCS811::enable_interupt(bool enable) {
UHSLMarcus 1:acfca1d3256d 264 bool old = _int_data_enabled; // incase the write fails, to roll back
UHSLMarcus 1:acfca1d3256d 265 _int_data_enabled = enable;
UHSLMarcus 1:acfca1d3256d 266
UHSLMarcus 1:acfca1d3256d 267 bool success = write_config();
UHSLMarcus 1:acfca1d3256d 268 if (!success)
UHSLMarcus 1:acfca1d3256d 269 _int_data_enabled = old;
UHSLMarcus 1:acfca1d3256d 270
UHSLMarcus 1:acfca1d3256d 271 return success;
UHSLMarcus 1:acfca1d3256d 272
UHSLMarcus 1:acfca1d3256d 273 }
UHSLMarcus 1:acfca1d3256d 274
UHSLMarcus 5:41e97348e9e7 275 int AMS_CCS811::interupt_enabled() {
UHSLMarcus 5:41e97348e9e7 276 int enabled = -1;
UHSLMarcus 1:acfca1d3256d 277
UHSLMarcus 5:41e97348e9e7 278 read_byte_result read_result = read_config();
UHSLMarcus 1:acfca1d3256d 279 if (read_result.success) {
UHSLMarcus 1:acfca1d3256d 280 enabled = (read_result.byte >> 3) & 1;
UHSLMarcus 6:22c0a7f2ece2 281 }
UHSLMarcus 1:acfca1d3256d 282
UHSLMarcus 2:e394671ef5f6 283 return enabled;
UHSLMarcus 1:acfca1d3256d 284 }
UHSLMarcus 1:acfca1d3256d 285
UHSLMarcus 1:acfca1d3256d 286 bool AMS_CCS811::interrupt_pin(PinName pin) {
UHSLMarcus 1:acfca1d3256d 287 bool success = false;
UHSLMarcus 1:acfca1d3256d 288
UHSLMarcus 2:e394671ef5f6 289 _int_data = _int_data == NULL ? new (std::nothrow) InterruptIn(pin) : new (_int_data) InterruptIn(pin);
UHSLMarcus 1:acfca1d3256d 290 if (_int_data != NULL) {
UHSLMarcus 2:e394671ef5f6 291 _int_data->fall(callback(this, &AMS_CCS811::_isr_data));
UHSLMarcus 1:acfca1d3256d 292 success = true;
UHSLMarcus 1:acfca1d3256d 293 }
UHSLMarcus 1:acfca1d3256d 294
UHSLMarcus 1:acfca1d3256d 295 return success;
UHSLMarcus 1:acfca1d3256d 296 }
UHSLMarcus 0:5edbf3550350 297
UHSLMarcus 0:5edbf3550350 298
UHSLMarcus 0:5edbf3550350 299
UHSLMarcus 1:acfca1d3256d 300
UHSLMarcus 1:acfca1d3256d 301 /** Private **/
UHSLMarcus 1:acfca1d3256d 302
UHSLMarcus 5:41e97348e9e7 303 void AMS_CCS811::set_defaults() {
UHSLMarcus 1:acfca1d3256d 304 if (_mode == NULL)
UHSLMarcus 1:acfca1d3256d 305 _mode = CONFIG_OP_MODE;
UHSLMarcus 1:acfca1d3256d 306 if (_addr_dir == NULL)
UHSLMarcus 1:acfca1d3256d 307 _addr_dir = CONFIG_ADDR_DIR;
UHSLMarcus 1:acfca1d3256d 308 if (_int_data_enabled == NULL)
UHSLMarcus 1:acfca1d3256d 309 _int_data_enabled = CONFIG_INTR;
UHSLMarcus 2:e394671ef5f6 310 if (_ens210_poll_split == NULL)
UHSLMarcus 2:e394671ef5f6 311 _ens210_poll_split = CONFIG_ENS210_POLL;
UHSLMarcus 2:e394671ef5f6 312
UHSLMarcus 5:41e97348e9e7 313 update_slave_addr();
UHSLMarcus 5:41e97348e9e7 314 }
UHSLMarcus 5:41e97348e9e7 315
UHSLMarcus 5:41e97348e9e7 316 void AMS_CCS811::_init_errors() {
UHSLMarcus 5:41e97348e9e7 317 clear_errors();
UHSLMarcus 5:41e97348e9e7 318 /* Sensor errors */
UHSLMarcus 5:41e97348e9e7 319 strcpy(_error_strings[0], CCS811_WRITE_REG_INVALID);
UHSLMarcus 5:41e97348e9e7 320 strcpy(_error_strings[1], CCS811_READ_REG_INVALID);
UHSLMarcus 5:41e97348e9e7 321 strcpy(_error_strings[2], CCS811_MEASMODE_INVALID);
UHSLMarcus 5:41e97348e9e7 322 strcpy(_error_strings[3], CCS811_MAX_RESISTANCE);
UHSLMarcus 5:41e97348e9e7 323 strcpy(_error_strings[4], CCS811_HEATER_FAULT);
UHSLMarcus 5:41e97348e9e7 324 strcpy(_error_strings[5], CCS811_HEATER_SUPPLY);
UHSLMarcus 5:41e97348e9e7 325 strcpy(_error_strings[6], CCS811_RESERVED);
UHSLMarcus 5:41e97348e9e7 326 strcpy(_error_strings[7], CCS811_RESERVED);
UHSLMarcus 5:41e97348e9e7 327 /* Library errors */
UHSLMarcus 5:41e97348e9e7 328 strcpy(_error_strings[CCS811_LIB_N_WAKE_ID+CCS811_ERR_NUM], CCS811_LIB_N_WAKE);
UHSLMarcus 5:41e97348e9e7 329 strcpy(_error_strings[CCS811_LIB_I2C_ID+CCS811_ERR_NUM], CCS811_LIB_I2C);
UHSLMarcus 5:41e97348e9e7 330 strcpy(_error_strings[CCS811_LIB_SLAVE_W_ID+CCS811_ERR_NUM], CCS811_LIB_SLAVE_W);
UHSLMarcus 5:41e97348e9e7 331 strcpy(_error_strings[CCS811_LIB_REG_ADDR_ID+CCS811_ERR_NUM], CCS811_LIB_REG_ADDR);
UHSLMarcus 5:41e97348e9e7 332 strcpy(_error_strings[CCS811_LIB_I2CWRITE_ID+CCS811_ERR_NUM], CCS811_LIB_I2CWRITE);
UHSLMarcus 5:41e97348e9e7 333 strcpy(_error_strings[CCS811_LIB_SLAVE_R_ID+CCS811_ERR_NUM], CCS811_LIB_SLAVE_R);
UHSLMarcus 6:22c0a7f2ece2 334 strcpy(_error_strings[CCS811_LIB_INV_MODE_ID+CCS811_ERR_NUM], CCS811_LIB_INV_MODE);
UHSLMarcus 5:41e97348e9e7 335 }
UHSLMarcus 5:41e97348e9e7 336
UHSLMarcus 5:41e97348e9e7 337 void AMS_CCS811::clear_errors() {
UHSLMarcus 5:41e97348e9e7 338 _error_count = 0;
UHSLMarcus 5:41e97348e9e7 339 for (int i = 0; i < CCS811_LIB_ERR_NUM; i++) {
UHSLMarcus 5:41e97348e9e7 340 _errors[i] = false;
UHSLMarcus 5:41e97348e9e7 341 }
UHSLMarcus 5:41e97348e9e7 342 }
UHSLMarcus 5:41e97348e9e7 343
UHSLMarcus 5:41e97348e9e7 344 void AMS_CCS811::new_error(int error_id) {
UHSLMarcus 5:41e97348e9e7 345 if (!_errors[error_id]) {
UHSLMarcus 5:41e97348e9e7 346 _errors[error_id] = true;
UHSLMarcus 5:41e97348e9e7 347 _error_count++;
UHSLMarcus 5:41e97348e9e7 348 }
UHSLMarcus 1:acfca1d3256d 349 }
UHSLMarcus 2:e394671ef5f6 350
UHSLMarcus 4:a6b8881eae87 351 void AMS_CCS811::update_ens210_timer() {
UHSLMarcus 4:a6b8881eae87 352 _ens210_poll_t.detach();
UHSLMarcus 4:a6b8881eae87 353 if (_ens210_enabled)
UHSLMarcus 4:a6b8881eae87 354 _ens210_poll_t.attach_us(callback(this, &AMS_CCS811::ens210_isr), _ens210_poll_split*1000);
UHSLMarcus 4:a6b8881eae87 355 }
UHSLMarcus 4:a6b8881eae87 356
UHSLMarcus 4:a6b8881eae87 357 void AMS_CCS811::ens210_isr() {
UHSLMarcus 4:a6b8881eae87 358 }
UHSLMarcus 4:a6b8881eae87 359
UHSLMarcus 3:782a719f47a5 360 void AMS_CCS811::update_slave_addr() {
UHSLMarcus 5:41e97348e9e7 361 _slave_addr = addr_mode() ? CCS811_SLAVE_ADDR_RAW_H : CCS811_SLAVE_ADDR_RAW_L;
UHSLMarcus 2:e394671ef5f6 362 }
UHSLMarcus 1:acfca1d3256d 363
UHSLMarcus 1:acfca1d3256d 364 void AMS_CCS811::_isr_data() {
UHSLMarcus 6:22c0a7f2ece2 365 has_new_data(); // populate the data array
UHSLMarcus 3:782a719f47a5 366 _isr_data_fp.call();
UHSLMarcus 1:acfca1d3256d 367 }
UHSLMarcus 1:acfca1d3256d 368
UHSLMarcus 1:acfca1d3256d 369 bool AMS_CCS811::write_config() {
UHSLMarcus 3:782a719f47a5 370 char cmd[1] = {0 | (_int_data_enabled << 3) | (_mode << 4)};
UHSLMarcus 5:41e97348e9e7 371 return i2c_write(MEAS_MODE, cmd, 1) == 1;
UHSLMarcus 5:41e97348e9e7 372 }
UHSLMarcus 5:41e97348e9e7 373
UHSLMarcus 5:41e97348e9e7 374 AMS_CCS811::read_byte_result AMS_CCS811::read_config() {
UHSLMarcus 5:41e97348e9e7 375 read_byte_result result;
UHSLMarcus 5:41e97348e9e7 376 char byte[1];
UHSLMarcus 5:41e97348e9e7 377 if (i2c_read(MEAS_MODE, byte, 1) == 1) {
UHSLMarcus 5:41e97348e9e7 378 result.success = true;
UHSLMarcus 5:41e97348e9e7 379 result.byte = byte[0];
UHSLMarcus 5:41e97348e9e7 380 }
UHSLMarcus 5:41e97348e9e7 381 return result;
UHSLMarcus 1:acfca1d3256d 382 }
UHSLMarcus 1:acfca1d3256d 383
UHSLMarcus 5:41e97348e9e7 384 AMS_CCS811::read_byte_result AMS_CCS811::read_status() {
UHSLMarcus 5:41e97348e9e7 385 read_byte_result result;
UHSLMarcus 2:e394671ef5f6 386 char byte[1];
UHSLMarcus 5:41e97348e9e7 387 if (i2c_read(STATUS, byte, 1) == 1) {
UHSLMarcus 2:e394671ef5f6 388 result.success = true;
UHSLMarcus 5:41e97348e9e7 389 result.byte = byte[0];
UHSLMarcus 5:41e97348e9e7 390 }
UHSLMarcus 6:22c0a7f2ece2 391
UHSLMarcus 5:41e97348e9e7 392 return result;
UHSLMarcus 5:41e97348e9e7 393 }
UHSLMarcus 5:41e97348e9e7 394
UHSLMarcus 5:41e97348e9e7 395 bool AMS_CCS811::boot_app_start() {
UHSLMarcus 5:41e97348e9e7 396 bool success = false;
UHSLMarcus 5:41e97348e9e7 397
UHSLMarcus 5:41e97348e9e7 398 if (i2c_write(APP_START, NULL, 0) == 0) {
UHSLMarcus 5:41e97348e9e7 399 wait_ms(70);
UHSLMarcus 5:41e97348e9e7 400 success = true;
UHSLMarcus 2:e394671ef5f6 401 }
UHSLMarcus 2:e394671ef5f6 402
UHSLMarcus 5:41e97348e9e7 403 return success;
UHSLMarcus 2:e394671ef5f6 404 }
UHSLMarcus 2:e394671ef5f6 405
UHSLMarcus 2:e394671ef5f6 406 int AMS_CCS811::i2c_read(char reg_addr, char* output, int len) {
UHSLMarcus 2:e394671ef5f6 407
UHSLMarcus 2:e394671ef5f6 408 int read_count = 0;
UHSLMarcus 2:e394671ef5f6 409 if (_n_wake_out != NULL) { // check nWAKE pin is set
UHSLMarcus 5:41e97348e9e7 410 _n_wake_out->write(0); // Hold low
UHSLMarcus 5:41e97348e9e7 411 wait_us(CCS811_T_AWAKE); // tAWAKE time to allow sensor I2C to wake up
UHSLMarcus 2:e394671ef5f6 412 if (_i2c != NULL) { // check I2C interface is set
UHSLMarcus 2:e394671ef5f6 413 _i2c->start(); // send start condition for write
UHSLMarcus 5:41e97348e9e7 414 if(_i2c->write(CCS811_SLAVE_ADDR_W) == 1) { // write slave address with write bit
UHSLMarcus 2:e394671ef5f6 415 if(_i2c->write(reg_addr) == 1) { // write register address
UHSLMarcus 2:e394671ef5f6 416 _i2c->start(); // send another start condition for read
UHSLMarcus 5:41e97348e9e7 417 if(_i2c->write(CCS811_SLAVE_ADDR_R) == 1) { // write slave address with read bit
UHSLMarcus 2:e394671ef5f6 418 for (int i = 0; i < len; i++) { // read len bytes
UHSLMarcus 2:e394671ef5f6 419 output[i] = _i2c->read(i < len-1 ? 1 : 0); // ack all reads aside from the final one (i == len-1)
UHSLMarcus 2:e394671ef5f6 420 read_count++;
UHSLMarcus 2:e394671ef5f6 421 }
UHSLMarcus 5:41e97348e9e7 422 } else new_error(CCS811_LIB_SLAVE_R_ID);
UHSLMarcus 5:41e97348e9e7 423 } else new_error(CCS811_LIB_REG_ADDR_ID);
UHSLMarcus 5:41e97348e9e7 424 } else new_error(CCS811_LIB_SLAVE_W_ID);
UHSLMarcus 2:e394671ef5f6 425 _i2c->stop(); // send stop condition
UHSLMarcus 5:41e97348e9e7 426 } else new_error(CCS811_LIB_I2C_ID);
UHSLMarcus 5:41e97348e9e7 427 _n_wake_out->write(1); // Set back to high
UHSLMarcus 5:41e97348e9e7 428 wait_us(CCS811_T_DWAKE); // tDWAKE time to allow sensor I2C to sleep
UHSLMarcus 5:41e97348e9e7 429 } else new_error(CCS811_LIB_N_WAKE_ID);
UHSLMarcus 2:e394671ef5f6 430
UHSLMarcus 2:e394671ef5f6 431 return read_count;
UHSLMarcus 2:e394671ef5f6 432 }
UHSLMarcus 2:e394671ef5f6 433
UHSLMarcus 5:41e97348e9e7 434 int AMS_CCS811::i2c_write(char reg_addr, char* input, int len) {
UHSLMarcus 2:e394671ef5f6 435
UHSLMarcus 5:41e97348e9e7 436 int write_count = -1;
UHSLMarcus 2:e394671ef5f6 437 if (_n_wake_out != NULL) { // check nWAKE pin is set
UHSLMarcus 5:41e97348e9e7 438 _n_wake_out->write(0); // Hold low
UHSLMarcus 5:41e97348e9e7 439 wait_us(CCS811_T_AWAKE); // tAWAKE time to allow sensor I2C to wake up
UHSLMarcus 2:e394671ef5f6 440 if (_i2c != NULL) { // check I2C interface is set
UHSLMarcus 2:e394671ef5f6 441 _i2c->start(); // send start condition for write
UHSLMarcus 5:41e97348e9e7 442 if(_i2c->write(CCS811_SLAVE_ADDR_W) == 1) { // write slave address
UHSLMarcus 2:e394671ef5f6 443 if(_i2c->write(reg_addr) == 1) { // write register address
UHSLMarcus 5:41e97348e9e7 444 write_count = 0;
UHSLMarcus 2:e394671ef5f6 445 for (int i = 0; i < len; i++) { // write len bytes
UHSLMarcus 2:e394671ef5f6 446 if(_i2c->write(input[i]) == 1) write_count++; // write each byte, if successful increment count
UHSLMarcus 5:41e97348e9e7 447 else new_error(CCS811_LIB_I2CWRITE_ID);
UHSLMarcus 2:e394671ef5f6 448 }
UHSLMarcus 5:41e97348e9e7 449 } else new_error(CCS811_LIB_REG_ADDR_ID);
UHSLMarcus 5:41e97348e9e7 450 } else new_error(CCS811_LIB_SLAVE_W_ID);
UHSLMarcus 2:e394671ef5f6 451 _i2c->stop(); // send stop condition
UHSLMarcus 5:41e97348e9e7 452 } else new_error(CCS811_LIB_I2C_ID);
UHSLMarcus 5:41e97348e9e7 453 _n_wake_out->write(1); // set back to high
UHSLMarcus 5:41e97348e9e7 454 wait_us(CCS811_T_DWAKE); // tDWAKE time to allow sensor I2C to sleep
UHSLMarcus 5:41e97348e9e7 455 }else new_error(CCS811_LIB_N_WAKE_ID);
UHSLMarcus 2:e394671ef5f6 456
UHSLMarcus 2:e394671ef5f6 457 return write_count;
UHSLMarcus 1:acfca1d3256d 458 }