Library for the AMS CC811 digitial gas sensor

Dependencies:   AMS_ENS210_temp_humid_sensor

Revision:
6:22c0a7f2ece2
Parent:
5:41e97348e9e7
Child:
7:5c95614a61ee
--- a/AMS_CCS811.cpp	Fri Jan 20 14:34:41 2017 +0000
+++ b/AMS_CCS811.cpp	Mon Jan 23 14:27:57 2017 +0000
@@ -15,6 +15,20 @@
     return b;
 }
 
+const char *short_to_binary(uint16_t in)
+{
+    static char b[17];
+    b[0] = '\0';
+
+    uint16_t z;
+    for (z = 32768; z > 0; z >>= 1)
+    {
+        strcat(b, ((in & z) == z) ? "1" : "0");
+    }
+
+    return b;
+}
+
 AMS_CCS811::AMS_CCS811(I2C * i2c, PinName n_wake_pin) { 
     _n_wake_out = new (std::nothrow) DigitalOut(n_wake_pin, 1);
     _i2c = i2c; 
@@ -34,26 +48,20 @@
 
 bool AMS_CCS811::init() {
    
-    USBserialComms.printf("Init()\r");
-   
     bool success = false;
     
     _init_errors();
     set_defaults();
     
     if (_n_wake_out) {
-        USBserialComms.printf("_n_wake_out: %d\r", _n_wake_out != NULL);
-        USBserialComms.printf("_n_wake_out I/0: %d\r", _n_wake_out->read());
     
         int fw_mode = firmware_mode();
        
         if (fw_mode == 1) {  
-            USBserialComms.printf("App Mode\r");
             enable_ens210(true);
             success = write_config();
     
         } else if (fw_mode == 0) {  // is in boot mode, needs to be loaded into app mode
-            USBserialComms.printf("Boot Mode\r");
             if (boot_app_start())   // if succesfully writes to app_start, retry init
                 init();
         }
@@ -94,15 +102,19 @@
 int AMS_CCS811::firmware_mode() {
     int firmware_result = -1;
     
+    clear_errors();
+    
     read_byte_result read_result = read_status();
     if (read_result.success) {
         firmware_result = (read_result.byte >> 7) & 1;
-    } // todo ... add a new "last error" here
+    }
     
     return firmware_result;
 }
 
 bool AMS_CCS811::mode(OP_MODES mode) {
+    clear_errors();
+    
     OP_MODES old = _mode;               // incase the write fails, to roll back
     _mode = mode;
     
@@ -114,13 +126,15 @@
 }
 
 AMS_CCS811::OP_MODES AMS_CCS811::mode() {
+    clear_errors();
+    
     OP_MODES result = INVALID;
     
     read_byte_result read_result = read_config();
     if (read_result.success) {
         int mode = (read_result.byte >> 4) & 0b111;
         result = mode > 4 ? INVALID : (OP_MODES)mode;
-    } // todo ... add a new "last error" here
+    }
     
     return result;
 }
@@ -160,26 +174,45 @@
 
 
 int AMS_CCS811::has_new_data() {
+
+    clear_errors();
+    
     int result = -1;
     
-    if (i2c_read(ALG_RESULT_DATA, _alg_result_data, 8) == 8) {
-        result = (_alg_result_data[4] >> 3) & 1;
+    char meas_mode[1];
+    if(i2c_read(MEAS_MODE, meas_mode, 1) == 1) {                                // one read here is quicker than calling read_config() twice
+    
+        int curr_mode = (meas_mode[0] >> 4) & 0b111;
+        if (curr_mode < 5) {
+            if (curr_mode > 0) {                                                // check for all valid modes other than idle
+                if (((meas_mode[0] >> 3) & 1) == 0) {                           // check if interrupts are disabled
+                    char status[1];                     
+                    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
+                        result = (status[0] >> 3) & 1;
+                
+                } else result = 1;
+                
+                if (result == 1) 
+                    if (i2c_read(ALG_RESULT_DATA, _alg_result_data, 8) != 8) result = -1;
+                
+  
+            } else result = 0;                                                  // return 0 when in idle
+        } else new_error(CCS811_LIB_INV_MODE_ID);
     }
-    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]);
     
     return result;
 }
 
 uint16_t AMS_CCS811::co2_read() {
-    return 0;
+    return 0 | (_alg_result_data[0] << 8) | _alg_result_data[1];
 }
 
 uint16_t AMS_CCS811::tvoc_read() {
-    return 0;
+    return 0 | (_alg_result_data[2] << 8) | _alg_result_data[3];
 }
 
 uint16_t AMS_CCS811::raw_read() {
-    return 0;
+    return 0 | (_alg_result_data[6] << 8) | _alg_result_data[7];
 }
 
 bool AMS_CCS811::error_status() {
@@ -245,7 +278,7 @@
     read_byte_result read_result = read_config();
     if (read_result.success) {
         enabled = (read_result.byte >> 3) & 1;
-    } // todo ... add a new "last error" here? or maybe the read method itself should set that.
+    }
     
     return enabled;
 }
@@ -277,11 +310,7 @@
     if (_ens210_poll_split == NULL)
         _ens210_poll_split = CONFIG_ENS210_POLL;
         
-    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);
-        
     update_slave_addr();
-    
-    USBserialComms.printf("_slave_addr: 0x%02X\r", _slave_addr);
 }
 
 void AMS_CCS811::_init_errors() {
@@ -302,6 +331,7 @@
     strcpy(_error_strings[CCS811_LIB_REG_ADDR_ID+CCS811_ERR_NUM], CCS811_LIB_REG_ADDR);
     strcpy(_error_strings[CCS811_LIB_I2CWRITE_ID+CCS811_ERR_NUM], CCS811_LIB_I2CWRITE);
     strcpy(_error_strings[CCS811_LIB_SLAVE_R_ID+CCS811_ERR_NUM], CCS811_LIB_SLAVE_R);
+    strcpy(_error_strings[CCS811_LIB_INV_MODE_ID+CCS811_ERR_NUM], CCS811_LIB_INV_MODE);
 }
 
 void AMS_CCS811::clear_errors() {
@@ -332,12 +362,12 @@
 }
         
 void AMS_CCS811::_isr_data() {
+    has_new_data();             // populate the data array
     _isr_data_fp.call();
 }
 
 bool AMS_CCS811::write_config() {
     char cmd[1] = {0 | (_int_data_enabled << 3) | (_mode << 4)};
-    USBserialComms.printf("write_config(addr: 0x%02X, byte: %s(%d))\r", MEAS_MODE, byte_to_binary(cmd[0]), cmd[0]);
     return i2c_write(MEAS_MODE, cmd, 1) == 1;
 }
 
@@ -348,7 +378,6 @@
         result.success = true;
         result.byte = byte[0];
     }
-    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);
     return result;
 }
 
@@ -359,7 +388,7 @@
         result.success = true;
         result.byte = byte[0];
     }
-    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);
+    
     return result;
 }