453 lines
14 KiB
C
453 lines
14 KiB
C
/*
|
|
* THIS FILE IS AUTOMATICALLY GENERATED AND MUST NOT BE EDITED MANUALLY!
|
|
*
|
|
* I2C-Generator: 0.2.0
|
|
* Yaml Version: 0.1.0
|
|
* Template Version: 0.2.1
|
|
*/
|
|
/*
|
|
* 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 "scd4x_i2c.h"
|
|
#include "sensirion_common.h"
|
|
#include "sensirion_i2c.h"
|
|
#include "sensirion_i2c_hal.h"
|
|
|
|
#define SCD4X_I2C_ADDRESS 98
|
|
|
|
int16_t scd4x_start_periodic_measurement() {
|
|
int16_t error;
|
|
uint8_t buffer[2];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x21B1);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
sensirion_i2c_hal_sleep_usec(1000);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_read_measurement_ticks(uint16_t* co2, uint16_t* temperature,
|
|
uint16_t* humidity) {
|
|
int16_t error;
|
|
uint8_t buffer[9];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0xEC05);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
|
|
sensirion_i2c_hal_sleep_usec(1000);
|
|
|
|
error = sensirion_i2c_read_data_inplace(SCD4X_I2C_ADDRESS, &buffer[0], 6);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
*co2 = sensirion_common_bytes_to_uint16_t(&buffer[0]);
|
|
*temperature = sensirion_common_bytes_to_uint16_t(&buffer[2]);
|
|
*humidity = sensirion_common_bytes_to_uint16_t(&buffer[4]);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_read_measurement(uint16_t* co2, int32_t* temperature_m_deg_c,
|
|
int32_t* humidity_m_percent_rh) {
|
|
int16_t error;
|
|
uint16_t temperature;
|
|
uint16_t humidity;
|
|
|
|
error = scd4x_read_measurement_ticks(co2, &temperature, &humidity);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
*temperature_m_deg_c = ((21875 * (int32_t)temperature) >> 13) - 45000;
|
|
*humidity_m_percent_rh = ((12500 * (int32_t)humidity) >> 13);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_stop_periodic_measurement() {
|
|
int16_t error;
|
|
uint8_t buffer[2];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x3F86);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
sensirion_i2c_hal_sleep_usec(500000);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_get_temperature_offset_ticks(uint16_t* t_offset) {
|
|
int16_t error;
|
|
uint8_t buffer[3];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x2318);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
|
|
sensirion_i2c_hal_sleep_usec(1000);
|
|
|
|
error = sensirion_i2c_read_data_inplace(SCD4X_I2C_ADDRESS, &buffer[0], 2);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
*t_offset = sensirion_common_bytes_to_uint16_t(&buffer[0]);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_get_temperature_offset(int32_t* t_offset_m_deg_c) {
|
|
int16_t error;
|
|
uint16_t t_offset;
|
|
|
|
error = scd4x_get_temperature_offset_ticks(&t_offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
*t_offset_m_deg_c = ((21875 * (int32_t)t_offset) >> 13);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_set_temperature_offset_ticks(uint16_t t_offset) {
|
|
int16_t error;
|
|
uint8_t buffer[5];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x241D);
|
|
|
|
offset = sensirion_i2c_add_uint16_t_to_buffer(&buffer[0], offset, t_offset);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
sensirion_i2c_hal_sleep_usec(1000);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_set_temperature_offset(int32_t t_offset_m_deg_c) {
|
|
uint16_t t_offset = (uint16_t)((t_offset_m_deg_c * 12271) >> 15);
|
|
return scd4x_set_temperature_offset_ticks(t_offset);
|
|
}
|
|
|
|
int16_t scd4x_get_sensor_altitude(uint16_t* sensor_altitude) {
|
|
int16_t error;
|
|
uint8_t buffer[3];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x2322);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
|
|
sensirion_i2c_hal_sleep_usec(1000);
|
|
|
|
error = sensirion_i2c_read_data_inplace(SCD4X_I2C_ADDRESS, &buffer[0], 2);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
*sensor_altitude = sensirion_common_bytes_to_uint16_t(&buffer[0]);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_set_sensor_altitude(uint16_t sensor_altitude) {
|
|
int16_t error;
|
|
uint8_t buffer[5];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x2427);
|
|
|
|
offset = sensirion_i2c_add_uint16_t_to_buffer(&buffer[0], offset,
|
|
sensor_altitude);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
sensirion_i2c_hal_sleep_usec(1000);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_set_ambient_pressure(uint16_t ambient_pressure) {
|
|
int16_t error;
|
|
uint8_t buffer[5];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0xE000);
|
|
|
|
offset = sensirion_i2c_add_uint16_t_to_buffer(&buffer[0], offset,
|
|
ambient_pressure);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
sensirion_i2c_hal_sleep_usec(1000);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_perform_forced_recalibration(uint16_t target_co2_concentration,
|
|
uint16_t* frc_correction) {
|
|
int16_t error;
|
|
uint8_t buffer[5];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x362F);
|
|
|
|
offset = sensirion_i2c_add_uint16_t_to_buffer(&buffer[0], offset,
|
|
target_co2_concentration);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
|
|
sensirion_i2c_hal_sleep_usec(400000);
|
|
|
|
error = sensirion_i2c_read_data_inplace(SCD4X_I2C_ADDRESS, &buffer[0], 2);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
*frc_correction = sensirion_common_bytes_to_uint16_t(&buffer[0]);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_get_automatic_self_calibration(uint16_t* asc_enabled) {
|
|
int16_t error;
|
|
uint8_t buffer[3];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x2313);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
|
|
sensirion_i2c_hal_sleep_usec(1000);
|
|
|
|
error = sensirion_i2c_read_data_inplace(SCD4X_I2C_ADDRESS, &buffer[0], 2);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
*asc_enabled = sensirion_common_bytes_to_uint16_t(&buffer[0]);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_set_automatic_self_calibration(uint16_t asc_enabled) {
|
|
int16_t error;
|
|
uint8_t buffer[5];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x2416);
|
|
|
|
offset =
|
|
sensirion_i2c_add_uint16_t_to_buffer(&buffer[0], offset, asc_enabled);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
sensirion_i2c_hal_sleep_usec(1000);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_start_low_power_periodic_measurement() {
|
|
uint8_t buffer[2];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x21AC);
|
|
|
|
return sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
}
|
|
|
|
int16_t scd4x_get_data_ready_status(uint16_t* data_ready) {
|
|
int16_t error;
|
|
uint8_t buffer[3];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0xE4B8);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
|
|
sensirion_i2c_hal_sleep_usec(1000);
|
|
|
|
error = sensirion_i2c_read_data_inplace(SCD4X_I2C_ADDRESS, &buffer[0], 2);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
*data_ready = sensirion_common_bytes_to_uint16_t(&buffer[0]);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_persist_settings() {
|
|
int16_t error;
|
|
uint8_t buffer[2];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x3615);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
sensirion_i2c_hal_sleep_usec(800000);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_get_serial_number(uint16_t* serial_0, uint16_t* serial_1,
|
|
uint16_t* serial_2) {
|
|
int16_t error;
|
|
uint8_t buffer[9];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x3682);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
|
|
sensirion_i2c_hal_sleep_usec(1000);
|
|
|
|
error = sensirion_i2c_read_data_inplace(SCD4X_I2C_ADDRESS, &buffer[0], 6);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
*serial_0 = sensirion_common_bytes_to_uint16_t(&buffer[0]);
|
|
*serial_1 = sensirion_common_bytes_to_uint16_t(&buffer[2]);
|
|
*serial_2 = sensirion_common_bytes_to_uint16_t(&buffer[4]);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_perform_self_test(uint16_t* sensor_status) {
|
|
int16_t error;
|
|
uint8_t buffer[3];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x3639);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
|
|
sensirion_i2c_hal_sleep_usec(10000000);
|
|
|
|
error = sensirion_i2c_read_data_inplace(SCD4X_I2C_ADDRESS, &buffer[0], 2);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
*sensor_status = sensirion_common_bytes_to_uint16_t(&buffer[0]);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_perform_factory_reset() {
|
|
int16_t error;
|
|
uint8_t buffer[2];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x3632);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
sensirion_i2c_hal_sleep_usec(800000);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_reinit() {
|
|
int16_t error;
|
|
uint8_t buffer[2];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x3646);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
sensirion_i2c_hal_sleep_usec(20000);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_measure_single_shot() {
|
|
int16_t error;
|
|
uint8_t buffer[2];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x219D);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
sensirion_i2c_hal_sleep_usec(5000000);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_measure_single_shot_rht_only() {
|
|
int16_t error;
|
|
uint8_t buffer[2];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x2196);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
sensirion_i2c_hal_sleep_usec(50000);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_power_down() {
|
|
int16_t error;
|
|
uint8_t buffer[2];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x36E0);
|
|
|
|
error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
if (error) {
|
|
return error;
|
|
}
|
|
sensirion_i2c_hal_sleep_usec(1000);
|
|
return NO_ERROR;
|
|
}
|
|
|
|
int16_t scd4x_wake_up() {
|
|
uint8_t buffer[2];
|
|
uint16_t offset = 0;
|
|
offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x36F6);
|
|
|
|
// Sensor does not acknowledge the wake-up call, error is ignored
|
|
(void)sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
|
|
sensirion_i2c_hal_sleep_usec(20000);
|
|
return NO_ERROR;
|
|
}
|