diff --git a/libtempered/temper_type.c b/libtempered/temper_type.c index 1b00b20..5cef273 100644 --- a/libtempered/temper_type.c +++ b/libtempered/temper_type.c @@ -10,6 +10,7 @@ #include "type_hid/sht1x.h" #include "type_hid/ntc.h" #include "type_hid/si7005.h" +#include "type_hid/si7021.h" // This is an array of known TEMPer types. struct temper_type known_temper_types[]={ @@ -37,6 +38,8 @@ struct temper_type known_temper_types[]={ .subtype_strings = (char *[]){ "TEMPerHumV1.0rHu", "TEMPerHumM12V1.0", + "TEMPerHumM12V1.2", + "TEMPerHumM12V1.3", NULL } }, @@ -103,6 +106,68 @@ struct temper_type known_temper_types[]={ } } }, + (struct temper_subtype*)&(struct temper_subtype_hid){ + .base = { + .id = 2, + .name = "TEMPerHumM12V1.2", + .open = tempered_type_hid_subtype_open, + .read_sensors = tempered_type_hid_read_sensors, + .get_temperature = tempered_type_hid_get_temperature, + .get_humidity = tempered_type_hid_get_humidity + }, + .sensor_group_count = 1, + .sensor_groups = (struct tempered_type_hid_sensor_group[]){ + { + .query = { + .length = 9, + .data = (unsigned char[]){ 0, 1, 0x80, 0x33, 1, 0, 0, 0, 0 } + }, + .read_sensors = tempered_type_hid_read_sensor_group, + .sensor_count = 1, + .sensors = (struct tempered_type_hid_sensor[]){ + { + .get_temperature = tempered_type_hid_get_temperature_si7021, + .get_humidity = tempered_type_hid_get_humidity_si7021, + .temperature_high_byte_offset = 2, + .temperature_low_byte_offset = 3, + .humidity_high_byte_offset = 4, + .humidity_low_byte_offset = 5 + } + } + } + } + }, + (struct temper_subtype*)&(struct temper_subtype_hid){ + .base = { + .id = 3, + .name = "TEMPerHumM12V1.3", + .open = tempered_type_hid_subtype_open, + .read_sensors = tempered_type_hid_read_sensors, + .get_temperature = tempered_type_hid_get_temperature, + .get_humidity = tempered_type_hid_get_humidity + }, + .sensor_group_count = 1, + .sensor_groups = (struct tempered_type_hid_sensor_group[]){ + { + .query = { + .length = 9, + .data = (unsigned char[]){ 0, 1, 0x80, 0x33, 1, 0, 0, 0, 0 } + }, + .read_sensors = tempered_type_hid_read_sensor_group, + .sensor_count = 1, + .sensors = (struct tempered_type_hid_sensor[]){ + { + .get_temperature = tempered_type_hid_get_temperature_si7021, + .get_humidity = tempered_type_hid_get_humidity_si7021, + .temperature_high_byte_offset = 2, + .temperature_low_byte_offset = 3, + .humidity_high_byte_offset = 4, + .humidity_low_byte_offset = 5 + } + } + } + } + }, NULL // List terminator for subtypes } }, diff --git a/libtempered/type_hid/si7021.c b/libtempered/type_hid/si7021.c new file mode 100644 index 0000000..0bf1506 --- /dev/null +++ b/libtempered/type_hid/si7021.c @@ -0,0 +1,69 @@ +#include +#include + +#include "type-info.h" +#include "../tempered-internal.h" + +bool tempered_type_hid_get_temperature_si7021( + tempered_device *device, struct tempered_type_hid_sensor *sensor, + struct tempered_type_hid_query_result *group_data, float *tempC +) { + if ( + group_data->length <= sensor->temperature_high_byte_offset || + group_data->length <= sensor->temperature_low_byte_offset + ) { + tempered_set_error( + device, strdup( "Not enough data was read from the sensor." ) + ); + return false; + } + + // Convert from two separate data bytes to a single integer. + // The result should be an unsigned int between 0x0000 and 0xFFFF. + int low_byte_offset = sensor->temperature_low_byte_offset; + int high_byte_offset = sensor->temperature_high_byte_offset; + int temp = ( group_data->data[low_byte_offset] & 0xFF ) + + ( ( group_data->data[high_byte_offset] & 0xFF ) << 8 ) + ; + + // These formulas and values are based on the Silicon Labs Si7021 datasheet + *tempC = 175.72*temp/65536 - 46.85; + + return true; +} + +bool tempered_type_hid_get_humidity_si7021( + tempered_device *device, struct tempered_type_hid_sensor *sensor, + struct tempered_type_hid_query_result *group_data, float *rel_hum +) { + float tempC; + if ( + !tempered_type_hid_get_temperature_si7021( + device, sensor, group_data, &tempC + ) + ) { + return false; + } + + if ( + group_data->length <= sensor->humidity_high_byte_offset || + group_data->length <= sensor->humidity_low_byte_offset + ) + { + tempered_set_error( + device, strdup( "Not enough data was read from the sensor." ) + ); + return false; + } + + int low_byte_offset = sensor->humidity_low_byte_offset; + int high_byte_offset = sensor->humidity_high_byte_offset; + int rh = ( group_data->data[low_byte_offset] & 0xFF ) + + ( ( group_data->data[high_byte_offset] & 0xFF ) << 8 ) + ; + + // These formulas and values are based on the Silicon Labs Si7021 datasheet + *rel_hum = 125.*rh/65536 - 6; + + return true; +} diff --git a/libtempered/type_hid/si7021.h b/libtempered/type_hid/si7021.h new file mode 100644 index 0000000..7b5de85 --- /dev/null +++ b/libtempered/type_hid/si7021.h @@ -0,0 +1,20 @@ +#ifndef TEMPERED__TYPE_HID__SI7021_H +#define TEMPERED__TYPE_HID__SI7021_H + +#include + +#include "type-info.h" + +// These methods are for the Silicon Labs Si7021 chip. + +bool tempered_type_hid_get_temperature_si7021( + tempered_device *device, struct tempered_type_hid_sensor *sensor, + struct tempered_type_hid_query_result *group_data, float *tempC +); + +bool tempered_type_hid_get_humidity_si7021( + tempered_device *device, struct tempered_type_hid_sensor *sensor, + struct tempered_type_hid_query_result *group_data, float *rel_hum +); + +#endif