Program Listing for File pas-co2-ino.cpp

Return to documentation for file (src/pas-co2-ino.cpp)

#include "pas-co2-ino.hpp"

#define INO_ASSERT_RET(x)   if( x != XENSIV_PASCO2_OK ) { return x; }

#define PAS_CO2_SERIAL_PAL_INIT_EXTERNAL

PASCO2Ino::PASCO2Ino(TwoWire * wire,
                                 uint8_t   intPin)
: i2c(wire), uart(nullptr), intPin(intPin)
{

}

PASCO2Ino::PASCO2Ino(HardwareSerial * serial,
                                 uint8_t          intPin)
: i2c(nullptr), uart(serial), intPin(intPin)
{

}

PASCO2Ino::~PASCO2Ino()
{

}

Error_t PASCO2Ino::begin()
{
    int32_t ret = XENSIV_PASCO2_OK;
    xensiv_pasco2_measurement_config_t  measConf;

    /* Initialize sensor interface */
    if(nullptr != i2c)
    {
        #ifndef PAS_CO2_SERIAL_PAL_INIT_EXTERNAL
        i2c->begin();
        i2c->setClock(freqHz);
        #endif
        ret = xensiv_pasco2_init_i2c(&dev, i2c);
    }
    else if(nullptr != uart)
    {
        #ifndef PAS_CO2_SERIAL_PAL_INIT_EXTERNAL
        uart->begin(baudrateBps);
        #endif
        ret = xensiv_pasco2_init_uart(&dev, uart);
    }

    /* Initialize int_pin */
    if( unusedPin != intPin)
    {
        pinMode(intPin, INPUT_PULLUP);
    }

    ret = xensiv_pasco2_get_measurement_config(&dev, &measConf);
    INO_ASSERT_RET(ret);

    measConf.b.op_mode = XENSIV_PASCO2_OP_MODE_IDLE;

    ret = xensiv_pasco2_set_measurement_config(&dev, measConf);

    return ret;
}

Error_t PASCO2Ino::end()
{
    if(nullptr != i2c)
    {
        #ifndef PAS_CO2_SERIAL_PAL_INIT_EXTERNAL
        #if !defined(ARDUINO_ARCH_ESP32)
        i2c->end();
        #endif
        #endif
    }
    else if(nullptr != uart)
    {
        #ifndef PAS_CO2_SERIAL_PAL_INIT_EXTERNAL
        uart->end();
        #endif
    }

    /* Deinitialize interrupt pin */
    if(unusedPin != intPin)
    {
        detachInterrupt(digitalPinToInterrupt(intPin));
    }

    return XENSIV_PASCO2_OK;
}

Error_t PASCO2Ino::startMeasure(int16_t periodInSec, int16_t alarmTh, void (*cback) (void *), bool earlyNotification)
{
    xensiv_pasco2_measurement_config_t  measConf;
    xensiv_pasco2_interrupt_config_t intConf;
    int32_t ret = XENSIV_PASCO2_OK;

    /* Get meas configuration*/
    ret = xensiv_pasco2_get_measurement_config(&dev, &measConf);
    INO_ASSERT_RET(ret);

    measConf.b.op_mode = XENSIV_PASCO2_OP_MODE_IDLE;

    ret = xensiv_pasco2_set_measurement_config(&dev, measConf);
    INO_ASSERT_RET(ret);

    /* Get int configuration */
    ret = xensiv_pasco2_get_interrupt_config(&dev, &intConf);
    INO_ASSERT_RET(ret);

    /* Default configuration */
    measConf.b.op_mode = XENSIV_PASCO2_OP_MODE_SINGLE;
    intConf.b.int_func = XENSIV_PASCO2_INTERRUPT_FUNCTION_DRDY;


    if( periodInSec > 0 )
    {
        ret = xensiv_pasco2_set_measurement_rate(&dev, periodInSec);
        INO_ASSERT_RET(ret);

        measConf.b.op_mode = XENSIV_PASCO2_OP_MODE_CONTINUOUS;
    }

    if( alarmTh >  0 )
    {
        ret = xensiv_pasco2_set_alarm_threshold(&dev, alarmTh);
        INO_ASSERT_RET(ret);

        intConf.b.alarm_typ = XENSIV_PASCO2_ALARM_TYPE_LOW_TO_HIGH;
        intConf.b.int_func  = XENSIV_PASCO2_INTERRUPT_FUNCTION_ALARM;
    }
    else
    {
        ret = xensiv_pasco2_set_alarm_threshold(&dev, 0x0000);
        INO_ASSERT_RET(ret);

        intConf.b.alarm_typ = XENSIV_PASCO2_ALARM_TYPE_HIGH_TO_LOW;
    }

    if(cback != nullptr)
    {
        /* Enable sensor interrupt */
        intConf.b.int_typ = XENSIV_PASCO2_INTERRUPT_TYPE_HIGH_ACTIVE;
        #ifdef ARDUINO_ARCH_SAMD
            PinStatus int_event;
        #else
            uint8_t int_event;
        #endif
        int_event = RISING;

        if(true == earlyNotification)
        {
           /* In this case it would be useful to have an interrupt
              for both the rising and falling edge. */
            int_event = CHANGE;
        }

        /* Enable mcu interupt */
        attachInterrupt(digitalPinToInterrupt(intPin), (void (*)())cback, int_event);
    }
    else
    {
        /* Disable sensor interrupt */
        intConf.b.int_func = XENSIV_PASCO2_INTERRUPT_FUNCTION_NONE;

        if(unusedPin != intPin)
        {
            /* Disable mcu interrupt */
            detachInterrupt(digitalPinToInterrupt(intPin));
        }
    }

    /* This option will disable the alarm interrupt function */
    if(true == earlyNotification)
    {
        intConf.b.int_func = XENSIV_PASCO2_INTERRUPT_FUNCTION_EARLY;
    }

    ret = xensiv_pasco2_set_interrupt_config(&dev, intConf);
    INO_ASSERT_RET(ret);

    ret = xensiv_pasco2_set_measurement_config(&dev, measConf);

    return ret;
}

