From 0387cd60318bcddc1ba2ce52daed0acf024a2979 Mon Sep 17 00:00:00 2001 From: Archie Atkinson Date: Fri, 25 Apr 2025 22:30:26 +0100 Subject: [PATCH 1/3] Inital Setup --- CMakeLists.txt | 1 + Kconfig | 3 +- cmake/Util.cmake | 3 +- drivers/CMakeLists.txt | 2 + drivers/Kconfig | 5 + drivers/sensor/CMakeLists.txt | 2 + drivers/sensor/Kconfig | 1 + drivers/sensor/ezo_ec/CMakeLists.txt | 4 + drivers/sensor/ezo_ec/Kconfig | 14 ++ drivers/sensor/ezo_ec/emul_ezo_ec.c | 186 +++++++++++++++++++++++++ drivers/sensor/ezo_ec/emul_ezo_ec.h | 23 +++ drivers/sensor/ezo_ec/ezo_ec.c | 88 ++++++++++++ drivers/sensor/ezo_ec/ezo_ec_util.h | 42 ++++++ dts/bindings/sensor/atlas,ezo-ec.yaml | 8 ++ tests/ezo_ec/CMakeLists.txt | 17 +++ tests/ezo_ec/boards/native_sim.overlay | 6 + tests/ezo_ec/main.cpp | 85 +++++++++++ tests/ezo_ec/prj.conf | 6 + tests/ezo_ec/testcase.yaml | 5 + 19 files changed, 499 insertions(+), 2 deletions(-) create mode 100644 drivers/CMakeLists.txt create mode 100644 drivers/Kconfig create mode 100644 drivers/sensor/CMakeLists.txt create mode 100644 drivers/sensor/Kconfig create mode 100644 drivers/sensor/ezo_ec/CMakeLists.txt create mode 100644 drivers/sensor/ezo_ec/Kconfig create mode 100644 drivers/sensor/ezo_ec/emul_ezo_ec.c create mode 100644 drivers/sensor/ezo_ec/emul_ezo_ec.h create mode 100644 drivers/sensor/ezo_ec/ezo_ec.c create mode 100644 drivers/sensor/ezo_ec/ezo_ec_util.h create mode 100644 dts/bindings/sensor/atlas,ezo-ec.yaml create mode 100644 tests/ezo_ec/CMakeLists.txt create mode 100644 tests/ezo_ec/boards/native_sim.overlay create mode 100644 tests/ezo_ec/main.cpp create mode 100644 tests/ezo_ec/prj.conf create mode 100644 tests/ezo_ec/testcase.yaml diff --git a/CMakeLists.txt b/CMakeLists.txt index 2158012..ede7e8f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,3 +11,4 @@ if(NOT CONFIG_RUST) endif() add_subdirectory(subsys) +add_subdirectory(drivers) diff --git a/Kconfig b/Kconfig index 71f891c..0ee8054 100755 --- a/Kconfig +++ b/Kconfig @@ -1,5 +1,6 @@ menu "Zephyr Playground" rsource "subsys/Kconfig" +rsource "drivers/Kconfig" -endmenu \ No newline at end of file +endmenu diff --git a/cmake/Util.cmake b/cmake/Util.cmake index f7106d0..7ac7c46 100755 --- a/cmake/Util.cmake +++ b/cmake/Util.cmake @@ -35,6 +35,7 @@ endfunction() function(SetupTarget target_name) target_include_directories(${target_name} PUBLIC $ENV{NOTUS_ROOT}/includes) + target_include_directories(${target_name} PUBLIC $ENV{NOTUS_ROOT}) target_compile_options( ${target_name} @@ -74,4 +75,4 @@ function(RunClangdTidy target sources) COMMENT "Running clangd-tidy" ) endif() -endfunction() \ No newline at end of file +endfunction() diff --git a/drivers/CMakeLists.txt b/drivers/CMakeLists.txt new file mode 100644 index 0000000..a5b547c --- /dev/null +++ b/drivers/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory_ifdef(CONFIG_SENSOR sensor) +message("Hello1") diff --git a/drivers/Kconfig b/drivers/Kconfig new file mode 100644 index 0000000..62e573c --- /dev/null +++ b/drivers/Kconfig @@ -0,0 +1,5 @@ +menu "Drivers" + +rsource "sensor/Kconfig" + +endmenu diff --git a/drivers/sensor/CMakeLists.txt b/drivers/sensor/CMakeLists.txt new file mode 100644 index 0000000..a8c9765 --- /dev/null +++ b/drivers/sensor/CMakeLists.txt @@ -0,0 +1,2 @@ +add_subdirectory_ifdef(CONFIG_EZO_EC ezo_ec) +message("Hello2") diff --git a/drivers/sensor/Kconfig b/drivers/sensor/Kconfig new file mode 100644 index 0000000..3ccd22f --- /dev/null +++ b/drivers/sensor/Kconfig @@ -0,0 +1 @@ +rsource "ezo_ec/Kconfig" diff --git a/drivers/sensor/ezo_ec/CMakeLists.txt b/drivers/sensor/ezo_ec/CMakeLists.txt new file mode 100644 index 0000000..6afaaa4 --- /dev/null +++ b/drivers/sensor/ezo_ec/CMakeLists.txt @@ -0,0 +1,4 @@ +zephyr_library() +zephyr_library_sources(ezo_ec.c) +zephyr_library_sources_ifdef(CONFIG_EZO_EC_EMUL emul_ezo_ec.c) +message("Hello3") diff --git a/drivers/sensor/ezo_ec/Kconfig b/drivers/sensor/ezo_ec/Kconfig new file mode 100644 index 0000000..eb4134e --- /dev/null +++ b/drivers/sensor/ezo_ec/Kconfig @@ -0,0 +1,14 @@ +config EZO_EC + bool "EZO-EC Sensor" + default n + depends on I2C + help + Enable EZO-EC + + +config EZO_EC_EMUL + bool "EZO-EC Emul" + default n + depends on I2C_EMUL + help + Enable EZO-EC Emulator diff --git a/drivers/sensor/ezo_ec/emul_ezo_ec.c b/drivers/sensor/ezo_ec/emul_ezo_ec.c new file mode 100644 index 0000000..7358e63 --- /dev/null +++ b/drivers/sensor/ezo_ec/emul_ezo_ec.c @@ -0,0 +1,186 @@ +#define DT_DRV_COMPAT atlas_ezo_ec +#define LOG_LEVEL CONFIG_I2C_LOG_LEVEL + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "emul_ezo_ec.h" +#include "ezo_ec_util.h" + +LOG_MODULE_REGISTER(EMUL_EZO_EC); + +// Runtime Data +struct emul_ezo_ec_data +{ + struct i2c_emul emul; + uint8_t cur_reg; + uint8_t registers[EZO_EC_REG_AMOUNT]; +}; + +uint8_t emul_ezo_ec_get_reg(const struct emul *emul, uint8_t address) +{ + struct emul_ezo_ec_data *data = emul->data; + + return data->registers[address]; +} + +void emul_ezo_ec_set_reg(const struct emul *emul, uint8_t address, uint8_t reg_value) +{ + struct emul_ezo_ec_data *data = emul->data; + + data->registers[address] = reg_value; +} + +void emul_ezo_ec_reset_registers(const struct emul *emul) +{ + LOG_INF("Resetting Registers"); + struct emul_ezo_ec_data *data = emul->data; + memset(data->registers, 0, EZO_EC_REG_AMOUNT * sizeof(uint8_t)); +} + +struct ezo_ec_config emul_ezo_ec_get_config(const struct emul *emul) +{ + // Here we are casting away const which is BAD but is required for unit testing + // to allow us to inject custom configs that are normally created at compile time + const struct ezo_ec_config *config = (struct ezo_ec_config *)emul->dev->config; + return *config; +} + +void emul_ezo_ec_set_config(const struct emul *emul, struct ezo_ec_config config) +{ + struct ezo_ec_config *current_config = (struct ezo_ec_config *)emul->dev->config; + *current_config = config; +} + +static int emul_ezo_ec_write(struct emul_ezo_ec_data *data, uint8_t len, const uint8_t *buf) +{ + if (data->cur_reg + len > EZO_EC_REG_AMOUNT) + { + LOG_ERR("Writing to nonexistant address"); + return -ENXIO; + } + for (int i = 0; i < len; i++) + { + data->registers[data->cur_reg] = buf[i]; + data->cur_reg++; + } + return 0; +} + +static int emul_ezo_ec_read(struct emul_ezo_ec_data *data, uint8_t len, uint8_t *buf) +{ + if (data->cur_reg + len > EZO_EC_REG_AMOUNT) + { + LOG_ERR("Reading from nonexistant address"); + return -ENXIO; + } + + for (int i = 0; i < len; i++) + { + buf[i] = data->registers[data->cur_reg]; + data->cur_reg++; + } + + return 0; +} + +static int emul_ezo_ec_transfer(const struct emul *target, struct i2c_msg *msgs, int num_msgs, int addr) +{ + struct emul_ezo_ec_data *data = target->data; + + i2c_dump_msgs(target->dev, msgs, num_msgs, addr); + + switch (num_msgs) + { + case 1: { + if ((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) + { + emul_ezo_ec_read(data, msgs[0].len, msgs[0].buf); + } + else if ((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) + { + data->cur_reg = msgs[0].buf[0]; + if (msgs[0].len != 1) + { + emul_ezo_ec_write(data, msgs[0].len - 1, &msgs[0].buf[1]); + } + } + else + { + LOG_ERR("Unknown transfer"); + return -EIO; + } + break; + } + case 2: { + if ((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) + { + return -EIO; + } + if (msgs[0].len != 1U) + { + return -EIO; + } + + data->cur_reg = msgs->buf[0]; + // Handle Second Message + + if ((msgs[1].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) + { + emul_ezo_ec_read(data, msgs[1].len, msgs[1].buf); + } + else if ((msgs[1].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) + { + emul_ezo_ec_write(data, msgs[1].len, msgs[1].buf); + } + break; + } + default: { + LOG_ERR("Invalid number of messages"); + return -EIO; + } + } + + return 0; +} + +const static struct i2c_emul_api emul_ezo_ec_api = { + .transfer = emul_ezo_ec_transfer, +}; + +static int emul_ezo_ec_init(const struct emul *target, const struct device *parent) +{ + LOG_INF("emul_ezo_ec_init"); + const struct emul_ezo_ec_config *config = target->cfg; + struct emul_ezo_ec_data *data = target->data; + + ARG_UNUSED(config); + ARG_UNUSED(data); + ARG_UNUSED(parent); + + emul_ezo_ec_reset_registers(target); + + return 0; +} + +// clang-format off +#define ezo_ec_EMUL(inst) \ + static struct emul_ezo_ec_data emul_ezo_ec_data_##inst; \ + EMUL_DT_INST_DEFINE(inst, \ + &emul_ezo_ec_init, \ + &emul_ezo_ec_data_##inst, \ + NULL, \ + &emul_ezo_ec_api, \ + NULL) + +DT_INST_FOREACH_STATUS_OKAY(ezo_ec_EMUL) // NOLINT +// clang-format on diff --git a/drivers/sensor/ezo_ec/emul_ezo_ec.h b/drivers/sensor/ezo_ec/emul_ezo_ec.h new file mode 100644 index 0000000..6f08775 --- /dev/null +++ b/drivers/sensor/ezo_ec/emul_ezo_ec.h @@ -0,0 +1,23 @@ +#ifndef APP_INCLUDE_EMUL_ezo_ec_H_ +#define APP_INCLUDE_EMUL_ezo_ec_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "ezo_ec_util.h" +#include + +uint8_t emul_ezo_ec_get_reg(const struct emul *emul, uint8_t address); +void emul_ezo_ec_set_reg(const struct emul *emul, uint8_t address, uint8_t reg_value); +void emul_ezo_ec_reset_registers(const struct emul *emul); + +struct ezo_ec_config emul_ezo_ec_get_config(const struct emul *emul); +void emul_ezo_ec_set_config(const struct emul *emul, struct ezo_ec_config config); + +#ifdef __cplusplus +} +#endif + +#endif // APP_INCLUDE_EMUL_ezo_ec_H_ diff --git a/drivers/sensor/ezo_ec/ezo_ec.c b/drivers/sensor/ezo_ec/ezo_ec.c new file mode 100644 index 0000000..e6cf6e3 --- /dev/null +++ b/drivers/sensor/ezo_ec/ezo_ec.c @@ -0,0 +1,88 @@ +#define DT_DRV_COMPAT atlas_ezo_ec + +#include +#include +#include +#include +#include +#include +#include + +#include "ezo_ec_util.h" + +LOG_MODULE_REGISTER(ezo_ec, CONFIG_SENSOR_LOG_LEVEL); // NOLINT + +static int ezo_ec_sample_fetch(const struct device *dev, enum sensor_channel chan) +{ + // It is recommended to read the data registers starting from the lower address to the higher address. + struct ezo_ec_data *data = dev->data; + const int transfer_length = 1; + const struct ezo_ec_config *config = dev->config; + uint8_t out[transfer_length]; + + __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL); + + // Burst read data + if (i2c_burst_read_dt(&config->i2c, 0, out, transfer_length) < 0) + { + LOG_DBG("Failed to read sample"); + return -EIO; + } + + return 0; +} + +static int ezo_ec_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) +{ + const struct ezo_ec_data *data = dev->data; + + if (chan == SENSOR_CHAN_PRESS) + { + } + else if (chan == SENSOR_CHAN_AMBIENT_TEMP) + { + } + else + { + return -ENOTSUP; + } + + return 0; +} + +int ezo_ec_init(const struct device *dev) +{ + const struct ezo_ec_config *const config = dev->config; + + // device is ready + if (!device_is_ready(config->i2c.bus)) + { + LOG_ERR("I2C bus device not ready"); + return -ENODEV; + } + + // uint8_t chip_id = 0; + // if (i2c_reg_read_byte_dt(&config->i2c, ezo_ec_REG_DEVICE_ID, &chip_id) < 0) + // { + // LOG_ERR("Failed reading chip id"); + // return -EIO; + // } + + return 0; +} + +static const struct sensor_driver_api ezo_ec_api_funcs = { + .sample_fetch = ezo_ec_sample_fetch, + .channel_get = ezo_ec_channel_get, +}; + +#define ezo_ec_DEFINE(inst) \ + static struct ezo_ec_data ezo_ec_data_##inst; \ + \ + static struct ezo_ec_config ezo_ec_config_##inst = { \ + .i2c = I2C_DT_SPEC_INST_GET(inst), \ + }; \ + \ + DEVICE_DT_INST_DEFINE(inst, ezo_ec_init, NULL, &ezo_ec_data_##inst, &ezo_ec_config_##inst, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &ezo_ec_api_funcs); + +DT_INST_FOREACH_STATUS_OKAY(ezo_ec_DEFINE) // NOLINT diff --git a/drivers/sensor/ezo_ec/ezo_ec_util.h b/drivers/sensor/ezo_ec/ezo_ec_util.h new file mode 100644 index 0000000..0f8ae9e --- /dev/null +++ b/drivers/sensor/ezo_ec/ezo_ec_util.h @@ -0,0 +1,42 @@ +#pragma once + +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +#define EZO_EC_REG_AMOUNT 10 + +int ezo_ec_init(const struct device *dev); + +typedef union { + uint8_t full_reg; + struct + { + uint8_t INT_S : 2; + uint8_t DRDY : 1; + uint8_t INT_F_OVR : 1; + uint8_t INT_F_WTM: 1; + uint8_t INT_F_FULL : 1; + uint8_t : 2; + }; +} ezo_ec_ctrl_3_reg_t; + +struct ezo_ec_config +{ + struct i2c_dt_spec i2c; +}; + +struct ezo_ec_data +{ + +}; + +#ifdef __cplusplus +} +#endif diff --git a/dts/bindings/sensor/atlas,ezo-ec.yaml b/dts/bindings/sensor/atlas,ezo-ec.yaml new file mode 100644 index 0000000..5afbf7b --- /dev/null +++ b/dts/bindings/sensor/atlas,ezo-ec.yaml @@ -0,0 +1,8 @@ +description: | + Sensor + +compatible: "atlas,ezo-ec" + +include: ["i2c-device.yaml", "sensor-device.yaml"] + +properties: diff --git a/tests/ezo_ec/CMakeLists.txt b/tests/ezo_ec/CMakeLists.txt new file mode 100644 index 0000000..bbf7bb6 --- /dev/null +++ b/tests/ezo_ec/CMakeLists.txt @@ -0,0 +1,17 @@ +cmake_minimum_required(VERSION 3.20.0) +list(APPEND CMAKE_MODULE_PATH "$ENV{NOTUS_ROOT}/cmake") +include(Util) + +ProjectSetup("standard;testing") + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +project(load_cell) + +set(SOURCES + main.cpp +) + +target_sources(app PRIVATE ${SOURCES}) +SetupTarget(app) + +RunClangdTidy(app "${SOURCES}") diff --git a/tests/ezo_ec/boards/native_sim.overlay b/tests/ezo_ec/boards/native_sim.overlay new file mode 100644 index 0000000..a181cf5 --- /dev/null +++ b/tests/ezo_ec/boards/native_sim.overlay @@ -0,0 +1,6 @@ +&i2c0 { + ezo_ec: ezoec@0 { + compatible = "atlas,ezo_ec"; + reg = <0x0>; + }; +}; diff --git a/tests/ezo_ec/main.cpp b/tests/ezo_ec/main.cpp new file mode 100644 index 0000000..6c4eaeb --- /dev/null +++ b/tests/ezo_ec/main.cpp @@ -0,0 +1,85 @@ +#include +#include + +#include "drivers/sensor/ezo_ec/emul_ezo_ec.h" +#include "drivers/sensor/ezo_ec/ezo_ec_util.h" + +#include "testing.hpp" + +namespace { + +const struct device *ezo = DEVICE_DT_GET(DT_NODELABEL(ezo_ec)); // NOLINT +const static struct emul *emul = nullptr; // NOLINT + +// static uint8_t get_emul_reg(uint8_t address) +// { +// return emul_ezo_ec_get_reg(emul, address); +// } + +// [[maybe_unused]] static void set_emul_reg(uint8_t address, uint8_t reg_value) +// { +// emul_ezo_ec_set_reg(emul, address, reg_value); +// } + +void reset_emul_registers() +{ + emul_ezo_ec_reset_registers(emul); +} + +ezo_ec_config get_emul_config() +{ + return emul_ezo_ec_get_config(emul); +} + +void re_init_pcf85063a(struct ezo_ec_config config) +{ + emul_ezo_ec_set_config(emul, config); + + // This is a bit hacky... but it works! + // Calls the init functions and updates the state used + // by `device_is_ready()`. Code taken from Zephyr's init.c + int ret = ezo_ec_init(emul->dev); + if (ret != 0) + { + if (ret < 0) + { + ret = -ret; + } + if (ret > UINT8_MAX) + { + ret = UINT8_MAX; + } + emul->dev->state->init_res = ret; + } + else + { + emul->dev->state->init_res = 0; + } +} + +void* setup() +{ + emul = emul_get_binding("ezoec@0"); + + struct ezo_ec_config config = get_emul_config(); + re_init_pcf85063a(config); + + zassert_true(device_is_ready(ezo), "Device is not ready"); + return nullptr; +} + +void teardown(void * /* f */) +{ + reset_emul_registers(); +} + + +ZTEST(t_ezo_ec, test_fetch_and_get) +{ + + zassert_true(true); +} + +ZTEST_SUITE(t_ezo_ec, NULL, setup, NULL, NULL, teardown); // NOLINT + +} diff --git a/tests/ezo_ec/prj.conf b/tests/ezo_ec/prj.conf new file mode 100644 index 0000000..549e5f6 --- /dev/null +++ b/tests/ezo_ec/prj.conf @@ -0,0 +1,6 @@ +CONFIG_I2C=y +CONFIG_EMUL=y +CONFIG_I2C_EMUL=y +CONFIG_EZO_EC=y +CONFIG_EZO_EC_EMUL=y +CONFIG_SENSOR=y diff --git a/tests/ezo_ec/testcase.yaml b/tests/ezo_ec/testcase.yaml new file mode 100644 index 0000000..9add19e --- /dev/null +++ b/tests/ezo_ec/testcase.yaml @@ -0,0 +1,5 @@ +tests: + drivers.sensor.ezo_ec: + platform_allow: native_sim + integration_platforms: + - native_sim From d1acd983c6d7fa18c99b7cd8a6c75064b4487845 Mon Sep 17 00:00:00 2001 From: Archie Atkinson Date: Sat, 26 Apr 2025 13:29:14 +0100 Subject: [PATCH 2/3] Working Channel --- drivers/sensor/ezo_ec/emul_ezo_ec.c | 151 +++++++++++++------------ drivers/sensor/ezo_ec/emul_ezo_ec.h | 6 +- drivers/sensor/ezo_ec/ezo_ec.c | 75 ++++++++---- drivers/sensor/ezo_ec/ezo_ec_util.h | 22 ++-- include/drivers/sensors/ezo_ec.h | 21 ++++ tests/ezo_ec/boards/native_sim.overlay | 4 +- tests/ezo_ec/main.cpp | 41 ++++--- 7 files changed, 195 insertions(+), 125 deletions(-) create mode 100644 include/drivers/sensors/ezo_ec.h diff --git a/drivers/sensor/ezo_ec/emul_ezo_ec.c b/drivers/sensor/ezo_ec/emul_ezo_ec.c index 7358e63..ce4f15a 100644 --- a/drivers/sensor/ezo_ec/emul_ezo_ec.c +++ b/drivers/sensor/ezo_ec/emul_ezo_ec.c @@ -22,29 +22,30 @@ LOG_MODULE_REGISTER(EMUL_EZO_EC); struct emul_ezo_ec_data { struct i2c_emul emul; - uint8_t cur_reg; - uint8_t registers[EZO_EC_REG_AMOUNT]; + char input[EZO_EC_BUFFER_SIZE]; + char output[EZO_EC_BUFFER_SIZE]; }; -uint8_t emul_ezo_ec_get_reg(const struct emul *emul, uint8_t address) +void emul_ezo_ec_get_input(const struct emul *emul, char *buf, int len) { struct emul_ezo_ec_data *data = emul->data; - - return data->registers[address]; + memcpy(buf, data->input, len); } -void emul_ezo_ec_set_reg(const struct emul *emul, uint8_t address, uint8_t reg_value) +void emul_ezo_ec_set_output(const struct emul *emul, const char *buf, int len) { struct emul_ezo_ec_data *data = emul->data; - - data->registers[address] = reg_value; + memset(data->output, 0, EZO_EC_BUFFER_SIZE); + data->output[0] = 1; // Hardcode response code for now; + memcpy(data->output+1, buf, len); } -void emul_ezo_ec_reset_registers(const struct emul *emul) +void emul_ezo_ec_reset_buffers(const struct emul *emul) { LOG_INF("Resetting Registers"); struct emul_ezo_ec_data *data = emul->data; - memset(data->registers, 0, EZO_EC_REG_AMOUNT * sizeof(uint8_t)); + memset(data->input,0, EZO_EC_BUFFER_SIZE); + memset(data->output, 0, EZO_EC_BUFFER_SIZE); } struct ezo_ec_config emul_ezo_ec_get_config(const struct emul *emul) @@ -63,32 +64,25 @@ void emul_ezo_ec_set_config(const struct emul *emul, struct ezo_ec_config config static int emul_ezo_ec_write(struct emul_ezo_ec_data *data, uint8_t len, const uint8_t *buf) { - if (data->cur_reg + len > EZO_EC_REG_AMOUNT) + if (len > EZO_EC_BUFFER_SIZE) { - LOG_ERR("Writing to nonexistant address"); + LOG_ERR("Write too large"); return -ENXIO; } - for (int i = 0; i < len; i++) - { - data->registers[data->cur_reg] = buf[i]; - data->cur_reg++; - } + + memcpy(data->input, buf, len); return 0; } static int emul_ezo_ec_read(struct emul_ezo_ec_data *data, uint8_t len, uint8_t *buf) { - if (data->cur_reg + len > EZO_EC_REG_AMOUNT) + if (len > EZO_EC_BUFFER_SIZE) { - LOG_ERR("Reading from nonexistant address"); + LOG_ERR("Read to large"); return -ENXIO; } - for (int i = 0; i < len; i++) - { - buf[i] = data->registers[data->cur_reg]; - data->cur_reg++; - } + memcpy(buf, data->output, len); return 0; } @@ -99,56 +93,70 @@ static int emul_ezo_ec_transfer(const struct emul *target, struct i2c_msg *msgs, i2c_dump_msgs(target->dev, msgs, num_msgs, addr); - switch (num_msgs) + if ((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) { - case 1: { - if ((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) - { - emul_ezo_ec_read(data, msgs[0].len, msgs[0].buf); - } - else if ((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) - { - data->cur_reg = msgs[0].buf[0]; - if (msgs[0].len != 1) - { - emul_ezo_ec_write(data, msgs[0].len - 1, &msgs[0].buf[1]); - } - } - else - { - LOG_ERR("Unknown transfer"); - return -EIO; - } - break; + emul_ezo_ec_read(data, msgs[0].len, msgs[0].buf); } - case 2: { - if ((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) - { - return -EIO; - } - if (msgs[0].len != 1U) - { - return -EIO; - } - - data->cur_reg = msgs->buf[0]; - // Handle Second Message - - if ((msgs[1].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) - { - emul_ezo_ec_read(data, msgs[1].len, msgs[1].buf); - } - else if ((msgs[1].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) - { - emul_ezo_ec_write(data, msgs[1].len, msgs[1].buf); - } - break; + else if ((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) + { + emul_ezo_ec_write(data, msgs[0].len, &msgs[0].buf[0]); } - default: { - LOG_ERR("Invalid number of messages"); + else + { + LOG_ERR("Unknown transfer"); return -EIO; } - } + + // switch (num_msgs) + // { + // case 1: { + // if ((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) + // { + // emul_ezo_ec_read(data, msgs[0].len, msgs[0].buf); + // } + // else if ((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) + // { + // data->cur_reg = msgs[0].buf[0]; + // if (msgs[0].len != 1) + // { + // emul_ezo_ec_write(data, msgs[0].len - 1, &msgs[0].buf[1]); + // } + // } + // else + // { + // LOG_ERR("Unknown transfer"); + // return -EIO; + // } + // break; + // } + // case 2: { + // if ((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) + // { + // return -EIO; + // } + // if (msgs[0].len != 1U) + // { + // return -EIO; + // } + + // data->cur_reg = msgs->buf[0]; + // // Handle Second Message + + // if ((msgs[1].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) + // { + // emul_ezo_ec_read(data, msgs[1].len, msgs[1].buf); + // } + // else if ((msgs[1].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) + // { + // emul_ezo_ec_write(data, msgs[1].len, msgs[1].buf); + // } + // break; + // } + // default: { + // LOG_ERR("Invalid number of messages"); + // return -EIO; + // } + // } return 0; } @@ -167,7 +175,10 @@ static int emul_ezo_ec_init(const struct emul *target, const struct device *pare ARG_UNUSED(data); ARG_UNUSED(parent); - emul_ezo_ec_reset_registers(target); + emul_ezo_ec_reset_buffers(target); + + char info[] = "?i,EC,2.16"; + emul_ezo_ec_set_output(target, info, strlen(info)); return 0; } diff --git a/drivers/sensor/ezo_ec/emul_ezo_ec.h b/drivers/sensor/ezo_ec/emul_ezo_ec.h index 6f08775..7253560 100644 --- a/drivers/sensor/ezo_ec/emul_ezo_ec.h +++ b/drivers/sensor/ezo_ec/emul_ezo_ec.h @@ -9,9 +9,9 @@ extern "C" #include "ezo_ec_util.h" #include -uint8_t emul_ezo_ec_get_reg(const struct emul *emul, uint8_t address); -void emul_ezo_ec_set_reg(const struct emul *emul, uint8_t address, uint8_t reg_value); -void emul_ezo_ec_reset_registers(const struct emul *emul); +void emul_ezo_ec_get_input(const struct emul *emul, char *buf, int len); +void emul_ezo_ec_set_output(const struct emul *emul, const char *buf, int len); +void emul_ezo_ec_reset_buffers(const struct emul *emul); struct ezo_ec_config emul_ezo_ec_get_config(const struct emul *emul); void emul_ezo_ec_set_config(const struct emul *emul, struct ezo_ec_config config); diff --git a/drivers/sensor/ezo_ec/ezo_ec.c b/drivers/sensor/ezo_ec/ezo_ec.c index e6cf6e3..739d3de 100644 --- a/drivers/sensor/ezo_ec/ezo_ec.c +++ b/drivers/sensor/ezo_ec/ezo_ec.c @@ -1,5 +1,7 @@ #define DT_DRV_COMPAT atlas_ezo_ec +#include + #include #include #include @@ -9,45 +11,63 @@ #include #include "ezo_ec_util.h" +#include "drivers/sensors/ezo_ec.h" LOG_MODULE_REGISTER(ezo_ec, CONFIG_SENSOR_LOG_LEVEL); // NOLINT static int ezo_ec_sample_fetch(const struct device *dev, enum sensor_channel chan) { - // It is recommended to read the data registers starting from the lower address to the higher address. struct ezo_ec_data *data = dev->data; - const int transfer_length = 1; const struct ezo_ec_config *config = dev->config; - uint8_t out[transfer_length]; __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL); - // Burst read data - if (i2c_burst_read_dt(&config->i2c, 0, out, transfer_length) < 0) + if (i2c_read_dt(&config->i2c, data->output, EZO_EC_BUFFER_SIZE) < 0) + { + LOG_ERR("Failed to read sample"); + return -EIO; + } + + if(data->output[0] != 1) { - LOG_DBG("Failed to read sample"); + LOG_ERR("Reponse Code not 1"); return -EIO; } return 0; } -static int ezo_ec_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) +static int convert_conductiviy(const struct ezo_ec_data *data, struct sensor_value *val) { - const struct ezo_ec_data *data = dev->data; + char *endptr = NULL; - if (chan == SENSOR_CHAN_PRESS) - { - } - else if (chan == SENSOR_CHAN_AMBIENT_TEMP) + double value = strtod(data->output + 1, &endptr); + + if(data->output + 1 == endptr) { + return -EIO; } - else + + sensor_value_from_double(val, value); + + return 0; + + +} + +static int ezo_ec_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) +{ + const struct ezo_ec_data *data = dev->data; + + enum sensor_channel_ezo_ec our_chan = (enum sensor_channel_ezo_ec)chan; + + if (our_chan == SENSOR_CHAN_CONDUCTIVITY) { - return -ENOTSUP; + return convert_conductiviy(data, val); } + + return -ENOTSUP; - return 0; } int ezo_ec_init(const struct device *dev) @@ -60,13 +80,26 @@ int ezo_ec_init(const struct device *dev) LOG_ERR("I2C bus device not ready"); return -ENODEV; } + + if (i2c_write_dt(&config->i2c, INFO_COMMAND, 1) < 0) + { + LOG_ERR("Failed sending info command"); + return -EIO; + } - // uint8_t chip_id = 0; - // if (i2c_reg_read_byte_dt(&config->i2c, ezo_ec_REG_DEVICE_ID, &chip_id) < 0) - // { - // LOG_ERR("Failed reading chip id"); - // return -EIO; - // } + k_msleep(RESPONSE_TIME_MS); // Required + + char buf[EZO_EC_BUFFER_SIZE]; + if(i2c_read_dt(&config->i2c, (uint8_t*)&buf, EZO_EC_BUFFER_SIZE)) + { + LOG_ERR("Failed to get info command"); + } + + char expected[] = "?i,EC,2.16"; + if (buf[0] != OK_RESPONSE_CODE && strcmp(expected, buf+1) != 0) + { + LOG_ERR("Incorrect Info %s", buf); + } return 0; } diff --git a/drivers/sensor/ezo_ec/ezo_ec_util.h b/drivers/sensor/ezo_ec/ezo_ec_util.h index 0f8ae9e..e42d89d 100644 --- a/drivers/sensor/ezo_ec/ezo_ec_util.h +++ b/drivers/sensor/ezo_ec/ezo_ec_util.h @@ -10,22 +10,14 @@ extern "C" { #endif -#define EZO_EC_REG_AMOUNT 10 +#define EZO_EC_BUFFER_SIZE 30 +#define RESPONSE_TIME_MS 300 +#define OK_RESPONSE_CODE 1 -int ezo_ec_init(const struct device *dev); +#define INFO_COMMAND "i" +#define READ_COMMAND "R" -typedef union { - uint8_t full_reg; - struct - { - uint8_t INT_S : 2; - uint8_t DRDY : 1; - uint8_t INT_F_OVR : 1; - uint8_t INT_F_WTM: 1; - uint8_t INT_F_FULL : 1; - uint8_t : 2; - }; -} ezo_ec_ctrl_3_reg_t; +int ezo_ec_init(const struct device *dev); struct ezo_ec_config { @@ -34,7 +26,7 @@ struct ezo_ec_config struct ezo_ec_data { - + char output[EZO_EC_BUFFER_SIZE]; }; #ifdef __cplusplus diff --git a/include/drivers/sensors/ezo_ec.h b/include/drivers/sensors/ezo_ec.h new file mode 100644 index 0000000..38b2c25 --- /dev/null +++ b/include/drivers/sensors/ezo_ec.h @@ -0,0 +1,21 @@ +#ifndef INCLUDE_DRIVERS_SENSOR_EZO_EC_H_ +#define INCLUDE_DRIVERS_SENSOR_EZO_EC_H_ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include +#include + +enum sensor_channel_ezo_ec +{ + SENSOR_CHAN_CONDUCTIVITY = SENSOR_CHAN_PRIV_START, +}; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/tests/ezo_ec/boards/native_sim.overlay b/tests/ezo_ec/boards/native_sim.overlay index a181cf5..06d258d 100644 --- a/tests/ezo_ec/boards/native_sim.overlay +++ b/tests/ezo_ec/boards/native_sim.overlay @@ -1,6 +1,6 @@ &i2c0 { - ezo_ec: ezoec@0 { + ezo_ec: ezoec@64 { compatible = "atlas,ezo_ec"; - reg = <0x0>; + reg = <0x64>; }; }; diff --git a/tests/ezo_ec/main.cpp b/tests/ezo_ec/main.cpp index 6c4eaeb..670b131 100644 --- a/tests/ezo_ec/main.cpp +++ b/tests/ezo_ec/main.cpp @@ -1,8 +1,11 @@ +#include +#include #include #include #include "drivers/sensor/ezo_ec/emul_ezo_ec.h" #include "drivers/sensor/ezo_ec/ezo_ec_util.h" +#include "drivers/sensors/ezo_ec.h" #include "testing.hpp" @@ -11,19 +14,19 @@ namespace { const struct device *ezo = DEVICE_DT_GET(DT_NODELABEL(ezo_ec)); // NOLINT const static struct emul *emul = nullptr; // NOLINT -// static uint8_t get_emul_reg(uint8_t address) -// { -// return emul_ezo_ec_get_reg(emul, address); -// } +void set_output(const char *buf, int len) +{ + emul_ezo_ec_set_output(emul,buf, len); +} -// [[maybe_unused]] static void set_emul_reg(uint8_t address, uint8_t reg_value) +// void get_input(char *buf, int len) // { -// emul_ezo_ec_set_reg(emul, address, reg_value); +// emul_ezo_ec_get_input(emul,buf,len); // } -void reset_emul_registers() +void reset_emul() { - emul_ezo_ec_reset_registers(emul); + emul_ezo_ec_reset_buffers(emul); } ezo_ec_config get_emul_config() @@ -31,10 +34,13 @@ ezo_ec_config get_emul_config() return emul_ezo_ec_get_config(emul); } -void re_init_pcf85063a(struct ezo_ec_config config) +void re_init(struct ezo_ec_config config) { emul_ezo_ec_set_config(emul, config); + std::string_view info = "?i,EC,2.16\0"; + set_output(info.data(), info.length()); // NOLINT + // This is a bit hacky... but it works! // Calls the init functions and updates the state used // by `device_is_ready()`. Code taken from Zephyr's init.c @@ -59,10 +65,10 @@ void re_init_pcf85063a(struct ezo_ec_config config) void* setup() { - emul = emul_get_binding("ezoec@0"); + emul = emul_get_binding("ezoec@64"); struct ezo_ec_config config = get_emul_config(); - re_init_pcf85063a(config); + re_init(config); zassert_true(device_is_ready(ezo), "Device is not ready"); return nullptr; @@ -70,14 +76,21 @@ void* setup() void teardown(void * /* f */) { - reset_emul_registers(); + reset_emul(); } - ZTEST(t_ezo_ec, test_fetch_and_get) { + std::string_view output = "4000.0"; + set_output(output.data(), output.length()); // NOLINT + + zassert_ok(sensor_sample_fetch(ezo)); + + sensor_value val {}; + zassert_ok(sensor_channel_get(ezo, (enum sensor_channel)SENSOR_CHAN_CONDUCTIVITY, &val)); - zassert_true(true); + zassert_equal(sensor_value_to_double(&val), 4000.0); + } ZTEST_SUITE(t_ezo_ec, NULL, setup, NULL, NULL, teardown); // NOLINT From 413c0136c27f32bb277473468bb9c509601ff243 Mon Sep 17 00:00:00 2001 From: Archie Atkinson Date: Thu, 8 May 2025 14:42:01 +0100 Subject: [PATCH 3/3] Small improvements --- cmake/Util.cmake | 3 + drivers/sensor/ezo_ec/emul_ezo_ec.c | 73 +++++------------------ drivers/sensor/ezo_ec/ezo_ec.c | 80 +++++++++++++++++++++++--- drivers/sensor/ezo_ec/ezo_ec_util.h | 12 +++- include/drivers/sensors/ezo_ec.h | 1 + tests/ezo_ec/boards/native_sim.overlay | 2 +- tests/ezo_ec/main.cpp | 25 ++++++-- 7 files changed, 121 insertions(+), 75 deletions(-) diff --git a/cmake/Util.cmake b/cmake/Util.cmake index 7ac7c46..87655f4 100755 --- a/cmake/Util.cmake +++ b/cmake/Util.cmake @@ -14,6 +14,9 @@ function(ProjectSetup snippets) list(APPEND SNIPPET_ROOT $ENV{NOTUS_ROOT}) set(SNIPPET_ROOT ${SNIPPET_ROOT} PARENT_SCOPE) + + list(APPEND DTS_ROOT $ENV{NOTUS_ROOT}) + set(DTS_ROOT ${DTS_ROOT} PARENT_SCOPE) set(SNIPPET ${snippets} PARENT_SCOPE) diff --git a/drivers/sensor/ezo_ec/emul_ezo_ec.c b/drivers/sensor/ezo_ec/emul_ezo_ec.c index ce4f15a..b4c0266 100644 --- a/drivers/sensor/ezo_ec/emul_ezo_ec.c +++ b/drivers/sensor/ezo_ec/emul_ezo_ec.c @@ -16,7 +16,12 @@ #include "emul_ezo_ec.h" #include "ezo_ec_util.h" -LOG_MODULE_REGISTER(EMUL_EZO_EC); +LOG_MODULE_REGISTER(EMUL_EZO_EC); //NOLINT + +// Future Updates: +// - Move to a circular buffer for input and output data +// - Add ability to set response code +// - Add support for the internal state? // Runtime Data struct emul_ezo_ec_data @@ -42,7 +47,6 @@ void emul_ezo_ec_set_output(const struct emul *emul, const char *buf, int len) void emul_ezo_ec_reset_buffers(const struct emul *emul) { - LOG_INF("Resetting Registers"); struct emul_ezo_ec_data *data = emul->data; memset(data->input,0, EZO_EC_BUFFER_SIZE); memset(data->output, 0, EZO_EC_BUFFER_SIZE); @@ -107,57 +111,6 @@ static int emul_ezo_ec_transfer(const struct emul *target, struct i2c_msg *msgs, return -EIO; } - // switch (num_msgs) - // { - // case 1: { - // if ((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) - // { - // emul_ezo_ec_read(data, msgs[0].len, msgs[0].buf); - // } - // else if ((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) - // { - // data->cur_reg = msgs[0].buf[0]; - // if (msgs[0].len != 1) - // { - // emul_ezo_ec_write(data, msgs[0].len - 1, &msgs[0].buf[1]); - // } - // } - // else - // { - // LOG_ERR("Unknown transfer"); - // return -EIO; - // } - // break; - // } - // case 2: { - // if ((msgs[0].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) - // { - // return -EIO; - // } - // if (msgs[0].len != 1U) - // { - // return -EIO; - // } - - // data->cur_reg = msgs->buf[0]; - // // Handle Second Message - - // if ((msgs[1].flags & I2C_MSG_RW_MASK) == I2C_MSG_READ) - // { - // emul_ezo_ec_read(data, msgs[1].len, msgs[1].buf); - // } - // else if ((msgs[1].flags & I2C_MSG_RW_MASK) == I2C_MSG_WRITE) - // { - // emul_ezo_ec_write(data, msgs[1].len, msgs[1].buf); - // } - // break; - // } - // default: { - // LOG_ERR("Invalid number of messages"); - // return -EIO; - // } - // } - return 0; } @@ -178,19 +131,19 @@ static int emul_ezo_ec_init(const struct emul *target, const struct device *pare emul_ezo_ec_reset_buffers(target); char info[] = "?i,EC,2.16"; - emul_ezo_ec_set_output(target, info, strlen(info)); + emul_ezo_ec_set_output(target, info, (int)strlen(info)); return 0; } // clang-format off #define ezo_ec_EMUL(inst) \ - static struct emul_ezo_ec_data emul_ezo_ec_data_##inst; \ - EMUL_DT_INST_DEFINE(inst, \ - &emul_ezo_ec_init, \ - &emul_ezo_ec_data_##inst, \ - NULL, \ - &emul_ezo_ec_api, \ + static struct emul_ezo_ec_data emul_ezo_ec_data_##inst; \ + EMUL_DT_INST_DEFINE(inst, \ + &emul_ezo_ec_init, \ + &emul_ezo_ec_data_##inst, \ + NULL, \ + &emul_ezo_ec_api, \ NULL) DT_INST_FOREACH_STATUS_OKAY(ezo_ec_EMUL) // NOLINT diff --git a/drivers/sensor/ezo_ec/ezo_ec.c b/drivers/sensor/ezo_ec/ezo_ec.c index 739d3de..d345dde 100644 --- a/drivers/sensor/ezo_ec/ezo_ec.c +++ b/drivers/sensor/ezo_ec/ezo_ec.c @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -15,6 +16,12 @@ LOG_MODULE_REGISTER(ezo_ec, CONFIG_SENSOR_LOG_LEVEL); // NOLINT +// TODO: +// Add while loop (with max timeout) for checking reponse codes +// Add all channels +// Add all attr +// Add support for DTS based configuration + static int ezo_ec_sample_fetch(const struct device *dev, enum sensor_channel chan) { struct ezo_ec_data *data = dev->data; @@ -22,13 +29,21 @@ static int ezo_ec_sample_fetch(const struct device *dev, enum sensor_channel cha __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL); + if (i2c_write_dt(&config->i2c, READ_COMMAND, 1) < 0) + { + LOG_ERR("Failed to request sample"); + return -EIO; + } + + k_msleep(READ_RESPONSE_TIME_MS); + if (i2c_read_dt(&config->i2c, data->output, EZO_EC_BUFFER_SIZE) < 0) { LOG_ERR("Failed to read sample"); return -EIO; } - if(data->output[0] != 1) + if(data->output[0] != OK_RESPONSE_CODE) { LOG_ERR("Reponse Code not 1"); return -EIO; @@ -37,10 +52,11 @@ static int ezo_ec_sample_fetch(const struct device *dev, enum sensor_channel cha return 0; } -static int convert_conductiviy(const struct ezo_ec_data *data, struct sensor_value *val) +static int str_double_to_sensor_val(const struct ezo_ec_data *data, struct sensor_value *val) { char *endptr = NULL; + // 1 byte offset for response code double value = strtod(data->output + 1, &endptr); if(data->output + 1 == endptr) @@ -50,9 +66,7 @@ static int convert_conductiviy(const struct ezo_ec_data *data, struct sensor_val sensor_value_from_double(val, value); - return 0; - - + return 0; } static int ezo_ec_channel_get(const struct device *dev, enum sensor_channel chan, struct sensor_value *val) @@ -63,18 +77,63 @@ static int ezo_ec_channel_get(const struct device *dev, enum sensor_channel chan if (our_chan == SENSOR_CHAN_CONDUCTIVITY) { - return convert_conductiviy(data, val); + return str_double_to_sensor_val(data, val); } return -ENOTSUP; } +static int calibrate(const struct device *dev) +{ + const struct ezo_ec_config *config = dev->config; + + if (i2c_write_dt(&config->i2c, CALIBRATE_DRY_COMMAND, sizeof(CALIBRATE_DRY_COMMAND)) < 0) + { + LOG_ERR("Failed to request sample"); + return -EIO; + } + + k_msleep(CALIBRATE_RESPONSE_TIME_MS); + + uint8_t response = 0; + + if (i2c_read_dt(&config->i2c, &response, 1) < 0) + { + LOG_ERR("Failed to read calibration response"); + return -EIO; + } + + if(response != OK_RESPONSE_CODE) + { + LOG_ERR("Reponse Code not 1"); + return -EIO; + } + + return 0; + +} + +static int ezo_ec_attr_set(const struct device *dev, enum sensor_channel chan, + enum sensor_attribute attr, const struct sensor_value *val) +{ + ARG_UNUSED(chan); + ARG_UNUSED(val); + + if(attr == SENSOR_ATTR_CALIBRATION) + { + return calibrate(dev); + } + + LOG_ERR("Attribute not recognised. Err: %i", attr); + return -ENOTSUP; +} + + int ezo_ec_init(const struct device *dev) { const struct ezo_ec_config *const config = dev->config; - // device is ready if (!device_is_ready(config->i2c.bus)) { LOG_ERR("I2C bus device not ready"); @@ -87,18 +146,20 @@ int ezo_ec_init(const struct device *dev) return -EIO; } - k_msleep(RESPONSE_TIME_MS); // Required + k_msleep(INFO_RESPONSE_TIME_MS); char buf[EZO_EC_BUFFER_SIZE]; if(i2c_read_dt(&config->i2c, (uint8_t*)&buf, EZO_EC_BUFFER_SIZE)) { LOG_ERR("Failed to get info command"); + return -EIO; } char expected[] = "?i,EC,2.16"; if (buf[0] != OK_RESPONSE_CODE && strcmp(expected, buf+1) != 0) { - LOG_ERR("Incorrect Info %s", buf); + LOG_ERR("Incorrect Device Info %s", buf); + return -EIO; } return 0; @@ -107,6 +168,7 @@ int ezo_ec_init(const struct device *dev) static const struct sensor_driver_api ezo_ec_api_funcs = { .sample_fetch = ezo_ec_sample_fetch, .channel_get = ezo_ec_channel_get, + .attr_set = ezo_ec_attr_set, }; #define ezo_ec_DEFINE(inst) \ diff --git a/drivers/sensor/ezo_ec/ezo_ec_util.h b/drivers/sensor/ezo_ec/ezo_ec_util.h index e42d89d..13e6558 100644 --- a/drivers/sensor/ezo_ec/ezo_ec_util.h +++ b/drivers/sensor/ezo_ec/ezo_ec_util.h @@ -11,11 +11,20 @@ extern "C" #endif #define EZO_EC_BUFFER_SIZE 30 -#define RESPONSE_TIME_MS 300 #define OK_RESPONSE_CODE 1 #define INFO_COMMAND "i" +#define INFO_RESPONSE_TIME_MS 300 + #define READ_COMMAND "R" +#define READ_RESPONSE_TIME_MS 600 + +#define CALIBRATE_DRY_COMMAND "Cal,dry" +#define CALIBRATE_RESPONSE_TIME_MS 600 + +#define PROBE_COMMAND "K," +#define PROBE_RESPONSE_TIME_MS 300 + int ezo_ec_init(const struct device *dev); @@ -26,6 +35,7 @@ struct ezo_ec_config struct ezo_ec_data { + double conductiviy; char output[EZO_EC_BUFFER_SIZE]; }; diff --git a/include/drivers/sensors/ezo_ec.h b/include/drivers/sensors/ezo_ec.h index 38b2c25..59e3024 100644 --- a/include/drivers/sensors/ezo_ec.h +++ b/include/drivers/sensors/ezo_ec.h @@ -14,6 +14,7 @@ enum sensor_channel_ezo_ec SENSOR_CHAN_CONDUCTIVITY = SENSOR_CHAN_PRIV_START, }; + #ifdef __cplusplus } #endif diff --git a/tests/ezo_ec/boards/native_sim.overlay b/tests/ezo_ec/boards/native_sim.overlay index 06d258d..63a2ad6 100644 --- a/tests/ezo_ec/boards/native_sim.overlay +++ b/tests/ezo_ec/boards/native_sim.overlay @@ -1,6 +1,6 @@ &i2c0 { ezo_ec: ezoec@64 { - compatible = "atlas,ezo_ec"; + compatible = "atlas,ezo-ec"; reg = <0x64>; }; }; diff --git a/tests/ezo_ec/main.cpp b/tests/ezo_ec/main.cpp index 670b131..c0df7ed 100644 --- a/tests/ezo_ec/main.cpp +++ b/tests/ezo_ec/main.cpp @@ -1,4 +1,6 @@ +#include #include +#include #include #include #include @@ -19,10 +21,10 @@ void set_output(const char *buf, int len) emul_ezo_ec_set_output(emul,buf, len); } -// void get_input(char *buf, int len) -// { -// emul_ezo_ec_get_input(emul,buf,len); -// } +void get_input(char *buf, int len) +{ + emul_ezo_ec_get_input(emul,buf,len); +} void reset_emul() { @@ -79,6 +81,17 @@ void teardown(void * /* f */) reset_emul(); } +ZTEST(t_ezo_ec, test_attr_set) +{ + zassert_ok(sensor_attr_set(ezo, SENSOR_CHAN_ALL, SENSOR_ATTR_CALIBRATION, nullptr)); + + std::array input{}; // NOLINT + get_input(input.data(), input.size()); + std::string input_str(input.begin(), input.end()); + zassert_equal(strcmp(input_str.c_str(), "Cal,dry"), 0); +} + + ZTEST(t_ezo_ec, test_fetch_and_get) { std::string_view output = "4000.0"; @@ -89,6 +102,10 @@ ZTEST(t_ezo_ec, test_fetch_and_get) sensor_value val {}; zassert_ok(sensor_channel_get(ezo, (enum sensor_channel)SENSOR_CHAN_CONDUCTIVITY, &val)); + std::array input{}; + get_input(input.data(), input.size()); + zassert_equal(input[0], 'R'); + zassert_equal(sensor_value_to_double(&val), 4000.0); }