/*
 * THIS FILE IS AUTOMATICALLY GENERATED
 *
 * Generator:     sensirion-driver-generator 0.36.0
 * Product:       sgp43
 * Model-Version: 2.1.0
 */
/*
 * Copyright (c) 2023, Sensirion AG
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * * Redistributions of source code must retain the above copyright notice, this
 *   list of conditions and the following disclaimer.
 *
 * * Redistributions in binary form must reproduce the above copyright notice,
 *   this list of conditions and the following disclaimer in the documentation
 *   and/or other materials provided with the distribution.
 *
 * * Neither the name of Sensirion AG nor the names of its
 *   contributors may be used to endorse or promote products derived from
 *   this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef SENSIRIONI2CSGP43_H
#define SENSIRIONI2CSGP43_H

#include <SensirionCore.h>
#include <Wire.h>

#define NO_ERROR 0
#define SGP43_I2C_ADDR_59 0x59

typedef enum {
    EXECUTE_CONDITIONING_CMD_ID = 0x2612,
    MEASURE_SET_MULTIPIXEL_TICKS_CMD_ID = 0x263e,
    MEASURE_RAW_SIGNALS_CMD_ID = 0x2619,
    EXECUTE_SELF_TEST_CMD_ID = 0x280e,
    TURN_HEATER_OFF_CMD_ID = 0x3615,
    GET_SERIAL_NUMBER_CMD_ID = 0x3682,
} CmdId;

class SensirionI2cSgp43 {
  public:
    SensirionI2cSgp43();
    /**
     * @brief Initializes the SGP43 class.
     *
     * @param i2cBus Arduino stream object to be used for communication.
     */
    void begin(TwoWire& i2cBus, uint8_t i2cAddress);

    /**
     * @brief Execute the measure_set_multipixel_ticks command for a specified
     * temperature.
     *
     * One temperature is applied on all pixels. Compensation of temperature and
     * relative humidity is turned off.
     *
     * @param[in] tempPixel Target temperature for the pixels.
     * @param[out] aSraw Raw measurement of one pixel
     * @param[out] aSraw1 Raw measurement of one pixel
     * @param[out] aSraw2 Raw measurement of one pixel
     * @param[out] aSraw3 Raw measurement of one pixel
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t measureSetMultipixelTemperature(uint16_t tempPixel, uint16_t& aSraw,
                                            uint16_t& aSraw1, uint16_t& aSraw2,
                                            uint16_t& aSraw3);

    /**
     * @brief executeConditioning
     *
     * This command starts the conditioning, i.e., the VOC pixel will be
     * operated at the same temperature as it is by calling the
     * sgp41_measure_raw command while the NOx pixel will be operated at a
     * different temperature for conditioning. This command returns only the
     * measured raw signal of the VOC pixel SRAW_VOC as 2 bytes (+ 1 CRC byte).
     *
     * @param[in] compensationRhTicks Compensation value for relative humidty in
     * ticks. tick = %RH * 65535 / 100
     * @param[in] compensationTTicks Compensation value for temperature in
     * ticks. tick = (temperature + 45) * 65535 / 175
     * @param[out] srawVoc u16 unsigned integer directly provides the raw signal
     * SRAW_VOC in ticks which is proportional to the logarithm of the
     * resistance of the sensing element.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t executeConditioning(uint16_t compensationRhTicks,
                                uint16_t compensationTTicks, uint16_t& srawVoc);

    /**
     * @brief SGP4x Measure-and-Set Multipixel.
     *
     * This performs a multipixel measurement and then sets the hotplate
     * temperatures.
     *
     * @param[in] relativeHumidity By setting the value of relative_humidity to
     * 0x8000 the compensation is disabled. To activate the compensation the
     * relative humidity has to be set in ticks (tick = %RH * 65535 / 100).
     * @param[in] temperature By setting the value of temperature to 0x6666 the
     * temperature compensation is disabled. To activate the compensation the
     * temperature has to be set in ticks (tick = (temperature + 45) * 65535 /
     * 175)
     * @param[in] temperaturePix1 temperature (in °C) to set on pixel 1
     * @param[in] temperaturePix2 temperature (in °C) to set on pixel 2
     * @param[in] temperaturePix3 temperature (in °C) to set on pixel 3
     * @param[in] temperaturePix4 temperature (in °C) to set on pixel 4
     * @param[in] conditionPix1 conditioning to apply on pixel 1
     * @param[in] conditionPix2 conditioning to apply on pixel 2
     * @param[in] conditionPix3 conditioning to apply on pixel 3
     * @param[in] conditionPix4 conditioning to apply on pixel 4
     * @param[out] rawSignalPix1 measured raw signal of pixel 1
     * @param[out] rawSignalPix2 measured raw signal of pixel 2
     * @param[out] rawSignalPix3 measured raw signal of pixel 3
     * @param[out] rawSignalPix4 measured raw signal of pixel 4
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t measureSetMultipixelTicks(
        uint16_t relativeHumidity, uint16_t temperature,
        uint16_t temperaturePix1, uint16_t temperaturePix2,
        uint16_t temperaturePix3, uint16_t temperaturePix4,
        uint16_t conditionPix1, uint16_t conditionPix2, uint16_t conditionPix3,
        uint16_t conditionPix4, uint16_t& rawSignalPix1,
        uint16_t& rawSignalPix2, uint16_t& rawSignalPix3,
        uint16_t& rawSignalPix4);

    /**
     * @brief measureRawSignals
     *
     * This command starts/continues the VOC+NOx measurement mode
     *
     * @param[in] relativeHumidity Leaves humidity compensation disabled by
     * sending the default value 0x8000 (50%RH) or enables humidity compensation
     * when sending the relative humidity in ticks (ticks = %RH * 65535 / 100)
     * @param[in] temperature Leaves humidity compensation disabled by sending
     * the default value 0x6666 (25 degC) or enables humidity compensation when
     * sending the temperature in ticks (ticks = (degC + 45) * 65535 / 175)
     * @param[out] srawVoc u16 unsigned integer directly provides the raw signal
     * SRAW_VOC in ticks which is proportional to the logarithm of the
     * resistance of the sensing element.
     * @param[out] srawNox u16 unsigned integer directly provides the raw signal
     * SRAW_NOX in ticks which is proportional to the logarithm of the
     * resistance of the sensing element.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t measureRawSignals(uint16_t relativeHumidity, uint16_t temperature,
                              uint16_t& srawVoc, uint16_t& srawNox);

    /**
     * @brief executeSelfTest
     *
     * This command triggers the built-in self-test checking for integrity of
     * both hotplate and MOX material and returns the result of this test as 2
     * bytes
     *
     * @param[out] testResult 0xXX 0xYY: ignore most significant byte 0xXX. The
     * four least significant bits of the least significant byte 0xYY provide
     * information if the self-test has or has not passed for each individual
     * pixel. All zero mean all tests passed successfully. Check the datasheet
     * for more detailed information.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t executeSelfTest(uint16_t& testResult);

    /**
     * @brief turnHeaterOff
     *
     * This command turns the hotplate off and stops the measurement.
     * Subsequently, the sensor enters the idle mode.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t turnHeaterOff();

    /**
     * @brief getSerialNumber
     *
     * This command provides the decimal serial number of the SGP41 chip by
     * returning 3x2 bytes.
     *
     * @param[out] serialNumber 48-bit unique serial number
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t getSerialNumber(uint8_t serialNumber[], uint16_t serialNumberSize);

  private:
    TwoWire* _i2cBus = nullptr;
    uint8_t _i2cAddress = 0;

    /**
     * @brief signalSraw
     *
     * @param[in] measurement
     *
     * @return Raw measurement of one pixel
     */
    uint16_t signalSraw(uint16_t measurement);
};

#endif  // SENSIRIONI2CSGP43_H