Port from Adafruit's SGP30 arduino lib(https://github.com/adafruit/Adafruit_SGP30) to use Mbed api

Dependents:   AMU_Polytech_Marseille_STM32InTheSky_01_05_2019 Sensor_SGP30 Sensor_iAQ_sgp30_bme_si7051 POCBreath_V2_smd_commercial

Revision:
0:41a622cdd86d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Adafruit_SGP30.cpp	Mon Jul 23 09:51:43 2018 +0000
@@ -0,0 +1,258 @@
+/*!
+ * @file Adafruit_SGP30.cpp
+ *
+ * @mainpage Adafruit SGP30 gas sensor driver
+ *
+ * @section intro_sec Introduction
+ *
+ * This is the documentation for Adafruit's SGP30 driver for the
+ * Arduino platform.  It is designed specifically to work with the
+ * Adafruit SGP30 breakout: http://www.adafruit.com/products/3709
+ *
+ * These sensors use I2C to communicate, 2 pins (SCL+SDA) are required
+ * to interface with the breakout.
+ *
+ * Adafruit invests time and resources providing this open source code,
+ * please support Adafruit and open-source hardware by purchasing
+ * products from Adafruit!
+ *
+ *
+ * @section author Author
+ * Written by Ladyada for Adafruit Industries.
+ *
+ * @section license License
+ * BSD license, all text here must be included in any redistribution.
+ *
+ */
+
+#include "mbed.h"
+#include "Adafruit_SGP30.h"
+
+//#define I2C_DEBUG
+
+/**************************************************************************/
+/*! 
+    @brief  Instantiates a new SGP30 class
+*/
+/**************************************************************************/
+Adafruit_SGP30::Adafruit_SGP30(PinName sda, PinName scl) : _i2c(sda, scl) {
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Setups the hardware and detects a valid SGP30. Initializes I2C
+    then reads the serialnumber and checks that we are talking to an SGP30
+    @param  theWire Optional pointer to I2C interface, otherwise use Wire
+    @returns True if SGP30 found on I2C, False if something went wrong!
+*/
+/**************************************************************************/
+bool Adafruit_SGP30::begin() {
+  //Mbed use 8bit addr
+  _i2caddr = SGP30_I2CADDR_DEFAULT << 1;
+  
+  uint8_t command[3];
+  command[0] = 0x36;
+  command[1] = 0x82;
+  command[2] = 0x0;
+  if (! readWordFromCommand(command, 2, 5, serialnumber, 3))
+    return false;
+
+  uint16_t featureset;
+  command[0] = 0x20;
+  command[1] = 0x2F;
+  if (! readWordFromCommand(command, 2, 10, &featureset, 1)) 
+    return false;
+  //Serial.print("Featureset 0x"); Serial.println(featureset, HEX);
+  if (featureset != SGP30_FEATURESET) 
+    return false;
+  if (! IAQinit()) 
+    return false;
+
+  return true;
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Commands the sensor to begin the IAQ algorithm. Must be called after startup.
+    @returns True if command completed successfully, false if something went wrong!
+*/
+/**************************************************************************/
+bool Adafruit_SGP30::IAQinit(void) {
+  uint8_t command[2];
+  command[0] = 0x20;
+  command[1] = 0x03;
+  return readWordFromCommand(command, 2, 10);
+}
+
+/**************************************************************************/
+/*! 
+    @brief  Commands the sensor to take a single eCO2/VOC measurement. Places results in {@link TVOC} and {@link eCO2}
+    @returns True if command completed successfully, false if something went wrong!
+*/
+/**************************************************************************/
+bool Adafruit_SGP30::IAQmeasure(void) {
+  uint8_t command[2];
+  command[0] = 0x20;
+  command[1] = 0x08;
+  uint16_t reply[2];
+  if (! readWordFromCommand(command, 2, 12, reply, 2))
+    return false;
+  TVOC = reply[1];
+  eCO2 = reply[0];
+  return true;
+}
+ 
+/**************************************************************************/
+/*! 
+    @brief Request baseline calibration values for both CO2 and TVOC IAQ calculations. Places results in parameter memory locaitons.
+    @param eco2_base A pointer to a uint16_t which we will save the calibration value to
+    @param tvoc_base A pointer to a uint16_t which we will save the calibration value to
+    @returns True if command completed successfully, false if something went wrong!
+*/
+/**************************************************************************/
+bool Adafruit_SGP30::getIAQBaseline(uint16_t *eco2_base, uint16_t *tvoc_base) {
+  uint8_t command[2];
+  command[0] = 0x20;
+  command[1] = 0x15;
+  uint16_t reply[2];
+  if (! readWordFromCommand(command, 2, 10, reply, 2))
+    return false;
+  *eco2_base = reply[0];
+  *tvoc_base = reply[1];
+  return true;
+}
+
+bool Adafruit_SGP30::getIAQRaw(uint16_t *H2_raw, uint16_t *Eth_raw) {
+  uint8_t command[2];
+  command[0] = 0x20;
+  command[1] = 0x50;
+  uint16_t reply[2];
+  if (! readWordFromCommand(command, 2, 40, reply, 2))
+    return false;
+  *H2_raw = reply[0];
+  *Eth_raw = reply[1];
+  return true;
+}
+
+/**************************************************************************/
+/*! 
+    @brief Assign baseline calibration values for both CO2 and TVOC IAQ calculations.
+    @param eco2_base A uint16_t which we will save the calibration value from
+    @param tvoc_base A uint16_t which we will save the calibration value from
+    @returns True if command completed successfully, false if something went wrong!
+*/
+/**************************************************************************/
+bool Adafruit_SGP30::setIAQBaseline(uint16_t eco2_base, uint16_t tvoc_base) {
+  uint8_t command[8];
+  command[0] = 0x20;
+  command[1] = 0x1e;
+  command[2] = tvoc_base >> 8;
+  command[3] = tvoc_base & 0xFF;
+  command[4] = generateCRC(command+2, 2);
+  command[5] = eco2_base >> 8;
+  command[6] = eco2_base & 0xFF;
+  command[7] = generateCRC(command+5, 2);
+
+  return readWordFromCommand(command, 8, 10);
+}
+
+/**************************************************************************/
+/*! 
+    @brief  I2C low level interfacing
+*/
+/**************************************************************************/
+
+
+bool Adafruit_SGP30::readWordFromCommand(uint8_t command[], uint8_t commandLength, uint16_t delayms, uint16_t *readdata, uint8_t readlen)
+{
+  uint8_t retval;
+  
+
+#ifdef I2C_DEBUG
+  printf("\t\t-> ");
+#endif
+
+    retval = _i2c.write((int)_i2caddr, (const char*)command, (int)commandLength);
+    //0=OK, 1=Fail https://os.mbed.com/docs/v5.9/reference/i2c.html
+    if ( retval != 0) 
+        return false;
+  
+#ifdef I2C_DEBUG
+    for (uint8_t i=0; i<commandLength; i++) {
+        printf("0x");
+        printf("%x", command[i]);
+        printf(", ");
+    }
+#endif
+
+#ifdef I2C_DEBUG
+  printf("\n");
+#endif
+
+  wait_ms(delayms);
+  
+  
+
+  if (readlen == 0) 
+    return true;
+
+  uint8_t replylen = readlen * (SGP30_WORD_LEN +1);
+  uint8_t replybuffer[replylen];
+  
+  retval = _i2c.read((int)_i2caddr, (char*)replybuffer, (int)replylen);
+    
+    //0=OK, 1=Fail https://os.mbed.com/docs/v5.9/reference/i2c.html
+  if ( retval != 0) 
+    return false;
+  
+#ifdef I2C_DEBUG
+    printf("\t\t<- ");
+    for (uint8_t i=0; i<replylen; i++) {
+        printf("0x");
+        printf("%x", replybuffer[i]);
+        printf(", ");
+    }
+#endif
+
+
+#ifdef I2C_DEBUG
+  printf("\n");
+#endif
+
+  for (uint8_t i=0; i<readlen; i++) {
+    uint8_t crc = generateCRC(replybuffer+i*3, 2);
+#ifdef I2C_DEBUG
+    printf("\t\tCRC calced: 0x");
+    printf("%x", crc);
+    printf(" vs. 0x");
+    printf("%x\n" ,replybuffer[i * 3 + 2];
+#endif
+    if (crc != replybuffer[i * 3 + 2])
+      return false;
+    // success! store it
+    readdata[i] = replybuffer[i*3];
+    readdata[i] <<= 8;
+    readdata[i] |= replybuffer[i*3 + 1];
+#ifdef I2C_DEBUG
+    printf("\t\tRead: 0x");
+    printf("%x\n", readdata[i]);
+#endif
+  }
+  return true;
+}
+
+uint8_t Adafruit_SGP30::generateCRC(uint8_t *data, uint8_t datalen) {
+  // calculates 8-Bit checksum with given polynomial
+  uint8_t crc = SGP30_CRC8_INIT;
+
+  for (uint8_t i=0; i<datalen; i++) {
+    crc ^= data[i];
+    for (uint8_t b=0; b<8; b++) {
+      if (crc & 0x80)
+    crc = (crc << 1) ^ SGP30_CRC8_POLYNOMIAL;
+      else
+    crc <<= 1;
+    }
+  }
+  return crc;
+}