simple CCS811 driver

Dependencies:   AMS_ENS210_temp_humid_sensor

Dependents:   TBSense2_Sensor_Demo

Fork of AMS_CCS811_gas_sensor by Marcus Lee

Committer:
Steven Cooreman
Date:
Tue Mar 05 20:18:27 2019 +0100
Revision:
15:cf658680c53f
Parent:
14:0e8f5bf68b50
Added FW v2.0.0 for CCS811 and introduced usage of mbed_trace

Who changed what in which revision?

UserRevisionLine numberNew contents of line
UHSLMarcus 0:5edbf3550350 1
UHSLMarcus 2:e394671ef5f6 2 #include "AMS_CCS811.h"
Steven Cooreman 15:cf658680c53f 3 #include "AMS_CCS811_fw_2_0_0.h"
Steven Cooreman 15:cf658680c53f 4 #include "mbed_trace.h"
Steven Cooreman 15:cf658680c53f 5
Steven Cooreman 15:cf658680c53f 6 #define TRACE_GROUP "CCS"
UHSLMarcus 0:5edbf3550350 7
UHSLMarcus 13:a74306788df7 8 AMS_CCS811::AMS_CCS811(I2C * i2c, PinName n_wake_pin) : _n_wake_out(), _addr_out(), _int_data(), _ens210(), _i2c() {
UHSLMarcus 5:41e97348e9e7 9 _n_wake_out = new (std::nothrow) DigitalOut(n_wake_pin, 1);
Steven Cooreman 15:cf658680c53f 10 _i2c = i2c;
UHSLMarcus 0:5edbf3550350 11 }
Steven Cooreman 15:cf658680c53f 12
UHSLMarcus 13:a74306788df7 13 AMS_CCS811::AMS_CCS811(I2C * i2c, PinName n_wake_pin, I2C * ens210_i2c) : _n_wake_out(), _addr_out(), _int_data(), _ens210(), _i2c() {
UHSLMarcus 5:41e97348e9e7 14 _n_wake_out = new (std::nothrow) DigitalOut(n_wake_pin, 1);
UHSLMarcus 0:5edbf3550350 15 _i2c = i2c;
UHSLMarcus 7:5c95614a61ee 16 ens210_i2c_interface(ens210_i2c);
UHSLMarcus 0:5edbf3550350 17 }
Steven Cooreman 15:cf658680c53f 18
UHSLMarcus 1:acfca1d3256d 19 AMS_CCS811::~AMS_CCS811() {
UHSLMarcus 1:acfca1d3256d 20 delete _n_wake_out;
UHSLMarcus 1:acfca1d3256d 21 delete _addr_out;
UHSLMarcus 1:acfca1d3256d 22 delete _int_data;
UHSLMarcus 7:5c95614a61ee 23 delete _ens210;
UHSLMarcus 1:acfca1d3256d 24 }
UHSLMarcus 1:acfca1d3256d 25
UHSLMarcus 1:acfca1d3256d 26 bool AMS_CCS811::init() {
Steven Cooreman 15:cf658680c53f 27
UHSLMarcus 5:41e97348e9e7 28 bool success = false;
Steven Cooreman 15:cf658680c53f 29
UHSLMarcus 5:41e97348e9e7 30 _init_errors();
UHSLMarcus 7:5c95614a61ee 31 _init_fractions();
UHSLMarcus 5:41e97348e9e7 32 set_defaults();
Steven Cooreman 15:cf658680c53f 33
UHSLMarcus 8:58a36d9218be 34 temp_reading = 0;
UHSLMarcus 8:58a36d9218be 35 humid_reading = 0;
Steven Cooreman 15:cf658680c53f 36
UHSLMarcus 5:41e97348e9e7 37 if (_n_wake_out) {
Steven Cooreman 15:cf658680c53f 38 char buffer[2];
Steven Cooreman 15:cf658680c53f 39
Steven Cooreman 15:cf658680c53f 40 if(i2c_read(HW_ID, buffer, 1) == 1) {
Steven Cooreman 15:cf658680c53f 41 if(buffer[0] != 0x81) {
Steven Cooreman 15:cf658680c53f 42 // not a CCS811
Steven Cooreman 15:cf658680c53f 43 tr_err("Not a CCS: %02x", buffer[0]);
Steven Cooreman 15:cf658680c53f 44 return false;
Steven Cooreman 15:cf658680c53f 45 }
Steven Cooreman 15:cf658680c53f 46 } else {
Steven Cooreman 15:cf658680c53f 47 return false;
Steven Cooreman 15:cf658680c53f 48 }
Steven Cooreman 15:cf658680c53f 49
Steven Cooreman 15:cf658680c53f 50 if(i2c_read(STATUS, buffer, 1) == 1) {
Steven Cooreman 15:cf658680c53f 51 if((buffer[0] & 0x10) == 0) {
Steven Cooreman 15:cf658680c53f 52 // does not have valid FW
Steven Cooreman 15:cf658680c53f 53 flash_firmware();
Steven Cooreman 15:cf658680c53f 54 }
Steven Cooreman 15:cf658680c53f 55 } else {
Steven Cooreman 15:cf658680c53f 56 return false;
Steven Cooreman 15:cf658680c53f 57 }
Steven Cooreman 15:cf658680c53f 58
Steven Cooreman 15:cf658680c53f 59 if(i2c_read(FW_APP_VERSION, buffer, 2) == 2) {
Steven Cooreman 15:cf658680c53f 60 tr_warn("CCS version %02x %02x", buffer[0], buffer[1]);
Steven Cooreman 15:cf658680c53f 61 if (buffer[0] < CCS_FW_UPGRADE_VERSION) {
Steven Cooreman 15:cf658680c53f 62 tr_warn("Flashing Firmware");
Steven Cooreman 15:cf658680c53f 63 flash_firmware();
Steven Cooreman 15:cf658680c53f 64 }
Steven Cooreman 15:cf658680c53f 65 } else {
Steven Cooreman 15:cf658680c53f 66 return false;
Steven Cooreman 15:cf658680c53f 67 }
Steven Cooreman 15:cf658680c53f 68
UHSLMarcus 5:41e97348e9e7 69 int fw_mode = firmware_mode();
Steven Cooreman 15:cf658680c53f 70
Steven Cooreman 15:cf658680c53f 71 if (fw_mode == 1) {
UHSLMarcus 13:a74306788df7 72 success = write_config();
UHSLMarcus 5:41e97348e9e7 73 enable_ens210(true);
Steven Cooreman 15:cf658680c53f 74
UHSLMarcus 5:41e97348e9e7 75 } else if (fw_mode == 0) { // is in boot mode, needs to be loaded into app mode
UHSLMarcus 5:41e97348e9e7 76 if (boot_app_start()) // if succesfully writes to app_start, retry init
UHSLMarcus 13:a74306788df7 77 success = init();
UHSLMarcus 5:41e97348e9e7 78 }
UHSLMarcus 5:41e97348e9e7 79 }
UHSLMarcus 13:a74306788df7 80
UHSLMarcus 5:41e97348e9e7 81 return success;
UHSLMarcus 4:a6b8881eae87 82 }
UHSLMarcus 4:a6b8881eae87 83
Steven Cooreman 15:cf658680c53f 84 bool AMS_CCS811::flash_firmware() {
Steven Cooreman 15:cf658680c53f 85 // kick into bootloader mode
Steven Cooreman 15:cf658680c53f 86 int fw_mode = firmware_mode();
Steven Cooreman 15:cf658680c53f 87 if (fw_mode == 1) {
Steven Cooreman 15:cf658680c53f 88 const char reset_sequence[] = {0x11, 0xE5, 0x72, 0x8A};
Steven Cooreman 15:cf658680c53f 89 if(i2c_write(0xFF, (char*)reset_sequence, 4) == 4) {
Steven Cooreman 15:cf658680c53f 90 fw_mode = firmware_mode();
Steven Cooreman 15:cf658680c53f 91 if(fw_mode == 1) {
Steven Cooreman 15:cf658680c53f 92 tr_err("Couldn't exit app mode");
Steven Cooreman 15:cf658680c53f 93 return false;
Steven Cooreman 15:cf658680c53f 94 }
Steven Cooreman 15:cf658680c53f 95 } else {
Steven Cooreman 15:cf658680c53f 96 tr_err("Couldn't issue reset command");
Steven Cooreman 15:cf658680c53f 97 return false;
Steven Cooreman 15:cf658680c53f 98 }
Steven Cooreman 15:cf658680c53f 99 }
Steven Cooreman 15:cf658680c53f 100
Steven Cooreman 15:cf658680c53f 101 // assert nwake
Steven Cooreman 15:cf658680c53f 102 if (_n_wake_out != NULL) {
Steven Cooreman 15:cf658680c53f 103 int write_count;
Steven Cooreman 15:cf658680c53f 104
Steven Cooreman 15:cf658680c53f 105 _n_wake_out->write(0);
Steven Cooreman 15:cf658680c53f 106 wait_ms(100);
Steven Cooreman 15:cf658680c53f 107
Steven Cooreman 15:cf658680c53f 108 // erase current FW
Steven Cooreman 15:cf658680c53f 109 static const char erase_sequence[4] = {0xE7, 0xA7, 0xE6, 0x09};
Steven Cooreman 15:cf658680c53f 110 write_count = 0;
Steven Cooreman 15:cf658680c53f 111 _i2c->start();
Steven Cooreman 15:cf658680c53f 112 if(_i2c->write(CCS811_SLAVE_ADDR_W) == 1) {
Steven Cooreman 15:cf658680c53f 113 if(_i2c->write(FW_ERASE) == 1) {
Steven Cooreman 15:cf658680c53f 114 for (size_t i = 0; i < 4; i++) {
Steven Cooreman 15:cf658680c53f 115 if(_i2c->write(erase_sequence[i]) == 1) write_count++;
Steven Cooreman 15:cf658680c53f 116 else new_error(CCS811_LIB_I2CWRITE_ID);
Steven Cooreman 15:cf658680c53f 117 }
Steven Cooreman 15:cf658680c53f 118 } else new_error(CCS811_LIB_REG_ADDR_ID);
Steven Cooreman 15:cf658680c53f 119 } else new_error(CCS811_LIB_SLAVE_W_ID);
Steven Cooreman 15:cf658680c53f 120 _i2c->stop();
Steven Cooreman 15:cf658680c53f 121
Steven Cooreman 15:cf658680c53f 122 if (write_count != 4) {
Steven Cooreman 15:cf658680c53f 123 _n_wake_out->write(1);
Steven Cooreman 15:cf658680c53f 124 return false;
Steven Cooreman 15:cf658680c53f 125 }
Steven Cooreman 15:cf658680c53f 126 tr_info("CCS FW erased");
Steven Cooreman 15:cf658680c53f 127 wait_ms(500);
Steven Cooreman 15:cf658680c53f 128
Steven Cooreman 15:cf658680c53f 129 // upload new FW
Steven Cooreman 15:cf658680c53f 130 tr_info("uploading new FW");
Steven Cooreman 15:cf658680c53f 131 char payload[8];
Steven Cooreman 15:cf658680c53f 132 for(size_t offset = 0; offset < 5120; offset += 8) {
Steven Cooreman 15:cf658680c53f 133 for(size_t j = 0; j < 8; j++) {
Steven Cooreman 15:cf658680c53f 134 payload[j] = ams_fw_image[offset + j];
Steven Cooreman 15:cf658680c53f 135 }
Steven Cooreman 15:cf658680c53f 136
Steven Cooreman 15:cf658680c53f 137 write_count = 0;
Steven Cooreman 15:cf658680c53f 138 _i2c->start();
Steven Cooreman 15:cf658680c53f 139 if(_i2c->write(CCS811_SLAVE_ADDR_W) == 1) {
Steven Cooreman 15:cf658680c53f 140 if(_i2c->write(FW_FLASH) == 1) {
Steven Cooreman 15:cf658680c53f 141 for (size_t j = 0; j < 8; j++) {
Steven Cooreman 15:cf658680c53f 142 if(_i2c->write(payload[j]) == 1) write_count++;
Steven Cooreman 15:cf658680c53f 143 else new_error(CCS811_LIB_I2CWRITE_ID);
Steven Cooreman 15:cf658680c53f 144 }
Steven Cooreman 15:cf658680c53f 145 } else new_error(CCS811_LIB_REG_ADDR_ID);
Steven Cooreman 15:cf658680c53f 146 } else new_error(CCS811_LIB_SLAVE_W_ID);
Steven Cooreman 15:cf658680c53f 147 _i2c->stop();
Steven Cooreman 15:cf658680c53f 148
Steven Cooreman 15:cf658680c53f 149 wait_ms(50);
Steven Cooreman 15:cf658680c53f 150
Steven Cooreman 15:cf658680c53f 151 if (write_count != 8) {
Steven Cooreman 15:cf658680c53f 152 _n_wake_out->write(1);
Steven Cooreman 15:cf658680c53f 153 tr_err("flash error");
Steven Cooreman 15:cf658680c53f 154 return false;
Steven Cooreman 15:cf658680c53f 155 }
Steven Cooreman 15:cf658680c53f 156
Steven Cooreman 15:cf658680c53f 157 tr_debug("Flashed byte %d of 5120", offset);
Steven Cooreman 15:cf658680c53f 158 }
Steven Cooreman 15:cf658680c53f 159 tr_info("CCS FW uploaded");
Steven Cooreman 15:cf658680c53f 160
Steven Cooreman 15:cf658680c53f 161 // verify new FW
Steven Cooreman 15:cf658680c53f 162 write_count = 0;
Steven Cooreman 15:cf658680c53f 163 _i2c->start();
Steven Cooreman 15:cf658680c53f 164 if(_i2c->write(CCS811_SLAVE_ADDR_W) == 1) {
Steven Cooreman 15:cf658680c53f 165 if(_i2c->write(FW_VERIFY) == 1) {
Steven Cooreman 15:cf658680c53f 166 write_count = 1;
Steven Cooreman 15:cf658680c53f 167 } else new_error(CCS811_LIB_REG_ADDR_ID);
Steven Cooreman 15:cf658680c53f 168 } else new_error(CCS811_LIB_SLAVE_W_ID);
Steven Cooreman 15:cf658680c53f 169 _i2c->stop();
Steven Cooreman 15:cf658680c53f 170
Steven Cooreman 15:cf658680c53f 171 wait_ms(500);
Steven Cooreman 15:cf658680c53f 172
Steven Cooreman 15:cf658680c53f 173 if (write_count != 1) {
Steven Cooreman 15:cf658680c53f 174 _n_wake_out->write(1);
Steven Cooreman 15:cf658680c53f 175 tr_err("Failed to issue verify");
Steven Cooreman 15:cf658680c53f 176 return false;
Steven Cooreman 15:cf658680c53f 177 }
Steven Cooreman 15:cf658680c53f 178
Steven Cooreman 15:cf658680c53f 179 char status = 0;
Steven Cooreman 15:cf658680c53f 180 _i2c->start();
Steven Cooreman 15:cf658680c53f 181 if(_i2c->write(CCS811_SLAVE_ADDR_W) == 1) {
Steven Cooreman 15:cf658680c53f 182 if(_i2c->write(STATUS) == 1) {
Steven Cooreman 15:cf658680c53f 183 _i2c->start();
Steven Cooreman 15:cf658680c53f 184 if(_i2c->write(CCS811_SLAVE_ADDR_R) == 1) {
Steven Cooreman 15:cf658680c53f 185 status = _i2c->read(0);
Steven Cooreman 15:cf658680c53f 186 } else new_error(CCS811_LIB_SLAVE_R_ID);
Steven Cooreman 15:cf658680c53f 187 } else new_error(CCS811_LIB_REG_ADDR_ID);
Steven Cooreman 15:cf658680c53f 188 } else new_error(CCS811_LIB_SLAVE_W_ID);
Steven Cooreman 15:cf658680c53f 189 _i2c->stop();
Steven Cooreman 15:cf658680c53f 190
Steven Cooreman 15:cf658680c53f 191 if (status == 0) {
Steven Cooreman 15:cf658680c53f 192 tr_err("Failed update");
Steven Cooreman 15:cf658680c53f 193 _n_wake_out->write(1);
Steven Cooreman 15:cf658680c53f 194 return false;
Steven Cooreman 15:cf658680c53f 195 }
Steven Cooreman 15:cf658680c53f 196
Steven Cooreman 15:cf658680c53f 197 if ((status & 0x30) != 0x30) {
Steven Cooreman 15:cf658680c53f 198 tr_err("Failed verify");
Steven Cooreman 15:cf658680c53f 199 _n_wake_out->write(1);
Steven Cooreman 15:cf658680c53f 200 return false;
Steven Cooreman 15:cf658680c53f 201 }
Steven Cooreman 15:cf658680c53f 202
Steven Cooreman 15:cf658680c53f 203 // boot into new FW
Steven Cooreman 15:cf658680c53f 204 tr_info("upgraded");
Steven Cooreman 15:cf658680c53f 205 _n_wake_out->write(1);
Steven Cooreman 15:cf658680c53f 206 wait_ms(50);
Steven Cooreman 15:cf658680c53f 207 return boot_app_start();
Steven Cooreman 15:cf658680c53f 208 } else {
Steven Cooreman 15:cf658680c53f 209 tr_err("No nWAKE available");
Steven Cooreman 15:cf658680c53f 210 return false;
Steven Cooreman 15:cf658680c53f 211 }
Steven Cooreman 15:cf658680c53f 212 }
Steven Cooreman 15:cf658680c53f 213
UHSLMarcus 4:a6b8881eae87 214 void AMS_CCS811::i2c_interface(I2C * i2c) {
UHSLMarcus 4:a6b8881eae87 215 _i2c = i2c;
UHSLMarcus 4:a6b8881eae87 216 }
Steven Cooreman 15:cf658680c53f 217
UHSLMarcus 7:5c95614a61ee 218 bool AMS_CCS811::ens210_i2c_interface(I2C * i2c) {
UHSLMarcus 11:ef2d4258cd15 219
UHSLMarcus 7:5c95614a61ee 220 bool success;
Steven Cooreman 15:cf658680c53f 221
UHSLMarcus 7:5c95614a61ee 222 if (_ens210 == NULL) {
UHSLMarcus 7:5c95614a61ee 223 _ens210 = new (std::nothrow) AMS_ENS210(i2c, true, true);
UHSLMarcus 7:5c95614a61ee 224 if (_ens210 != NULL) {
UHSLMarcus 7:5c95614a61ee 225 if (_ens210->init()) {
UHSLMarcus 7:5c95614a61ee 226 success = _ens210->start();
UHSLMarcus 7:5c95614a61ee 227 }
Steven Cooreman 15:cf658680c53f 228 }
UHSLMarcus 7:5c95614a61ee 229 } else {
UHSLMarcus 7:5c95614a61ee 230 _ens210->i2c_interface(i2c);
UHSLMarcus 7:5c95614a61ee 231 success = true;
UHSLMarcus 7:5c95614a61ee 232 }
Steven Cooreman 15:cf658680c53f 233
UHSLMarcus 7:5c95614a61ee 234 if (!success) new_error(CCS811_LIB_ENS210_INIT_ID);
Steven Cooreman 15:cf658680c53f 235
UHSLMarcus 7:5c95614a61ee 236 return success;
UHSLMarcus 4:a6b8881eae87 237 }
UHSLMarcus 4:a6b8881eae87 238
UHSLMarcus 4:a6b8881eae87 239 bool AMS_CCS811::enable_ens210(bool enable) {
Steven Cooreman 15:cf658680c53f 240
UHSLMarcus 4:a6b8881eae87 241 _ens210_enabled = false;
UHSLMarcus 7:5c95614a61ee 242 if (_ens210 != NULL) {
UHSLMarcus 7:5c95614a61ee 243 if (_ens210->i2c_interface() != NULL) _ens210_enabled = enable;
UHSLMarcus 7:5c95614a61ee 244 }
UHSLMarcus 4:a6b8881eae87 245 update_ens210_timer();
UHSLMarcus 4:a6b8881eae87 246 return _ens210_enabled;
UHSLMarcus 4:a6b8881eae87 247 }
UHSLMarcus 4:a6b8881eae87 248
UHSLMarcus 4:a6b8881eae87 249 bool AMS_CCS811::ens210_is_enabled() {
UHSLMarcus 7:5c95614a61ee 250 enable_ens210(_ens210_enabled); // Make sure the state is representive
UHSLMarcus 4:a6b8881eae87 251 return _ens210_enabled;
UHSLMarcus 4:a6b8881eae87 252 }
Steven Cooreman 15:cf658680c53f 253
UHSLMarcus 4:a6b8881eae87 254 void AMS_CCS811::ens210_poll_interval(int poll_ms) {
UHSLMarcus 4:a6b8881eae87 255 _ens210_poll_split = poll_ms;
UHSLMarcus 7:5c95614a61ee 256 enable_ens210(_ens210_enabled); // makes sure the state is representive, and will also update the timer
UHSLMarcus 4:a6b8881eae87 257 }
UHSLMarcus 4:a6b8881eae87 258
UHSLMarcus 4:a6b8881eae87 259 int AMS_CCS811::ens210_poll_interval() {
UHSLMarcus 4:a6b8881eae87 260 return _ens210_poll_split;
UHSLMarcus 1:acfca1d3256d 261 }
UHSLMarcus 1:acfca1d3256d 262
UHSLMarcus 5:41e97348e9e7 263 int AMS_CCS811::firmware_mode() {
UHSLMarcus 5:41e97348e9e7 264 int firmware_result = -1;
Steven Cooreman 15:cf658680c53f 265
UHSLMarcus 6:22c0a7f2ece2 266 clear_errors();
Steven Cooreman 15:cf658680c53f 267
UHSLMarcus 5:41e97348e9e7 268 read_byte_result read_result = read_status();
UHSLMarcus 5:41e97348e9e7 269 if (read_result.success) {
UHSLMarcus 5:41e97348e9e7 270 firmware_result = (read_result.byte >> 7) & 1;
UHSLMarcus 6:22c0a7f2ece2 271 }
Steven Cooreman 15:cf658680c53f 272
UHSLMarcus 5:41e97348e9e7 273 return firmware_result;
UHSLMarcus 5:41e97348e9e7 274 }
UHSLMarcus 5:41e97348e9e7 275
UHSLMarcus 1:acfca1d3256d 276 bool AMS_CCS811::mode(OP_MODES mode) {
UHSLMarcus 6:22c0a7f2ece2 277 clear_errors();
Steven Cooreman 15:cf658680c53f 278
UHSLMarcus 1:acfca1d3256d 279 OP_MODES old = _mode; // incase the write fails, to roll back
UHSLMarcus 1:acfca1d3256d 280 _mode = mode;
Steven Cooreman 15:cf658680c53f 281
UHSLMarcus 1:acfca1d3256d 282 bool success = write_config();
UHSLMarcus 1:acfca1d3256d 283 if (!success)
UHSLMarcus 1:acfca1d3256d 284 _mode = old;
Steven Cooreman 15:cf658680c53f 285
UHSLMarcus 1:acfca1d3256d 286 return success;
UHSLMarcus 1:acfca1d3256d 287 }
UHSLMarcus 1:acfca1d3256d 288
UHSLMarcus 1:acfca1d3256d 289 AMS_CCS811::OP_MODES AMS_CCS811::mode() {
UHSLMarcus 6:22c0a7f2ece2 290 clear_errors();
Steven Cooreman 15:cf658680c53f 291
UHSLMarcus 5:41e97348e9e7 292 OP_MODES result = INVALID;
Steven Cooreman 15:cf658680c53f 293
UHSLMarcus 5:41e97348e9e7 294 read_byte_result read_result = read_config();
UHSLMarcus 1:acfca1d3256d 295 if (read_result.success) {
UHSLMarcus 1:acfca1d3256d 296 int mode = (read_result.byte >> 4) & 0b111;
UHSLMarcus 2:e394671ef5f6 297 result = mode > 4 ? INVALID : (OP_MODES)mode;
UHSLMarcus 6:22c0a7f2ece2 298 }
Steven Cooreman 15:cf658680c53f 299
UHSLMarcus 2:e394671ef5f6 300 return result;
UHSLMarcus 1:acfca1d3256d 301 }
UHSLMarcus 1:acfca1d3256d 302
Steven Cooreman 15:cf658680c53f 303 bool AMS_CCS811::addr_mode(bool high) {
UHSLMarcus 1:acfca1d3256d 304 _addr_dir = high;
UHSLMarcus 5:41e97348e9e7 305 if (_addr_out != NULL) _addr_out->write(_addr_dir);
Steven Cooreman 15:cf658680c53f 306
UHSLMarcus 2:e394671ef5f6 307 update_slave_addr();
Steven Cooreman 15:cf658680c53f 308
UHSLMarcus 1:acfca1d3256d 309 return addr_mode() == high;
UHSLMarcus 1:acfca1d3256d 310 }
UHSLMarcus 1:acfca1d3256d 311
UHSLMarcus 1:acfca1d3256d 312 bool AMS_CCS811::addr_mode() {
UHSLMarcus 13:a74306788df7 313 _addr_dir = false;
UHSLMarcus 1:acfca1d3256d 314 if (_addr_out != NULL) {
Steven Cooreman 15:cf658680c53f 315 _addr_dir = _addr_out->read();
UHSLMarcus 1:acfca1d3256d 316 }
Steven Cooreman 15:cf658680c53f 317
UHSLMarcus 1:acfca1d3256d 318 return _addr_dir;
UHSLMarcus 1:acfca1d3256d 319 }
UHSLMarcus 1:acfca1d3256d 320
UHSLMarcus 1:acfca1d3256d 321 bool AMS_CCS811::addr_pin(PinName pin) {
UHSLMarcus 1:acfca1d3256d 322 _addr_out = _addr_out == NULL ? new (std::nothrow) DigitalOut(pin) : new (_addr_out) DigitalOut(pin);
UHSLMarcus 1:acfca1d3256d 323 addr_mode(_addr_dir);
Steven Cooreman 15:cf658680c53f 324
UHSLMarcus 1:acfca1d3256d 325 return _addr_out != NULL;
UHSLMarcus 1:acfca1d3256d 326 }
UHSLMarcus 1:acfca1d3256d 327
UHSLMarcus 1:acfca1d3256d 328 bool AMS_CCS811::n_wake_pin(PinName pin) {
UHSLMarcus 1:acfca1d3256d 329 _n_wake_out = _n_wake_out == NULL ? new (std::nothrow) DigitalOut(pin) : new (_n_wake_out) DigitalOut(pin);
UHSLMarcus 1:acfca1d3256d 330 return _n_wake_out != NULL;
UHSLMarcus 1:acfca1d3256d 331 }
UHSLMarcus 1:acfca1d3256d 332
UHSLMarcus 2:e394671ef5f6 333 bool AMS_CCS811::env_data(float humid, float temp) {
UHSLMarcus 7:5c95614a61ee 334 char bytes[4];
UHSLMarcus 7:5c95614a61ee 335 if (humid > CCS811_MAX_HUMID) humid = CCS811_MAX_HUMID;
UHSLMarcus 7:5c95614a61ee 336 if (humid < 0) humid = 0;
Steven Cooreman 15:cf658680c53f 337
UHSLMarcus 7:5c95614a61ee 338 temp += 25;
UHSLMarcus 7:5c95614a61ee 339 if (temp > CCS811_MAX_TEMP) humid = CCS811_MAX_TEMP;
UHSLMarcus 7:5c95614a61ee 340 if (temp < 0) temp = 0;
Steven Cooreman 15:cf658680c53f 341
UHSLMarcus 7:5c95614a61ee 342 float_to_short(humid, bytes);
UHSLMarcus 7:5c95614a61ee 343 float_to_short(temp, bytes+2);
Steven Cooreman 15:cf658680c53f 344
UHSLMarcus 7:5c95614a61ee 345 return i2c_write(ENV_DATA, bytes, 4) == 4;
UHSLMarcus 1:acfca1d3256d 346 }
UHSLMarcus 1:acfca1d3256d 347
UHSLMarcus 1:acfca1d3256d 348
UHSLMarcus 5:41e97348e9e7 349 int AMS_CCS811::has_new_data() {
UHSLMarcus 6:22c0a7f2ece2 350
UHSLMarcus 6:22c0a7f2ece2 351 clear_errors();
Steven Cooreman 15:cf658680c53f 352
UHSLMarcus 5:41e97348e9e7 353 int result = -1;
Steven Cooreman 15:cf658680c53f 354
UHSLMarcus 6:22c0a7f2ece2 355 char meas_mode[1];
UHSLMarcus 6:22c0a7f2ece2 356 if(i2c_read(MEAS_MODE, meas_mode, 1) == 1) { // one read here is quicker than calling read_config() twice
Steven Cooreman 15:cf658680c53f 357
UHSLMarcus 6:22c0a7f2ece2 358 int curr_mode = (meas_mode[0] >> 4) & 0b111;
UHSLMarcus 6:22c0a7f2ece2 359 if (curr_mode < 5) {
UHSLMarcus 6:22c0a7f2ece2 360 if (curr_mode > 0) { // check for all valid modes other than idle
UHSLMarcus 6:22c0a7f2ece2 361 if (((meas_mode[0] >> 3) & 1) == 0) { // check if interrupts are disabled
Steven Cooreman 15:cf658680c53f 362 char status[1];
UHSLMarcus 6:22c0a7f2ece2 363 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 364 result = (status[0] >> 3) & 1;
Steven Cooreman 15:cf658680c53f 365
UHSLMarcus 6:22c0a7f2ece2 366 } else result = 1;
Steven Cooreman 15:cf658680c53f 367
Steven Cooreman 15:cf658680c53f 368 if (result == 1)
UHSLMarcus 6:22c0a7f2ece2 369 if (i2c_read(ALG_RESULT_DATA, _alg_result_data, 8) != 8) result = -1;
Steven Cooreman 15:cf658680c53f 370
Steven Cooreman 15:cf658680c53f 371
UHSLMarcus 6:22c0a7f2ece2 372 } else result = 0; // return 0 when in idle
UHSLMarcus 6:22c0a7f2ece2 373 } else new_error(CCS811_LIB_INV_MODE_ID);
UHSLMarcus 5:41e97348e9e7 374 }
Steven Cooreman 15:cf658680c53f 375
UHSLMarcus 5:41e97348e9e7 376 return result;
UHSLMarcus 1:acfca1d3256d 377 }
UHSLMarcus 1:acfca1d3256d 378
UHSLMarcus 1:acfca1d3256d 379 uint16_t AMS_CCS811::co2_read() {
UHSLMarcus 6:22c0a7f2ece2 380 return 0 | (_alg_result_data[0] << 8) | _alg_result_data[1];
UHSLMarcus 2:e394671ef5f6 381 }
UHSLMarcus 1:acfca1d3256d 382
UHSLMarcus 1:acfca1d3256d 383 uint16_t AMS_CCS811::tvoc_read() {
UHSLMarcus 6:22c0a7f2ece2 384 return 0 | (_alg_result_data[2] << 8) | _alg_result_data[3];
UHSLMarcus 1:acfca1d3256d 385 }
UHSLMarcus 1:acfca1d3256d 386
UHSLMarcus 1:acfca1d3256d 387 uint16_t AMS_CCS811::raw_read() {
UHSLMarcus 6:22c0a7f2ece2 388 return 0 | (_alg_result_data[6] << 8) | _alg_result_data[7];
UHSLMarcus 1:acfca1d3256d 389 }
UHSLMarcus 1:acfca1d3256d 390
UHSLMarcus 8:58a36d9218be 391 float AMS_CCS811::temp_read() {
UHSLMarcus 8:58a36d9218be 392 return temp_reading;
UHSLMarcus 8:58a36d9218be 393 }
UHSLMarcus 8:58a36d9218be 394
UHSLMarcus 8:58a36d9218be 395 float AMS_CCS811::humid_read() {
UHSLMarcus 8:58a36d9218be 396 return humid_reading;
UHSLMarcus 8:58a36d9218be 397 }
UHSLMarcus 8:58a36d9218be 398
UHSLMarcus 5:41e97348e9e7 399 bool AMS_CCS811::error_status() {
UHSLMarcus 5:41e97348e9e7 400 bool result = false;
Steven Cooreman 15:cf658680c53f 401
UHSLMarcus 5:41e97348e9e7 402 read_byte_result read_result = read_status();
UHSLMarcus 5:41e97348e9e7 403 if (read_result.success) {
UHSLMarcus 5:41e97348e9e7 404 result = read_result.byte & 1;
UHSLMarcus 5:41e97348e9e7 405 }
Steven Cooreman 15:cf658680c53f 406
UHSLMarcus 5:41e97348e9e7 407 result = result || (_error_count > 0);
Steven Cooreman 15:cf658680c53f 408
UHSLMarcus 5:41e97348e9e7 409 return result;
UHSLMarcus 5:41e97348e9e7 410 }
Steven Cooreman 15:cf658680c53f 411
UHSLMarcus 5:41e97348e9e7 412 AMS_CCS811::ccs811_errors AMS_CCS811::errors() {
UHSLMarcus 5:41e97348e9e7 413 ccs811_errors error_result;
Steven Cooreman 15:cf658680c53f 414
UHSLMarcus 5:41e97348e9e7 415 char byte[1];
UHSLMarcus 5:41e97348e9e7 416 if (i2c_read(ERROR_ID, byte, 1) == 1) {
UHSLMarcus 5:41e97348e9e7 417 for(int i = 0; i < CCS811_ERR_NUM; i++) {
UHSLMarcus 5:41e97348e9e7 418 if ((byte[0] << i) & 1) {
UHSLMarcus 5:41e97348e9e7 419 error_result.codes[error_result.count++] = i;
UHSLMarcus 5:41e97348e9e7 420 }
UHSLMarcus 5:41e97348e9e7 421 }
UHSLMarcus 5:41e97348e9e7 422 }
UHSLMarcus 5:41e97348e9e7 423 for(int i = 0; i < CCS811_LIB_ERR_NUM; i++) {
UHSLMarcus 5:41e97348e9e7 424 if (_errors[i]) {
UHSLMarcus 5:41e97348e9e7 425 error_result.codes[error_result.count++] = i + CCS811_ERR_NUM;
UHSLMarcus 5:41e97348e9e7 426 }
UHSLMarcus 5:41e97348e9e7 427 }
Steven Cooreman 15:cf658680c53f 428
UHSLMarcus 5:41e97348e9e7 429 return error_result;
Steven Cooreman 15:cf658680c53f 430
UHSLMarcus 5:41e97348e9e7 431 }
UHSLMarcus 5:41e97348e9e7 432
UHSLMarcus 5:41e97348e9e7 433 const char * AMS_CCS811::error_string(int err_code){
UHSLMarcus 5:41e97348e9e7 434 static char result[255];
UHSLMarcus 5:41e97348e9e7 435 result[0] = 0;
Steven Cooreman 15:cf658680c53f 436 if (err_code < CCS811_TOTAL_ERR_NUM && err_code > -1)
UHSLMarcus 5:41e97348e9e7 437 strcpy(result, _error_strings[err_code]);
Steven Cooreman 15:cf658680c53f 438 else
UHSLMarcus 5:41e97348e9e7 439 sprintf(result, "Invalid Code: %d is out of range (0 - %d)", err_code, CCS811_TOTAL_ERR_NUM-1);
Steven Cooreman 15:cf658680c53f 440
UHSLMarcus 5:41e97348e9e7 441 return result;
UHSLMarcus 1:acfca1d3256d 442 }
UHSLMarcus 1:acfca1d3256d 443
UHSLMarcus 1:acfca1d3256d 444 bool AMS_CCS811::enable_interupt(bool enable) {
UHSLMarcus 1:acfca1d3256d 445 bool old = _int_data_enabled; // incase the write fails, to roll back
UHSLMarcus 1:acfca1d3256d 446 _int_data_enabled = enable;
Steven Cooreman 15:cf658680c53f 447
UHSLMarcus 1:acfca1d3256d 448 bool success = write_config();
UHSLMarcus 1:acfca1d3256d 449 if (!success)
UHSLMarcus 1:acfca1d3256d 450 _int_data_enabled = old;
Steven Cooreman 15:cf658680c53f 451
UHSLMarcus 1:acfca1d3256d 452 return success;
UHSLMarcus 1:acfca1d3256d 453
UHSLMarcus 1:acfca1d3256d 454 }
UHSLMarcus 1:acfca1d3256d 455
UHSLMarcus 5:41e97348e9e7 456 int AMS_CCS811::interupt_enabled() {
UHSLMarcus 5:41e97348e9e7 457 int enabled = -1;
Steven Cooreman 15:cf658680c53f 458
UHSLMarcus 5:41e97348e9e7 459 read_byte_result read_result = read_config();
UHSLMarcus 1:acfca1d3256d 460 if (read_result.success) {
UHSLMarcus 1:acfca1d3256d 461 enabled = (read_result.byte >> 3) & 1;
UHSLMarcus 6:22c0a7f2ece2 462 }
Steven Cooreman 15:cf658680c53f 463
UHSLMarcus 2:e394671ef5f6 464 return enabled;
UHSLMarcus 1:acfca1d3256d 465 }
UHSLMarcus 1:acfca1d3256d 466
UHSLMarcus 1:acfca1d3256d 467 bool AMS_CCS811::interrupt_pin(PinName pin) {
UHSLMarcus 1:acfca1d3256d 468 bool success = false;
Steven Cooreman 15:cf658680c53f 469
UHSLMarcus 2:e394671ef5f6 470 _int_data = _int_data == NULL ? new (std::nothrow) InterruptIn(pin) : new (_int_data) InterruptIn(pin);
UHSLMarcus 1:acfca1d3256d 471 if (_int_data != NULL) {
UHSLMarcus 2:e394671ef5f6 472 _int_data->fall(callback(this, &AMS_CCS811::_isr_data));
UHSLMarcus 1:acfca1d3256d 473 success = true;
UHSLMarcus 1:acfca1d3256d 474 }
Steven Cooreman 15:cf658680c53f 475
UHSLMarcus 1:acfca1d3256d 476 return success;
UHSLMarcus 1:acfca1d3256d 477 }
UHSLMarcus 0:5edbf3550350 478
UHSLMarcus 0:5edbf3550350 479
UHSLMarcus 0:5edbf3550350 480
UHSLMarcus 1:acfca1d3256d 481
UHSLMarcus 1:acfca1d3256d 482 /** Private **/
UHSLMarcus 1:acfca1d3256d 483
UHSLMarcus 5:41e97348e9e7 484 void AMS_CCS811::set_defaults() {
Steven Cooreman 15:cf658680c53f 485 if (_mode == NULL)
UHSLMarcus 1:acfca1d3256d 486 _mode = CONFIG_OP_MODE;
UHSLMarcus 1:acfca1d3256d 487 if (_addr_dir == NULL)
UHSLMarcus 1:acfca1d3256d 488 _addr_dir = CONFIG_ADDR_DIR;
UHSLMarcus 1:acfca1d3256d 489 if (_int_data_enabled == NULL)
UHSLMarcus 1:acfca1d3256d 490 _int_data_enabled = CONFIG_INTR;
UHSLMarcus 2:e394671ef5f6 491 if (_ens210_poll_split == NULL)
UHSLMarcus 2:e394671ef5f6 492 _ens210_poll_split = CONFIG_ENS210_POLL;
Steven Cooreman 15:cf658680c53f 493
UHSLMarcus 5:41e97348e9e7 494 update_slave_addr();
UHSLMarcus 5:41e97348e9e7 495 }
UHSLMarcus 5:41e97348e9e7 496
UHSLMarcus 5:41e97348e9e7 497 void AMS_CCS811::_init_errors() {
UHSLMarcus 5:41e97348e9e7 498 clear_errors();
UHSLMarcus 5:41e97348e9e7 499 /* Sensor errors */
UHSLMarcus 5:41e97348e9e7 500 strcpy(_error_strings[0], CCS811_WRITE_REG_INVALID);
UHSLMarcus 5:41e97348e9e7 501 strcpy(_error_strings[1], CCS811_READ_REG_INVALID);
UHSLMarcus 5:41e97348e9e7 502 strcpy(_error_strings[2], CCS811_MEASMODE_INVALID);
UHSLMarcus 5:41e97348e9e7 503 strcpy(_error_strings[3], CCS811_MAX_RESISTANCE);
UHSLMarcus 5:41e97348e9e7 504 strcpy(_error_strings[4], CCS811_HEATER_FAULT);
UHSLMarcus 5:41e97348e9e7 505 strcpy(_error_strings[5], CCS811_HEATER_SUPPLY);
UHSLMarcus 5:41e97348e9e7 506 strcpy(_error_strings[6], CCS811_RESERVED);
UHSLMarcus 5:41e97348e9e7 507 strcpy(_error_strings[7], CCS811_RESERVED);
UHSLMarcus 5:41e97348e9e7 508 /* Library errors */
UHSLMarcus 5:41e97348e9e7 509 strcpy(_error_strings[CCS811_LIB_N_WAKE_ID+CCS811_ERR_NUM], CCS811_LIB_N_WAKE);
UHSLMarcus 5:41e97348e9e7 510 strcpy(_error_strings[CCS811_LIB_I2C_ID+CCS811_ERR_NUM], CCS811_LIB_I2C);
UHSLMarcus 5:41e97348e9e7 511 strcpy(_error_strings[CCS811_LIB_SLAVE_W_ID+CCS811_ERR_NUM], CCS811_LIB_SLAVE_W);
UHSLMarcus 5:41e97348e9e7 512 strcpy(_error_strings[CCS811_LIB_REG_ADDR_ID+CCS811_ERR_NUM], CCS811_LIB_REG_ADDR);
UHSLMarcus 5:41e97348e9e7 513 strcpy(_error_strings[CCS811_LIB_I2CWRITE_ID+CCS811_ERR_NUM], CCS811_LIB_I2CWRITE);
UHSLMarcus 5:41e97348e9e7 514 strcpy(_error_strings[CCS811_LIB_SLAVE_R_ID+CCS811_ERR_NUM], CCS811_LIB_SLAVE_R);
UHSLMarcus 6:22c0a7f2ece2 515 strcpy(_error_strings[CCS811_LIB_INV_MODE_ID+CCS811_ERR_NUM], CCS811_LIB_INV_MODE);
UHSLMarcus 7:5c95614a61ee 516 strcpy(_error_strings[CCS811_LIB_ENS210_INIT_ID+CCS811_ERR_NUM], CCS811_LIB_ENS210_INIT);
UHSLMarcus 5:41e97348e9e7 517 }
UHSLMarcus 5:41e97348e9e7 518
UHSLMarcus 5:41e97348e9e7 519 void AMS_CCS811::clear_errors() {
UHSLMarcus 5:41e97348e9e7 520 _error_count = 0;
UHSLMarcus 5:41e97348e9e7 521 for (int i = 0; i < CCS811_LIB_ERR_NUM; i++) {
UHSLMarcus 5:41e97348e9e7 522 _errors[i] = false;
UHSLMarcus 5:41e97348e9e7 523 }
UHSLMarcus 5:41e97348e9e7 524 }
UHSLMarcus 5:41e97348e9e7 525
UHSLMarcus 5:41e97348e9e7 526 void AMS_CCS811::new_error(int error_id) {
UHSLMarcus 5:41e97348e9e7 527 if (!_errors[error_id]) {
UHSLMarcus 5:41e97348e9e7 528 _errors[error_id] = true;
UHSLMarcus 5:41e97348e9e7 529 _error_count++;
UHSLMarcus 5:41e97348e9e7 530 }
UHSLMarcus 1:acfca1d3256d 531 }
UHSLMarcus 2:e394671ef5f6 532
UHSLMarcus 4:a6b8881eae87 533 void AMS_CCS811::update_ens210_timer() {
UHSLMarcus 4:a6b8881eae87 534 _ens210_poll_t.detach();
UHSLMarcus 4:a6b8881eae87 535 if (_ens210_enabled)
UHSLMarcus 4:a6b8881eae87 536 _ens210_poll_t.attach_us(callback(this, &AMS_CCS811::ens210_isr), _ens210_poll_split*1000);
UHSLMarcus 4:a6b8881eae87 537 }
UHSLMarcus 4:a6b8881eae87 538
UHSLMarcus 4:a6b8881eae87 539 void AMS_CCS811::ens210_isr() {
UHSLMarcus 8:58a36d9218be 540 temp_reading = ((float)_ens210->temp_read() / 64) - - 273.15;
UHSLMarcus 8:58a36d9218be 541 humid_reading = (float)_ens210->humid_read()/512;
UHSLMarcus 8:58a36d9218be 542 env_data(humid_reading, temp_reading);
UHSLMarcus 7:5c95614a61ee 543 }
UHSLMarcus 7:5c95614a61ee 544
UHSLMarcus 7:5c95614a61ee 545 void AMS_CCS811::_init_fractions() {
Steven Cooreman 15:cf658680c53f 546
UHSLMarcus 7:5c95614a61ee 547 fractions[0] = 0.5;
UHSLMarcus 7:5c95614a61ee 548 fractions[1] = 0.25;
UHSLMarcus 7:5c95614a61ee 549 fractions[2] = 0.125;
UHSLMarcus 7:5c95614a61ee 550 fractions[3] = 0.0625;
UHSLMarcus 7:5c95614a61ee 551 fractions[4] = 0.03125;
UHSLMarcus 7:5c95614a61ee 552 fractions[5] = 0.015625;
UHSLMarcus 7:5c95614a61ee 553 fractions[6] = 0.0078125;
UHSLMarcus 7:5c95614a61ee 554 fractions[7] = 0.00390625;
UHSLMarcus 7:5c95614a61ee 555 fractions[8] = 0.001953125;
Steven Cooreman 15:cf658680c53f 556
UHSLMarcus 7:5c95614a61ee 557 }
UHSLMarcus 7:5c95614a61ee 558
UHSLMarcus 7:5c95614a61ee 559 void AMS_CCS811::float_to_short(float in, char * output) {
UHSLMarcus 7:5c95614a61ee 560
UHSLMarcus 7:5c95614a61ee 561 uint8_t int_part = (uint8_t)in;
UHSLMarcus 7:5c95614a61ee 562 float dec_part = in - int_part;
UHSLMarcus 7:5c95614a61ee 563
UHSLMarcus 7:5c95614a61ee 564 uint16_t _short = 0;
UHSLMarcus 7:5c95614a61ee 565 for (int i = 0; i < 9; i++) {
Steven Cooreman 15:cf658680c53f 566 if (dec_part == 0) break;
UHSLMarcus 7:5c95614a61ee 567 if (dec_part >= fractions[i]) {
UHSLMarcus 7:5c95614a61ee 568 dec_part -= fractions[i];
UHSLMarcus 7:5c95614a61ee 569 _short |= 256 >> i;
UHSLMarcus 10:225a71ec316c 570 }
UHSLMarcus 7:5c95614a61ee 571 }
Steven Cooreman 15:cf658680c53f 572
UHSLMarcus 7:5c95614a61ee 573 _short |= int_part << 9;
Steven Cooreman 15:cf658680c53f 574
UHSLMarcus 7:5c95614a61ee 575 output[0] = _short >> 8;
UHSLMarcus 7:5c95614a61ee 576 output[1] = _short;
UHSLMarcus 4:a6b8881eae87 577 }
UHSLMarcus 4:a6b8881eae87 578
UHSLMarcus 3:782a719f47a5 579 void AMS_CCS811::update_slave_addr() {
UHSLMarcus 13:a74306788df7 580 _slave_addr = addr_mode() ? CCS811_SLAVE_ADDR_RAW_H : CCS811_SLAVE_ADDR_RAW_L;
UHSLMarcus 2:e394671ef5f6 581 }
Steven Cooreman 15:cf658680c53f 582
UHSLMarcus 1:acfca1d3256d 583 void AMS_CCS811::_isr_data() {
UHSLMarcus 6:22c0a7f2ece2 584 has_new_data(); // populate the data array
UHSLMarcus 3:782a719f47a5 585 _isr_data_fp.call();
UHSLMarcus 1:acfca1d3256d 586 }
UHSLMarcus 1:acfca1d3256d 587
UHSLMarcus 1:acfca1d3256d 588 bool AMS_CCS811::write_config() {
stevew817 14:0e8f5bf68b50 589 char cmd[1] = {0 | (_int_data_enabled ? 1 << 3 : 0) | (_mode << 4)};
UHSLMarcus 5:41e97348e9e7 590 return i2c_write(MEAS_MODE, cmd, 1) == 1;
UHSLMarcus 5:41e97348e9e7 591 }
UHSLMarcus 5:41e97348e9e7 592
UHSLMarcus 5:41e97348e9e7 593 AMS_CCS811::read_byte_result AMS_CCS811::read_config() {
UHSLMarcus 5:41e97348e9e7 594 read_byte_result result;
UHSLMarcus 5:41e97348e9e7 595 char byte[1];
UHSLMarcus 5:41e97348e9e7 596 if (i2c_read(MEAS_MODE, byte, 1) == 1) {
UHSLMarcus 5:41e97348e9e7 597 result.success = true;
UHSLMarcus 5:41e97348e9e7 598 result.byte = byte[0];
UHSLMarcus 5:41e97348e9e7 599 }
UHSLMarcus 5:41e97348e9e7 600 return result;
UHSLMarcus 1:acfca1d3256d 601 }
UHSLMarcus 1:acfca1d3256d 602
UHSLMarcus 5:41e97348e9e7 603 AMS_CCS811::read_byte_result AMS_CCS811::read_status() {
UHSLMarcus 5:41e97348e9e7 604 read_byte_result result;
UHSLMarcus 2:e394671ef5f6 605 char byte[1];
UHSLMarcus 5:41e97348e9e7 606 if (i2c_read(STATUS, byte, 1) == 1) {
UHSLMarcus 2:e394671ef5f6 607 result.success = true;
UHSLMarcus 5:41e97348e9e7 608 result.byte = byte[0];
UHSLMarcus 5:41e97348e9e7 609 }
Steven Cooreman 15:cf658680c53f 610
UHSLMarcus 5:41e97348e9e7 611 return result;
UHSLMarcus 5:41e97348e9e7 612 }
UHSLMarcus 5:41e97348e9e7 613
UHSLMarcus 5:41e97348e9e7 614 bool AMS_CCS811::boot_app_start() {
UHSLMarcus 5:41e97348e9e7 615 bool success = false;
Steven Cooreman 15:cf658680c53f 616
UHSLMarcus 5:41e97348e9e7 617 if (i2c_write(APP_START, NULL, 0) == 0) {
UHSLMarcus 5:41e97348e9e7 618 wait_ms(70);
UHSLMarcus 5:41e97348e9e7 619 success = true;
UHSLMarcus 2:e394671ef5f6 620 }
Steven Cooreman 15:cf658680c53f 621
UHSLMarcus 5:41e97348e9e7 622 return success;
UHSLMarcus 2:e394671ef5f6 623 }
UHSLMarcus 2:e394671ef5f6 624
UHSLMarcus 2:e394671ef5f6 625 int AMS_CCS811::i2c_read(char reg_addr, char* output, int len) {
UHSLMarcus 13:a74306788df7 626
UHSLMarcus 2:e394671ef5f6 627 int read_count = 0;
Steven Cooreman 15:cf658680c53f 628 if (_n_wake_out != NULL) { // check nWAKE pin is set
Steven Cooreman 15:cf658680c53f 629 _n_wake_out->write(0); // Hold low
UHSLMarcus 5:41e97348e9e7 630 wait_us(CCS811_T_AWAKE); // tAWAKE time to allow sensor I2C to wake up
UHSLMarcus 2:e394671ef5f6 631 if (_i2c != NULL) { // check I2C interface is set
UHSLMarcus 2:e394671ef5f6 632 _i2c->start(); // send start condition for write
UHSLMarcus 5:41e97348e9e7 633 if(_i2c->write(CCS811_SLAVE_ADDR_W) == 1) { // write slave address with write bit
UHSLMarcus 2:e394671ef5f6 634 if(_i2c->write(reg_addr) == 1) { // write register address
UHSLMarcus 2:e394671ef5f6 635 _i2c->start(); // send another start condition for read
UHSLMarcus 5:41e97348e9e7 636 if(_i2c->write(CCS811_SLAVE_ADDR_R) == 1) { // write slave address with read bit
UHSLMarcus 2:e394671ef5f6 637 for (int i = 0; i < len; i++) { // read len bytes
UHSLMarcus 2:e394671ef5f6 638 output[i] = _i2c->read(i < len-1 ? 1 : 0); // ack all reads aside from the final one (i == len-1)
UHSLMarcus 2:e394671ef5f6 639 read_count++;
UHSLMarcus 2:e394671ef5f6 640 }
UHSLMarcus 5:41e97348e9e7 641 } else new_error(CCS811_LIB_SLAVE_R_ID);
UHSLMarcus 5:41e97348e9e7 642 } else new_error(CCS811_LIB_REG_ADDR_ID);
UHSLMarcus 5:41e97348e9e7 643 } else new_error(CCS811_LIB_SLAVE_W_ID);
Steven Cooreman 15:cf658680c53f 644 _i2c->stop(); // send stop condition
UHSLMarcus 5:41e97348e9e7 645 } else new_error(CCS811_LIB_I2C_ID);
UHSLMarcus 5:41e97348e9e7 646 _n_wake_out->write(1); // Set back to high
UHSLMarcus 5:41e97348e9e7 647 wait_us(CCS811_T_DWAKE); // tDWAKE time to allow sensor I2C to sleep
UHSLMarcus 5:41e97348e9e7 648 } else new_error(CCS811_LIB_N_WAKE_ID);
Steven Cooreman 15:cf658680c53f 649
UHSLMarcus 2:e394671ef5f6 650 return read_count;
UHSLMarcus 2:e394671ef5f6 651 }
UHSLMarcus 2:e394671ef5f6 652
UHSLMarcus 5:41e97348e9e7 653 int AMS_CCS811::i2c_write(char reg_addr, char* input, int len) {
Steven Cooreman 15:cf658680c53f 654
UHSLMarcus 5:41e97348e9e7 655 int write_count = -1;
UHSLMarcus 2:e394671ef5f6 656 if (_n_wake_out != NULL) { // check nWAKE pin is set
UHSLMarcus 5:41e97348e9e7 657 _n_wake_out->write(0); // Hold low
UHSLMarcus 5:41e97348e9e7 658 wait_us(CCS811_T_AWAKE); // tAWAKE time to allow sensor I2C to wake up
UHSLMarcus 2:e394671ef5f6 659 if (_i2c != NULL) { // check I2C interface is set
UHSLMarcus 2:e394671ef5f6 660 _i2c->start(); // send start condition for write
UHSLMarcus 5:41e97348e9e7 661 if(_i2c->write(CCS811_SLAVE_ADDR_W) == 1) { // write slave address
UHSLMarcus 2:e394671ef5f6 662 if(_i2c->write(reg_addr) == 1) { // write register address
UHSLMarcus 5:41e97348e9e7 663 write_count = 0;
UHSLMarcus 2:e394671ef5f6 664 for (int i = 0; i < len; i++) { // write len bytes
UHSLMarcus 2:e394671ef5f6 665 if(_i2c->write(input[i]) == 1) write_count++; // write each byte, if successful increment count
UHSLMarcus 5:41e97348e9e7 666 else new_error(CCS811_LIB_I2CWRITE_ID);
UHSLMarcus 2:e394671ef5f6 667 }
UHSLMarcus 5:41e97348e9e7 668 } else new_error(CCS811_LIB_REG_ADDR_ID);
UHSLMarcus 5:41e97348e9e7 669 } else new_error(CCS811_LIB_SLAVE_W_ID);
Steven Cooreman 15:cf658680c53f 670 _i2c->stop(); // send stop condition
UHSLMarcus 5:41e97348e9e7 671 } else new_error(CCS811_LIB_I2C_ID);
UHSLMarcus 5:41e97348e9e7 672 _n_wake_out->write(1); // set back to high
UHSLMarcus 5:41e97348e9e7 673 wait_us(CCS811_T_DWAKE); // tDWAKE time to allow sensor I2C to sleep
UHSLMarcus 5:41e97348e9e7 674 }else new_error(CCS811_LIB_N_WAKE_ID);
Steven Cooreman 15:cf658680c53f 675
UHSLMarcus 2:e394671ef5f6 676 return write_count;
UHSLMarcus 1:acfca1d3256d 677 }