simple CCS811 driver

Dependencies:   AMS_ENS210_temp_humid_sensor

Dependents:   TBSense2_Sensor_Demo

Fork of AMS_CCS811_gas_sensor by Marcus Lee

Committer:
UHSLMarcus
Date:
Thu Jan 19 14:27:44 2017 +0000
Revision:
4:a6b8881eae87
Parent:
3:782a719f47a5
Child:
5:41e97348e9e7
starting tests on simple implimentations

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 0:5edbf3550350 4
UHSLMarcus 0:5edbf3550350 5 AMS_CCS811::AMS_CCS811(I2C * i2c, PinName n_wake_pin) {
UHSLMarcus 1:acfca1d3256d 6 _n_wake_out = new (std::nothrow) DigitalOut(n_wake_pin);
UHSLMarcus 4:a6b8881eae87 7 _i2c = i2c;
UHSLMarcus 0:5edbf3550350 8 }
UHSLMarcus 0:5edbf3550350 9
UHSLMarcus 0:5edbf3550350 10 AMS_CCS811::AMS_CCS811(I2C * i2c, PinName n_wake_pin, I2C * ens210_i2c) {
UHSLMarcus 1:acfca1d3256d 11 _n_wake_out = new (std::nothrow) DigitalOut(n_wake_pin);
UHSLMarcus 0:5edbf3550350 12 _i2c = i2c;
UHSLMarcus 0:5edbf3550350 13 _ens210_i2c = ens210_i2c;
UHSLMarcus 0:5edbf3550350 14 }
UHSLMarcus 0:5edbf3550350 15
UHSLMarcus 1:acfca1d3256d 16 AMS_CCS811::~AMS_CCS811() {
UHSLMarcus 1:acfca1d3256d 17 delete _n_wake_out;
UHSLMarcus 1:acfca1d3256d 18 delete _addr_out;
UHSLMarcus 1:acfca1d3256d 19 delete _int_data;
UHSLMarcus 1:acfca1d3256d 20 }
UHSLMarcus 1:acfca1d3256d 21
UHSLMarcus 1:acfca1d3256d 22 bool AMS_CCS811::init() {
UHSLMarcus 4:a6b8881eae87 23 enable_ens210(true);
UHSLMarcus 4:a6b8881eae87 24
UHSLMarcus 4:a6b8881eae87 25 return set_defaults();
UHSLMarcus 4:a6b8881eae87 26 }
UHSLMarcus 4:a6b8881eae87 27
UHSLMarcus 4:a6b8881eae87 28 void AMS_CCS811::i2c_interface(I2C * i2c) {
UHSLMarcus 4:a6b8881eae87 29 _i2c = i2c;
UHSLMarcus 4:a6b8881eae87 30 }
UHSLMarcus 4:a6b8881eae87 31
UHSLMarcus 4:a6b8881eae87 32 void AMS_CCS811::ens210_i2c_interface(I2C * i2c) {
UHSLMarcus 4:a6b8881eae87 33 _ens210_i2c = i2c;
UHSLMarcus 4:a6b8881eae87 34 }
UHSLMarcus 4:a6b8881eae87 35
UHSLMarcus 4:a6b8881eae87 36 bool AMS_CCS811::enable_ens210(bool enable) {
UHSLMarcus 4:a6b8881eae87 37
UHSLMarcus 4:a6b8881eae87 38 _ens210_enabled = false;
UHSLMarcus 4:a6b8881eae87 39 if (_ens210_i2c != NULL) _ens210_enabled = enable;
UHSLMarcus 4:a6b8881eae87 40 update_ens210_timer();
UHSLMarcus 4:a6b8881eae87 41
UHSLMarcus 4:a6b8881eae87 42 return _ens210_enabled;
UHSLMarcus 4:a6b8881eae87 43 }
UHSLMarcus 4:a6b8881eae87 44
UHSLMarcus 4:a6b8881eae87 45 bool AMS_CCS811::ens210_is_enabled() {
UHSLMarcus 4:a6b8881eae87 46 return _ens210_enabled;
UHSLMarcus 4:a6b8881eae87 47 }
UHSLMarcus 4:a6b8881eae87 48
UHSLMarcus 4:a6b8881eae87 49 void AMS_CCS811::ens210_poll_interval(int poll_ms) {
UHSLMarcus 4:a6b8881eae87 50 _ens210_poll_split = poll_ms;
UHSLMarcus 4:a6b8881eae87 51 update_ens210_timer();
UHSLMarcus 4:a6b8881eae87 52 }
UHSLMarcus 4:a6b8881eae87 53
UHSLMarcus 4:a6b8881eae87 54 int AMS_CCS811::ens210_poll_interval() {
UHSLMarcus 4:a6b8881eae87 55 return _ens210_poll_split;
UHSLMarcus 1:acfca1d3256d 56 }
UHSLMarcus 1:acfca1d3256d 57
UHSLMarcus 1:acfca1d3256d 58 bool AMS_CCS811::mode(OP_MODES mode) {
UHSLMarcus 1:acfca1d3256d 59 OP_MODES old = _mode; // incase the write fails, to roll back
UHSLMarcus 1:acfca1d3256d 60 _mode = mode;
UHSLMarcus 1:acfca1d3256d 61
UHSLMarcus 1:acfca1d3256d 62 bool success = write_config();
UHSLMarcus 1:acfca1d3256d 63 if (!success)
UHSLMarcus 1:acfca1d3256d 64 _mode = old;
UHSLMarcus 1:acfca1d3256d 65
UHSLMarcus 1:acfca1d3256d 66 return success;
UHSLMarcus 1:acfca1d3256d 67 }
UHSLMarcus 1:acfca1d3256d 68
UHSLMarcus 1:acfca1d3256d 69 AMS_CCS811::OP_MODES AMS_CCS811::mode() {
UHSLMarcus 1:acfca1d3256d 70 OP_MODES result = _mode; // rather not rely on this, but just incase the read fails
UHSLMarcus 1:acfca1d3256d 71
UHSLMarcus 1:acfca1d3256d 72 read_config_result read_result = read_config();
UHSLMarcus 1:acfca1d3256d 73 if (read_result.success) {
UHSLMarcus 1:acfca1d3256d 74 int mode = (read_result.byte >> 4) & 0b111;
UHSLMarcus 2:e394671ef5f6 75 result = mode > 4 ? INVALID : (OP_MODES)mode;
UHSLMarcus 1:acfca1d3256d 76 } // todo ... add a new "last error" here
UHSLMarcus 1:acfca1d3256d 77
UHSLMarcus 2:e394671ef5f6 78 return result;
UHSLMarcus 1:acfca1d3256d 79 }
UHSLMarcus 1:acfca1d3256d 80
UHSLMarcus 1:acfca1d3256d 81 bool AMS_CCS811::addr_mode(bool high) {
UHSLMarcus 1:acfca1d3256d 82 _addr_dir = high;
UHSLMarcus 1:acfca1d3256d 83 if (_addr_out != NULL) *_addr_out = _addr_dir;
UHSLMarcus 1:acfca1d3256d 84
UHSLMarcus 2:e394671ef5f6 85 update_slave_addr();
UHSLMarcus 2:e394671ef5f6 86
UHSLMarcus 1:acfca1d3256d 87 return addr_mode() == high;
UHSLMarcus 1:acfca1d3256d 88 }
UHSLMarcus 1:acfca1d3256d 89
UHSLMarcus 1:acfca1d3256d 90 bool AMS_CCS811::addr_mode() {
UHSLMarcus 1:acfca1d3256d 91 if (_addr_out != NULL) {
UHSLMarcus 1:acfca1d3256d 92 _addr_dir = *_addr_out;
UHSLMarcus 1:acfca1d3256d 93 }
UHSLMarcus 1:acfca1d3256d 94
UHSLMarcus 1:acfca1d3256d 95 return _addr_dir;
UHSLMarcus 1:acfca1d3256d 96 }
UHSLMarcus 1:acfca1d3256d 97
UHSLMarcus 1:acfca1d3256d 98 bool AMS_CCS811::addr_pin(PinName pin) {
UHSLMarcus 1:acfca1d3256d 99 _addr_out = _addr_out == NULL ? new (std::nothrow) DigitalOut(pin) : new (_addr_out) DigitalOut(pin);
UHSLMarcus 1:acfca1d3256d 100 addr_mode(_addr_dir);
UHSLMarcus 1:acfca1d3256d 101
UHSLMarcus 1:acfca1d3256d 102 return _addr_out != NULL;
UHSLMarcus 1:acfca1d3256d 103 }
UHSLMarcus 1:acfca1d3256d 104
UHSLMarcus 1:acfca1d3256d 105 bool AMS_CCS811::n_wake_pin(PinName pin) {
UHSLMarcus 1:acfca1d3256d 106 _n_wake_out = _n_wake_out == NULL ? new (std::nothrow) DigitalOut(pin) : new (_n_wake_out) DigitalOut(pin);
UHSLMarcus 1:acfca1d3256d 107 return _n_wake_out != NULL;
UHSLMarcus 1:acfca1d3256d 108 }
UHSLMarcus 1:acfca1d3256d 109
UHSLMarcus 2:e394671ef5f6 110 bool AMS_CCS811::env_data(float humid, float temp) {
UHSLMarcus 1:acfca1d3256d 111 return true;
UHSLMarcus 1:acfca1d3256d 112 }
UHSLMarcus 1:acfca1d3256d 113
UHSLMarcus 1:acfca1d3256d 114
UHSLMarcus 1:acfca1d3256d 115 AMS_CCS811::DATA_STATUS AMS_CCS811::has_new_data() {
UHSLMarcus 1:acfca1d3256d 116 return (DATA_STATUS) 0;
UHSLMarcus 1:acfca1d3256d 117 }
UHSLMarcus 1:acfca1d3256d 118
UHSLMarcus 1:acfca1d3256d 119 uint16_t AMS_CCS811::co2_read() {
UHSLMarcus 1:acfca1d3256d 120 return 0;
UHSLMarcus 2:e394671ef5f6 121 }
UHSLMarcus 1:acfca1d3256d 122
UHSLMarcus 1:acfca1d3256d 123 uint16_t AMS_CCS811::tvoc_read() {
UHSLMarcus 1:acfca1d3256d 124 return 0;
UHSLMarcus 1:acfca1d3256d 125 }
UHSLMarcus 1:acfca1d3256d 126
UHSLMarcus 1:acfca1d3256d 127 uint16_t AMS_CCS811::raw_read() {
UHSLMarcus 1:acfca1d3256d 128 return 0;
UHSLMarcus 1:acfca1d3256d 129 }
UHSLMarcus 1:acfca1d3256d 130
UHSLMarcus 1:acfca1d3256d 131 const char * AMS_CCS811::last_error() {
UHSLMarcus 4:a6b8881eae87 132 return "TODO";
UHSLMarcus 1:acfca1d3256d 133 }
UHSLMarcus 1:acfca1d3256d 134
UHSLMarcus 1:acfca1d3256d 135 bool AMS_CCS811::enable_interupt(bool enable) {
UHSLMarcus 1:acfca1d3256d 136 bool old = _int_data_enabled; // incase the write fails, to roll back
UHSLMarcus 1:acfca1d3256d 137 _int_data_enabled = enable;
UHSLMarcus 1:acfca1d3256d 138
UHSLMarcus 1:acfca1d3256d 139 bool success = write_config();
UHSLMarcus 1:acfca1d3256d 140 if (!success)
UHSLMarcus 1:acfca1d3256d 141 _int_data_enabled = old;
UHSLMarcus 1:acfca1d3256d 142
UHSLMarcus 1:acfca1d3256d 143 return success;
UHSLMarcus 1:acfca1d3256d 144
UHSLMarcus 1:acfca1d3256d 145 }
UHSLMarcus 1:acfca1d3256d 146
UHSLMarcus 1:acfca1d3256d 147 bool AMS_CCS811::interupt_enabled() {
UHSLMarcus 1:acfca1d3256d 148 bool enabled = _int_data_enabled; // rather not rely on this, but just incase the read fails
UHSLMarcus 1:acfca1d3256d 149
UHSLMarcus 1:acfca1d3256d 150 read_config_result read_result = read_config();
UHSLMarcus 1:acfca1d3256d 151 if (read_result.success) {
UHSLMarcus 1:acfca1d3256d 152 enabled = (read_result.byte >> 3) & 1;
UHSLMarcus 1:acfca1d3256d 153 } // todo ... add a new "last error" here? or maybe the read method itself should set that.
UHSLMarcus 1:acfca1d3256d 154
UHSLMarcus 2:e394671ef5f6 155 return enabled;
UHSLMarcus 1:acfca1d3256d 156 }
UHSLMarcus 1:acfca1d3256d 157
UHSLMarcus 1:acfca1d3256d 158 bool AMS_CCS811::interrupt_pin(PinName pin) {
UHSLMarcus 1:acfca1d3256d 159 bool success = false;
UHSLMarcus 1:acfca1d3256d 160
UHSLMarcus 2:e394671ef5f6 161 _int_data = _int_data == NULL ? new (std::nothrow) InterruptIn(pin) : new (_int_data) InterruptIn(pin);
UHSLMarcus 1:acfca1d3256d 162 if (_int_data != NULL) {
UHSLMarcus 2:e394671ef5f6 163 _int_data->fall(callback(this, &AMS_CCS811::_isr_data));
UHSLMarcus 1:acfca1d3256d 164 success = true;
UHSLMarcus 1:acfca1d3256d 165 }
UHSLMarcus 1:acfca1d3256d 166
UHSLMarcus 1:acfca1d3256d 167 return success;
UHSLMarcus 1:acfca1d3256d 168 }
UHSLMarcus 0:5edbf3550350 169
UHSLMarcus 0:5edbf3550350 170
UHSLMarcus 0:5edbf3550350 171
UHSLMarcus 1:acfca1d3256d 172
UHSLMarcus 1:acfca1d3256d 173 /** Private **/
UHSLMarcus 1:acfca1d3256d 174
UHSLMarcus 1:acfca1d3256d 175 bool AMS_CCS811::set_defaults() {
UHSLMarcus 1:acfca1d3256d 176 if (_mode == NULL)
UHSLMarcus 1:acfca1d3256d 177 _mode = CONFIG_OP_MODE;
UHSLMarcus 1:acfca1d3256d 178 if (_addr_dir == NULL)
UHSLMarcus 1:acfca1d3256d 179 _addr_dir = CONFIG_ADDR_DIR;
UHSLMarcus 1:acfca1d3256d 180 if (_int_data_enabled == NULL)
UHSLMarcus 1:acfca1d3256d 181 _int_data_enabled = CONFIG_INTR;
UHSLMarcus 2:e394671ef5f6 182 if (_ens210_poll_split == NULL)
UHSLMarcus 2:e394671ef5f6 183 _ens210_poll_split = CONFIG_ENS210_POLL;
UHSLMarcus 2:e394671ef5f6 184
UHSLMarcus 2:e394671ef5f6 185 update_slave_addr();
UHSLMarcus 1:acfca1d3256d 186
UHSLMarcus 1:acfca1d3256d 187 return write_config();
UHSLMarcus 1:acfca1d3256d 188 }
UHSLMarcus 2:e394671ef5f6 189
UHSLMarcus 4:a6b8881eae87 190 void AMS_CCS811::update_ens210_timer() {
UHSLMarcus 4:a6b8881eae87 191 _ens210_poll_t.detach();
UHSLMarcus 4:a6b8881eae87 192 if (_ens210_enabled)
UHSLMarcus 4:a6b8881eae87 193 _ens210_poll_t.attach_us(callback(this, &AMS_CCS811::ens210_isr), _ens210_poll_split*1000);
UHSLMarcus 4:a6b8881eae87 194 }
UHSLMarcus 4:a6b8881eae87 195
UHSLMarcus 4:a6b8881eae87 196 void AMS_CCS811::ens210_isr() {
UHSLMarcus 4:a6b8881eae87 197 }
UHSLMarcus 4:a6b8881eae87 198
UHSLMarcus 3:782a719f47a5 199 void AMS_CCS811::update_slave_addr() {
UHSLMarcus 2:e394671ef5f6 200 slave_addr = addr_mode() ? SLAVE_ADDR_RAW_H : SLAVE_ADDR_RAW_L;
UHSLMarcus 2:e394671ef5f6 201 }
UHSLMarcus 1:acfca1d3256d 202
UHSLMarcus 1:acfca1d3256d 203 void AMS_CCS811::_isr_data() {
UHSLMarcus 3:782a719f47a5 204 _isr_data_fp.call();
UHSLMarcus 1:acfca1d3256d 205 }
UHSLMarcus 1:acfca1d3256d 206
UHSLMarcus 1:acfca1d3256d 207 bool AMS_CCS811::write_config() {
UHSLMarcus 3:782a719f47a5 208 char cmd[1] = {0 | (_int_data_enabled << 3) | (_mode << 4)};
UHSLMarcus 2:e394671ef5f6 209 return i2c_write(SYS_MODE, cmd, 1) == 1;
UHSLMarcus 1:acfca1d3256d 210 }
UHSLMarcus 1:acfca1d3256d 211
UHSLMarcus 3:782a719f47a5 212 AMS_CCS811::read_config_result AMS_CCS811::read_config() {
UHSLMarcus 2:e394671ef5f6 213 read_config_result result;
UHSLMarcus 2:e394671ef5f6 214 char byte[1];
UHSLMarcus 2:e394671ef5f6 215 if (i2c_read(SYS_MODE, byte, 1) == 1) {
UHSLMarcus 2:e394671ef5f6 216 result.success = true;
UHSLMarcus 2:e394671ef5f6 217 result.byte = byte[1];
UHSLMarcus 2:e394671ef5f6 218 }
UHSLMarcus 2:e394671ef5f6 219
UHSLMarcus 2:e394671ef5f6 220 return result;
UHSLMarcus 2:e394671ef5f6 221 }
UHSLMarcus 2:e394671ef5f6 222
UHSLMarcus 2:e394671ef5f6 223 int AMS_CCS811::i2c_read(char reg_addr, char* output, int len) {
UHSLMarcus 2:e394671ef5f6 224
UHSLMarcus 2:e394671ef5f6 225 int read_count = 0;
UHSLMarcus 2:e394671ef5f6 226 if (_n_wake_out != NULL) { // check nWAKE pin is set
UHSLMarcus 2:e394671ef5f6 227 if (_i2c != NULL) { // check I2C interface is set
UHSLMarcus 2:e394671ef5f6 228 _i2c->start(); // send start condition for write
UHSLMarcus 2:e394671ef5f6 229 if(_i2c->write(SLAVE_ADDR_W) == 1) { // write slave address with write bit
UHSLMarcus 2:e394671ef5f6 230 if(_i2c->write(reg_addr) == 1) { // write register address
UHSLMarcus 2:e394671ef5f6 231 _i2c->start(); // send another start condition for read
UHSLMarcus 2:e394671ef5f6 232 if(_i2c->write(SLAVE_ADDR_R) == 1) { // write slave address with read bit
UHSLMarcus 2:e394671ef5f6 233 for (int i = 0; i < len; i++) { // read len bytes
UHSLMarcus 2:e394671ef5f6 234 output[i] = _i2c->read(i < len-1 ? 1 : 0); // ack all reads aside from the final one (i == len-1)
UHSLMarcus 2:e394671ef5f6 235 read_count++;
UHSLMarcus 2:e394671ef5f6 236 }
UHSLMarcus 2:e394671ef5f6 237 }
UHSLMarcus 2:e394671ef5f6 238 }
UHSLMarcus 2:e394671ef5f6 239 }
UHSLMarcus 2:e394671ef5f6 240 _i2c->stop(); // send stop condition
UHSLMarcus 2:e394671ef5f6 241 }
UHSLMarcus 2:e394671ef5f6 242 }
UHSLMarcus 2:e394671ef5f6 243
UHSLMarcus 2:e394671ef5f6 244 return read_count;
UHSLMarcus 2:e394671ef5f6 245 }
UHSLMarcus 2:e394671ef5f6 246
UHSLMarcus 2:e394671ef5f6 247 int AMS_CCS811::i2c_write(char reg_addr, char* input, int len) { // to do... error reporting
UHSLMarcus 2:e394671ef5f6 248
UHSLMarcus 2:e394671ef5f6 249 int write_count = 0;
UHSLMarcus 2:e394671ef5f6 250 if (_n_wake_out != NULL) { // check nWAKE pin is set
UHSLMarcus 2:e394671ef5f6 251 if (_i2c != NULL) { // check I2C interface is set
UHSLMarcus 2:e394671ef5f6 252 _i2c->start(); // send start condition for write
UHSLMarcus 2:e394671ef5f6 253 if(_i2c->write(SLAVE_ADDR_W) == 1) { // write slave address
UHSLMarcus 2:e394671ef5f6 254 if(_i2c->write(reg_addr) == 1) { // write register address
UHSLMarcus 2:e394671ef5f6 255 for (int i = 0; i < len; i++) { // write len bytes
UHSLMarcus 2:e394671ef5f6 256 if(_i2c->write(input[i]) == 1) write_count++; // write each byte, if successful increment count
UHSLMarcus 2:e394671ef5f6 257 }
UHSLMarcus 2:e394671ef5f6 258 }
UHSLMarcus 2:e394671ef5f6 259 }
UHSLMarcus 2:e394671ef5f6 260 _i2c->stop(); // send stop condition
UHSLMarcus 2:e394671ef5f6 261 }
UHSLMarcus 2:e394671ef5f6 262 }
UHSLMarcus 2:e394671ef5f6 263
UHSLMarcus 2:e394671ef5f6 264 return write_count;
UHSLMarcus 1:acfca1d3256d 265 }