Library for the AMS CC811 digitial gas sensor

Dependencies:   AMS_ENS210_temp_humid_sensor

Committer:
UHSLMarcus
Date:
Fri Jan 20 14:34:41 2017 +0000
Revision:
5:41e97348e9e7
Parent:
4:a6b8881eae87
Child:
6:22c0a7f2ece2
Implimented error methods and starting data collection. Added a few extra methods to read the status and boot into app mode from boot mode

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