/*
 * THIS FILE IS AUTOMATICALLY GENERATED
 *
 * Generator:     sensirion-driver-generator 1.2.0
 * Product:       stcc4
 * Model-Version: 3.4.0
 */
/*
 * Copyright (c) 2025, 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 SENSIRIONI2CSTCC4_H
#define SENSIRIONI2CSTCC4_H

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

#define STCC4_I2C_ADDR_64 0x64

typedef enum {
    STCC4_START_CONTINUOUS_MEASUREMENT_CMD_ID = 0x218b,
    STCC4_READ_MEASUREMENT_RAW_CMD_ID = 0xec05,
    STCC4_STOP_CONTINUOUS_MEASUREMENT_CMD_ID = 0x3f86,
    STCC4_MEASURE_SINGLE_SHOT_CMD_ID = 0x219d,
    STCC4_PERFORM_FORCED_RECALIBRATION_CMD_ID = 0x362f,
    STCC4_GET_PRODUCT_ID_CMD_ID = 0x365b,
    STCC4_SET_RHT_COMPENSATION_CMD_ID = 0xe000,
    STCC4_SET_PRESSURE_COMPENSATION_RAW_CMD_ID = 0xe016,
    STCC4_PERFORM_SELF_TEST_CMD_ID = 0x278c,
    STCC4_PERFORM_CONDITIONING_CMD_ID = 0x29bc,
    STCC4_ENTER_SLEEP_MODE_CMD_ID = 0x3650,
    STCC4_EXIT_SLEEP_MODE_CMD_ID = 0x0,
    STCC4_ENABLE_TESTING_MODE_CMD_ID = 0x3fbc,
    STCC4_DISABLE_TESTING_MODE_CMD_ID = 0x3f3d,
    STCC4_PERFORM_FACTORY_RESET_CMD_ID = 0x3632,
} STCC4CmdId;

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

    /**
     * @brief readMeasurement
     *
     * reads measurement data
     *
     * @param[out] co2Concentration
     * @param[out] temperature
     * @param[out] relativeHumidity
     * @param[out] sensorStatus
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t readMeasurement(int16_t& co2Concentration, float& temperature,
                            float& relativeHumidity, uint16_t& sensorStatus);

    /**
     * @brief Set the pressure compensation in Pa
     *
     * External pressure values can be set through the set_pressure_compensation
     * command. The written pressure value is applied for pressure compensation
     * after a maximum of one measurement interval. Power cycling resets the
     * sensor to the default value of 101'300 Pa.
     *
     * @param[in] pressure
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t setPressureCompensation(uint16_t pressure);

    /**
     * @brief Start a continuous measurement (interval 1 s).
     *
     * After sending the start_continuous_measurement command, the sensor will
     * begin measuring the CO2 gas concentration continuously with a sampling
     * interval of 1 second. The recommended communication sequence for
     * continuous measurement is as follows: 1. The sensor is powered up into
     * the idle state. 2. The I2C controller sends a
     * start_continuous_measurement command. 3. The I2C controller periodically
     * reads out data with the read_measurement command. 4. If desired, stop
     * taking measurements using the stop_continuous_measurement command.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t startContinuousMeasurement();

    /**
     * @brief Read CO₂, temperature, and humidity measurements.
     *
     * After the command *start_continuous_measurement* has been sent, the chip
     * continuously measures and updates the measurement results. New results
     * (co2_concentration, temperature, and relative_humidity) can be read
     * continuously with this command.
     *
     * @param[out] co2ConcentrationRaw CO2 concentration in ppm. No conversion
     * needed.
     * @param[out] temperatureRaw Raw temperature signal. The signal s can be
     * converted into a temperature in °C (t) by applying the formula t = -45 +
     * 175
     * * s / 65535.
     * @param[out] relativeHumidityRaw Raw relative humidity signal. The signal
     * s can be converted into relative humidity in % (rh) by applying the
     * formula rh = -6 + 125 * s / 65535.
     * @param[out] sensorStatusRaw The sensor status. If the sensor is in
     * testing mode, byte 10 is equal to 4.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t readMeasurementRaw(int16_t& co2ConcentrationRaw,
                               uint16_t& temperatureRaw,
                               uint16_t& relativeHumidityRaw,
                               uint16_t& sensorStatusRaw);

    /**
     * @brief The command stops the continuous measurement and puts the sensor
     * into idle mode.
     *
     * After receiving the stop_continuous_measurement command, the sensor will
     * finish the currently running measurement before returning to idle mode.
     * Therefore, a wait time of one measurement interval plus a 200 ms clock
     * tolerance is required before a new command is acknowledged.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t stopContinuousMeasurement();

    /**
     * @brief Performs a single shot measurement.
     *
     * The measure_single_shot command conducts an on-demand measurement of CO2
     * gas concentration. The typical communication sequence is as follows: 1.
     * The sensor is powered up with the exit_sleep_mode command if previously
     * powered down using the enter_sleep_mode command. 2. The I2C controller
     * sends a measure_single_shot command and waits for the execution time. 3.
     * The I2C controller reads out data with the read_measurement command. 4.
     * Repeat steps 2-3 as required by the application. 5. If desired, set the
     * sensor to sleep with the enter_sleep_mode command.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t measureSingleShot();

    /**
     * @brief Perform a forced recalibration (FRC) of the CO₂ concentration.
     *
     * The forced recalibration (FRC) can be applied to correct the sensor's
     * output by means of an externally obtained CO 2 reference value. The
     * recommended communication sequence for a successful FRC in continuous
     * mode is as follows:
     * 1. Operate the STCC4 for at least 3 minutes. Ensure the sensor reading
     * and environmental conditions, including CO2 concentration, are stable. 2.
     * The I2C controller sends the stop_continuous_measurement command
     * (Section 5.3.2) 3. Wait for the specified execution time of
     * stop_continuous_measurement command.
     * 4. Issue the perform_forced_recalibration command with the target CO2
     * concentration and read out the applied FRC correction.
     *
     * The recommended communication sequence for a successful FRC in single
     * shot mode is as follows: 1. Operate the STCC4 for at least 3 minutes. For
     * sampling intervals significantly larger than 10 seconds, increase the
     * operation time accordingly. Ensure the sensor reading and environmental
     * conditions, including CO2 concentration, are stable. 2. Issue the
     * perform_forced_recalibration command with the reference CO2 concentration
     * and read out the applied FRC correction. The sensor must remain in idle
     * mode after operation before command execution.
     *
     * @param[in] targetCO2Concentration Target CO₂ concentration in ppm.
     * @param[out] frcCorrection Returns the FRC correction value if FRC has
     * been successful. 0xFFFF on failure.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t performForcedRecalibration(int16_t targetCO2Concentration,
                                       int16_t& frcCorrection);

    /**
     * @brief Read the sensor's 32-bit product id and 64-bit serial number.
     *
     * The get_product_ID command retrieves the product identifier and serial
     * number. The command can be used to check communication with the sensor.
     *
     * @param[out] productId 32-bit
     * @param[out] serialNumber 64-bit unique serial number of the sensor.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t getProductId(uint32_t& productId, uint64_t& serialNumber);

    /**
     * @brief Write the raw SHT4x temperature and humidity values to the STCC4.
     *
     * When the SHT4x is not directly connected to the STCC4 for humidity and
     * temperature compensation, the set_rht_compensation command allows
     * external input of relative humidity (RH) and temperature (T) values. The
     * temperature value must be provided from the RHT sensor providing the RH
     * value for correct absolute humidity calculation. The written RHT values
     * are applied for compensation after a maximum of one measurement interval.
     * The default or last written values are used for RHT compensation until
     * overwritten. Power cycling resets the sensor to the default values of
     * 25°C and 50 %RH.
     *
     * @param[in] rawTemperature raw temperature ticks as provided by SHT4x
     * sensor
     * @param[in] rawHumidity raw humidity ticks as provided by SHT4x sensor
     *
     * @return error_code 0 on success, an error code otherwise.
     *
     * Example:
     * --------
     *
     * @code{.cpp}
     *
     *     int16_t localError = 0;
     *     localError = sensor.setRhtCompensation(26214, 29359);
     *     if (localError != NO_ERROR) {
     *         return;
     *     }
     *
     * @endcode
     *
     */
    int16_t setRhtCompensation(uint16_t rawTemperature, uint16_t rawHumidity);

    /**
     * @brief Write the pressure value to the STCC4
     *
     * External pressure values can be set through the set_pressure_compensation
     * command. The written pressure value is applied for pressure compensation
     * after a maximum of one measurement interval. Power cycling resets the
     * sensor to the default value of 101'300 Pa. The default or the last
     * written value is used in pressure compensation until overwritten.
     *
     * @param[in] pressure The pressure value as Pa divided by 2. E.g. for
     * 101300 Pa you have to send 50650
     *
     * @return error_code 0 on success, an error code otherwise.
     *
     * Example:
     * --------
     *
     * @code{.cpp}
     *
     *     int16_t localError = 0;
     *     localError = sensor.setPressureCompensationRaw(50650);
     *     if (localError != NO_ERROR) {
     *         return;
     *     }
     *
     * @endcode
     *
     */
    int16_t setPressureCompensationRaw(uint16_t pressure);

    /**
     * @brief Performs an internal check to determine if the sensor has a
     * malfunction.
     *
     * The perform_self_test command can be used as an end-of-line test to check
     * the sensor functionality. Word[0] = 0 → pass Word[0] ≠ 0 → malfunction
     * detected
     *
     * @param[out] testResult Test result of the self-test. If the result is ≠
     * 0, the self-test failed.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t performSelfTest(uint16_t& testResult);

    /**
     * @brief Conditions the sensor with a set operation profile.
     *
     * The perform_conditioning command is recommended to improve sensor
     * performance when the sensor has not completed measurements for more than
     * 3 hours. It is recommended to allow a settling time of 2 seconds after
     * the execution time is complete. The recommended communication sequence is
     * as follows: 1. The sensor is woken up with the exit_sleep_mode command if
     * previously put to sleep using the enter_sleep_mode command. 2. The I2C
     * controller sends a perform_conditioning command. 3. Wait for the
     * specified execution time of perform_conditioning command plus a 2 second
     * settling time. 4. The I2C controller sends a measurement command (e.g.
     * start_continuous_measurement command or measure_single_shot command.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t performConditioning();

    /**
     * @brief Sets the sensor from idle mode into sleep mode.
     *
     * The enter_sleep_mode command sets the sensor to sleep mode through the
     * I2C interface. The written relative humidity, temperature, and pressure
     * compensation values as well as the ASC state will be retained while in
     * sleep mode.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t enterSleepMode();

    /**
     * @brief The sensor is set from sleep mode into idle mode when it receives
     * the valid I²C address and a write bit (‘0’).
     *
     * The exit_sleep_mode command sets the sensor to idle mode through the I2C
     * interface. The sensor's idle state can be verified by reading out the
     * product ID.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t exitSleepMode();

    /**
     * @brief Enable the sensor testing mode.
     *
     * The enable_testing_mode command is used to test the sensor with  the ASC
     * algorithm disabled. The sensor state can be verified by reading out the
     * sensor status word in the read_measurement command.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t enableTestingMode();

    /**
     * @brief Disable the sensor testing mode.
     *
     * The disable_testing_mode command is used to exit the testing mode. The
     * sensor state can be verified by reading out the sensor status word in the
     * read_measurement command.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t disableTestingMode();

    /**
     * @brief Reset the FRC and ASC algorithm history.
     *
     * The perform_factory_reset command can be used to reset the FRC and ASC
     * algorithm history.
     *
     * @param[out] factoryResetResult The result of the factory reset. If the
     * result is ≠ 0, the factory reset failed.
     *
     * @return error_code 0 on success, an error code otherwise.
     */
    int16_t performFactoryReset(uint16_t& factoryResetResult);

    /**
     * @brief signalTemperature
     *
     * @param[in] rawTemperature
     *
     * @return
     */
    static float signalTemperature(uint16_t rawTemperature);

    /**
     * @brief signalRelativeHumidity
     *
     * @param[in] rawRelativeHumidity
     *
     * @return
     */
    static float signalRelativeHumidity(uint16_t rawRelativeHumidity);

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

#endif  // SENSIRIONI2CSTCC4_H