Error_t PASCO2Ino::stopMeasure()
{
    int32_t ret = XENSIV_PASCO2_OK;

    xensiv_pasco2_measurement_config_t  measConf;

    /* Get meas configuration*/
    ret = xensiv_pasco2_get_measurement_config(&dev, &measConf);
    INO_ASSERT_RET(ret);

    /* Set meas configuration to idle mode */
    measConf.b.op_mode = XENSIV_PASCO2_OP_MODE_IDLE;
    ret = xensiv_pasco2_set_measurement_config(&dev, measConf);

    return ret;
}

Error_t PASCO2Ino::getCO2(int16_t & CO2PPM)
{
    int32_t ret = XENSIV_PASCO2_OK;

    /* Initially set to 0.*/
    CO2PPM = 0;

    /* Read the data */
    ret = xensiv_pasco2_get_result(&dev, (uint16_t*)&CO2PPM);
    INO_ASSERT_RET(ret);

    /* Clear masks from status register */
    ret = xensiv_pasco2_clear_measurement_status(&dev,(XENSIV_PASCO2_REG_MEAS_STS_INT_STS_CLR_MSK | XENSIV_PASCO2_REG_MEAS_STS_ALARM_CLR_MSK));
    INO_ASSERT_RET(ret);

    return ret;
}

Error_t PASCO2Ino::getDiagnosis(Diag_t & diagnosis)
{
    int32_t ret = XENSIV_PASCO2_OK;

    /* Get current status */
    ret = xensiv_pasco2_get_status(&dev, &diagnosis);
    INO_ASSERT_RET(ret);

    /* Clear read flags */
    ret = xensiv_pasco2_clear_status(&dev, (XENSIV_PASCO2_REG_SENS_STS_ICCER_CLR_MSK |
                                            XENSIV_PASCO2_REG_SENS_STS_ORVS_CLR_MSK  |
                                            XENSIV_PASCO2_REG_SENS_STS_ORTMP_CLR_MSK ));

    return ret;
}

Error_t PASCO2Ino::setABOC(ABOC_t aboc, int16_t abocRef)
{
    xensiv_pasco2_measurement_config_t  measConf;
    int32_t ret = XENSIV_PASCO2_OK;

    /* Get meas configuration */
    ret = xensiv_pasco2_get_measurement_config(&dev, &measConf);
    INO_ASSERT_RET(ret);

    /* Set compensation offset */
    ret = xensiv_pasco2_set_offset_compensation(&dev, (uint16_t) abocRef);
    INO_ASSERT_RET(ret);

    /* Set meas configuration with ABOC */
    measConf.b.boc_cfg = aboc;
    ret = xensiv_pasco2_set_measurement_config(&dev, measConf);

    return ret;
}

Error_t PASCO2Ino::performForcedCompensation(uint16_t co2Ref)
{
    return xensiv_pasco2_perform_forced_compensation(&dev, co2Ref);
}

Error_t PASCO2Ino::clearForcedCompensation()
{
    return xensiv_pasco2_cmd(&dev, XENSIV_PASCO2_CMD_RESET_FCS);
}

Error_t PASCO2Ino::setPressRef(uint16_t pressRef)
{
    int32_t ret = XENSIV_PASCO2_OK;

    ret = xensiv_pasco2_set_pressure_compensation(&dev, pressRef);

    return ret;
}

Error_t PASCO2Ino::reset()
{
    int32_t ret = XENSIV_PASCO2_OK;

    ret = xensiv_pasco2_cmd(&dev, XENSIV_PASCO2_CMD_SOFT_RESET);
    INO_ASSERT_RET(ret);

    return ret;
}

Error_t PASCO2Ino::getDeviceID(uint8_t & prodID, uint8_t & revID)
{
    int32_t ret = XENSIV_PASCO2_OK;
    xensiv_pasco2_id_t id;

    ret = xensiv_pasco2_get_id(&dev, &id);
    INO_ASSERT_RET(ret);

    prodID = id.b.prod;
    revID =  id.b.rev;

    return ret;
}

Error_t PASCO2Ino::getRegister(uint8_t regAddr, uint8_t * data, uint8_t len)
{
    return xensiv_pasco2_get_reg(&dev, regAddr, data, len);
}

Error_t PASCO2Ino::setRegister(uint8_t regAddr, const uint8_t * data, uint8_t len)
{
    return xensiv_pasco2_set_reg(&dev, regAddr, data, len);
}