/*
 * THIS FILE IS AUTOMATICALLY GENERATED
 *
 * Generator:     sensirion-driver-generator 0.40.1
 * Product:       sfx6xxx
 * Model-Version: 2.3.1
 */
/*
 * Copyright (c) 2024, 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 SFX6XXX_I2C_H
#define SFX6XXX_I2C_H

#ifdef __cplusplus
extern "C" {
#endif

#include "sensirion_config.h"
#define SFC6000_I2C_ADDR_24 0x24
#define SFC6000_I2C_ADDR_23 0x23
#define SFC6000_I2C_ADDR_22 0x22
#define SFC6000_I2C_ADDR_21 0x21
#define SFC6000_I2C_ADDR_20 0x20
#define SFC6000_I2C_ADDR_42 0x42
#define SFC6000_I2C_ADDR_41 0x41
#define SFC6000D_5SLM_I2C_ADDR_24 0x24
#define SFC6000D_5SLM_I2C_ADDR_23 0x23
#define SFC6000D_5SLM_I2C_ADDR_22 0x22
#define SFC6000D_5SLM_I2C_ADDR_21 0x21
#define SFC6000D_5SLM_I2C_ADDR_20 0x20
#define SFC6000D_5SLM_I2C_ADDR_42 0x42
#define SFC6000D_5SLM_I2C_ADDR_41 0x41
#define SFC6000D_50SLM_I2C_ADDR_24 0x24
#define SFC6000D_50SLM_I2C_ADDR_23 0x23
#define SFC6000D_50SLM_I2C_ADDR_22 0x22
#define SFC6000D_50SLM_I2C_ADDR_21 0x21
#define SFC6000D_50SLM_I2C_ADDR_20 0x20
#define SFC6000D_50SLM_I2C_ADDR_42 0x42
#define SFC6000D_50SLM_I2C_ADDR_41 0x41
#define SFC6000D_20SLM_I2C_ADDR_24 0x24
#define SFC6000D_20SLM_I2C_ADDR_23 0x23
#define SFC6000D_20SLM_I2C_ADDR_22 0x22
#define SFC6000D_20SLM_I2C_ADDR_21 0x21
#define SFC6000D_20SLM_I2C_ADDR_20 0x20
#define SFC6000D_20SLM_I2C_ADDR_42 0x42
#define SFC6000D_20SLM_I2C_ADDR_41 0x41
#define SFM6000_I2C_ADDR_24 0x24
#define SFM6000_I2C_ADDR_23 0x23
#define SFM6000_I2C_ADDR_22 0x22
#define SFM6000_I2C_ADDR_21 0x21
#define SFM6000_I2C_ADDR_20 0x20
#define SFM6000_I2C_ADDR_42 0x42
#define SFM6000_I2C_ADDR_41 0x41
#define SFM6000D_20SLM_I2C_ADDR_24 0x24
#define SFM6000D_20SLM_I2C_ADDR_23 0x23
#define SFM6000D_20SLM_I2C_ADDR_22 0x22
#define SFM6000D_20SLM_I2C_ADDR_21 0x21
#define SFM6000D_20SLM_I2C_ADDR_20 0x20
#define SFM6000D_20SLM_I2C_ADDR_42 0x42
#define SFM6000D_20SLM_I2C_ADDR_41 0x41
#define SFM6000D_50SLM_I2C_ADDR_24 0x24
#define SFM6000D_50SLM_I2C_ADDR_23 0x23
#define SFM6000D_50SLM_I2C_ADDR_22 0x22
#define SFM6000D_50SLM_I2C_ADDR_21 0x21
#define SFM6000D_50SLM_I2C_ADDR_20 0x20
#define SFM6000D_50SLM_I2C_ADDR_42 0x42
#define SFM6000D_50SLM_I2C_ADDR_41 0x41
#define SFM6000D_5SLM_I2C_ADDR_24 0x24
#define SFM6000D_5SLM_I2C_ADDR_23 0x23
#define SFM6000D_5SLM_I2C_ADDR_22 0x22
#define SFM6000D_5SLM_I2C_ADDR_21 0x21
#define SFM6000D_5SLM_I2C_ADDR_20 0x20
#define SFM6000D_5SLM_I2C_ADDR_42 0x42
#define SFM6000D_5SLM_I2C_ADDR_41 0x41

typedef enum {
    SFX6XXX_READ_PRODUCT_IDENTIFIER_CMD_ID = 0xe102,
    SFX6XXX_RESET_POINTER_TO_MEASUREMENT_BUFFER_CMD_ID = 0xe000,
    SFX6XXX_UPDATE_SETPOINT_CMD_ID = 0xf054,
    SFX6XXX_UPDATE_INIT_STEP_CMD_ID = 0xe1b9,
    SFX6XXX_UPDATE_CUSTOMER_GAIN_CMD_ID = 0xe1b2,
    SFX6XXX_START_O2_CONTINUOUS_MEASUREMENT_CMD_ID = 0x3603,
    SFX6XXX_START_AIR_CONTINUOUS_MEASUREMENT_CMD_ID = 0x3608,
    SFX6XXX_START_CO2_CONTINUOUS_MEASUREMENT_CMD_ID = 0x3615,
    SFX6XXX_START_N2O_CONTINUOUS_MEASUREMENT_CMD_ID = 0x361e,
    SFX6XXX_START_AR_CONTINUOUS_MEASUREMENT_CMD_ID = 0x3624,
    SFX6XXX_START_RAW_THERMAL_CONDUCTIVITY_CONTINUOUS_MEASUREMENT_CMD_ID =
        0x3624,
    SFX6XXX_START_O2_IN_AIR_CONTINUOUS_MEASUREMENT_CMD_ID = 0x3650,
    SFX6XXX_STOP_CONTINUOUS_MEASUREMENT_CMD_ID = 0x3ff9,
    SFX6XXX_GET_RAW_TEMPERATURE_CMD_ID = 0xe102,
    SFX6XXX_FORCE_OPEN_VALVE_CMD_ID = 0x3fe4,
    SFX6XXX_RESET_FORCE_OPEN_VALVE_CMD_ID = 0x3f65,
    SFX6XXX_FORCE_CLOSE_VALVE_CMD_ID = 0x3fef,
    SFX6XXX_RESET_FORCE_CLOSE_VALVE_CMD_ID = 0x3f6e,
    SFX6XXX_UPDATE_GAS_CONCENTRATION_CMD_ID = 0xe17d,
    SFX6XXX_PREPARE_READ_GAS_CALIBRATION_CMD_ID = 0x3661,
    SFX6XXX_READ_GAS_CALIBRATION_CMD_ID = 0xe151,
    SFX6XXX_ENABLE_RAW_FLOW_VALUES_CMD_ID = 0x3fde,
    SFX6XXX_DISABLE_RAW_FLOW_VALUES_CMD_ID = 0x3f5f,
} SFX6XXX_CMD_ID;

typedef enum {
    SFX6XXX_ERROR_CODE_I2C_ERROR = 0,
    SFX6XXX_ERROR_CODE_TIMEOUT = 1,
} sfx6xxx_error_code_t;

typedef union {
    struct {
        uint16_t gas_conc : 10;
        uint16_t pressure_controller_functionality : 1;
        uint16_t flow_controller_functionality : 1;
        uint16_t command_code : 4;
    };
    uint16_t value;
} sfx6xxx_status_word_t;

typedef union {
    struct {
        uint16_t prefix : 4;
        uint16_t time_base : 4;
        uint16_t unit : 5;
    };
    uint16_t value;
} sfx6xxx_flow_unit_t;

/**
 * @brief Initialize i2c address of driver
 *
 * @param[in] i2c_address Used i2c address
 *
 */
