/*
 * THIS FILE IS AUTOMATICALLY GENERATED
 *
 * I2C-Generator: 0.2.0
 * Yaml Version: 0.1.0
 * Template Version: 0.7.0-12-g6411a7e
 */
/*
 * Copyright (c) 2021, 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.
 */

#include "sts4x_i2c.h"
#include "sensirion_common.h"
#include "sensirion_i2c.h"
#include "sensirion_i2c_hal.h"

static sts4x_t _driver = {.i2c_address = ADDR_STS4X};

void init_driver(uint8_t i2c_address) {
    _driver.i2c_address = i2c_address;
}

#define STS4X_I2C_ADDRESS _driver.i2c_address

static int32_t convert_ticks_to_celsius(uint16_t ticks) {
    return ((21875 * (int32_t)ticks) >> 13) - 45000;
}

int16_t sts4x_measure_high_precision_ticks(uint16_t* temperature_ticks) {
    int16_t error;
    uint8_t buffer[3];
    uint16_t offset = 0;
    buffer[offset++] = (uint8_t)0xFD;

    error = sensirion_i2c_write_data(STS4X_I2C_ADDRESS, &buffer[0], offset);
    if (error) {
        return error;
    }

    sensirion_i2c_hal_sleep_usec(10000);

    error = sensirion_i2c_read_data_inplace(STS4X_I2C_ADDRESS, &buffer[0], 2);
    if (error) {
        return error;
    }
    *temperature_ticks = sensirion_common_bytes_to_uint16_t(&buffer[0]);
    return NO_ERROR;
}

int16_t sts4x_measure_high_precision(int32_t* temperature) {
    int16_t error;
    uint16_t temperature_ticks;

    error = sts4x_measure_high_precision_ticks(&temperature_ticks);
    if (error) {
        return error;
    }
    *temperature = convert_ticks_to_celsius(temperature_ticks);
    return NO_ERROR;
}

int16_t sts4x_measure_medium_precision_ticks(uint16_t* temperature_ticks) {
    int16_t error;
    uint8_t buffer[3];
    uint16_t offset = 0;
    buffer[offset++] = (uint8_t)0xF6;

    error = sensirion_i2c_write_data(STS4X_I2C_ADDRESS, &buffer[0], offset);
    if (error) {
        return error;
    }

    sensirion_i2c_hal_sleep_usec(10000);

    error = sensirion_i2c_read_data_inplace(STS4X_I2C_ADDRESS, &buffer[0], 2);
    if (error) {
        return error;
    }
    *temperature_ticks = sensirion_common_bytes_to_uint16_t(&buffer[0]);
    return NO_ERROR;
}

int16_t sts4x_measure_medium_precision(int32_t* temperature) {
    int16_t error;
    uint16_t temperature_ticks;

    error = sts4x_measure_medium_precision_ticks(&temperature_ticks);
    if (error) {
        return error;
    }
    *temperature = convert_ticks_to_celsius(temperature_ticks);
    return NO_ERROR;
}

int16_t sts4x_measure_lowest_precision_ticks(uint16_t* temperature_ticks) {
    int16_t error;
    uint8_t buffer[3];
    uint16_t offset = 0;
    buffer[offset++] = (uint8_t)0xE0;

    error = sensirion_i2c_write_data(STS4X_I2C_ADDRESS, &buffer[0], offset);
    if (error) {
        return error;
    }

    sensirion_i2c_hal_sleep_usec(10000);

    error = sensirion_i2c_read_data_inplace(STS4X_I2C_ADDRESS, &buffer[0], 2);
    if (error) {
        return error;
    }
    *temperature_ticks = sensirion_common_bytes_to_uint16_t(&buffer[0]);
    return NO_ERROR;
}

int16_t sts4x_measure_lowest_precision(int32_t* temperature) {
    int16_t error;
    uint16_t temperature_ticks;

    error = sts4x_measure_lowest_precision_ticks(&temperature_ticks);
    if (error) {
        return error;
    }
    *temperature = convert_ticks_to_celsius(temperature_ticks);
    return NO_ERROR;
}

int16_t sts4x_serial_number(uint32_t* serial_number) {
    int16_t error;
    uint8_t buffer[6];
    uint16_t offset = 0;
    buffer[offset++] = (uint8_t)0x89;

    error = sensirion_i2c_write_data(STS4X_I2C_ADDRESS, &buffer[0], offset);
    if (error) {
        return error;
    }

    sensirion_i2c_hal_sleep_usec(10000);

    error = sensirion_i2c_read_data_inplace(STS4X_I2C_ADDRESS, &buffer[0], 4);
    if (error) {
        return error;
    }
    *serial_number = sensirion_common_bytes_to_uint32_t(&buffer[0]);
    return NO_ERROR;
}

int16_t sts4x_soft_reset(void) {
    int16_t error;
    uint8_t buffer[2];
    uint16_t offset = 0;
    buffer[offset++] = (uint8_t)0x94;

    error = sensirion_i2c_write_data(STS4X_I2C_ADDRESS, &buffer[0], offset);
    if (error) {
        return error;
    }
    sensirion_i2c_hal_sleep_usec(10000);
    return NO_ERROR;
}
