From c03e0f2bf36deb0be6f5697bf4817d3b4dfe1d91 Mon Sep 17 00:00:00 2001 From: Timo Kokkonen Date: Fri, 4 Oct 2024 21:24:51 -0700 Subject: [PATCH] Move I2C Sensor code into separate library: pico-sensor-lib --- .gitmodules | 3 + CMakeLists.txt | 23 +-- README.md | 1 + credits.txt | 6 +- libs/pico-sensor-lib | 1 + src/command.c | 1 + src/config.c | 1 + src/fanpico.h | 4 - src/i2c.c | 451 ++----------------------------------------- src/i2c.h | 91 --------- src/i2c_adt7410.c | 134 ------------- src/i2c_aht.c | 180 ----------------- src/i2c_as621x.c | 138 ------------- src/i2c_bmp180.c | 232 ---------------------- src/i2c_bmp280.c | 213 -------------------- src/i2c_dps310.c | 234 ---------------------- src/i2c_lps22.c | 168 ---------------- src/i2c_lps25.c | 158 --------------- src/i2c_mcp9808.c | 119 ------------ src/i2c_ms8607.c | 349 --------------------------------- src/i2c_pct2075.c | 122 ------------ src/i2c_sht3x.c | 200 ------------------- src/i2c_sht4x.c | 180 ----------------- src/i2c_shtc3.c | 201 ------------------- src/i2c_stts22h.c | 119 ------------ src/i2c_tmp102.c | 135 ------------- src/i2c_tmp117.c | 121 ------------ 27 files changed, 29 insertions(+), 3556 deletions(-) create mode 160000 libs/pico-sensor-lib delete mode 100644 src/i2c.h delete mode 100644 src/i2c_adt7410.c delete mode 100644 src/i2c_aht.c delete mode 100644 src/i2c_as621x.c delete mode 100644 src/i2c_bmp180.c delete mode 100644 src/i2c_bmp280.c delete mode 100644 src/i2c_dps310.c delete mode 100644 src/i2c_lps22.c delete mode 100644 src/i2c_lps25.c delete mode 100644 src/i2c_mcp9808.c delete mode 100644 src/i2c_ms8607.c delete mode 100644 src/i2c_pct2075.c delete mode 100644 src/i2c_sht3x.c delete mode 100644 src/i2c_sht4x.c delete mode 100644 src/i2c_shtc3.c delete mode 100644 src/i2c_stts22h.c delete mode 100644 src/i2c_tmp102.c delete mode 100644 src/i2c_tmp117.c diff --git a/.gitmodules b/.gitmodules index 6306f7c..4f5dabf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -19,3 +19,6 @@ [submodule "libs/pico-1wire-lib"] path = libs/pico-1wire-lib url = https://github.com/tjko/pico-1wire-lib.git +[submodule "libs/pico-sensor-lib"] + path = libs/pico-sensor-lib + url = https://github.com/tjko/pico-sensor-lib.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 351de1c..6ebe0bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -80,9 +80,12 @@ target_sources(libb64 INTERFACE # pico-telnetd add_subdirectory(libs/pico-telnetd) -# pico-1wire-libe +# pico-1wire-lib add_subdirectory(libs/pico-1wire-lib) +# pico-sensor-lib +add_subdirectory(libs/pico-sensor-lib) + # fanpico firmware @@ -101,23 +104,6 @@ add_executable(fanpico src/tacho.c src/sensors.c src/i2c.c - src/i2c_adt7410.c - src/i2c_aht.c - src/i2c_as621x.c - src/i2c_bmp180.c - src/i2c_bmp280.c - src/i2c_dps310.c - src/i2c_lps22.c - src/i2c_lps25.c - src/i2c_mcp9808.c - src/i2c_ms8607.c - src/i2c_pct2075.c - src/i2c_shtc3.c - src/i2c_sht3x.c - src/i2c_sht4x.c - src/i2c_stts22h.c - src/i2c_tmp102.c - src/i2c_tmp117.c src/onewire.c src/filters.c src/filter_lossypeak.c @@ -179,6 +165,7 @@ target_link_libraries(fanpico PRIVATE bb_spi_lcd-lib libb64 pico_1wire_lib + pico_sensor_lib ) if (PICO_CYW43_SUPPORTED) # set by PICO_BOARD=pico_w diff --git a/README.md b/README.md index d72afb7..75ff290 100644 --- a/README.md +++ b/README.md @@ -201,6 +201,7 @@ Raspberry Pi Pico C/C++ SDK is required for compiling the firmware: * [libb64](https://github.com/libb64/libb64) * [pico-telnetd](https://github.com/tjko/pico-telnetd) * [pico-1wire-lib](https://github.com/tjko/pico-1wire-lib) +* [pico-sensor-lib](https://github.com/tjko/pico-sensor-lib) ##### Install Pico SDK Pico SDK must be installed working before you can compile fanpico. diff --git a/credits.txt b/credits.txt index 7590715..7888eb5 100644 --- a/credits.txt +++ b/credits.txt @@ -1,4 +1,4 @@ -FanPico: Smart PWM (PC) Fan Controller +FanPico: Smart PWM (PC) Fan Controller Copyright (C) 2021-2024 Timo Kokkonen https://github.com/tjko/fanpico @@ -43,3 +43,7 @@ https://github.com/tjko/pico-telnetd pico-1wire-lib Copryight (c) 2024 Timo Kokkonen (tjko@iki.fi) https://github.com/tjko/pico-1wire-lib + +pico-sensor-lib +Copryight (c) 2024 Timo Kokkonen (tjko@iki.fi) +https://github.com/tjko/pico-sensor-lib diff --git a/libs/pico-sensor-lib b/libs/pico-sensor-lib new file mode 160000 index 0000000..81b159c --- /dev/null +++ b/libs/pico-sensor-lib @@ -0,0 +1 @@ +Subproject commit 81b159cceab7fa5ff8e8e19d5bcbe5edf519179c diff --git a/src/command.c b/src/command.c index 2f8c47a..3d9a038 100644 --- a/src/command.c +++ b/src/command.c @@ -34,6 +34,7 @@ #include "pico/rand.h" #include "hardware/watchdog.h" #include "cJSON.h" +#include "pico_sensor_lib.h" #include "fanpico.h" #ifdef WIFI_SUPPORT #include "lwip/ip_addr.h" diff --git a/src/config.c b/src/config.c index 40e6504..378afc6 100644 --- a/src/config.c +++ b/src/config.c @@ -26,6 +26,7 @@ #include "pico/stdlib.h" #include "pico/mutex.h" #include "cJSON.h" +#include "pico_sensor_lib.h" #ifdef WIFI_SUPPORT #include "lwip/ip_addr.h" #endif diff --git a/src/fanpico.h b/src/fanpico.h index 4846a8a..306ea69 100644 --- a/src/fanpico.h +++ b/src/fanpico.h @@ -442,12 +442,8 @@ uint64_t onewire_address(uint sensor); void scan_i2c_bus(); void display_i2c_status(); void setup_i2c_bus(struct fanpico_config *config); -uint get_i2c_sensor_type(const char *name); -const char *i2c_sensor_type_str(uint type); -bool i2c_reserved_address(uint8_t addr); int i2c_read_temps(struct fanpico_config *config); - /* tls.c */ int read_pem_file(char *buf, uint32_t size, uint32_t timeout, bool append); #ifdef WIFI_SUPPORT diff --git a/src/i2c.c b/src/i2c.c index fe4ba60..054321d 100644 --- a/src/i2c.c +++ b/src/i2c.c @@ -26,443 +26,15 @@ #include "pico/stdlib.h" #include "hardware/gpio.h" #include "hardware/i2c.h" +#include "pico_sensor_lib.h" #include "fanpico.h" -#include "i2c.h" - - - -/* i2c_adt7410.c */ -void* adt7410_init(i2c_inst_t *i2c, uint8_t addr); -int adt7410_start_measurement(void *ctx); -int adt7410_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -/* i2c_aht.c */ -void* aht1x_init(i2c_inst_t *i2c, uint8_t addr); -void* aht2x_init(i2c_inst_t *i2c, uint8_t addr); -int aht_start_measurement(void *ctx); -int aht_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -/* i2c_as621x.c */ -void* as621x_init(i2c_inst_t *i2c, uint8_t addr); -int as621x_start_measurement(void *ctx); -int as621x_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -/* i2c_bmp180.c */ -void* bmp180_init(i2c_inst_t *i2c, uint8_t addr); -int bmp180_start_measurement(void *ctx); -int bmp180_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -/* i2c_bmp280.c */ -void* bmp280_init(i2c_inst_t *i2c, uint8_t addr); -int bmp280_start_measurement(void *ctx); -int bmp280_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -/* i2c_dps310.c */ -void* dps310_init(i2c_inst_t *i2c, uint8_t addr); -int dps310_start_measurement(void *ctx); -int dps310_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -/* i2c_lps22.c */ -void* lps22_init(i2c_inst_t *i2c, uint8_t addr); -int lps22_start_measurement(void *ctx); -int lps22_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -/* i2c_lps25.c */ -void* lps25_init(i2c_inst_t *i2c, uint8_t addr); -int lps25_start_measurement(void *ctx); -int lps25_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -/* i2c_mcp9808.c */ -void* mcp9808_init(i2c_inst_t *i2c, uint8_t addr); -int mcp9808_start_measurement(void *ctx); -int mcp9808_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -/* i2c_ms8607.c */ -void* ms8607_init(i2c_inst_t *i2c, uint8_t addr); -int ms8607_start_measurement(void *ctx); -int ms8607_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -/* i2c_pct2075.c */ -void* pct2075_init(i2c_inst_t *i2c, uint8_t addr); -int pct2075_start_measurement(void *ctx); -int pct2075_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -/* i2c_shtc3.c */ -void* shtc3_init(i2c_inst_t *i2c, uint8_t addr); -int shtc3_start_measurement(void *ctx); -int shtc3_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -/* i2c_sht3x.c */ -void* sht3x_init(i2c_inst_t *i2c, uint8_t addr); -int sht3x_start_measurement(void *ctx); -int sht3x_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -/* i2c_sht4x.c */ -void* sht4x_init(i2c_inst_t *i2c, uint8_t addr); -int sht4x_start_measurement(void *ctx); -int sht4x_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -/* i2c_stts22h.c */ -void* stts22h_init(i2c_inst_t *i2c, uint8_t addr); -int stts22h_start_measurement(void *ctx); -int stts22h_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -/* i2c_tmp102.c */ -void* tmp102_init(i2c_inst_t *i2c, uint8_t addr); -int tmp102_start_measurement(void *ctx); -int tmp102_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -/* i2c_tmp117.c */ -void* tmp117_init(i2c_inst_t *i2c, uint8_t addr); -int tmp117_start_measurement(void *ctx); -int tmp117_get_measurement(void *ctx, float *temp, float *pressure, float *humidity); - -static const i2c_sensor_entry_t i2c_sensor_types[] = { - { "NONE", NULL, NULL, NULL, false }, /* this needs to be first so that valid sensors have index > 0 */ - { "ADT7410", adt7410_init, adt7410_start_measurement, adt7410_get_measurement, false }, - { "AHT1x", aht1x_init, aht_start_measurement, aht_get_measurement, false }, - { "AHT2x", aht2x_init, aht_start_measurement, aht_get_measurement, false }, - { "AS621x", as621x_init, as621x_start_measurement, as621x_get_measurement, false }, - { "BMP180", bmp180_init, bmp180_start_measurement, bmp180_get_measurement, false }, - { "BMP280", bmp280_init, bmp280_start_measurement, bmp280_get_measurement, false }, - { "DPS310", dps310_init, dps310_start_measurement, dps310_get_measurement, false }, - { "LPS22", lps22_init, lps22_start_measurement, lps22_get_measurement, false }, - { "LPS25", lps25_init, lps25_start_measurement, lps25_get_measurement, false }, - { "MCP9808", mcp9808_init, mcp9808_start_measurement, mcp9808_get_measurement, false }, - { "MS8607", ms8607_init, ms8607_start_measurement, ms8607_get_measurement, true }, - { "PCT2075", pct2075_init, pct2075_start_measurement, pct2075_get_measurement, false }, - { "SHTC3", shtc3_init, shtc3_start_measurement, shtc3_get_measurement, false }, - { "SHT3x", sht3x_init, sht3x_start_measurement, sht3x_get_measurement, true }, - { "SHT4x", sht4x_init, sht4x_start_measurement, sht4x_get_measurement, true }, - { "STTS22H", stts22h_init, stts22h_start_measurement, stts22h_get_measurement, false }, - { "TMP102", tmp102_init, tmp102_start_measurement, tmp102_get_measurement, false }, - { "TMP117", tmp117_init, tmp117_start_measurement, tmp117_get_measurement, false }, - { NULL, NULL, NULL, NULL, false } -}; + static bool i2c_bus_active = false; static i2c_inst_t *i2c_bus = NULL; static int i2c_temp_sensors = 0; -uint i2c_current_baudrate = I2C_DEFAULT_SPEED / 1000; // kHz - - -static int i2c_init_sensor(uint8_t type, uint8_t addr, void **ctx) -{ - uint8_t buf[2]; - - if (type < 1 || !ctx || i2c_reserved_address(addr)) - return -1; - - /* Check for a device on given address... */ - if (!i2c_sensor_types[type].no_scan) { - if (i2c_read_timeout_us(i2c_bus, addr, buf, 1, false, - I2C_READ_TIMEOUT(1)) < 0) - return -2; - } - - /* Initialize sensor */ - *ctx = i2c_sensor_types[type].init(i2c_bus, addr); - - return (*ctx ? 0 : -3); -} - - -static int i2c_start_measurement(int sensor_type, void *ctx) -{ - if (sensor_type < 1 || !ctx) - return -1; - - return i2c_sensor_types[sensor_type].start_measurement(ctx); -} - -static int i2c_get_measurement(int sensor_type, void *ctx, float *temp, float *pressure, float *humidity) -{ - if (sensor_type < 1 || !ctx) - return -1; - - return i2c_sensor_types[sensor_type].get_measurement(ctx, temp, pressure, humidity); -} - - - -inline int32_t twos_complement(uint32_t value, uint8_t bits) -{ - uint32_t mask = ((uint32_t)0xffffffff >> (32 - bits)); - - if (value & ((uint32_t)1 << (bits - 1))) { - /* negative value, set high bits */ - value |= ~mask; - } else { - /* positive value, clear high bits */ - value &= mask; - } - - return (int32_t)value; -} - - -inline bool i2c_reserved_address(uint8_t addr) -{ - return (addr & 0x78) == 0 || (addr & 0x78) == 0x78; -} - - -int i2c_read_register_block(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint8_t *buf, size_t len, - uint32_t read_delay_us) -{ - int res; - - DEBUG_PRINT("args=%p,%02x,%02x,%p,%u\n", i2c, addr, reg, buf, len); - res = i2c_write_timeout_us(i2c, addr, ®, 1, true, - I2C_WRITE_TIMEOUT(1)); - if (res < 1) { - DEBUG_PRINT("write failed (%d)\n", res); - return -1; - } - - if (read_delay_us > 0) - sleep_us(read_delay_us); - - res = i2c_read_timeout_us(i2c, addr, buf, len, false, - I2C_READ_TIMEOUT(len)); - if (res < len) { - DEBUG_PRINT("read failed (%d)\n", res); - return -2; - } else { -#if I2C_DEBUG > 0 - DEBUG_PRINT("read ok: "); - for(int i = 0; i < len; i++) { - printf(" %02x", buf[i]); - } - printf("\n"); -#endif - } - - return 0; -} - - -int i2c_read_register_u24(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint32_t *val) -{ - uint8_t buf[3]; - int res; - - DEBUG_PRINT("args=%p,%02x,%02x,%p\n", i2c, addr, reg, val); - res = i2c_read_register_block(i2c, addr, reg, buf, sizeof(buf), 0); - if (res) { - DEBUG_PRINT("failed to read register\n"); - return -1; - } - - *val = (buf[0] << 16) | (buf[1] << 8) | buf[2]; - DEBUG_PRINT("read ok: [%02x %02x %02x] %08lx (%lu)\n", buf[0], buf[1], buf[2], *val, *val); - - return 0; -} - - -int i2c_read_register_u16(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint16_t *val) -{ - uint8_t buf[2]; - int res; - - DEBUG_PRINT("args=%p,%02x,%02x,%p\n", i2c, addr, reg, val); - res = i2c_read_register_block(i2c, addr, reg, buf, sizeof(buf), 0); - if (res) { - DEBUG_PRINT("failed to read register\n"); - return -1; - } - - *val = (buf[0] << 8) | buf[1]; - DEBUG_PRINT("read ok: [%02x %02x] %04x (%u)\n", buf[0], buf[1], *val, *val); - - return 0; -} - - -int i2c_read_register_u8(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint8_t *val) -{ - uint8_t buf[1]; - int res; - - DEBUG_PRINT("args=%p,%02x,%02x,%p\n", i2c, addr, reg, val); - res = i2c_read_register_block(i2c, addr, reg, buf, sizeof(buf), 0); - if (res) { - DEBUG_PRINT("failed to read register\n"); - return -1; - } - - *val = buf[0]; - DEBUG_PRINT("read ok: %02x (%u)\n", *val, *val); - - return 0; -} - - -int i2c_write_register_block(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, const uint8_t *buf, size_t len) -{ - uint8_t tmp[128]; - int res; - - DEBUG_PRINT("args=%p,%02x,%02x,%p,%u\n", i2c, addr, reg, buf, len); - tmp[0] = reg; - if (len >= sizeof(tmp)) { - DEBUG_PRINT("too large buffer: %d\n", len); - return -1; - } - memcpy(&tmp[1], buf, len); - res = i2c_write_timeout_us(i2c, addr, buf, len + 1, false, - I2C_WRITE_TIMEOUT(len + 1)); - if (res < len + 1) { - DEBUG_PRINT("write register values failed (%d)\n", res); - return -2; - } else { -#if I2C_DEBUG > 0 - DEBUG_PRINT("write ok: %d [", res); - for(int i = 0; i <= len; i++) { - printf(" %02x", tmp[i]); - } - printf(" ]\n"); -#endif - } - - return 0; -} - - -int i2c_write_register_u16(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint16_t val) -{ - uint8_t buf[3]; - int res; - - buf[0] = reg; - buf[1] = val >> 8; - buf[2] = val & 0xff; - - DEBUG_PRINT("args=%p,%02x,%02x,%04x (%u)\n", i2c, addr, reg, val, val); - - res = i2c_write_timeout_us(i2c, addr, buf, 3, false, - I2C_WRITE_TIMEOUT(3)); - if (res < 3) { - DEBUG_PRINT("write failed (%d)\n", res); - return -1; - } - - return 0; -} - - -int i2c_write_register_u8(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint8_t val) -{ - uint8_t buf[2]; - int res; - - buf[0] = reg; - buf[1] = val; - - DEBUG_PRINT("args=%p,%02x,%02x,%02x (%u)\n", i2c, addr, reg, val, val); - - res = i2c_write_timeout_us(i2c, addr, buf, 2, false, - I2C_WRITE_TIMEOUT(2)); - if (res < 2) { - DEBUG_PRINT("write failed (%d)\n", res); - return -1; - } - - return 0; -} - - -int i2c_read_raw(i2c_inst_t *i2c, uint8_t addr, uint8_t *buf, size_t len, bool nostop) -{ - int res; - - DEBUG_PRINT("args=%p,%02x,%p,%u\n", i2c, addr, buf, len); - - res = i2c_read_timeout_us(i2c, addr, buf, len, nostop, - I2C_READ_TIMEOUT(len)); - if (res < len) { - DEBUG_PRINT("read failed (%d)\n", res); - return -2; - } - - DEBUG_PRINT("read ok: %u\n", len); - - return 0; -} - - -int i2c_write_raw_u16(i2c_inst_t *i2c, uint8_t addr, uint16_t cmd, bool nostop) -{ - uint8_t buf[2]; - int res; - - buf[0] = cmd >> 8; - buf[1] = cmd & 0xff; - - DEBUG_PRINT("args=%p,%02x,%04x\n", i2c, addr, cmd); - - res = i2c_write_timeout_us(i2c, addr, buf, 2, nostop, - I2C_WRITE_TIMEOUT(2)); - if (res < 2) { - DEBUG_PRINT("write failed (%d)\n", res); - return -1; - } - - return 0; -} - - -int i2c_write_raw_u8(i2c_inst_t *i2c, uint8_t addr, uint8_t cmd, bool nostop) -{ - int res; - - DEBUG_PRINT("args=%p,%02x,%04x\n", i2c, addr, cmd); - - res = i2c_write_timeout_us(i2c, addr, &cmd, 1, nostop, - I2C_WRITE_TIMEOUT(1)); - if (res < 1) { - DEBUG_PRINT("write failed (%d)\n", res); - return -1; - } - - return 0; -} - - -uint get_i2c_sensor_type(const char *name) -{ - int type = -1; - int len; - - if (!name) - return 0; - - len = strlen(name); - - for (int i = 0; i2c_sensor_types[i].name; i++) { - if (!strncasecmp(i2c_sensor_types[i].name, name, len)) { - type = i; - break; - } - } - - return (type > 0 ? type : 0); -} - - -const char *i2c_sensor_type_str(uint type) -{ - for (int i = 0; i2c_sensor_types[i].name; i++) { - if (i == type) { - return i2c_sensor_types[i].name; - } - } - - return "NONE"; -} void scan_i2c_bus() @@ -479,8 +51,7 @@ void scan_i2c_bus() for (uint addr = 0; addr < 0x80; addr++) { if (i2c_reserved_address(addr)) continue; - res = i2c_read_timeout_us(i2c_bus, addr, buf, 1, false, - I2C_READ_TIMEOUT(1)); + res = i2c_read_timeout_us(i2c_bus, addr, buf, 1, false, 10000); if (res < 0) continue; if (found > 0) @@ -503,6 +74,7 @@ void display_i2c_status() void setup_i2c_bus(struct fanpico_config *config) { int res; + uint baudrate; i2c_bus_active = false; #if SDA_PIN >= 0 @@ -518,9 +90,10 @@ void setup_i2c_bus(struct fanpico_config *config) log_msg(LOG_INFO, "Initializing I2C Bus.."); i2c_bus = (I2C_HW > 1 ? i2c1 : i2c0); - i2c_current_baudrate = i2c_init(i2c_bus, config->i2c_speed); - i2c_current_baudrate /= 1000; - log_msg(LOG_INFO, "I2C Bus initalized at %u kHz", i2c_current_baudrate); + baudrate = i2c_init(i2c_bus, config->i2c_speed); + baudrate /= 1000; + i2c_sensor_baudrate(baudrate); + log_msg(LOG_INFO, "I2C Bus initalized at %u kHz", baudrate); gpio_set_function(SDA_PIN, GPIO_FUNC_I2C); gpio_set_function(SCL_PIN, GPIO_FUNC_I2C); gpio_pull_up(SDA_PIN); @@ -535,10 +108,10 @@ void setup_i2c_bus(struct fanpico_config *config) if (v->mode != VSMODE_I2C) continue; - if (v->i2c_type < 1 || i2c_reserved_address(v->i2c_addr)) + if (v->i2c_type < 1) continue; - res = i2c_init_sensor(v->i2c_type, v->i2c_addr, &ctx); + res = i2c_init_sensor(v->i2c_type, i2c_bus, v->i2c_addr, &ctx); if (res) { log_msg(LOG_NOTICE, "I2C Device %s (at 0x%02x): failed to initialize: %d", i2c_sensor_type_str(v->i2c_type), v->i2c_addr, res); @@ -578,7 +151,7 @@ int i2c_read_temps(struct fanpico_config *config) continue; if (v->i2c_type < 1 || !config->i2c_context[i]) continue; - res = i2c_start_measurement(v->i2c_type, config->i2c_context[i]); + res = i2c_start_measurement(config->i2c_context[i]); if (res >= 0) { if (res > wait_time) wait_time = res; @@ -605,7 +178,7 @@ int i2c_read_temps(struct fanpico_config *config) if (v->i2c_type < 1 || !config->i2c_context[i]) continue; - res = i2c_get_measurement(v->i2c_type, config->i2c_context[i], &temp, &pressure, &humidity); + res = i2c_read_measurement(config->i2c_context[i], &temp, &pressure, &humidity); if (res == 0) { if (pressure >= 0.0 || humidity >= 0.0 ) { log_msg(LOG_DEBUG, "vsensor%d: temp=%0.4fC, pressure=%0.2fhPa, humidity=%0.2f%%", diff --git a/src/i2c.h b/src/i2c.h deleted file mode 100644 index 09d450a..0000000 --- a/src/i2c.h +++ /dev/null @@ -1,91 +0,0 @@ -/* i2c.h - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#ifndef FANPICO_I2C_H -#define FANPICO_I2C_H 1 - -#include "hardware/i2c.h" - - - -#define I2C_DEBUG 0 - - -#if I2C_DEBUG > 0 -#define DEBUG_PRINT(fmt, ...) \ - do { \ - uint64_t ttt = to_us_since_boot(get_absolute_time()); \ - printf("[%6llu.%06llu] %s:%d: %s(): " fmt, \ - (ttt / 1000000), (ttt % 1000000), \ - __FILE__, __LINE__, __func__, \ - ##__VA_ARGS__); \ - } while (0) -#else -#define DEBUG_PRINT(...) -#endif - - -extern uint i2c_current_baudrate; // kHz - -#define I2C_TIMEOUT_SCALE_FACTOR (10000 / i2c_current_baudrate) - - -// timeouts in us (at 1000kHz) -#define I2C_READ_BASE_TIMEOUT 10000 -#define I2C_WRITE_BASE_TIMEOUT 10000 - -#define I2C_READ_TIMEOUT(x) ((I2C_READ_BASE_TIMEOUT + (x * 250)) * 10 / I2C_TIMEOUT_SCALE_FACTOR) -#define I2C_WRITE_TIMEOUT(x) ((I2C_WRITE_BASE_TIMEOUT + (x * 250)) * 10 / I2C_TIMEOUT_SCALE_FACTOR) - - -typedef void* (i2c_init_func_t)(i2c_inst_t *i2c, uint8_t addr); -typedef int (i2c_start_measurement_func_t)(void *ctx); -typedef int (i2c_get_measurement_func_t)(void *ctx, float *temp, float *pressure, float *humidity); - -typedef struct i2c_sensor_entry { - const char* name; - i2c_init_func_t *init; - i2c_start_measurement_func_t *start_measurement; - i2c_get_measurement_func_t *get_measurement; - bool no_scan; -} i2c_sensor_entry_t; - - -/* Helper functions for reading/writing sensor registers */ -int i2c_read_register_block(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint8_t *buf, size_t len, - uint32_t read_delay_us); -int i2c_read_register_u24(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint32_t *val); -int i2c_read_register_u16(i2c_inst_t *i2c, uint8_t i2c_addr, uint8_t reg, uint16_t *val); -int i2c_read_register_u8(i2c_inst_t *i2c, uint8_t i2c_addr, uint8_t reg, uint8_t *val); -int i2c_write_register_block(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, const uint8_t *buf, size_t len); -int i2c_write_register_u16(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint16_t val); -int i2c_write_register_u8(i2c_inst_t *i2c, uint8_t addr, uint8_t reg, uint8_t val); - -int i2c_read_raw(i2c_inst_t *i2c, uint8_t addr, uint8_t *buf, size_t len, bool nostop); -int i2c_write_raw_u16(i2c_inst_t *i2c, uint8_t addr, uint16_t cmd, bool nostop); -int i2c_write_raw_u8(i2c_inst_t *i2c, uint8_t addr, uint8_t cmd, bool nostop); - -int32_t twos_complement(uint32_t value, uint8_t bits); - - - - -#endif /* FANPICO_I2C_H */ diff --git a/src/i2c_adt7410.c b/src/i2c_adt7410.c deleted file mode 100644 index fff0dc8..0000000 --- a/src/i2c_adt7410.c +++ /dev/null @@ -1,134 +0,0 @@ -/* i2c_adt7410.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - -/* ADT7410 Registers */ -#define REG_TEMP_MSB 0x00 -#define REG_TEMP_LSB 0x01 -#define REG_STATUS 0x02 -#define REG_CONFIG 0x03 -#define REG_ID 0x0b -#define REG_RESET 0x2f - -#define ADT7410_DEVICE_ID 0xc8 // bits 7-3 (bits 2-0 contain silicon revision) - - -typedef struct adt7410_context_t { - i2c_inst_t *i2c; - uint8_t addr; -} adt7410_context_t; - - - -void* adt7410_init(i2c_inst_t *i2c, uint8_t addr) -{ - int res; - uint8_t val = 0; - uint8_t buf[3]; - adt7410_context_t *ctx = calloc(1, sizeof(adt7410_context_t)); - - - if (!ctx) - return NULL; - ctx->i2c = i2c; - ctx->addr = addr; - - /* Read and verify device ID */ - res = i2c_read_register_u8(i2c, addr, REG_ID, &val); - if (res || (val & 0xf8) != ADT7410_DEVICE_ID) - goto panic; - - /* Reset Sensor */ - buf[0] = REG_RESET; - res = i2c_write_timeout_us(i2c, addr, buf, 1, false, - I2C_WRITE_TIMEOUT(1)); - if (res < 1) - goto panic; - - /* Wait for sensor to soft reset (reset should take 200us per datasheet) */ - sleep_us(250); - - /* Write configuration register */ - res = i2c_write_register_u8(i2c, addr, REG_CONFIG, 0x80); - if (res) - goto panic; - - /* Read configuration register */ - res = i2c_read_register_u8(i2c, addr, REG_CONFIG, &val); - if (res) - goto panic; - - /* Check that confuration is now as expected... */ - if (val != 0x80) - goto panic; - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -int adt7410_start_measurement(void *ctx) -{ - /* Nothing to do, sensor is in continuous measurement mode... */ - - return 1000; /* measurement should be available after 1s */ -} - - -int adt7410_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - adt7410_context_t *c = (adt7410_context_t*)ctx; - int res; - uint8_t val; - uint16_t meas; - - - /* Read status register */ - res = i2c_read_register_u8(c->i2c, c->addr, REG_STATUS, &val); - if (res) - return -1; - - /* Check !RDY bit */ - if ((val & 0x80) != 0) - return 1; - - /* Get Measurement */ - res = i2c_read_register_u16(c->i2c, c->addr, REG_TEMP_MSB, &meas); - if (res) - return -2; - - *temp = ((int16_t)meas) / 128.0; - *pressure = -1.0; - *humidity = -1.0; - - return 0; -} diff --git a/src/i2c_aht.c b/src/i2c_aht.c deleted file mode 100644 index 762e5c1..0000000 --- a/src/i2c_aht.c +++ /dev/null @@ -1,180 +0,0 @@ -/* i2c_aht.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - - -/* AHT1x / AHT2x Registers */ - -#define AHT_REG_STATUS 0x71 -#define AHT_REG_START_MEAS 0xac -#define AHT_REG_RESET 0xba -#define AHT2_REG_INIT 0xbe -#define AHT1_REG_INIT 0xe1 - - -typedef struct aht_context_t { - i2c_inst_t *i2c; - uint8_t addr; - uint8_t type; // 1 = AHT1x, 2 = AHX2x -} aht_context_t; - - - -static uint8_t aht_crc8(uint8_t *buf, uint len) -{ - uint8_t crc = 0xff; - - for (uint i = 0; i < len; i++){ - crc ^= buf[i]; - for (uint j = 8; j > 0; --j) { - if (crc & 0x80) - crc = (crc << 1) ^ 0x31; - else - crc = (crc << 1); - } - } - - return crc; -} - - -static void* aht_init(i2c_inst_t *i2c, uint8_t addr, uint8_t type) -{ - int res; - uint8_t buf[2]; - aht_context_t *ctx = calloc(1, sizeof(aht_context_t)); - - if (!ctx) - return NULL; - ctx->i2c = i2c; - ctx->addr = addr; - ctx->type = type; - - /* Reset sensor*/ - buf[0] = AHT_REG_RESET; - res = i2c_write_timeout_us(i2c, addr, buf, 1, false, - I2C_WRITE_TIMEOUT(1)); - if (res < 1) - goto panic; - - /* Wait for sensor to soft reset (should be done in 20ms?) */ - sleep_us(25000); - - /* Write initialization register: set normal mode */ - res = i2c_write_register_u16(i2c, addr, - (type == 1 ? AHT1_REG_INIT : AHT2_REG_INIT), - 0x0800); - if (res) - goto panic; - - /* Read status register */ - res = i2c_read_register_u8(i2c, addr, AHT_REG_STATUS, buf); - if (res) - goto panic; - - /* Check that calibration bit is on */ - if ((buf[0] & 0x08) == 0) - goto panic; - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -void* aht1x_init(i2c_inst_t *i2c, uint8_t addr, uint8_t type) -{ - return aht_init(i2c, addr, 1); -} - - -void* aht2x_init(i2c_inst_t *i2c, uint8_t addr, uint8_t type) -{ - return aht_init(i2c, addr, 2); -} - - -int aht_start_measurement(void *ctx) -{ - aht_context_t *c = (aht_context_t*)ctx; - int res; - - /* Send start measurement command */ - res = i2c_write_register_u16(c->i2c, c->addr, AHT_REG_START_MEAS, 0x3300); - if (res) { - DEBUG_PRINT("aht: start measure failed: %d\n", res); - } - - return 100; /* measurement should be available after 100ms */ -} - - -int aht_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - aht_context_t *c = (aht_context_t*)ctx; - int res; - uint8_t buf[7]; - uint32_t raw_t, raw_h; - int len = c->type == 1 ? 6 : 7; - - /* Read data from sensor... */ - res = i2c_read_timeout_us(c->i2c, c->addr, buf, len, false, - I2C_READ_TIMEOUT(len)); - if (res < len) - return -1; - - DEBUG_PRINT("aht: len=%d, status=%02x\n", len, buf[0]); - - /* Check busy bit */ - if ((buf[0] & 0x80)) - return -2; - - /* Check CRC */ - if (c->type == 2) { - if (aht_crc8(buf, len - 1) != buf[len - 1]) { - DEBUG_PRINT("aht2x: CRC mismatch\n"); - return -3; - } - } - - raw_h = (buf[1] << 12) | (buf[2] << 4) | (buf[3] >> 4); - if (raw_h > 0x100000) - raw_h = 0x100000; - raw_t = ((buf[3] & 0x0f) << 16) | (buf[4] << 8) | buf[5]; - - - *temp = ((double)raw_t / 0x100000) * 200 - 50; - *humidity = ((double)raw_h / 0x100000) * 100; - *pressure = -1.0; - - return 0; -} - diff --git a/src/i2c_as621x.c b/src/i2c_as621x.c deleted file mode 100644 index 6e14ea5..0000000 --- a/src/i2c_as621x.c +++ /dev/null @@ -1,138 +0,0 @@ -/* i2c_as621x.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - -/* AS621x (AS6212/AS6214/AS6128) Registers */ -#define REG_TVAL 0x00 -#define REG_CONFIG 0x01 -#define REG_T_LOW 0x02 -#define REG_T_HIGH 0x03 - - -#define AS621X_DEVICE_ID 0x117 - -typedef struct as621x_context_t { - i2c_inst_t *i2c; - uint8_t addr; -} as621x_context_t; - - -void* as621x_init(i2c_inst_t *i2c, uint8_t addr) -{ - int res; - uint16_t val = 0; - int16_t temp; - as621x_context_t *ctx = calloc(1, sizeof(as621x_context_t)); - - if (!ctx) - return NULL; - ctx->i2c = i2c; - ctx->addr = addr; - - - /* Check that configuration register reserved bits are set as expected for AS621x */ - - res = i2c_read_register_u16(i2c, addr, REG_CONFIG, &val); - if (res || (val & 0x601f) != 0x4000) - goto panic; - - - /* Try to detect device by T_HIGH and T_LOW register default values (80C and 75C) */ - - res = i2c_read_register_u16(i2c, addr, REG_T_HIGH, &val); - if (res) - goto panic; - temp = (int16_t)val / 128; - DEBUG_PRINT("T_high = %d\n", temp); - if (temp != 80) - goto panic; - - res = i2c_read_register_u16(i2c, addr, REG_T_LOW, &val); - if (res) - goto panic; - temp = (int16_t)val / 128; - DEBUG_PRINT("T_low = %d\n", temp); - if (temp != 75) - goto panic; - - - /* Set sensor configuration: continuous measruements at 4Hz */ - res = i2c_write_register_u16(i2c, addr, REG_CONFIG, 0x00a0); - if (res) - goto panic; - - sleep_us(100); - - /* Read configuration register */ - res = i2c_read_register_u16(i2c, addr, REG_CONFIG, &val); - if (res) - goto panic; - - /* Check that confuration is now as expected (excluding read-only reserved bits)... */ - if ((val & 0x9fe0) != 0x00a0) - goto panic; - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -int as621x_start_measurement(void *ctx) -{ - /* Nothing to do, sensor is in continuous measurement mode... */ - - return 250; /* measurement should be available after 250ms */ -} - - -int as621x_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - as621x_context_t *c = (as621x_context_t*)ctx; - int res; - uint16_t val; - - - /* Get Measurement */ - res = i2c_read_register_u16(c->i2c, c->addr, REG_TVAL, &val); - if (res) - return -2; - - *temp = ((int16_t)val) / 128.0; - DEBUG_PRINT("t_raw = %d, temp=%0.2f\n", val, *temp); - - *pressure = -1.0; - *humidity = -1.0; - - return 0; -} - - diff --git a/src/i2c_bmp180.c b/src/i2c_bmp180.c deleted file mode 100644 index 7efa30b..0000000 --- a/src/i2c_bmp180.c +++ /dev/null @@ -1,232 +0,0 @@ -/* i2c_bmp180.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - -/* BMP180 Registers */ -#define REG_CALIB 0xaa // 0xaa to 0xbf -#define REG_ID 0xd0 -#define REG_RESET 0xe0 // write 0xb6 to reset -#define REG_CTRL_MEAS 0xf4 -#define REG_OUT_MSB 0xf6 -#define REG_OUT_LSB 0xf7 -#define REG_OUT_XLSB 0xf8 - - -#define BMP180_DEVICE_ID 0x55 - - -typedef struct bmp180_context_t { - i2c_inst_t *i2c; - uint8_t addr; - uint8_t state; - int32_t temp; - int32_t pressure; - // Calibration Data - int16_t ac1; - int16_t ac2; - int16_t ac3; - uint16_t ac4; - uint16_t ac5; - uint16_t ac6; - int16_t b1; - int16_t b2; - int16_t mb; - int16_t mc; - int16_t md; - // Calculation vars - int32_t x1; - int32_t x2; - int32_t b5; -} bmp180_context_t; - - - -void* bmp180_init(i2c_inst_t *i2c, uint8_t addr) -{ - bmp180_context_t *ctx = calloc(1, sizeof(bmp180_context_t)); - uint8_t buf[22]; - uint8_t val = 0; - int res; - - if (!ctx) - return NULL; - ctx->i2c = i2c; - ctx->addr = addr; - ctx->state = 0; - ctx->temp = 0; - ctx->pressure = -1; - - /* Read and verify device ID */ - res = i2c_read_register_u8(i2c, addr, REG_ID, &val); - if (res || (val != BMP180_DEVICE_ID)) - goto panic; - - /* Reset Sensor */ - res = i2c_write_register_u8(i2c, addr, REG_RESET, 0xb6); - if (res) - goto panic; - - /* Wait for sensor to soft reset (reset should take 2ms per datasheet) */ - sleep_ms(10); - - - /* Read calibration data */ - res = i2c_read_register_block(i2c, addr, REG_CALIB, buf, 22, 0); - if (res) - goto panic; - - ctx->ac1 = (buf[0] << 8) | buf[1]; - ctx->ac2 = (buf[2] << 8) | buf[3]; - ctx->ac3 = (buf[4] << 8) | buf[5]; - ctx->ac4 = (buf[6] << 8) | buf[7]; - ctx->ac5 = (buf[8] << 8) | buf[9]; - ctx->ac6 = (buf[10] << 8) | buf[11]; - DEBUG_PRINT("ac1=%04x %d\n", ctx->ac1, ctx->ac1); - DEBUG_PRINT("ac2=%04x %d\n", ctx->ac2, ctx->ac2); - DEBUG_PRINT("ac3=%04x %d\n", ctx->ac3, ctx->ac3); - DEBUG_PRINT("ac4=%04x %u\n", ctx->ac4, ctx->ac4); - DEBUG_PRINT("ac5=%04x %u\n", ctx->ac5, ctx->ac5); - DEBUG_PRINT("ac6=%04x %u\n", ctx->ac6, ctx->ac6); - - ctx->b1 = (buf[12] << 8) | buf[13]; - ctx->b2 = (buf[14] << 8) | buf[15]; - ctx->mb = (buf[16] << 8) | buf[17]; - ctx->mc = (buf[18] << 8) | buf[19]; - ctx->md = (buf[20] << 8) | buf[21]; - DEBUG_PRINT("b1=%04x %d\n", ctx->b1, ctx->b1); - DEBUG_PRINT("b2=%04x %d\n", ctx->b2, ctx->b2); - DEBUG_PRINT("mb=%04x %d\n", ctx->mb, ctx->mb); - DEBUG_PRINT("mc=%04x %d\n", ctx->mc, ctx->mc); - DEBUG_PRINT("md=%04x %d\n", ctx->md, ctx->md); - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -int bmp180_start_measurement(void *ctx) -{ - bmp180_context_t *c = (bmp180_context_t*)ctx; - uint8_t val; - int t; - - if (c->state == 0) { - /* measure temp */ - val = 0x2e; - t = 10; - } else { - val = 0xf4; - t = 30; - } - i2c_write_register_u8(c->i2c, c->addr, REG_CTRL_MEAS, val); - - return t; -} - - -/* Calculactions based on datasheet example */ -static int32_t bmp180_compensated_t(int32_t ut, bmp180_context_t *c) -{ - int32_t t; - - c->x1 = (ut - (uint32_t)c->ac6) * (uint32_t)c->ac5 / 32768; - c->x2 = (int32_t)c->mc * 2048 / (c->x1 + c->md); - c->b5 = c->x1 + c->x2; - t = (c->b5 + 8) / 16; - - return t; -} - - -/* Calculactions based on datasheet example */ -static int32_t bmp180_compensated_p(int32_t up, bmp180_context_t *c) -{ - int32_t b3, b6, x1, x2, x3, p; - uint32_t b4, b7; - - b6 = c->b5 - 4000; - x1 = ((int32_t)c->b2 * (b6 * b6 / 4096)) / 2048; - x2 = (int32_t)c->ac2 * b6 / 2048; - x3 = x1 + x2; - b3 = ((((int32_t)c->ac1 * 4 + x3) << 3) + 2) / 4; - x1 = (int32_t)c->ac3 * b6 / 8192; - x2 = ((int32_t)c->b1 * (b6 * b6 / 4096)) / 32768; - x3 = ((x1 + x2) + 2) / 4; - b4 = (uint32_t)c->ac4 * (uint32_t)(x3 + 32768) / 32768; - b7 = ((uint32_t)up - b3) * (50000 >> 3); - - if (b7 < 0x80000000) - p = (b7 * 2) / b4; - else - p = (b7 / b4) * 2; - - x1 = (p / 256) * (p / 256); - x1 = (x1 * 3038) / 65536; - x2 = (-7357 * p) / 65536; - p = p + (x1 + x2 + 3791) / 16; - - return p; -} - - -int bmp180_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - bmp180_context_t *c = (bmp180_context_t*)ctx; - int res; - uint16_t t_raw; - uint32_t p; - - if (c->state == 0) { - /* Read temperature measurement */ - res = i2c_read_register_u16(c->i2c, c->addr, REG_OUT_MSB, &t_raw); - if (res) - return -2; - c->temp = bmp180_compensated_t(t_raw, c); - DEBUG_PRINT("raw temp = %u, temp=%ld\n", t_raw, c->temp); - c->state = 1; - } else { - /* Read pressure measurement */ - res = i2c_read_register_u24(c->i2c, c->addr, REG_OUT_MSB, &p); - if (res) - return -3; - p >>= 5; - c->pressure = bmp180_compensated_p(p, c); - DEBUG_PRINT("raw pressure = %lu, pressure = %ld\n", p, c->pressure); - c->state = 0; - } - - *temp = c->temp / 10.0; - *pressure = (float)c->pressure; - *humidity = -1.0; - - return 0; -} diff --git a/src/i2c_bmp280.c b/src/i2c_bmp280.c deleted file mode 100644 index 9d4ab6b..0000000 --- a/src/i2c_bmp280.c +++ /dev/null @@ -1,213 +0,0 @@ -/* i2c_bmp280.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - -/* BMP280 Registers */ -#define REG_CALIB 0x88 // 0x88 - 0xa1 -#define REG_ID 0xd0 -#define REG_RESET 0xe0 // write 0xb6 to reset -#define REG_STATUS 0xf3 -#define REG_CTRL_MEAS 0xf4 -#define REG_CONFIG 0xf5 -#define REG_PRESS_MSB 0xf7 -#define REG_PRESS_LSB 0xf8 -#define REG_PRESS_XLSB 0xf9 -#define REG_TEMP_MSB 0xfa -#define REG_TEMP_LSB 0xfb -#define REG_TEMP_XLSB 0xfc - - -#define BMP280_DEVICE_ID 0x58 - - -typedef struct bmp280_context_t { - i2c_inst_t *i2c; - uint8_t addr; - // Calibration Data - uint16_t t1; - int16_t t2; - int16_t t3; - uint16_t p1; - int16_t p2; - int16_t p3; - int16_t p4; - int16_t p5; - int16_t p6; - int16_t p7; - int16_t p8; - int16_t p9; -} bmp280_context_t; - - - -void* bmp280_init(i2c_inst_t *i2c, uint8_t addr) -{ - bmp280_context_t *ctx = calloc(1, sizeof(bmp280_context_t)); - uint8_t buf[26]; - uint8_t val = 0; - int res; - - if (!ctx) - return NULL; - ctx->i2c = i2c; - ctx->addr = addr; - - - /* Read and verify device ID */ - res = i2c_read_register_u8(i2c, addr, REG_ID, &val); - if (res || (val != BMP280_DEVICE_ID)) - goto panic; - - /* Reset Sensor */ - res = i2c_write_register_u8(i2c, addr, REG_RESET, 0xb6); - if (res) - goto panic; - - /* Wait for sensor to soft reset (reset should take 2ms per datasheet) */ - sleep_ms(10); - - /* Set CTRL_MEAS register: oversampling 16x (p)/ 2x (t), normal mode */ - res = i2c_write_register_u8(i2c, addr, REG_CTRL_MEAS, 0xab); - if (res) - goto panic; - - /* Set CONFIG register: t_standby = 0.5ms, filter = 16 */ - res = i2c_write_register_u8(i2c, addr, REG_CONFIG, 0x1c); - if (res) - goto panic; - - - - /* Read calibration data */ - res = i2c_read_register_block(i2c, addr, REG_CALIB, buf, 26, 0); - if (res) - goto panic; - - ctx->t1 = (buf[0] | (buf[1] << 8)); - ctx->t2 = (buf[2] | (buf[3] << 8)); - ctx->t3 = (buf[4] | (buf[5] << 8)); - DEBUG_PRINT("t1=%04x %u\n", ctx->t1, ctx->t1); - DEBUG_PRINT("t2=%04x %d\n", ctx->t2, ctx->t2); - DEBUG_PRINT("t2=%04x %d\n", ctx->t3, ctx->t3); - - ctx->p1 = (buf[6] | (buf[7] << 8)); - ctx->p2 = (buf[8] | (buf[9] << 8)); - ctx->p3 = (buf[10] | (buf[11] << 8)); - ctx->p4 = (buf[12] | (buf[13] << 8)); - ctx->p5 = (buf[14] | (buf[15] << 8)); - ctx->p6 = (buf[16] | (buf[17] << 8)); - ctx->p7 = (buf[18] | (buf[19] << 8)); - ctx->p8 = (buf[20] | (buf[21] << 8)); - ctx->p9 = (buf[22] | (buf[23] << 8)); - DEBUG_PRINT("p1=%04x %u\n", ctx->p1, ctx->p1); - DEBUG_PRINT("p2=%04x %d\n", ctx->p2, ctx->p2); - DEBUG_PRINT("p3=%04x %d\n", ctx->p3, ctx->p3); - DEBUG_PRINT("p4=%04x %d\n", ctx->p4, ctx->p4); - DEBUG_PRINT("p5=%04x %d\n", ctx->p5, ctx->p5); - DEBUG_PRINT("p6=%04x %d\n", ctx->p6, ctx->p6); - DEBUG_PRINT("p7=%04x %d\n", ctx->p7, ctx->p7); - DEBUG_PRINT("p8=%04x %d\n", ctx->p8, ctx->p8); - DEBUG_PRINT("p9=%04x %d\n", ctx->p9, ctx->p9); - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -int bmp280_start_measurement(void *ctx) -{ - /* Nothing to do, sensor is in continuous measurement mode... */ - - return 1000; /* measurement should be available after 1s */ -} - - -/* Temperature compensation based on datasheet example */ -static int32_t bmp280_compensate_t(int32_t adc_t, int32_t *t_fine, bmp280_context_t *c) -{ - int32_t var1, var2, t; - - var1 = ((((adc_t >> 3) - ((int32_t)c->t1 << 1))) * ((int32_t)c->t2)) >> 11; - var2 = (((((adc_t >> 4) - ((int32_t)c->t1)) * ((adc_t >> 4) - ((int32_t)c->t1))) >> 12) * ((int32_t)c->t3)) >> 14; - *t_fine = var1 + var2; - t = (*t_fine * 5 + 128) >> 8; - - return t; -} - - -/* Pressure compensation based on datasheet example */ -static uint32_t bmp280_compensate_p(int32_t adc_p, int32_t t_fine, bmp280_context_t *c) -{ - int64_t var1, var2, p; - - var1 = ((int64_t)t_fine) - 128000; - var2 = var1 * var1 * (int64_t)c->p6; - var2 = var2 + ((var1 * (int64_t)c->p5) << 17); - var2 = var2 + (((int64_t)c->p4) << 35); - var1 = ((var1 * var1 * (int64_t)c->p3) >> 8) + ((var1 * (int64_t)c->p2) << 12); - var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)c->p1) >> 33; - if (var1 == 0) - return 0; - p = 1048576 - adc_p; - p = (((p << 31) - var2) * 3125) / var1; - var1 = (((int64_t)c->p9) * (p >> 13) * (p >> 13)) >> 25; - var2 = (((int64_t)c->p8) * p) >> 19; - p = ((p + var1 + var2) >> 8) + (((int64_t)c->p7) << 4); - - return (uint32_t)p; -} - - -int bmp280_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - bmp280_context_t *c = (bmp280_context_t*)ctx; - int res; - uint8_t buf[6]; - int32_t p_raw, t_raw, t_fine; - - - /* Read Pressure & Temperature registers */ - res = i2c_read_register_block(c->i2c, c->addr, REG_PRESS_MSB, buf, 6, 0); - if (res) - return -2; - - p_raw = (buf[0] << 12) | (buf[1] << 4) | (buf[2] >> 4); - t_raw = (buf[3] << 12) | (buf[4] << 4) | (buf[5] >> 4); - DEBUG_PRINT("p_raw=%ld, t_raw=%ld\n", p_raw, t_raw); - - *temp = bmp280_compensate_t(t_raw, &t_fine, c) / 100.0; - *pressure = bmp280_compensate_p(p_raw, t_fine, c) / 256.0; - *humidity = -1.0; - - return 0; -} diff --git a/src/i2c_dps310.c b/src/i2c_dps310.c deleted file mode 100644 index 1bf91f7..0000000 --- a/src/i2c_dps310.c +++ /dev/null @@ -1,234 +0,0 @@ -/* i2c_dps310.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - -/* DPS310 Registers */ -#define REG_PSR_B2 0x00 -#define REG_PSR_B1 0x01 -#define REG_PST_B0 0x02 -#define REG_TMP_B2 0x03 -#define REG_TMP_B1 0x04 -#define REG_TMP_B0 0x05 -#define REG_PRS_CFG 0x06 -#define REG_TMP_CFG 0x07 -#define REG_MEAS_CFG 0x08 -#define REG_CFG 0x09 -#define REG_INT_STS 0x0a -#define REG_FIFO_STS 0x0b -#define REG_RESET 0x0c -#define REG_ID 0x0d -#define REG_COEF 0x10 // 0x10 - 0x21 (18 bytes to read) -#define REG_COEF_SRCE 0x28 - - -#define DPS310_DEVICE_ID 0x10 // revision id [7:4], product id [3:0] - -#define SCALE_FACTOR 1040384 // 64 times oversampling (high precision) - -typedef struct dps310_context_t { - i2c_inst_t *i2c; - uint8_t addr; - float temp; - float pressure; - // Calibration Coefficients - int16_t c0; - int16_t c1; - int32_t c00; - int32_t c10; - int16_t c01; - int16_t c11; - int16_t c20; - int16_t c21; - int16_t c30; -} dps310_context_t; - - - -void* dps310_init(i2c_inst_t *i2c, uint8_t addr) -{ - int res; - uint8_t val = 0; - uint8_t buf[18]; - uint8_t coef_source; - dps310_context_t *ctx = calloc(1, sizeof(dps310_context_t)); - - - if (!ctx) - return NULL; - ctx->i2c = i2c; - ctx->addr = addr; - ctx->temp = 0.0; - ctx->pressure = -1.0; - - /* Read and verify device ID */ - res = i2c_read_register_u8(i2c, addr, REG_ID, &val); - if (res || (val & 0x0f) != (DPS310_DEVICE_ID & 0x0f)) - goto panic; - /* Revision ID should greater than zero... */ - if (val >> 4 == 0) - goto panic; - - - /* Reset Sensor */ - res = i2c_write_register_u8(i2c, addr, REG_RESET, 0x89); - if (res) - goto panic; - - /* Wait for sensor to soft reset (reset should take 40ms per datasheet) */ - sleep_ms(40); - - /* Get coefficient source */ - res = i2c_read_register_u8(i2c, addr, REG_COEF_SRCE, &val); - if (res) - goto panic; - coef_source = (val >> 7); - - - /* Write configuration registers */ - - // 4 pressure measruementes per second, 64 times oversampling - res = i2c_write_register_u8(i2c, addr, REG_PRS_CFG, 0x26); - if (res) - goto panic; - // 4 temp measurements per second, 64 times oversampling - res = i2c_write_register_u8(i2c, addr, REG_TMP_CFG, (coef_source << 7) | 0x26); - if (res) - goto panic; - // enable continuous pressure and temperature measurement - res = i2c_write_register_u8(i2c, addr, REG_MEAS_CFG, 0x07); - if (res) - goto panic; - // enable pressure result bit-shift and temperature result bit-shift - res = i2c_write_register_u8(i2c, addr, REG_CFG, 0x0c); - if (res) - goto panic; - - - /* Get sensor status and check COEF_RDY bit */ - res = i2c_read_register_u8(i2c, addr, REG_MEAS_CFG, &val); - if (res || (val & 0x80) == 0) - goto panic; - - /* Read calibration coefficients */ - res = i2c_read_register_block(i2c, addr, REG_COEF, buf, 18, 0); - if (res) - goto panic; - - ctx->c0 = twos_complement((buf[0] << 4) | (buf[1] >> 4), 12); - DEBUG_PRINT("c0 = %08x %d\n", ctx->c0, ctx->c0); - - ctx->c1 = twos_complement(((buf[1] & 0x0f) << 8) | (buf[2]), 12); - DEBUG_PRINT("c1 = %08x %d\n", ctx->c1, ctx->c1); - - ctx->c00 = twos_complement((buf[3] << 12) | (buf[4] << 4) | (buf[5] >> 4), 20); - DEBUG_PRINT("c00 = %08lx %ld\n", ctx->c00, ctx->c00); - - ctx->c10 = twos_complement(((buf[5] & 0x0f) << 16) | (buf[6] << 8) | buf[7], 20); - DEBUG_PRINT("c10 = %08lx %ld\n", ctx->c10, ctx->c10); - - ctx->c01 = twos_complement((buf[8] << 8) | buf[9], 16); - DEBUG_PRINT("c01 = %08x %d\n", ctx->c01, ctx->c01); - - ctx->c11 = twos_complement((buf[10] << 8) | buf[11], 16); - DEBUG_PRINT("c11 = %08x %d\n", ctx->c11, ctx->c11); - - ctx->c20 = twos_complement((buf[12] << 8) | buf[13], 16); - DEBUG_PRINT("c20 = %08x %d\n", ctx->c20, ctx->c20); - - ctx->c21 = twos_complement((buf[14] << 8) | buf[15], 16); - DEBUG_PRINT("c21 = %08x %d\n", ctx->c21, ctx->c21); - - ctx->c30 = twos_complement((buf[16] << 8) | buf[17], 16); - DEBUG_PRINT("c30 = %08x %d\n", ctx->c30, ctx->c30); - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -int dps310_start_measurement(void *ctx) -{ - /* Nothing to do, sensor is in continuous measurement mode... */ - - return 1000; /* measurement should be available after 1s */ -} - - -int dps310_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - dps310_context_t *c = (dps310_context_t*)ctx; - int res; - uint8_t status; - uint32_t meas; - double t_raw_sc, p_raw_sc; - - - /* Get sensor status */ - res = i2c_read_register_u8(c->i2c, c->addr, REG_MEAS_CFG, &status); - if (res) - return -1; - - /* Get Temperature Measurement if TMP_RDY bit is set */ - if ((status & 0x20)) { - res = i2c_read_register_u24(c->i2c, c->addr, REG_TMP_B2, &meas); - if (res) - return -2; - - t_raw_sc = (double)twos_complement(meas, 24) / SCALE_FACTOR; - DEBUG_PRINT("T_raw_sc = %0.6lf\n", t_raw_sc); - *temp = c->c0 * 0.5 + c->c1 * t_raw_sc; - c->temp = *temp; - } else { - *temp = c->temp; - *pressure = c->pressure; - return 0; - } - - /* Get Pressure Measurement if PRS_RDY bit is set */ - if ((status & 0x10)) { - res = i2c_read_register_u24(c->i2c, c->addr, REG_PSR_B2, &meas); - if (res) - return -4; - - p_raw_sc = (double)twos_complement(meas, 24) / SCALE_FACTOR; - DEBUG_PRINT("P_raw_sc = %0.6lf\n", p_raw_sc); - *pressure = c->c00 + p_raw_sc * (c->c10 + p_raw_sc * (c->c20 + p_raw_sc * c->c30)) - + t_raw_sc * c->c01 + t_raw_sc * p_raw_sc * (c->c11 + p_raw_sc * c->c21); - c->pressure = *pressure; - } else { - *pressure = c->pressure; - } - - *humidity = -1.0; - - return 0; -} diff --git a/src/i2c_lps22.c b/src/i2c_lps22.c deleted file mode 100644 index 410adfd..0000000 --- a/src/i2c_lps22.c +++ /dev/null @@ -1,168 +0,0 @@ -/* i2c_lps22.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - -/* LPS22 Registers */ -#define INTERRUPT_CFG 0x0b -#define THS_P_L 0x0c -#define THS_P_H 0x0d -#define IF_CTRL 0x0e -#define WHO_AM_I 0x0f -#define CTRL_REG1 0x10 -#define CTRL_REG2 0x11 -#define CTRL_REG3 0x12 -#define FIFO_CTRL 0x13 -#define FIFO_WTM 0x14 -#define REF_P_L 0x15 -#define REF_P_H 0x16 -#define RPDS_L 0x18 -#define RPDS_H 0x19 -#define INT_SOURCE 0x24 -#define FIFO_STATUS1 0x25 -#define FIFO_STATUS2 0x26 -#define STATUS 0x27 -#define PRES_OUT_XL 0x28 -#define PRES_OUT_L 0x29 -#define PRES_OUT_H 0x2a -#define TEMP_OUT_L 0x2b -#define TEMP_OUT_H 0x2c -#define FIFO_DATA_OUT_PRESS_XL 0x78 -#define FIFO_DATA_OUT_PRESS_L 0x79 -#define FIFO_DATA_OUT_PRESS_H 0x7a -#define FIFO_DATA_OUT_TEMP_L 0x7b -#define FIFO_DATA_OUT_TEMP_H 0x7c - -#define LPS22_DEVICE_ID 0xb1 - - -typedef struct lps22_context_t { - i2c_inst_t *i2c; - uint8_t addr; -} lps22_context_t; - - -void* lps22_init(i2c_inst_t *i2c, uint8_t addr) -{ - int res; - uint8_t val = 0; - lps22_context_t *ctx = calloc(1, sizeof(lps22_context_t)); - - if (!ctx) - return NULL; - ctx->i2c = i2c; - ctx->addr = addr; - - /* Read and verify device ID */ - res = i2c_read_register_u8(i2c, addr, WHO_AM_I, &val); - if (res || val != LPS22_DEVICE_ID) - goto panic; - - /* Reset Sensor */ - res = i2c_write_register_u8(i2c, addr, CTRL_REG2, 0x04); // SWRESET - if (res) - goto panic; - sleep_us(5); - res = i2c_write_register_u8(i2c, addr, CTRL_REG2, 0x92); // BOOT - if (res) - goto panic; - sleep_us(2300); - - /* Read configuration register */ - res = i2c_read_register_u8(i2c, addr, CTRL_REG2, &val); - if (res) - goto panic; - /* Check that boot is complete */ - if (val & 0x80) - goto panic; - - - /* Set continuous mode and output data rate (25Hz) */ - res = i2c_write_register_u8(i2c, addr, CTRL_REG1, 0x3c); - if (res) - goto panic; - - /* Set FIFO to Continuous mode */ - res = i2c_write_register_u8(i2c, addr, FIFO_CTRL, 0x03); - if (res) - goto panic; - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -int lps22_start_measurement(void *ctx) -{ - /* Nothing to do, sensor is in continuous measurement mode... */ - - return 1000; /* measurement should be available after 1s */ -} - - -int lps22_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - lps22_context_t *c = (lps22_context_t*)ctx; - int res; - uint8_t val; - uint8_t buf[5]; - int32_t t_raw, p_raw; - - - /* Read status register */ - res = i2c_read_register_u8(c->i2c, c->addr, STATUS, &val); - if (res) - return -1; - - /* Check P_DA and T_DA (data available) bits */ - if ((val & 0x03) != 0x03) - return 1; - - /* Get Measurement */ - res = i2c_read_register_block(c->i2c, c->addr, PRES_OUT_XL, buf, sizeof(buf), 0); - if (res) - return -2; - - p_raw = twos_complement((uint32_t)((buf[2] << 16) | (buf[1] << 8) | buf[0]), 24); - t_raw = twos_complement((uint32_t)(((buf[4] << 8) | buf[3])), 16); - - DEBUG_PRINT("t_raw = %ld, p_raw = %ld\n", t_raw, p_raw); - - *temp = t_raw / 100.0; - *pressure = p_raw / 4096.0; - *humidity = -1.0; - - DEBUG_PRINT("temp = %0.1f C, pressure = %0.1f hPa\n", *temp, *pressure); - - return 0; -} - - diff --git a/src/i2c_lps25.c b/src/i2c_lps25.c deleted file mode 100644 index 59ab0b7..0000000 --- a/src/i2c_lps25.c +++ /dev/null @@ -1,158 +0,0 @@ -/* i2c_lps25.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - -/* LPS25 Registers */ -#define WHO_AM_I 0x0f -#define RES_CONF 0x10 -#define CTRL_REG1 0x20 -#define CTRL_REG2 0x21 -#define CTRL_REG3 0x22 -#define CTRL_REG4 0x23 -#define STATUS_REG 0x27 -#define PRES_OUT_XL 0x28 -#define PRES_OUT_L 0x29 -#define PRES_OUT_H 0x2a -#define TEMP_OUT_L 0x2b -#define TEMP_OUT_H 0x2c -#define FIFO_CTRL 0x2e -#define FIFO_STATUS 0x2f - -#define LPS25_DEVICE_ID 0xbd - - -typedef struct lps25_context_t { - i2c_inst_t *i2c; - uint8_t addr; -} lps25_context_t; - - -void* lps25_init(i2c_inst_t *i2c, uint8_t addr) -{ - int res; - uint8_t val = 0; - lps25_context_t *ctx = calloc(1, sizeof(lps25_context_t)); - - if (!ctx) - return NULL; - ctx->i2c = i2c; - ctx->addr = addr; - - /* Read and verify device ID */ - res = i2c_read_register_u8(i2c, addr, WHO_AM_I, &val); - if (res || val != LPS25_DEVICE_ID) - goto panic; - - /* Reset Sensor */ - res = i2c_write_register_u8(i2c, addr, CTRL_REG2, 0x04); // SWRESET - if (res) - goto panic; - sleep_us(5); - res = i2c_write_register_u8(i2c, addr, CTRL_REG2, 0x80); // BOOT - if (res) - goto panic; - sleep_us(2300); - - /* Read configuration register */ - res = i2c_read_register_u8(i2c, addr, CTRL_REG2, &val); - if (res) - goto panic; - /* Check that boot is complete */ - if (val & 0x80) - goto panic; - - /* Set Pressure and temperature resolution */ - res = i2c_write_register_u8(i2c, addr, RES_CONF, 0x0f); - if (res) - goto panic; - - /* Set active mode and output data rate (12.5Hz) */ - res = i2c_write_register_u8(i2c, addr, CTRL_REG1, 0xb0); - if (res) - goto panic; - - /* Set FIFO to Mean mode (32-sample moving average) */ - res = i2c_write_register_u8(i2c, addr, FIFO_CTRL, 0xdf); - if (res) - goto panic; - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -int lps25_start_measurement(void *ctx) -{ - /* Nothing to do, sensor is in continuous measurement mode... */ - - return 1000; /* measurement should be available after 1s */ -} - - -int lps25_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - lps25_context_t *c = (lps25_context_t*)ctx; - int res; - uint8_t val; - uint8_t buf[5]; - int32_t t_raw, p_raw; - - - /* Read status register */ - res = i2c_read_register_u8(c->i2c, c->addr, STATUS_REG, &val); - if (res) - return -1; - - /* Check P_DA and T_DA (data available) bits */ - if ((val & 0x03) != 0x03) - return 1; - - /* Get Measurement */ - res = i2c_read_register_block(c->i2c, c->addr, PRES_OUT_XL | 0x80, buf, sizeof(buf), 0); - if (res) - return -2; - - p_raw = twos_complement((uint32_t)((buf[2] << 16) | (buf[1] << 8) | buf[0]), 24); - t_raw = twos_complement((uint32_t)(((buf[4] << 8) | buf[3])), 16); - - DEBUG_PRINT("t_raw = %ld, p_raw = %ld\n", t_raw, p_raw); - - *temp = 42.5 + t_raw / 480.0; - *pressure = p_raw / 4096.0; - *humidity = -1.0; - - DEBUG_PRINT("temp = %0.1f C, pressure = %0.1f hPa\n", *temp, *pressure); - - return 0; -} - - diff --git a/src/i2c_mcp9808.c b/src/i2c_mcp9808.c deleted file mode 100644 index 6b63a92..0000000 --- a/src/i2c_mcp9808.c +++ /dev/null @@ -1,119 +0,0 @@ -/* i2c_mcp9808.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - -/* MCP9808 Registers */ -#define REG_CONFIG 0x01 -#define REG_T_UPPER 0x02 -#define REG_T_LOWER 0x03 -#define REG_T_CRIT 0x04 -#define REG_T_A 0x05 -#define REG_MANUF_ID 0x06 -#define REG_DEVICE_ID 0x07 -#define REG_RESOLUTION 0x08 - -#define MCP9808_MANUF_ID 0x0054 -#define MCP9808_DEVICE_ID 0x04 - - -typedef struct mcp9808_context_t { - i2c_inst_t *i2c; - uint8_t addr; -} mcp9808_context_t; - - - -void* mcp9808_init(i2c_inst_t *i2c, uint8_t addr) -{ - int res; - uint16_t val = 0; - mcp9808_context_t *ctx = calloc(1, sizeof(mcp9808_context_t)); - - - if (!ctx) - return NULL; - ctx->i2c = i2c; - ctx->addr = addr; - - /* Read and verify manufacturer ID */ - res = i2c_read_register_u16(i2c, addr, REG_MANUF_ID, &val); - if (res || (val != MCP9808_MANUF_ID)) - goto panic; - - /* Read and verify device ID */ - res = i2c_read_register_u16(i2c, addr, REG_DEVICE_ID, &val); - if (res || ((val >> 8) != MCP9808_DEVICE_ID)) - goto panic; - - - /* Set sensor configuration */ - res = i2c_write_register_u16(i2c, addr, REG_CONFIG, 0x0000); - if (res) - goto panic; - - /* Set resolution */ - res = i2c_write_register_u8(i2c, addr, REG_CONFIG, 0x03); - if (res) - goto panic; - - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -int mcp9808_start_measurement(void *ctx) -{ - /* Nothing to do, sensor is in continuous measurement mode... */ - - return 250; /* measurement should be available after 250ms (4 measurements/sec) */ -} - - -int mcp9808_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - mcp9808_context_t *c = (mcp9808_context_t*)ctx; - uint16_t meas = 0; - int res; - - - /* Get Temperature Measurement */ - res = i2c_read_register_u16(c->i2c, c->addr, REG_T_A, &meas); - if (res) - return -1; - - *temp = (double)twos_complement(meas, 13) / 16.0; - *pressure = -1.0; - *humidity = -1.0; - - return 0; -} diff --git a/src/i2c_ms8607.c b/src/i2c_ms8607.c deleted file mode 100644 index 3fdc925..0000000 --- a/src/i2c_ms8607.c +++ /dev/null @@ -1,349 +0,0 @@ -/* i2c_ms8607.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - -/* MS8607 Registers */ - -#define RESET_PT 0x1e -#define CONVERT_D1 0x4a // OSR=8192 -#define CONVERT_D2 0x5a // OSR=8192 -#define READ_ADC 0x00 -#define PROM_READ 0xa0 - -#define RESET_RH 0xfe -#define WRITE_USER 0xe6 -#define READ_USER 0xe7 -#define MEASURE_RH 0xf5 // No Hold master - - - -typedef struct ms8607_context_t { - i2c_inst_t *i2c; - uint8_t addr; - uint8_t addr2; - uint8_t state; - uint16_t prom_pt[7]; - uint16_t prom_rh[7]; - uint32_t d1; - uint32_t d2; - float temp; - float pressure; - float humidity; -} ms8607_context_t; - - - -static uint8_t crc4_pt(const uint16_t prom[]) -{ - uint16_t n_rem = 0; - uint16_t n_prom[8]; - - memcpy(n_prom, prom, 7 * sizeof(uint16_t)); - n_prom[7] = 0; - n_prom[0] &= 0x0fff; - - for (int cnt = 0; cnt < 16; cnt++) { - if (cnt % 2 == 1) - n_rem ^= n_prom[cnt >> 1] & 0xff; - else - n_rem ^= n_prom[cnt >> 1] >> 8; - - for (int n_bit = 8; n_bit > 0; n_bit--) { - if (n_rem & 0x8000) - n_rem = (n_rem << 1) ^ 0x3000; - else - n_rem = (n_rem << 1); - } - } - - n_rem = (n_rem >> 12) & 0x000f; - return n_rem ^ 0x00; -} - -#if 0 -static uint8_t crc4_rh(const uint16_t prom[]) -{ - uint16_t n_rem = 0; - uint16_t n_prom[8]; - - memcpy(n_prom, prom, 7 * sizeof(uint16_t)); - n_prom[7] = 0; - n_prom[6] &= 0xfff0; - - for (int cnt = 0; cnt < 16; cnt++) { - if (cnt % 2 == 1) - n_rem ^= n_prom[cnt >> 1] & 0xff; - else - n_rem ^= n_prom[cnt >> 1] >> 8; - - for (int n_bit = 8; n_bit > 0; n_bit--) { - if (n_rem & 0x8000) - n_rem = (n_rem << 1) ^ 0x3000; - else - n_rem = (n_rem << 1); - } - } - - n_rem = (n_rem >> 12) & 0x000f; - return n_rem ^ 0x00; -} -#endif - -static uint8_t crc_hsensor(uint16_t value) -{ - uint32_t polynom = 0x988000; - uint32_t msb = 0x800000; - uint32_t mask = 0xff8000; - uint32_t result = (uint32_t)value << 8; - - while (msb != 0x80) { - if (result & msb) - result = ((result ^ polynom) & mask) | (result & ~mask); - msb >>= 1; - mask >>= 1; - polynom >>= 1; - } - - return result & 0xff; -} - - -void* ms8607_init(i2c_inst_t *i2c, uint8_t addr) -{ - ms8607_context_t *ctx = calloc(1, sizeof(ms8607_context_t)); - uint8_t crc, reg; - int res; - - if (!ctx) - return NULL; - - ctx->i2c = i2c; - ctx->addr = 0x76; - ctx->addr2 = 0x40; - ctx->state = 0; - ctx->temp = 0.0; - ctx->pressure = -1.0; - ctx->humidity = -1.0; - - - /* Reset P&T and RH Sensor */ - res = i2c_write_raw_u8(ctx->i2c, ctx->addr, RESET_PT, false); - if (res) - goto panic; - res = i2c_write_raw_u8(ctx->i2c, ctx->addr2, RESET_RH, false); - if (res) - goto panic; - sleep_ms(15); - - - /* Read P&T PROM */ - for (int i = 0; i < 7; i++) { - res = i2c_read_register_u16(ctx->i2c, ctx->addr, PROM_READ + (i * 2), - &ctx->prom_pt[i]); - if (res) - goto panic; - sleep_us(100); - } - DEBUG_PRINT("C1=%u\n", ctx->prom_pt[1]); - DEBUG_PRINT("C2=%u\n", ctx->prom_pt[2]); - DEBUG_PRINT("C3=%u\n", ctx->prom_pt[3]); - DEBUG_PRINT("C4=%u\n", ctx->prom_pt[4]); - DEBUG_PRINT("C5=%u\n", ctx->prom_pt[5]); - DEBUG_PRINT("C6=%u\n", ctx->prom_pt[6]); - crc = crc4_pt(ctx->prom_pt); - DEBUG_PRINT("CRC-4: %02x (%02x)\n", crc, ctx->prom_pt[0] >> 12); - if (crc != (ctx->prom_pt[0] >> 12)) - goto panic; - -#if 0 - /* Read RH PROM */ - sleep_us(1000); - for (int i = 0; i < 7; i++) { - res = i2c_read_register_u16(ctx->i2c, ctx->addr2, PROM_READ + (i * 2), - &ctx->prom_rh[i]); - if (res) - goto panic; - sleep_us(1000); - } - crc = crc4_rh(ctx->prom_rh); - DEBUG_PRINT("CRC-4: %02x (%02x)\n", crc, ctx->prom_rh[6] & 0x0f); - if (crc != (ctx->prom_rh[6] & 0x0f)) - goto panic; -#endif - - /* Read User Register */ - res = i2c_read_register_u8(ctx->i2c, ctx->addr2, READ_USER, ®); - if (res) - goto panic; - DEBUG_PRINT("Current User Register value: %02x\n", reg); - - /* Update User Register if needed */ - if (reg != (reg & 0x7a)) { - reg = (reg &0x7a); - res = i2c_write_register_u8(ctx->i2c, ctx->addr2, WRITE_USER, reg); - if (res) - goto panic; - DEBUG_PRINT("User register changed to: %02x\n", reg); - } - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -int ms8607_start_measurement(void *ctx) -{ - ms8607_context_t *c = (ms8607_context_t*)ctx; - int res; - uint8_t cmd = 0; - uint8_t addr = c->addr; - int delay = 18; - - switch (c->state) { - - case 0: - /* Start D1 (pressure) Measurement */ - cmd = CONVERT_D1; - break; - - case 1: - /* Start D2 (temperature) Measurement */ - cmd = CONVERT_D2; - break; - - case 2: - /* Start Humidity Measurement */ - cmd = MEASURE_RH; - addr = c->addr2; - delay = 16; - break; - - } - - if (cmd) { - res = i2c_write_raw_u8(c->i2c, addr, cmd, false); - if (res) - return -1; - } - - return delay; -} - - -int ms8607_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - ms8607_context_t *c = (ms8607_context_t*)ctx; - int res; - uint32_t val; - uint8_t buf[3], crc; - int32_t dt, t, p, rh, t2; - int64_t off, sens, off2, sens2; - - - if (c->state == 0 || c->state == 1) { - res = i2c_read_register_u24(c->i2c, c->addr, READ_ADC, &val); - if (res) - return -1; - - if (c->state == 0) { - c->d1 = val; - } else { - c->d2 = val; - - DEBUG_PRINT("D1 = %lu\n", c->d1); - DEBUG_PRINT("D2 = %lu\n", c->d2); - - dt = (int32_t)c->d2 - ((int32_t)c->prom_pt[5] << 8); - DEBUG_PRINT("dT = %ld\n", dt); - t = 2000 + (((int64_t)dt * (int64_t)(c->prom_pt[6])) >> 23); - DEBUG_PRINT("TEMP = %ld\n", t); - - /* Second order compensation */ - if (t < 2000) { - t2 = (3 * (int64_t)dt * (int64_t)dt) >> 33; - off2 = (61 * ((int64_t)t - 2000) * ((int64_t)t - 2000)) >> 4; - sens2 = (29 * ((int64_t)t - 2000) * ((int64_t)t - 2000)) >> 4; - if (t < -1500) { - off2 += 17 * ((int64_t)t + 1500) * ((int64_t)t + 1500); - sens2 += 9 * ((int64_t)t + 1500) * ((int64_t)t + 1500); - } - } else { - t2 = (5 * ((int64_t)dt * (int64_t)dt)) >> 38; - off2 = 0; - sens2 = 0; - } - - off = ((int64_t)c->prom_pt[2] << 17) + (((int64_t)(c->prom_pt[4] * dt)) >> 6); - off -= off2; - DEBUG_PRINT("OFF = %lld\n", off); - sens = ((int64_t)c->prom_pt[1] << 16) + (((int64_t)c->prom_pt[3] * dt) >> 7); - sens -= sens2; - DEBUG_PRINT("SENS = %lld\n", sens); - p = (((c->d1 * sens) >> 21) - off) >> 15; - DEBUG_PRINT("P = %ld\n", p); - - c->temp = (t - t2) / 100.0; - c->pressure = p / 100.0; - } - } - else { - res = i2c_read_raw(c->i2c, c->addr2, buf, sizeof(buf), false); - if (res) - return -2; - val = ((buf[0] << 8) | buf[1]); // & 0xfffc; - crc = crc_hsensor(val); - if (crc != buf[2]) { - DEBUG_PRINT("CRC mismatch: %02x (%02x)\n", crc, buf[2]); - return -2; - } - - rh = -600 + ((12500 * val) >> 16); - - c->humidity = rh / 100.0; - } - DEBUG_PRINT("state=%d, val=%lu\n", c->state, val); - - c->state++; - if (c->state > 2) - c->state = 0; - - *temp = c->temp; - *pressure = c->pressure; - *humidity = c->humidity; - - DEBUG_PRINT("temp = %0.1f C, pressure = %0.1f hPa, humidity = %0.1f %%\n", - *temp, *pressure, *humidity); - - return 0; -} - - diff --git a/src/i2c_pct2075.c b/src/i2c_pct2075.c deleted file mode 100644 index 5f8c4b2..0000000 --- a/src/i2c_pct2075.c +++ /dev/null @@ -1,122 +0,0 @@ -/* i2c_pct2075.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - -/* PCT2075 Registers */ -#define REG_TEMP 0x00 -#define REG_CONFIG 0x01 -#define REG_T_HYST 0x02 -#define REG_T_OS 0x03 -#define REG_T_IDLE 0x04 - - -typedef struct pct2075_context_t { - i2c_inst_t *i2c; - uint8_t addr; -} pct2075_context_t; - - - -void* pct2075_init(i2c_inst_t *i2c, uint8_t addr) -{ - int res; - uint8_t cfg = 0; - pct2075_context_t *ctx = calloc(1, sizeof(pct2075_context_t)); - - - if (!ctx) - return NULL; - ctx->i2c = i2c; - ctx->addr = addr; - - /* Read config register */ - res = i2c_read_register_u8(i2c, addr, REG_CONFIG, &cfg); - if (res) - goto panic; - - /* High 3bits should always be zero */ - if ((cfg & 0xe0) != 0) - goto panic; - - /* Read T_idle register */ - res = i2c_read_register_u8(i2c, addr, REG_T_IDLE, &cfg); - if (res) - goto panic; - - /* T_idle should default to 1 */ - if ((cfg & 0x1f) != 1) - goto panic; - - - /* Set configuration (to defaults) */ - res = i2c_write_register_u8(i2c, addr, REG_CONFIG, 0x00); - if (res) - goto panic; - - /* Set sampling period to 100ms */ - res = i2c_write_register_u8(i2c, addr, REG_T_IDLE, 0x01); - if (res) - goto panic; - - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -int pct2075_start_measurement(void *ctx) -{ - /* Nothing to do, sensor is in continuous measurement mode... */ - - return 100; /* measurement should be available after 250ms (4 measurements/sec) */ -} - - -int pct2075_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - pct2075_context_t *c = (pct2075_context_t*)ctx; - uint16_t meas = 0; - int res; - - - /* Get Temperature Measurement */ - res = i2c_read_register_u16(c->i2c, c->addr, REG_TEMP, &meas); - if (res) - return -1; - - meas >>= 5; - *temp = (double)twos_complement(meas, 11) / 8.0; - *pressure = -1.0; - *humidity = -1.0; - - return 0; -} diff --git a/src/i2c_sht3x.c b/src/i2c_sht3x.c deleted file mode 100644 index 953e39c..0000000 --- a/src/i2c_sht3x.c +++ /dev/null @@ -1,200 +0,0 @@ -/* i2c_sht3x.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - -/* SHT3X Commands */ -#define CMD_MEASURE 0x2400 // high repeatability, clock stretching disabled -#define CMD_FETCH 0xe000 -#define CMD_ART 0x2b32 -#define CMD_BREAK 0x3093 -#define CMD_RESET 0x30a2 -#define CMD_HEATER_ON 0x306d -#define CMD_HEATER_OFF 0x3066 -#define CMD_STATUS 0xf32d -#define CMD_CLEAR_STATUS 0x3041 - - - -typedef struct sht3x_context_t { - i2c_inst_t *i2c; - uint8_t addr; -} sht3x_context_t; - - -/* CRC-8 Lookup Table (Polymonial 0x31) */ -static const uint8_t sht3x_crc_lookup_table[] = { - 0x00,0x31,0x62,0x53,0xC4,0xF5,0xA6,0x97,0xB9,0x88,0xDB,0xEA,0x7D,0x4C,0x1F,0x2E, - 0x43,0x72,0x21,0x10,0x87,0xB6,0xE5,0xD4,0xFA,0xCB,0x98,0xA9,0x3E,0x0F,0x5C,0x6D, - 0x86,0xB7,0xE4,0xD5,0x42,0x73,0x20,0x11,0x3F,0x0E,0x5D,0x6C,0xFB,0xCA,0x99,0xA8, - 0xC5,0xF4,0xA7,0x96,0x01,0x30,0x63,0x52,0x7C,0x4D,0x1E,0x2F,0xB8,0x89,0xDA,0xEB, - 0x3D,0x0C,0x5F,0x6E,0xF9,0xC8,0x9B,0xAA,0x84,0xB5,0xE6,0xD7,0x40,0x71,0x22,0x13, - 0x7E,0x4F,0x1C,0x2D,0xBA,0x8B,0xD8,0xE9,0xC7,0xF6,0xA5,0x94,0x03,0x32,0x61,0x50, - 0xBB,0x8A,0xD9,0xE8,0x7F,0x4E,0x1D,0x2C,0x02,0x33,0x60,0x51,0xC6,0xF7,0xA4,0x95, - 0xF8,0xC9,0x9A,0xAB,0x3C,0x0D,0x5E,0x6F,0x41,0x70,0x23,0x12,0x85,0xB4,0xE7,0xD6, - 0x7A,0x4B,0x18,0x29,0xBE,0x8F,0xDC,0xED,0xC3,0xF2,0xA1,0x90,0x07,0x36,0x65,0x54, - 0x39,0x08,0x5B,0x6A,0xFD,0xCC,0x9F,0xAE,0x80,0xB1,0xE2,0xD3,0x44,0x75,0x26,0x17, - 0xFC,0xCD,0x9E,0xAF,0x38,0x09,0x5A,0x6B,0x45,0x74,0x27,0x16,0x81,0xB0,0xE3,0xD2, - 0xBF,0x8E,0xDD,0xEC,0x7B,0x4A,0x19,0x28,0x06,0x37,0x64,0x55,0xC2,0xF3,0xA0,0x91, - 0x47,0x76,0x25,0x14,0x83,0xB2,0xE1,0xD0,0xFE,0xCF,0x9C,0xAD,0x3A,0x0B,0x58,0x69, - 0x04,0x35,0x66,0x57,0xC0,0xF1,0xA2,0x93,0xBD,0x8C,0xDF,0xEE,0x79,0x48,0x1B,0x2A, - 0xC1,0xF0,0xA3,0x92,0x05,0x34,0x67,0x56,0x78,0x49,0x1A,0x2B,0xBC,0x8D,0xDE,0xEF, - 0x82,0xB3,0xE0,0xD1,0x46,0x77,0x24,0x15,0x3B,0x0A,0x59,0x68,0xFF,0xCE,0x9D,0xAC -}; - -static uint8_t crc8(uint8_t *buf, size_t len) -{ - uint8_t crc = 0xff; - - for (int i = 0; i < len; i++) { - crc = sht3x_crc_lookup_table[crc ^ buf[i]]; - } - - return crc; -} - - -static int sht3x_read_u16(i2c_inst_t *i2c, uint8_t addr, uint16_t *val, bool nostop) -{ - uint8_t buf[3], crc; - int res; - - DEBUG_PRINT("args=%p,%02x,%p\n", i2c, addr, val); - - res = i2c_read_raw(i2c, addr, buf, 3, nostop); - if (res) { - DEBUG_PRINT("read failed (%d)\n", res); - return -1; - } - - *val = (buf[0] << 8) | buf[1]; - crc = crc8(buf, 2); - DEBUG_PRINT("read ok: [%02x %02x (%02x)] %04x (%u), crc=%02x\n", buf[0], buf[1], buf[2], *val, *val, crc); - - if (crc != buf[2]) { - DEBUG_PRINT("checksum mismatch!\n"); - return -2; - } - - return 0; -} - - -void* sht3x_init(i2c_inst_t *i2c, uint8_t addr) -{ - int res; - uint16_t val = 0; - sht3x_context_t *ctx = calloc(1, sizeof(sht3x_context_t)); - - if (!ctx) - return NULL; - ctx->i2c = i2c; - ctx->addr = addr; - - - /* Read status register to verify correct device... */ - res = i2c_write_raw_u16(i2c, addr, CMD_STATUS, false); - if (res) - goto panic; - sleep_us(10); - res = sht3x_read_u16(i2c, addr, &val, false); - if (res) - goto panic; - if ((val & 0x500c) != 0) - goto panic; - - - /* Reset sensor */ - res = i2c_write_raw_u16(i2c, addr, CMD_RESET, false); - if (res) - goto panic; - sleep_us(1500); - - - /* Read status register again... */ - res = i2c_write_raw_u16(i2c, addr, CMD_STATUS, false); - if (res) - goto panic; - sleep_us(10); - res = sht3x_read_u16(i2c, addr, &val, false); - if (res) - goto panic; - - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -int sht3x_start_measurement(void *ctx) -{ - sht3x_context_t *c = (sht3x_context_t*)ctx; - int res; - - /* Initiate measurement */ - res = i2c_write_raw_u16(c->i2c, c->addr, CMD_MEASURE, false); - if (res) - return -1; - - return 16; /* measurement should be available after 15.5ms */ -} - - -int sht3x_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - sht3x_context_t *c = (sht3x_context_t*)ctx; - int res; - uint8_t buf[6]; - uint16_t t_raw = 0; - uint16_t h_raw = 0; - - /* Get Measurement */ - res = i2c_read_raw(c->i2c, c->addr, buf, 6, false); - if (res) - return -1; - - /* Check CRC of received values */ - if ((crc8(&buf[0], 2) != buf[2]) || (crc8(&buf[3], 2) != buf[5])) - return -2; - - t_raw = (buf[0] << 8) | buf[1]; - h_raw = (buf[3] << 8) | buf[4]; - DEBUG_PRINT("h_raw = %u, t_raw = %u\n", h_raw, t_raw); - - *temp = -45 + 175 * (double) t_raw / 65535; - *pressure = -1.0; - *humidity = 100 * (double) h_raw / 65535; - DEBUG_PRINT("temp: %0.1f, humidity: %0.1f\n", *temp, *humidity); - - return 0; -} - - diff --git a/src/i2c_sht4x.c b/src/i2c_sht4x.c deleted file mode 100644 index a36bbb3..0000000 --- a/src/i2c_sht4x.c +++ /dev/null @@ -1,180 +0,0 @@ -/* i2c_sht4x.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - -/* SHT4X Commands */ -#define CMD_MEASURE_HP 0xfd -#define CMD_MEASURE_MP 0xf6 -#define CMD_MEASURE_LR 0xe0 -#define CMD_READ_SERIAL 0x89 -#define CMD_SOFT_RESET 0x94 - -typedef struct sht4x_context_t { - i2c_inst_t *i2c; - uint8_t addr; -} sht4x_context_t; - - -/* CRC-8 Lookup Table (Polymonial 0x31) */ -static const uint8_t sht4x_crc_lookup_table[] = { - 0x00,0x31,0x62,0x53,0xC4,0xF5,0xA6,0x97,0xB9,0x88,0xDB,0xEA,0x7D,0x4C,0x1F,0x2E, - 0x43,0x72,0x21,0x10,0x87,0xB6,0xE5,0xD4,0xFA,0xCB,0x98,0xA9,0x3E,0x0F,0x5C,0x6D, - 0x86,0xB7,0xE4,0xD5,0x42,0x73,0x20,0x11,0x3F,0x0E,0x5D,0x6C,0xFB,0xCA,0x99,0xA8, - 0xC5,0xF4,0xA7,0x96,0x01,0x30,0x63,0x52,0x7C,0x4D,0x1E,0x2F,0xB8,0x89,0xDA,0xEB, - 0x3D,0x0C,0x5F,0x6E,0xF9,0xC8,0x9B,0xAA,0x84,0xB5,0xE6,0xD7,0x40,0x71,0x22,0x13, - 0x7E,0x4F,0x1C,0x2D,0xBA,0x8B,0xD8,0xE9,0xC7,0xF6,0xA5,0x94,0x03,0x32,0x61,0x50, - 0xBB,0x8A,0xD9,0xE8,0x7F,0x4E,0x1D,0x2C,0x02,0x33,0x60,0x51,0xC6,0xF7,0xA4,0x95, - 0xF8,0xC9,0x9A,0xAB,0x3C,0x0D,0x5E,0x6F,0x41,0x70,0x23,0x12,0x85,0xB4,0xE7,0xD6, - 0x7A,0x4B,0x18,0x29,0xBE,0x8F,0xDC,0xED,0xC3,0xF2,0xA1,0x90,0x07,0x36,0x65,0x54, - 0x39,0x08,0x5B,0x6A,0xFD,0xCC,0x9F,0xAE,0x80,0xB1,0xE2,0xD3,0x44,0x75,0x26,0x17, - 0xFC,0xCD,0x9E,0xAF,0x38,0x09,0x5A,0x6B,0x45,0x74,0x27,0x16,0x81,0xB0,0xE3,0xD2, - 0xBF,0x8E,0xDD,0xEC,0x7B,0x4A,0x19,0x28,0x06,0x37,0x64,0x55,0xC2,0xF3,0xA0,0x91, - 0x47,0x76,0x25,0x14,0x83,0xB2,0xE1,0xD0,0xFE,0xCF,0x9C,0xAD,0x3A,0x0B,0x58,0x69, - 0x04,0x35,0x66,0x57,0xC0,0xF1,0xA2,0x93,0xBD,0x8C,0xDF,0xEE,0x79,0x48,0x1B,0x2A, - 0xC1,0xF0,0xA3,0x92,0x05,0x34,0x67,0x56,0x78,0x49,0x1A,0x2B,0xBC,0x8D,0xDE,0xEF, - 0x82,0xB3,0xE0,0xD1,0x46,0x77,0x24,0x15,0x3B,0x0A,0x59,0x68,0xFF,0xCE,0x9D,0xAC -}; - -static uint8_t crc8(uint8_t *buf, size_t len) -{ - uint8_t crc = 0xff; - - for (int i = 0; i < len; i++) { - crc = sht4x_crc_lookup_table[crc ^ buf[i]]; - } - - return crc; -} - - -void* sht4x_init(i2c_inst_t *i2c, uint8_t addr) -{ - sht4x_context_t *ctx = calloc(1, sizeof(sht4x_context_t)); - uint8_t buf[6]; - int res; - - if (!ctx) - return NULL; - ctx->i2c = i2c; - ctx->addr = addr; - - memset(buf, 0, sizeof(buf)); - - /* Read and verify device serial */ - res = i2c_read_register_block(i2c, addr, CMD_READ_SERIAL, buf, sizeof(buf), 1000); - if (res) - goto panic; - - /* Check CRC of received values */ - if ((crc8(&buf[0], 2) != buf[2]) || (crc8(&buf[3], 2) != buf[5])) { - DEBUG_PRINT("invalid serial (CRC mismatch)\n"); - goto panic; - } -#if I2C_DEBUG > 0 - uint32_t serial = (buf[0] << 24 | buf[1] << 16 | buf[3] << 8 | buf[4]); - DEBUG_PRINT("sensor serial: %08lx\n", serial); -#endif - - /* Reset sensor */ - res = i2c_write_raw_u8(i2c, addr, CMD_SOFT_RESET, false); - if (res) - goto panic; - sleep_us(1000); - - - /* Read and verify device serial again */ - res = i2c_read_register_block(i2c, addr, CMD_READ_SERIAL, buf, sizeof(buf), 1000); - if (res) - goto panic; - - /* Check CRC of received values */ - if ((crc8(&buf[0], 2) != buf[2]) || (crc8(&buf[3], 2) != buf[5])) { - DEBUG_PRINT("invalid serial (CRC mismatch)\n"); - goto panic; - } - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -int sht4x_start_measurement(void *ctx) -{ - sht4x_context_t *c = (sht4x_context_t*)ctx; - int res; - - /* Initiate measurement */ - res = i2c_write_raw_u8(c->i2c, c->addr, CMD_MEASURE_HP, false); - if (res) - return -1; - - return 9; /* measurement should be available after 8.3ms */ -} - - -int sht4x_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - sht4x_context_t *c = (sht4x_context_t*)ctx; - int res; - uint8_t buf[6]; - uint16_t t_raw = 0; - uint16_t h_raw = 0; - - /* Get Measurement */ - res = i2c_read_raw(c->i2c, c->addr, buf, 6, false); - if (res) - return -1; - - /* Check CRC of received values */ - if (crc8(&buf[0], 2) != buf[2]) - return -2; - if (crc8(&buf[3], 2) != buf[5]) - return -3; - - t_raw = (buf[0] << 8) | buf[1]; - h_raw = (buf[3] << 8) | buf[4]; - DEBUG_PRINT("h_raw = %u, t_raw = %u\n", h_raw, t_raw); - - *temp = -45 + 175 * (double) t_raw / 65535; - *pressure = -1.0; - *humidity = -6 + 125 * (double) h_raw / 65535; - if (*humidity > 100.0) - *humidity = 100.0; - if (*humidity < 0.0) - *humidity = 0.0; - - DEBUG_PRINT("temp: %0.1f, humidity: %0.1f\n", *temp, *humidity); - - return 0; -} - - diff --git a/src/i2c_shtc3.c b/src/i2c_shtc3.c deleted file mode 100644 index fda86f1..0000000 --- a/src/i2c_shtc3.c +++ /dev/null @@ -1,201 +0,0 @@ -/* i2c_shtc3.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - -/* SHTC3 Commands */ -#define CMD_SLEEP 0xb098 -#define CMD_WAKEUP 0x3517 -#define CMD_MEASURE 0x58e0 -#define CMD_RESET 0x805d -#define CMD_ID 0xefc8 - -#define SHTC3_DEVICE_ID 0x0807 -#define SHTC3_DEVICE_ID_MASK 0x083f - - -typedef struct shtc3_context_t { - i2c_inst_t *i2c; - uint8_t addr; -} shtc3_context_t; - - -/* CRC-8 Lookup Table (Polymonial 0x31) */ -static const uint8_t shtc3_crc_lookup_table[] = { - 0x00,0x31,0x62,0x53,0xC4,0xF5,0xA6,0x97,0xB9,0x88,0xDB,0xEA,0x7D,0x4C,0x1F,0x2E, - 0x43,0x72,0x21,0x10,0x87,0xB6,0xE5,0xD4,0xFA,0xCB,0x98,0xA9,0x3E,0x0F,0x5C,0x6D, - 0x86,0xB7,0xE4,0xD5,0x42,0x73,0x20,0x11,0x3F,0x0E,0x5D,0x6C,0xFB,0xCA,0x99,0xA8, - 0xC5,0xF4,0xA7,0x96,0x01,0x30,0x63,0x52,0x7C,0x4D,0x1E,0x2F,0xB8,0x89,0xDA,0xEB, - 0x3D,0x0C,0x5F,0x6E,0xF9,0xC8,0x9B,0xAA,0x84,0xB5,0xE6,0xD7,0x40,0x71,0x22,0x13, - 0x7E,0x4F,0x1C,0x2D,0xBA,0x8B,0xD8,0xE9,0xC7,0xF6,0xA5,0x94,0x03,0x32,0x61,0x50, - 0xBB,0x8A,0xD9,0xE8,0x7F,0x4E,0x1D,0x2C,0x02,0x33,0x60,0x51,0xC6,0xF7,0xA4,0x95, - 0xF8,0xC9,0x9A,0xAB,0x3C,0x0D,0x5E,0x6F,0x41,0x70,0x23,0x12,0x85,0xB4,0xE7,0xD6, - 0x7A,0x4B,0x18,0x29,0xBE,0x8F,0xDC,0xED,0xC3,0xF2,0xA1,0x90,0x07,0x36,0x65,0x54, - 0x39,0x08,0x5B,0x6A,0xFD,0xCC,0x9F,0xAE,0x80,0xB1,0xE2,0xD3,0x44,0x75,0x26,0x17, - 0xFC,0xCD,0x9E,0xAF,0x38,0x09,0x5A,0x6B,0x45,0x74,0x27,0x16,0x81,0xB0,0xE3,0xD2, - 0xBF,0x8E,0xDD,0xEC,0x7B,0x4A,0x19,0x28,0x06,0x37,0x64,0x55,0xC2,0xF3,0xA0,0x91, - 0x47,0x76,0x25,0x14,0x83,0xB2,0xE1,0xD0,0xFE,0xCF,0x9C,0xAD,0x3A,0x0B,0x58,0x69, - 0x04,0x35,0x66,0x57,0xC0,0xF1,0xA2,0x93,0xBD,0x8C,0xDF,0xEE,0x79,0x48,0x1B,0x2A, - 0xC1,0xF0,0xA3,0x92,0x05,0x34,0x67,0x56,0x78,0x49,0x1A,0x2B,0xBC,0x8D,0xDE,0xEF, - 0x82,0xB3,0xE0,0xD1,0x46,0x77,0x24,0x15,0x3B,0x0A,0x59,0x68,0xFF,0xCE,0x9D,0xAC -}; - -static uint8_t crc8(uint8_t *buf, size_t len) -{ - uint8_t crc = 0xff; - - for (int i = 0; i < len; i++) { - crc = shtc3_crc_lookup_table[crc ^ buf[i]]; - } - - return crc; -} - - -static int shtc3_read_u16(i2c_inst_t *i2c, uint8_t addr, uint16_t *val, bool nostop) -{ - uint8_t buf[3], crc; - int res; - - DEBUG_PRINT("args=%p,%02x,%p\n", i2c, addr, val); - - res = i2c_read_raw(i2c, addr, buf, 3, nostop); - if (res) { - DEBUG_PRINT("read failed (%d)\n", res); - return -1; - } - - *val = (buf[0] << 8) | buf[1]; - crc = crc8(buf, 2); - DEBUG_PRINT("read ok: [%02x %02x (%02x)] %04x (%u), crc=%02x\n", buf[0], buf[1], buf[2], *val, *val, crc); - - if (crc != buf[2]) { - DEBUG_PRINT("checksum mismatch!\n"); - return -2; - } - - return 0; -} - - -void* shtc3_init(i2c_inst_t *i2c, uint8_t addr) -{ - int res; - uint16_t val = 0; - shtc3_context_t *ctx = calloc(1, sizeof(shtc3_context_t)); - - if (!ctx) - return NULL; - ctx->i2c = i2c; - ctx->addr = addr; - - - /* Read and verify device ID */ - res = i2c_write_raw_u16(i2c, addr, CMD_ID, false); - if (res) - goto panic; - sleep_us(10); - res = shtc3_read_u16(i2c, addr, &val, false); - if (res) - goto panic; - if ((val & SHTC3_DEVICE_ID_MASK) != SHTC3_DEVICE_ID) - goto panic; - - - /* Reset sensor */ - res = i2c_write_raw_u16(i2c, addr, CMD_RESET, false); - if (res) - goto panic; - sleep_us(250); - - - /* Read and verify device ID again... */ - res = i2c_write_raw_u16(i2c, addr, CMD_ID, false); - if (res) - goto panic; - sleep_us(10); - res = shtc3_read_u16(i2c, addr, &val, false); - if (res) - goto panic; - if ((val & SHTC3_DEVICE_ID_MASK) != SHTC3_DEVICE_ID) - goto panic; - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -int shtc3_start_measurement(void *ctx) -{ - shtc3_context_t *c = (shtc3_context_t*)ctx; - int res; - - /* Initiate measurement */ - res = i2c_write_raw_u16(c->i2c, c->addr, CMD_MEASURE, false); - if (res) - return -1; - - return 13; /* measurement should be available after 12.1ms */ -} - - -int shtc3_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - shtc3_context_t *c = (shtc3_context_t*)ctx; - int res; - uint8_t buf[6]; - uint16_t t_raw = 0; - uint16_t h_raw = 0; - - /* Get Measurement */ - res = i2c_read_raw(c->i2c, c->addr, buf, 6, false); - if (res) - return -1; - - /* Check CRC of received values */ - if (crc8(&buf[0], 2) != buf[2]) - return -2; - if (crc8(&buf[3], 2) != buf[5]) - return -3; - - h_raw = (buf[0] << 8) | buf[1]; - t_raw = (buf[3] << 8) | buf[4]; - DEBUG_PRINT("h_raw = %u, t_raw = %u\n", h_raw, t_raw); - - *temp = -45 + 175 * (double) t_raw / 65536; - *pressure = -1.0; - *humidity = 100 * (double) h_raw / 65536; - DEBUG_PRINT("temp: %0.1f, humidity: %0.1f\n", *temp, *humidity); - - return 0; -} - - diff --git a/src/i2c_stts22h.c b/src/i2c_stts22h.c deleted file mode 100644 index 3d42aaa..0000000 --- a/src/i2c_stts22h.c +++ /dev/null @@ -1,119 +0,0 @@ -/* i2c_stts22h.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - -/* STTS22H Registers */ -#define REG_DEVICE_ID 0x01 -#define REG_TEMP_H_LIMIT 0x02 -#define REG_TEMP_L_LIMIT 0x03 -#define REG_CTRL 0x04 -#define REG_STATUS 0x05 -#define REG_TEMP_L_OUT 0x06 -#define REG_TEMP_H_OUT 0x07 - -#define STTS22H_DEVICE_ID 0xa0 - -typedef struct stts22h_context_t { - i2c_inst_t *i2c; - uint8_t addr; -} stts22h_context_t; - - -void* stts22h_init(i2c_inst_t *i2c, uint8_t addr) -{ - int res; - uint8_t val = 0; - stts22h_context_t *ctx = calloc(1, sizeof(stts22h_context_t)); - - if (!ctx) - return NULL; - ctx->i2c = i2c; - ctx->addr = addr; - - /* Read and verify device ID */ - res = i2c_read_register_u8(i2c, addr, REG_DEVICE_ID, &val); - if (res || val != STTS22H_DEVICE_ID) - goto panic; - - /* Configure Sensor: set to defaults first */ - res = i2c_write_register_u8(i2c, addr, REG_CTRL, 0x00); - if (res) - goto panic; - - sleep_us(10); - - /* Configure Sensor: avg=00, if_add_inc=1, freerun=1 */ - res = i2c_write_register_u8(i2c, addr, REG_CTRL, 0x0c); - if (res) - goto panic; - - /* Read and check configuration register */ - res = i2c_read_register_u8(i2c, addr, REG_CTRL, &val); - if (res | (val != 0x0c)) - goto panic; - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -int stts22h_start_measurement(void *ctx) -{ - /* Nothing to do, sensor is in continuous measurement mode... */ - - return 50; /* measurement should be available after 40ms (25Hz) */ -} - - -int stts22h_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - stts22h_context_t *c = (stts22h_context_t*)ctx; - int res; - uint16_t val; - - - /* Get Measurement */ - res = i2c_read_register_u16(c->i2c, c->addr, REG_TEMP_L_OUT, &val); - if (res) - return -2; - - val = (val << 8) | (val >> 8); /* reverse byte order */ - *temp = ((int16_t)val) / 100.0; - *pressure = -1.0; - *humidity = -1.0; - - DEBUG_PRINT("raw_temp=%d, temp=%0.2f\n", val, *temp); - - return 0; -} - - diff --git a/src/i2c_tmp102.c b/src/i2c_tmp102.c deleted file mode 100644 index 60d645f..0000000 --- a/src/i2c_tmp102.c +++ /dev/null @@ -1,135 +0,0 @@ -/* i2c_tmp102.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - -/* TMP102 Registers */ -#define REG_TEMP_RESULT 0x00 -#define REG_CONFIG 0x01 -#define REG_T_LOW 0x02 -#define REG_T_HIGH 0x03 - - - -typedef struct tmp102_context_t { - i2c_inst_t *i2c; - uint8_t addr; -} tmp102_context_t; - - -void* tmp102_init(i2c_inst_t *i2c, uint8_t addr) -{ - int res; - uint16_t val = 0; - tmp102_context_t *ctx = calloc(1, sizeof(tmp102_context_t)); - - if (!ctx) - return NULL; - ctx->i2c = i2c; - ctx->addr = addr; - - - /* Verify configuration register read-only bits */ - res = i2c_read_register_u16(i2c, addr, REG_CONFIG, &val); - if (res || ((val & 0x600f) != 0x6000)) - goto panic; - - /* Try to detect device by T_HIGH and T_LOW register default values (80C and 75C) */ - - res = i2c_read_register_u16(i2c, addr, REG_T_HIGH, &val); - if (res) - goto panic; - val = twos_complement((val >> 4), 12) / 16; - DEBUG_PRINT("T_high = %d\n", val); - if (val != 80) - goto panic; - - res = i2c_read_register_u16(i2c, addr, REG_T_LOW, &val); - if (res) - goto panic; - val = twos_complement((val >> 4), 12) / 16; - DEBUG_PRINT("T_low = %d\n", val); - if (val != 75) - goto panic; - - - /* Set sensor configuration: enable EM mode */ - res = i2c_write_register_u16(i2c, addr, REG_CONFIG, 0x00b0); - if (res) - goto panic; - - sleep_us(100); - - /* Read configuration register */ - res = i2c_read_register_u16(i2c, addr, REG_CONFIG, &val); - if (res) - goto panic; - - /* Check that confuration is now as expected (excluding read-only bits R1/R0)... */ - if ((val & 0x9fff) != 0x00b0) - goto panic; - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -int tmp102_start_measurement(void *ctx) -{ - /* Nothing to do, sensor is in continuous measurement mode... */ - - return 250; /* measurement should be available after 250ms */ -} - - -int tmp102_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - tmp102_context_t *c = (tmp102_context_t*)ctx; - int res; - uint16_t val; - - - /* Get Measurement */ - res = i2c_read_register_u16(c->i2c, c->addr, REG_TEMP_RESULT, &val); - if (res) - return -2; - - val = twos_complement((val >> 3), 13); - *temp = ((int16_t)val) / 16.0; - DEBUG_PRINT("t_raw = %d, temp=%0.2f\n", val, *temp); - - *pressure = -1.0; - *humidity = -1.0; - - return 0; -} - - diff --git a/src/i2c_tmp117.c b/src/i2c_tmp117.c deleted file mode 100644 index 950b751..0000000 --- a/src/i2c_tmp117.c +++ /dev/null @@ -1,121 +0,0 @@ -/* i2c_tmp117.c - Copyright (C) 2024 Timo Kokkonen - - SPDX-License-Identifier: GPL-3.0-or-later - - This file is part of FanPico. - - FanPico is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - FanPico is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with FanPico. If not, see . -*/ - -#include -#include -#include -#include "pico/stdlib.h" -#include "hardware/gpio.h" -#include "hardware/i2c.h" - -#include "i2c.h" - -/* TMP117 Registers */ -#define TMP117_REG_TEMP_RESULT 0x00 -#define TMP117_REG_CONFIG 0x01 -#define TMP117_REG_DEVICE_ID 0x0f - -#define TMP117_DEVICE_ID 0x117 - -typedef struct tmp117_context_t { - i2c_inst_t *i2c; - uint8_t addr; -} tmp117_context_t; - - -void* tmp117_init(i2c_inst_t *i2c, uint8_t addr) -{ - int res; - uint16_t val = 0; - tmp117_context_t *ctx = calloc(1, sizeof(tmp117_context_t)); - - if (!ctx) - return NULL; - ctx->i2c = i2c; - ctx->addr = addr; - - /* Read and verify device ID */ - res = i2c_read_register_u16(i2c, addr, TMP117_REG_DEVICE_ID, &val); - if (res || val != TMP117_DEVICE_ID) - goto panic; - - /* Reset Sensor */ - res = i2c_write_register_u16(i2c, addr, TMP117_REG_CONFIG, 0x0222); - if (res) - goto panic; - - /* Wait for sensor to soft reset (reset should take 2ms per datasheet) */ - sleep_us(2500); - - /* Read configuration register */ - res = i2c_read_register_u16(i2c, addr, TMP117_REG_CONFIG, &val); - if (res) - goto panic; - - /* Check that confuration is now as expected... */ - if ((val & 0x0FFC) != 0x0220) - goto panic; - - return ctx; - -panic: - free(ctx); - return NULL; -} - - -int tmp117_start_measurement(void *ctx) -{ - /* Nothing to do, sensor is in continuous measurement mode... */ - - return 1000; /* measurement should be available after 1s */ -} - - -int tmp117_get_measurement(void *ctx, float *temp, float *pressure, float *humidity) -{ - tmp117_context_t *c = (tmp117_context_t*)ctx; - int res; - uint16_t val; - - - /* Read configuration register */ - res = i2c_read_register_u16(c->i2c, c->addr, TMP117_REG_CONFIG, &val); - if (res) - return -1; - - /* Check Data_Ready bit */ - if ((val & 0x2000) == 0) - return 1; - - /* Get Measurement */ - res = i2c_read_register_u16(c->i2c, c->addr, TMP117_REG_TEMP_RESULT, &val); - if (res) - return -2; - - *temp = ((int16_t)val) / 128.0; - *pressure = -1.0; - *humidity = -1.0; - - return 0; -} - -