void sfx6xxx_init(uint8_t i2c_address);

/**
 * @brief Read the flow scale, offset and unit, full-scale flow and unique
 * gas-ID for one of the calibrated gases.
 *
 * @param[in] measurement_command The continuous measurement command, that will
 * be used.
 * @param[out] flow_scale_factor Scale factor used by the sensor.
 * @param[out] flow_offset Offset used by the sensor.
 * @param[out] flow_unit Applicable flow unit.
 * @param[out] full_scale_flow The full-scale flow value as a two's complement.
 * @param[out] gas_id The unique gas-ID represents the code assigned to a gas by
 * the SEMI standards.
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_get_gas_calibration(uint16_t measurement_command,
                                    int16_t* flow_scale_factor,
                                    int16_t* flow_offset,
                                    sfx6xxx_flow_unit_t* flow_unit,
                                    int16_t* full_scale_flow, uint16_t* gas_id);

/**
 * @brief Start measurement and update internal state.
 *
 * Start O2 measurement and readout the corresponding scale factor from the
 * sensor
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_start_o2_continuous_measurement();

/**
 * @brief Start measurement and update internal state
 *
 * Start Air measurement and readout the corresponding scale factor from the
 * sensor
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_start_air_continuous_measurement();

/**
 * @brief Start measurement and update internal state
 *
 * Start CO2 measurement and readout the corresponding scale factor from the
 * sensor
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_start_co2_continuous_measurement();

/**
 * @brief Start measurement and update internal state
 *
 * Start N2O measurement and readout the corresponding scale factor from the
 * sensor
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_start_n2o_continuous_measurement();

/**
 * @brief Start measurement and update internal state
 *
 * Start Ar measurement and readout the corresponding scale factor from the
 * sensor
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_start_ar_continuous_measurement();

/**
 * @brief Start measurement and update internal state
 *
 * Start O2 in air measurement and readout the corresponding scale factor from
 * the sensor
 *
 * @param[in] volume_fraction Volume fraction of O2 in Air in per mille (‰).
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t
sfx6xxx_start_o2_in_air_continuous_measurement(uint16_t volume_fraction);

/**
 * @brief Start measurement and update internal state
 *
 * Start thermal conductivity measurement and readout the corresponding scale
 * factor from the sensor
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_start_raw_thermal_conductivity_continuous_measurement();

/**
 * @brief Read raw flow value
 *
 * @param[out] arg_0
 * @param[out] a_status_word
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_read_measurement_data_raw(int16_t* arg_0,
                                          sfx6xxx_status_word_t* a_status_word);

/**
 * @brief Read raw flow value in ticks.
 *
 * @param[out] arg_0
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_read_flow_raw(int16_t* arg_0);

/**
 * @brief Read temperature in degrees celsius.
 *
 * @param[out] arg_0
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_read_raw_temperature(int16_t* arg_0);

/**
 * @brief Read product identifier and the serial number.
 *
 * @param[out] product_identifier 32-bit product and revision number.
 * @param[out] serial_number 64-bit unique serial number.
 *
 * @note
 * * This command is only available while no measurement is running
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_read_product_identifier(uint32_t* product_identifier,
                                        uint64_t* serial_number);

/**
 * @brief sfx6xxx_reset_pointer_to_measurement_buffer
 *
 * This instruction resets the I2C address pointer to the regular result output
 * buffer such that the measurement data are obtained upon a subsequent read
 * header.
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_reset_pointer_to_measurement_buffer();

/**
 * @brief Update setpoint value dynamically.
 *
 * Set the flow setpoint as a physical value which is used by the flow
 * controller as reference input.
 *
 * @param[in] setpoint The new setpoint. The value has to be given in the
 * regular two's complement format, which is also used for the flow value
 * output.
 *
 * @note
 * * The setpoint is set to 0 if calibration is changed.
 * * You have to call reset_pointer_to_measurement_buffer after updating the
 *   setpoint
 * * Only applicable for SFC6xxx mass flow controllers.
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_update_setpoint(int16_t setpoint);

/**
 * @brief Update init step value dynamically.
 *
 * This instruction transmits the InitStep value to the MFC. An MFC variant
 * specific InitStep value is used by default, which will be applied after a
 * hard- or soft-reset of the sensor.
 *
 * @param[in] init_step InitStep value in range [0..1] multiplied by 2^16.
 *
 * @note
 * * Only applicable for SFC6xxx mass flow controllers
 * * You have to reset i2c address after updating the init step
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_update_init_step(uint16_t init_step);

/**
 * @brief Update CustomerGain value dynamically.
 *
 * This instruction transmits the CustomerGain value to the MFC. A value of 1 is
 * used by default for the CustomerGain, which will be applied after a hard- or
 * soft-reset of the sensor.
 *
 * @param[in] customer_gain CustomerGain value in range [0..4] multiplied by
 * 2^14.
 *
 * @note
 * * Only applicable for SFC6xxx mass flow controllers
 * * You have to reset i2c address after updating the init step
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_update_customer_gain(uint16_t customer_gain);

/**
 * @brief Start continuous O₂ measurement.
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t ll_sfx6xxx_start_o2_continuous_measurement();

/**
 * @brief Start continuous air measurement.
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t ll_sfx6xxx_start_air_continuous_measurement();

/**
 * @brief Start continuous CO₂ measurement.
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t ll_sfx6xxx_start_co2_continuous_measurement();

/**
 * @brief Start continuous N₂O measurement.
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t ll_sfx6xxx_start_n2o_continuous_measurement();

/**
 * @brief Start continuous Ar measurement.
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t ll_sfx6xxx_start_ar_continuous_measurement();

/**
 * @brief Raw thermal conductivity measurement with closed valve.
 *
 * Start measurement for raw thermal conductivity. In this measurement mode the
 * valve remains closed and the flow value is replaced by the raw thermal
 * conductivity value.
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t ll_sfx6xxx_start_raw_thermal_conductivity_continuous_measurement();

/**
 * @brief Start continuous measurement for gas mixture of O2 in Air.
 *
 * @param[in] volume_fraction Volume fraction of O2 in Air in per mille (‰).
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t
ll_sfx6xxx_start_o2_in_air_continuous_measurement(uint16_t volume_fraction);

/**
 * @brief This transfer stops the continuous measurement and puts the sensor in
 * idle mode.
 *
 * @note
 * * After it receives the stop command, the sensor needs up to 1 ms to power
 *   down the heater, enter idle mode and be receptive for a new command.
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_stop_continuous_measurement();

/**
 * @brief Read out the data from the sensor.
 *
 * @param[out] flow Calibrated flow signal read from the sensor.
 * @param[out] reserved Reserved value for future use.
 * @param[out] status_word Contains status information about the read data.
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_read_measurement_data(int16_t* flow, int16_t* reserved,
                                      sfx6xxx_status_word_t* status_word);

/**
 * @brief Read out the flow only from the sensor.
 *
 * @param[out] flow Calibrated flow signal read from the sensor.
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_read_flow(int16_t* flow);

/**
 * @brief Get the raw scaled temperature of the bulk silikon in the flow-sensor.
 *
 * While the sensor is in continuous measurement mode, the temperature of the
 * bulk silicon in the flow-sensor chip can be read with a special I2C
 * transmission sequence. The sensor must be in continuous measurement mode and
 * the temperature is read without interrupting the running measurement. To this
 * end a transmission sequence consisting of multiple instructions is detailed
 * in this section.
 *
 * @param[out] temperature 16-bit temperature
 *
 * @note
 * * The first valid temperature value can be read after about 12 ms (i.e. for
 *   simplicity, the temperature shall be read upon the sensor acknowledged a
 *   read of the flow value, to make sure that a temperature value is available
 *   from the buffer)
 * * The update rate for the temperature value is significantly slower than for
 *   the flow value. The most up- to-date temperature value is always available
 *   from the buffer (the sensor will ACK a corresponding read). Hence, the
 *   identical internally acquired temperature value can be read multiple times,
 *   which is not the case for the flow value, where the sensor will NACK if no
 *   new measurement data is yet available
 * * You have to call reset_pointer_to_measurement_buffer after reading out the
 *   temperature
 * * temperature value has a scaling factor or 1/200
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_get_raw_temperature(int16_t* temperature);

/**
 * @brief Overrule the valve regulation and fully open the valve
 *
 * Fully opens the valve. The flow value can still be read from the sensor. Call
 * reset_force_open_valve to return to normal valve regulation.
 *
 * @note
 * * Only applicable for SFC6xxx mass flow controllers
 * * Command has to be issued while continuous measurement is running
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_force_open_valve();

/**
 * @brief Return to normal valve regulation after fully opening the valve.
 *
 * @note
 * * Only applicable for SFC6xxx mass flow controllers
 * * Command has to be issued after force_open_valve
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_reset_force_open_valve();

/**
 * @brief Overrule the valve regulation and force closes the valve.
 *
 * Fully closes the valve. The flow value can still be read from the sensor.
 * Call reset_force_close_valve to return to normal valve regulation.
 *
 * @note
 * * Only applicable for SFC6xxx mass flow controllers
 * * Command has to be issued while continuous measurement is running
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_force_close_valve();

/**
 * @brief Return to normal valve regulation after force closing the valve.
 *
 * @note
 * * Only applicable for SFC6xxx mass flow controllers
 * * Command has to be issued after force_close_valve
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_reset_force_close_valve();

/**
 * @brief Update the concentration of a binary gas mixture dynamically.
 *
 * @param[in] volume_fraction New O₂ volume fraction in Air
 *
 * @note
 * * You have to call reset_pointer_to_measurement_buffer after updating gas
 *   concentration
 * * The concentration value must not be updated more than once per millisecond
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_update_gas_concentration(uint16_t volume_fraction);

/**
 * @brief This command prepares read out of gas calibration.
 *
 * @param[in] measurement_command The continuous measurement command, that will
 * be used.
 *
 * @note
 * * This command has to be sent before read_gas_calibration
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_prepare_read_gas_calibration(uint16_t measurement_command);

/**
 * @brief Read scale factor, offset, flow unit, full scale flow and gas-ID
 *
 * Read the flow scale, offset and unit, full-scale flow and unique gas-ID for
 * one of the calibrated gases.
 *
 * @param[out] flow_scale_factor Scale factor used by the sensor.
 * @param[out] flow_offset Offset used by the sensor.
 * @param[out] flow_unit Applicable flow unit.
 * @param[out] full_scale_flow The full-scale flow value as a two's complement.
 * @param[out] gas_id The unique gas-ID represents the code assigned to a gas by
 * the SEMI standards.
 *
 * @note
 * * This command is only valid after prepare_read_gas_calibration
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_read_gas_calibration(int16_t* flow_scale_factor,
                                     int16_t* flow_offset,
                                     sfx6xxx_flow_unit_t* flow_unit,
                                     int16_t* full_scale_flow,
                                     uint16_t* gas_id);

/**
 * @brief Causes the sensor to return raw flow values.
 *
 * There might be special cases where it is beneficial to read the uncalibrated
 * raw flow value from the sensor. To this end a dedicated command can be issued
 * requesting the sensor to return the uncalibrated raw flow values as opposed
 * to the default linearized flow values.
 *
 * @note
 * * This command has to be issued while a continuous measurement is running
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_enable_raw_flow_values();

/**
 * @brief Causes the sensor to switch back to normalized flow values.
 *
 * @note
 * * This command has to be issued while a continuous measurement is running
 * * Use this command to return to regular normalized flow values after enabling
 *   raw flow values
 *
 * @return error_code 0 on success, an error code otherwise.
 */
int16_t sfx6xxx_disable_raw_flow_values();

#ifdef __cplusplus
}
#endif
#endif  // SFX6XXX_I2C_H
