simple CCS811 driver

Dependencies:   AMS_ENS210_temp_humid_sensor

Dependents:   TBSense2_Sensor_Demo

Fork of AMS_CCS811_gas_sensor by Marcus Lee

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers AMS_CCS811.cpp Source File

AMS_CCS811.cpp

00001 
00002 #include "AMS_CCS811.h"
00003 #include "AMS_CCS811_fw_2_0_0.h"
00004 #include "mbed_trace.h"
00005 
00006 #define TRACE_GROUP "CCS"
00007 
00008 AMS_CCS811::AMS_CCS811(I2C * i2c, PinName n_wake_pin) : _n_wake_out(), _addr_out(), _int_data(), _ens210(), _i2c() {
00009     _n_wake_out = new (std::nothrow) DigitalOut(n_wake_pin, 1);
00010     _i2c = i2c;
00011 }
00012 
00013 AMS_CCS811::AMS_CCS811(I2C * i2c, PinName n_wake_pin, I2C * ens210_i2c) : _n_wake_out(), _addr_out(), _int_data(), _ens210(), _i2c() {
00014     _n_wake_out = new (std::nothrow) DigitalOut(n_wake_pin, 1);
00015     _i2c = i2c;
00016     ens210_i2c_interface(ens210_i2c);
00017 }
00018 
00019 AMS_CCS811::~AMS_CCS811() {
00020     delete _n_wake_out;
00021     delete _addr_out;
00022     delete _int_data;
00023     delete _ens210;
00024 }
00025 
00026 bool AMS_CCS811::init() {
00027 
00028     bool success = false;
00029 
00030     _init_errors();
00031     _init_fractions();
00032     set_defaults();
00033 
00034     temp_reading = 0;
00035     humid_reading = 0;
00036 
00037     if (_n_wake_out) {
00038         char buffer[2];
00039 
00040         if(i2c_read(HW_ID, buffer, 1) == 1) {
00041             if(buffer[0] != 0x81) {
00042                 // not a CCS811
00043                 tr_err("Not a CCS: %02x", buffer[0]);
00044                 return false;
00045             }
00046         } else {
00047             return false;
00048         }
00049 
00050         if(i2c_read(STATUS, buffer, 1) == 1) {
00051             if((buffer[0] & 0x10) == 0) {
00052                 // does not have valid FW
00053                 flash_firmware();
00054             }
00055         } else {
00056             return false;
00057         }
00058 
00059         if(i2c_read(FW_APP_VERSION, buffer, 2) == 2) {
00060             tr_warn("CCS version %02x %02x", buffer[0], buffer[1]);
00061             if (buffer[0] < CCS_FW_UPGRADE_VERSION) {
00062                 tr_warn("Flashing Firmware");
00063                 flash_firmware();
00064             }
00065         } else {
00066             return false;
00067         }
00068 
00069         int fw_mode = firmware_mode();
00070 
00071         if (fw_mode == 1) {
00072             success = write_config();
00073             enable_ens210(true);
00074 
00075         } else if (fw_mode == 0) {  // is in boot mode, needs to be loaded into app mode
00076             if (boot_app_start())   // if succesfully writes to app_start, retry init
00077                 success = init();
00078         }
00079     }
00080 
00081     return success;
00082 }
00083 
00084 bool AMS_CCS811::flash_firmware() {
00085     // kick into bootloader mode
00086     int fw_mode = firmware_mode();
00087     if (fw_mode == 1) {
00088         const char reset_sequence[] = {0x11, 0xE5, 0x72, 0x8A};
00089         if(i2c_write(0xFF, (char*)reset_sequence, 4) == 4) {
00090             fw_mode = firmware_mode();
00091             if(fw_mode == 1) {
00092                 tr_err("Couldn't exit app mode");
00093                 return false;
00094             }
00095         } else {
00096             tr_err("Couldn't issue reset command");
00097             return false;
00098         }
00099     }
00100 
00101     // assert nwake
00102     if (_n_wake_out != NULL) {
00103         int write_count;
00104 
00105         _n_wake_out->write(0);
00106         wait_ms(100);
00107 
00108         // erase current FW
00109         static const char erase_sequence[4] = {0xE7, 0xA7, 0xE6, 0x09};
00110         write_count = 0;
00111         _i2c->start();
00112         if(_i2c->write(CCS811_SLAVE_ADDR_W) == 1) {
00113             if(_i2c->write(FW_ERASE) == 1) {
00114                 for (size_t i = 0; i < 4; i++) {
00115                     if(_i2c->write(erase_sequence[i]) == 1) write_count++;
00116                     else new_error(CCS811_LIB_I2CWRITE_ID);
00117                 }
00118             } else new_error(CCS811_LIB_REG_ADDR_ID);
00119         } else new_error(CCS811_LIB_SLAVE_W_ID);
00120         _i2c->stop();
00121 
00122         if (write_count != 4) {
00123             _n_wake_out->write(1);
00124             return false;
00125         }
00126         tr_info("CCS FW erased");
00127         wait_ms(500);
00128 
00129         // upload new FW
00130         tr_info("uploading new FW");
00131         char payload[8];
00132         for(size_t offset = 0; offset < 5120; offset += 8) {
00133             for(size_t j = 0; j < 8; j++) {
00134                 payload[j] = ams_fw_image[offset + j];
00135             }
00136 
00137             write_count = 0;
00138             _i2c->start();
00139             if(_i2c->write(CCS811_SLAVE_ADDR_W) == 1) {
00140                 if(_i2c->write(FW_FLASH) == 1) {
00141                     for (size_t j = 0; j < 8; j++) {
00142                         if(_i2c->write(payload[j]) == 1) write_count++;
00143                         else new_error(CCS811_LIB_I2CWRITE_ID);
00144                     }
00145                 } else new_error(CCS811_LIB_REG_ADDR_ID);
00146             } else new_error(CCS811_LIB_SLAVE_W_ID);
00147             _i2c->stop();
00148 
00149             wait_ms(50);
00150 
00151             if (write_count != 8) {
00152                 _n_wake_out->write(1);
00153                 tr_err("flash error");
00154                 return false;
00155             }
00156 
00157             tr_debug("Flashed byte %d of 5120", offset);
00158         }
00159         tr_info("CCS FW uploaded");
00160 
00161         // verify new FW
00162         write_count = 0;
00163         _i2c->start();
00164         if(_i2c->write(CCS811_SLAVE_ADDR_W) == 1) {
00165             if(_i2c->write(FW_VERIFY) == 1) {
00166                 write_count = 1;
00167             } else new_error(CCS811_LIB_REG_ADDR_ID);
00168         } else new_error(CCS811_LIB_SLAVE_W_ID);
00169         _i2c->stop();
00170 
00171         wait_ms(500);
00172 
00173         if (write_count != 1) {
00174             _n_wake_out->write(1);
00175             tr_err("Failed to issue verify");
00176             return false;
00177         }
00178 
00179         char status = 0;
00180         _i2c->start();
00181         if(_i2c->write(CCS811_SLAVE_ADDR_W) == 1) {
00182             if(_i2c->write(STATUS) == 1) {
00183                 _i2c->start();
00184                 if(_i2c->write(CCS811_SLAVE_ADDR_R) == 1) {
00185                     status = _i2c->read(0);
00186                 } else new_error(CCS811_LIB_SLAVE_R_ID);
00187             } else new_error(CCS811_LIB_REG_ADDR_ID);
00188         } else new_error(CCS811_LIB_SLAVE_W_ID);
00189         _i2c->stop();
00190 
00191         if (status == 0) {
00192             tr_err("Failed update");
00193             _n_wake_out->write(1);
00194             return false;
00195         }
00196 
00197         if ((status & 0x30) != 0x30) {
00198             tr_err("Failed verify");
00199             _n_wake_out->write(1);
00200             return false;
00201         }
00202 
00203         // boot into new FW
00204         tr_info("upgraded");
00205         _n_wake_out->write(1);
00206         wait_ms(50);
00207         return boot_app_start();
00208     } else {
00209         tr_err("No nWAKE available");
00210         return false;
00211     }
00212 }
00213 
00214 void AMS_CCS811::i2c_interface(I2C * i2c) {
00215     _i2c = i2c;
00216 }
00217 
00218 bool AMS_CCS811::ens210_i2c_interface(I2C * i2c) {
00219 
00220     bool success;
00221 
00222     if (_ens210 == NULL) {
00223         _ens210 = new (std::nothrow) AMS_ENS210(i2c, true, true);
00224         if (_ens210 != NULL) {
00225             if (_ens210->init()) {
00226                 success = _ens210->start();
00227             }
00228         }
00229     } else {
00230         _ens210->i2c_interface(i2c);
00231         success = true;
00232     }
00233 
00234     if (!success) new_error(CCS811_LIB_ENS210_INIT_ID);
00235 
00236     return success;
00237 }
00238 
00239 bool AMS_CCS811::enable_ens210(bool enable) {
00240 
00241     _ens210_enabled = false;
00242     if (_ens210 != NULL) {
00243         if (_ens210->i2c_interface() != NULL) _ens210_enabled = enable;
00244     }
00245     update_ens210_timer();
00246     return _ens210_enabled;
00247 }
00248 
00249 bool AMS_CCS811::ens210_is_enabled() {
00250     enable_ens210(_ens210_enabled);     // Make sure the state is representive
00251     return _ens210_enabled;
00252 }
00253 
00254 void AMS_CCS811::ens210_poll_interval(int poll_ms) {
00255     _ens210_poll_split = poll_ms;
00256     enable_ens210(_ens210_enabled);     // makes sure the state is representive, and will also update the timer
00257 }
00258 
00259 int AMS_CCS811::ens210_poll_interval() {
00260     return _ens210_poll_split;
00261 }
00262 
00263 int AMS_CCS811::firmware_mode() {
00264     int firmware_result = -1;
00265 
00266     clear_errors();
00267 
00268     read_byte_result read_result = read_status();
00269     if (read_result.success) {
00270         firmware_result = (read_result.byte >> 7) & 1;
00271     }
00272 
00273     return firmware_result;
00274 }
00275 
00276 bool AMS_CCS811::mode(OP_MODES mode) {
00277     clear_errors();
00278 
00279     OP_MODES old = _mode;               // incase the write fails, to roll back
00280     _mode = mode;
00281 
00282     bool success = write_config();
00283     if (!success)
00284         _mode = old;
00285 
00286     return success;
00287 }
00288 
00289 AMS_CCS811::OP_MODES AMS_CCS811::mode() {
00290     clear_errors();
00291 
00292     OP_MODES result = INVALID;
00293 
00294     read_byte_result read_result = read_config();
00295     if (read_result.success) {
00296         int mode = (read_result.byte >> 4) & 0b111;
00297         result = mode > 4 ? INVALID : (OP_MODES)mode;
00298     }
00299 
00300     return result;
00301 }
00302 
00303 bool AMS_CCS811::addr_mode(bool high) {
00304     _addr_dir = high;
00305     if (_addr_out != NULL) _addr_out->write(_addr_dir);
00306 
00307     update_slave_addr();
00308 
00309     return addr_mode() == high;
00310 }
00311 
00312 bool AMS_CCS811::addr_mode() {
00313     _addr_dir = false;
00314     if (_addr_out != NULL) {
00315         _addr_dir = _addr_out->read();
00316     }
00317 
00318     return _addr_dir;
00319 }
00320 
00321 bool AMS_CCS811::addr_pin(PinName pin) {
00322     _addr_out = _addr_out == NULL ? new (std::nothrow) DigitalOut(pin) : new (_addr_out) DigitalOut(pin);
00323     addr_mode(_addr_dir);
00324 
00325     return _addr_out != NULL;
00326 }
00327 
00328 bool AMS_CCS811::n_wake_pin(PinName pin) {
00329     _n_wake_out = _n_wake_out == NULL ? new (std::nothrow) DigitalOut(pin) : new (_n_wake_out) DigitalOut(pin);
00330     return _n_wake_out != NULL;
00331 }
00332 
00333 bool AMS_CCS811::env_data(float humid, float temp) {
00334     char bytes[4];
00335     if (humid > CCS811_MAX_HUMID) humid = CCS811_MAX_HUMID;
00336     if (humid < 0) humid = 0;
00337 
00338     temp += 25;
00339     if (temp > CCS811_MAX_TEMP) humid = CCS811_MAX_TEMP;
00340     if (temp < 0) temp = 0;
00341 
00342     float_to_short(humid, bytes);
00343     float_to_short(temp, bytes+2);
00344 
00345     return i2c_write(ENV_DATA, bytes, 4) == 4;
00346 }
00347 
00348 
00349 int AMS_CCS811::has_new_data() {
00350 
00351     clear_errors();
00352 
00353     int result = -1;
00354 
00355     char meas_mode[1];
00356     if(i2c_read(MEAS_MODE, meas_mode, 1) == 1) {                                // one read here is quicker than calling read_config() twice
00357 
00358         int curr_mode = (meas_mode[0] >> 4) & 0b111;
00359         if (curr_mode < 5) {
00360             if (curr_mode > 0) {                                                // check for all valid modes other than idle
00361                 if (((meas_mode[0] >> 3) & 1) == 0) {                           // check if interrupts are disabled
00362                     char status[1];
00363                     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
00364                         result = (status[0] >> 3) & 1;
00365 
00366                 } else result = 1;
00367 
00368                 if (result == 1)
00369                     if (i2c_read(ALG_RESULT_DATA, _alg_result_data, 8) != 8) result = -1;
00370 
00371 
00372             } else result = 0;                                                  // return 0 when in idle
00373         } else new_error(CCS811_LIB_INV_MODE_ID);
00374     }
00375 
00376     return result;
00377 }
00378 
00379 uint16_t AMS_CCS811::co2_read() {
00380     return 0 | (_alg_result_data[0] << 8) | _alg_result_data[1];
00381 }
00382 
00383 uint16_t AMS_CCS811::tvoc_read() {
00384     return 0 | (_alg_result_data[2] << 8) | _alg_result_data[3];
00385 }
00386 
00387 uint16_t AMS_CCS811::raw_read() {
00388     return 0 | (_alg_result_data[6] << 8) | _alg_result_data[7];
00389 }
00390 
00391 float AMS_CCS811::temp_read() {
00392     return temp_reading;
00393 }
00394 
00395 float AMS_CCS811::humid_read() {
00396     return humid_reading;
00397 }
00398 
00399 bool AMS_CCS811::error_status() {
00400     bool result = false;
00401 
00402     read_byte_result read_result = read_status();
00403     if (read_result.success) {
00404         result = read_result.byte & 1;
00405     }
00406 
00407     result = result || (_error_count > 0);
00408 
00409     return result;
00410 }
00411 
00412 AMS_CCS811::ccs811_errors AMS_CCS811::errors() {
00413     ccs811_errors error_result;
00414 
00415     char byte[1];
00416     if (i2c_read(ERROR_ID, byte, 1) == 1) {
00417         for(int i = 0; i < CCS811_ERR_NUM; i++) {
00418             if ((byte[0] << i) & 1) {
00419                 error_result.codes[error_result.count++] = i;
00420             }
00421         }
00422     }
00423     for(int i = 0; i < CCS811_LIB_ERR_NUM; i++) {
00424         if (_errors[i]) {
00425             error_result.codes[error_result.count++] = i + CCS811_ERR_NUM;
00426         }
00427     }
00428 
00429     return error_result;
00430 
00431 }
00432 
00433 const char * AMS_CCS811::error_string(int err_code){
00434     static char result[255];
00435     result[0] = 0;
00436     if (err_code < CCS811_TOTAL_ERR_NUM && err_code > -1)
00437         strcpy(result, _error_strings[err_code]);
00438     else
00439         sprintf(result, "Invalid Code: %d is out of range (0 - %d)", err_code, CCS811_TOTAL_ERR_NUM-1);
00440 
00441     return result;
00442 }
00443 
00444 bool AMS_CCS811::enable_interupt(bool enable) {
00445     bool old = _int_data_enabled;   // incase the write fails, to roll back
00446     _int_data_enabled = enable;
00447 
00448     bool success = write_config();
00449     if (!success)
00450         _int_data_enabled = old;
00451 
00452     return success;
00453 
00454 }
00455 
00456 int AMS_CCS811::interupt_enabled() {
00457     int enabled = -1;
00458 
00459     read_byte_result read_result = read_config();
00460     if (read_result.success) {
00461         enabled = (read_result.byte >> 3) & 1;
00462     }
00463 
00464     return enabled;
00465 }
00466 
00467 bool AMS_CCS811::interrupt_pin(PinName pin) {
00468     bool success = false;
00469 
00470     _int_data = _int_data == NULL ? new (std::nothrow) InterruptIn(pin) : new (_int_data) InterruptIn(pin);
00471     if (_int_data != NULL) {
00472         _int_data->fall(callback(this, &AMS_CCS811::_isr_data));
00473         success = true;
00474     }
00475 
00476     return success;
00477 }
00478 
00479 
00480 
00481 
00482 /** Private **/
00483 
00484 void AMS_CCS811::set_defaults() {
00485     if (_mode == NULL)
00486         _mode = CONFIG_OP_MODE;
00487     if (_addr_dir == NULL)
00488         _addr_dir = CONFIG_ADDR_DIR;
00489     if (_int_data_enabled == NULL)
00490         _int_data_enabled = CONFIG_INTR;
00491     if (_ens210_poll_split == NULL)
00492         _ens210_poll_split = CONFIG_ENS210_POLL;
00493 
00494     update_slave_addr();
00495 }
00496 
00497 void AMS_CCS811::_init_errors() {
00498     clear_errors();
00499     /* Sensor errors */
00500     strcpy(_error_strings[0], CCS811_WRITE_REG_INVALID);
00501     strcpy(_error_strings[1], CCS811_READ_REG_INVALID);
00502     strcpy(_error_strings[2], CCS811_MEASMODE_INVALID);
00503     strcpy(_error_strings[3], CCS811_MAX_RESISTANCE);
00504     strcpy(_error_strings[4], CCS811_HEATER_FAULT);
00505     strcpy(_error_strings[5], CCS811_HEATER_SUPPLY);
00506     strcpy(_error_strings[6], CCS811_RESERVED);
00507     strcpy(_error_strings[7], CCS811_RESERVED);
00508     /* Library errors */
00509     strcpy(_error_strings[CCS811_LIB_N_WAKE_ID+CCS811_ERR_NUM], CCS811_LIB_N_WAKE);
00510     strcpy(_error_strings[CCS811_LIB_I2C_ID+CCS811_ERR_NUM], CCS811_LIB_I2C);
00511     strcpy(_error_strings[CCS811_LIB_SLAVE_W_ID+CCS811_ERR_NUM], CCS811_LIB_SLAVE_W);
00512     strcpy(_error_strings[CCS811_LIB_REG_ADDR_ID+CCS811_ERR_NUM], CCS811_LIB_REG_ADDR);
00513     strcpy(_error_strings[CCS811_LIB_I2CWRITE_ID+CCS811_ERR_NUM], CCS811_LIB_I2CWRITE);
00514     strcpy(_error_strings[CCS811_LIB_SLAVE_R_ID+CCS811_ERR_NUM], CCS811_LIB_SLAVE_R);
00515     strcpy(_error_strings[CCS811_LIB_INV_MODE_ID+CCS811_ERR_NUM], CCS811_LIB_INV_MODE);
00516     strcpy(_error_strings[CCS811_LIB_ENS210_INIT_ID+CCS811_ERR_NUM], CCS811_LIB_ENS210_INIT);
00517 }
00518 
00519 void AMS_CCS811::clear_errors() {
00520     _error_count = 0;
00521     for (int i = 0; i < CCS811_LIB_ERR_NUM; i++) {
00522         _errors[i] = false;
00523     }
00524 }
00525 
00526 void AMS_CCS811::new_error(int error_id) {
00527     if (!_errors[error_id]) {
00528         _errors[error_id] = true;
00529         _error_count++;
00530     }
00531 }
00532 
00533 void AMS_CCS811::update_ens210_timer() {
00534     _ens210_poll_t.detach();
00535     if (_ens210_enabled)
00536         _ens210_poll_t.attach_us(callback(this, &AMS_CCS811::ens210_isr), _ens210_poll_split*1000);
00537 }
00538 
00539 void AMS_CCS811::ens210_isr() {
00540     temp_reading = ((float)_ens210->temp_read() / 64) - - 273.15;
00541     humid_reading = (float)_ens210->humid_read()/512;
00542     env_data(humid_reading, temp_reading);
00543 }
00544 
00545 void AMS_CCS811::_init_fractions() {
00546 
00547     fractions[0] = 0.5;
00548     fractions[1] = 0.25;
00549     fractions[2] = 0.125;
00550     fractions[3] = 0.0625;
00551     fractions[4] = 0.03125;
00552     fractions[5] = 0.015625;
00553     fractions[6] = 0.0078125;
00554     fractions[7] = 0.00390625;
00555     fractions[8] = 0.001953125;
00556 
00557 }
00558 
00559 void AMS_CCS811::float_to_short(float in, char * output) {
00560 
00561     uint8_t int_part = (uint8_t)in;
00562     float dec_part = in - int_part;
00563 
00564     uint16_t _short = 0;
00565     for (int i = 0; i < 9; i++) {
00566         if (dec_part == 0) break;
00567         if (dec_part >= fractions[i]) {
00568             dec_part -= fractions[i];
00569             _short |= 256 >> i;
00570         }
00571     }
00572 
00573     _short |= int_part << 9;
00574 
00575     output[0] = _short >> 8;
00576     output[1] = _short;
00577 }
00578 
00579 void AMS_CCS811::update_slave_addr() {
00580     _slave_addr = addr_mode() ? CCS811_SLAVE_ADDR_RAW_H : CCS811_SLAVE_ADDR_RAW_L;
00581 }
00582 
00583 void AMS_CCS811::_isr_data() {
00584     has_new_data();             // populate the data array
00585     _isr_data_fp.call();
00586 }
00587 
00588 bool AMS_CCS811::write_config() {
00589     char cmd[1] = {0 | (_int_data_enabled ? 1 << 3 : 0) | (_mode << 4)};
00590     return i2c_write(MEAS_MODE, cmd, 1) == 1;
00591 }
00592 
00593 AMS_CCS811::read_byte_result AMS_CCS811::read_config() {
00594     read_byte_result result;
00595     char byte[1];
00596     if (i2c_read(MEAS_MODE, byte, 1) == 1) {
00597         result.success = true;
00598         result.byte = byte[0];
00599     }
00600     return result;
00601 }
00602 
00603 AMS_CCS811::read_byte_result AMS_CCS811::read_status() {
00604     read_byte_result result;
00605     char byte[1];
00606     if (i2c_read(STATUS, byte, 1) == 1) {
00607         result.success = true;
00608         result.byte = byte[0];
00609     }
00610 
00611     return result;
00612 }
00613 
00614 bool AMS_CCS811::boot_app_start() {
00615     bool success = false;
00616 
00617     if (i2c_write(APP_START, NULL, 0) == 0) {
00618         wait_ms(70);
00619         success = true;
00620     }
00621 
00622     return success;
00623 }
00624 
00625 int AMS_CCS811::i2c_read(char reg_addr, char* output, int len) {
00626 
00627     int read_count = 0;
00628     if (_n_wake_out != NULL) {                                          // check nWAKE pin is set
00629         _n_wake_out->write(0);                                          // Hold low
00630         wait_us(CCS811_T_AWAKE);                                        // tAWAKE time to allow sensor I2C to wake up
00631         if (_i2c != NULL) {                                             // check I2C interface is set
00632             _i2c->start();                                              // send start condition for write
00633             if(_i2c->write(CCS811_SLAVE_ADDR_W) == 1) {                 // write slave address with write bit
00634                 if(_i2c->write(reg_addr) == 1) {                        // write register address
00635                     _i2c->start();                                      // send another start condition for read
00636                     if(_i2c->write(CCS811_SLAVE_ADDR_R) == 1) {         // write slave address with read bit
00637                         for (int i = 0; i < len; i++) {                 // read len bytes
00638                             output[i] = _i2c->read(i < len-1 ? 1 : 0);  // ack all reads aside from the final one (i == len-1)
00639                             read_count++;
00640                         }
00641                     } else new_error(CCS811_LIB_SLAVE_R_ID);
00642                 } else new_error(CCS811_LIB_REG_ADDR_ID);
00643             } else new_error(CCS811_LIB_SLAVE_W_ID);
00644             _i2c->stop();                                               // send stop condition
00645         } else new_error(CCS811_LIB_I2C_ID);
00646         _n_wake_out->write(1);                                          // Set back to high
00647         wait_us(CCS811_T_DWAKE);                                        // tDWAKE time to allow sensor I2C to sleep
00648     } else new_error(CCS811_LIB_N_WAKE_ID);
00649 
00650     return read_count;
00651 }
00652 
00653 int AMS_CCS811::i2c_write(char reg_addr, char* input, int len) {
00654 
00655     int write_count = -1;
00656     if (_n_wake_out != NULL) {                                          // check nWAKE pin is set
00657         _n_wake_out->write(0);                                          // Hold low
00658         wait_us(CCS811_T_AWAKE);                                        // tAWAKE time to allow sensor I2C to wake up
00659         if (_i2c != NULL) {                                             // check I2C interface is set
00660             _i2c->start();                                              // send start condition for write
00661             if(_i2c->write(CCS811_SLAVE_ADDR_W) == 1) {                 // write slave address
00662                 if(_i2c->write(reg_addr) == 1) {                        // write register address
00663                     write_count = 0;
00664                     for (int i = 0; i < len; i++) {                     // write len bytes
00665                         if(_i2c->write(input[i]) == 1) write_count++;   // write each byte, if successful increment count
00666                         else new_error(CCS811_LIB_I2CWRITE_ID);
00667                     }
00668                 } else new_error(CCS811_LIB_REG_ADDR_ID);
00669             } else new_error(CCS811_LIB_SLAVE_W_ID);
00670             _i2c->stop();                                               // send stop condition
00671         } else new_error(CCS811_LIB_I2C_ID);
00672         _n_wake_out->write(1);                                          // set back to high
00673         wait_us(CCS811_T_DWAKE);                                        // tDWAKE time to allow sensor I2C to sleep
00674     }else new_error(CCS811_LIB_N_WAKE_ID);
00675 
00676     return write_count;
00677 }