From 7b3d7eb7652eb6c271195f3aba9106c8843be39b Mon Sep 17 00:00:00 2001 From: Ryan Howard Date: Wed, 24 Jul 2024 16:50:26 -0400 Subject: [PATCH] feat(sensors): support new pipette sensor board (#797) * add a singlton to hold the version info and an i2c task to attempt to read the io expander and update the singleton * EXEC-617 connect sensor hardware to the version wrapper * EXEC_618 remove e1 firmware varient for pipettes * get tests, simulators compiling and run format * add test for reading presssure when board rev changes * add a test for max pressure cause i'm supprised there wasn't one * format the tests * spelling * lint * format * delay was too short for no reason * R13 was intentionally not populated on the board so the expander returns 0x1 instead of 0x3 * add a getter for max sensor reading * format * format' --- gripper/firmware/main_proto.cpp | 4 +- gripper/firmware/main_rev1.cpp | 4 +- gripper/simulator/main.cpp | 3 +- include/bootloader/core/ids.h | 2 + include/can/core/ids.hpp | 2 + include/can/core/messages.hpp | 48 ++++++++++ include/gripper/core/can_task.hpp | 3 +- include/pipettes/core/dispatch_builder.hpp | 3 +- include/pipettes/core/sensor_tasks.hpp | 24 +++-- .../firmware/utility_configurations.hpp | 4 +- .../sensors/core/message_handlers/sensors.hpp | 5 + include/sensors/core/pie4ioe5.hpp | 37 ++++++++ .../core/sensor_hardware_interface.hpp | 33 ++++++- .../core/tasks/capacitive_sensor_task.hpp | 4 + .../core/tasks/environmental_sensor_task.hpp | 4 + .../sensors/core/tasks/pressure_driver.hpp | 20 ++-- .../core/tasks/pressure_sensor_task.hpp | 23 +++-- .../core/tasks/read_sensor_board_rev_task.hpp | 93 +++++++++++++++++++ .../tasks/tip_presence_notification_task.hpp | 1 - include/sensors/core/utils.hpp | 8 +- include/sensors/firmware/sensor_hardware.hpp | 5 +- include/sensors/simulation/mock_hardware.hpp | 3 + include/sensors/tests/mock_hardware.hpp | 3 + pipettes/core/sensor_tasks.cpp | 24 +++-- pipettes/firmware/CMakeLists.txt | 6 +- pipettes/firmware/main.cpp | 25 ++--- pipettes/firmware/utility_configurations.cpp | 13 ++- pipettes/simulator/main.cpp | 33 +++---- sensors/tests/test_capacitive_sensor.cpp | 12 ++- sensors/tests/test_pressure_driver.cpp | 77 ++++++++++++++- sensors/tests/test_pressure_sensor.cpp | 13 +-- sensors/tests/test_sensor_hardware.cpp | 6 +- 32 files changed, 443 insertions(+), 102 deletions(-) create mode 100644 include/sensors/core/pie4ioe5.hpp create mode 100644 include/sensors/core/tasks/read_sensor_board_rev_task.hpp diff --git a/gripper/firmware/main_proto.cpp b/gripper/firmware/main_proto.cpp index b34d83acf..0b7a11581 100644 --- a/gripper/firmware/main_proto.cpp +++ b/gripper/firmware/main_proto.cpp @@ -86,7 +86,9 @@ auto sensor_pins = sensors::hardware::SensorHardwareConfiguration{ .pin = GPIO_PIN_6, .active_setting = GPIO_PIN_RESET}}; -auto sensor_hardware = sensors::hardware::SensorHardware(sensor_pins); +auto version_wrapper = sensors::hardware::SensorHardwareVersionSingleton(); +auto sensor_hardware = + sensors::hardware::SensorHardware(sensor_pins, version_wrapper); auto main() -> int { HardwareInit(); diff --git a/gripper/firmware/main_rev1.cpp b/gripper/firmware/main_rev1.cpp index 62572ef6a..93ad86c92 100644 --- a/gripper/firmware/main_rev1.cpp +++ b/gripper/firmware/main_rev1.cpp @@ -97,7 +97,9 @@ auto sensor_pins = sensors::hardware::SensorHardwareConfiguration{ .pin = NSYNC_OUT_PIN, .active_setting = GPIO_PIN_RESET}}; -auto sensor_hardware = sensors::hardware::SensorHardware(sensor_pins); +auto version_wrapper = sensors::hardware::SensorHardwareVersionSingleton(); +auto sensor_hardware = + sensors::hardware::SensorHardware(sensor_pins, version_wrapper); auto main() -> int { HardwareInit(); diff --git a/gripper/simulator/main.cpp b/gripper/simulator/main.cpp index 831f2673d..da80eafb5 100644 --- a/gripper/simulator/main.cpp +++ b/gripper/simulator/main.cpp @@ -35,7 +35,8 @@ static auto sensor_map = i2c::hardware::SimI2C::DeviceMap{{capsensor.get_address(), capsensor}}; static auto i2c2 = i2c::hardware::SimI2C{sensor_map}; -static sim_mocks::MockSensorHardware fake_sensor_hw{}; +static sensors::hardware::SensorHardwareVersionSingleton version_wrapper{}; +static sim_mocks::MockSensorHardware fake_sensor_hw{version_wrapper}; static std::shared_ptr> diff --git a/include/bootloader/core/ids.h b/include/bootloader/core/ids.h index 78a9d69da..7c776a8ef 100644 --- a/include/bootloader/core/ids.h +++ b/include/bootloader/core/ids.h @@ -101,6 +101,8 @@ typedef enum { can_messageid_gear_set_current_request = 0x505, can_messageid_gear_write_motor_driver_request = 0x506, can_messageid_gear_read_motor_driver_request = 0x507, + can_messageid_max_sensor_value_request = 0x70, + can_messageid_max_sensor_value_response = 0x71, can_messageid_read_sensor_request = 0x82, can_messageid_write_sensor_request = 0x83, can_messageid_baseline_sensor_request = 0x84, diff --git a/include/can/core/ids.hpp b/include/can/core/ids.hpp index 50232ad3f..636a70cdd 100644 --- a/include/can/core/ids.hpp +++ b/include/can/core/ids.hpp @@ -103,6 +103,8 @@ enum class MessageId { gear_set_current_request = 0x505, gear_write_motor_driver_request = 0x506, gear_read_motor_driver_request = 0x507, + max_sensor_value_request = 0x70, + max_sensor_value_response = 0x71, read_sensor_request = 0x82, write_sensor_request = 0x83, baseline_sensor_request = 0x84, diff --git a/include/can/core/messages.hpp b/include/can/core/messages.hpp index d040ed580..3ad1da7c5 100644 --- a/include/can/core/messages.hpp +++ b/include/can/core/messages.hpp @@ -776,6 +776,54 @@ struct SendAccumulatedSensorDataRequest -> bool = default; }; +struct MaxSensorValueRequest + : BaseMessage { + uint32_t message_index = 0; + uint8_t sensor = 0; + uint8_t sensor_id = 0; + uint8_t offset_reading = 0; + + template + static auto parse(Input body, Limit limit) -> MaxSensorValueRequest { + uint8_t sensor = 0; + uint8_t sensor_id = 0; + uint8_t offset_reading = 0; + uint32_t msg_ind = 0; + + body = bit_utils::bytes_to_int(body, limit, msg_ind); + body = bit_utils::bytes_to_int(body, limit, sensor); + body = bit_utils::bytes_to_int(body, limit, sensor_id); + body = bit_utils::bytes_to_int(body, limit, offset_reading); + return MaxSensorValueRequest{.message_index = msg_ind, + .sensor = sensor, + .sensor_id = sensor_id, + .offset_reading = offset_reading}; + } + + auto operator==(const MaxSensorValueRequest& other) const -> bool = default; +}; + +struct MaxSensorValueResponse + : BaseMessage { + uint32_t message_index = 0; + can::ids::SensorType sensor{}; + can::ids::SensorId sensor_id{}; + int32_t sensor_data = 0; + + template + auto serialize(Output body, Limit limit) const -> uint8_t { + auto iter = bit_utils::int_to_bytes(message_index, body, limit); + iter = + bit_utils::int_to_bytes(static_cast(sensor), iter, limit); + iter = bit_utils::int_to_bytes(static_cast(sensor_id), iter, + limit); + iter = bit_utils::int_to_bytes(sensor_data, iter, limit); + return iter - body; + } + auto operator==(const MaxSensorValueResponse& other) const + -> bool = default; +}; + struct ReadFromSensorRequest : BaseMessage { uint32_t message_index = 0; uint8_t sensor = 0; diff --git a/include/gripper/core/can_task.hpp b/include/gripper/core/can_task.hpp index e3b3f294c..c31568ded 100644 --- a/include/gripper/core/can_task.hpp +++ b/include/gripper/core/can_task.hpp @@ -79,7 +79,8 @@ using SensorDispatchTarget = can::dispatch::DispatchParseTarget< can::messages::WriteToSensorRequest, can::messages::BaselineSensorRequest, can::messages::SetSensorThresholdRequest, can::messages::BindSensorOutputRequest, - can::messages::PeripheralStatusRequest>; + can::messages::PeripheralStatusRequest, + can::messages::MaxSensorValueRequest>; auto constexpr reader_message_buffer_size = 1024; diff --git a/include/pipettes/core/dispatch_builder.hpp b/include/pipettes/core/dispatch_builder.hpp index e5d0950c6..7bb94358b 100644 --- a/include/pipettes/core/dispatch_builder.hpp +++ b/include/pipettes/core/dispatch_builder.hpp @@ -96,7 +96,8 @@ using SensorDispatchTarget = can::dispatch::DispatchParseTarget< can::messages::WriteToSensorRequest, can::messages::BaselineSensorRequest, can::messages::SetSensorThresholdRequest, can::messages::BindSensorOutputRequest, - can::messages::PeripheralStatusRequest>; + can::messages::PeripheralStatusRequest, + can::messages::MaxSensorValueRequest>; using PipetteInfoDispatchTarget = can::dispatch::DispatchParseTarget< pipette_info::PipetteInfoMessageHandler; -void start_tasks(CanWriterTask& can_writer, I2CClient& i2c3_task_client, - I2CPollerClient& i2c3_poller_client, - I2CClient& i2c1_task_client, - I2CPollerClient& i2c1_poller_client, - sensors::hardware::SensorHardwareBase& sensor_hardware_primary, - can::ids::NodeId id, - eeprom::hardware_iface::EEPromHardwareIface& eeprom_hardware, - sensors::mmr920::SensorVersion sensor_version); +void start_tasks( + CanWriterTask& can_writer, I2CClient& i2c3_task_client, + I2CPollerClient& i2c3_poller_client, I2CClient& i2c1_task_client, + I2CPollerClient& i2c1_poller_client, + sensors::hardware::SensorHardwareBase& sensor_hardware_primary, + sensors::hardware::SensorHardwareVersionSingleton& version_wrapper, + can::ids::NodeId id, + eeprom::hardware_iface::EEPromHardwareIface& eeprom_hardware); void start_tasks( CanWriterTask& can_writer, I2CClient& i2c3_task_client, @@ -49,9 +50,9 @@ void start_tasks( I2CPollerClient& i2c1_poller_client, sensors::hardware::SensorHardwareBase& sensor_hardware_primary, sensors::hardware::SensorHardwareBase& sensor_hardware_secondary, + sensors::hardware::SensorHardwareVersionSingleton& version_wrapper, can::ids::NodeId id, - eeprom::hardware_iface::EEPromHardwareIface& eeprom_hardware, - sensors::mmr920::SensorVersion sensor_version); + eeprom::hardware_iface::EEPromHardwareIface& eeprom_hardware); /** * Access to all sensor/eeprom tasks. This will be a singleton. @@ -80,6 +81,9 @@ struct Tasks { sensors::tasks::TipPresenceNotificationTask< freertos_message_queue::FreeRTOSMessageQueue>* tip_notification_task_front{nullptr}; + sensors::tasks::ReadSensorBoardTask< + freertos_message_queue::FreeRTOSMessageQueue>* read_sensor_board_task{ + nullptr}; }; /** diff --git a/include/pipettes/firmware/utility_configurations.hpp b/include/pipettes/firmware/utility_configurations.hpp index d4c18035f..1f8ae83e1 100644 --- a/include/pipettes/firmware/utility_configurations.hpp +++ b/include/pipettes/firmware/utility_configurations.hpp @@ -21,7 +21,9 @@ struct SensorHardwareContainer { auto led_gpio(PipetteType pipette_type) -> gpio::PinConfig; -auto get_sensor_hardware_container(SensorHardwareGPIO pins) +auto get_sensor_hardware_container( + SensorHardwareGPIO pins, + sensors::hardware::SensorHardwareVersionSingleton& version_wrapper) -> SensorHardwareContainer; template diff --git a/include/sensors/core/message_handlers/sensors.hpp b/include/sensors/core/message_handlers/sensors.hpp index 533db997a..67da440cb 100644 --- a/include/sensors/core/message_handlers/sensors.hpp +++ b/include/sensors/core/message_handlers/sensors.hpp @@ -46,6 +46,11 @@ class SensorHandler { can::ids::SensorId(m.sensor_id), m); } + void visit(const can::messages::MaxSensorValueRequest &m) { + send_to_queue(can::ids::SensorType(m.sensor), + can::ids::SensorId(m.sensor_id), m); + } + void visit(const can::messages::SendAccumulatedSensorDataRequest &m) { if (can::ids::SensorType(m.sensor_type) == can::ids::SensorType::pressure) { diff --git a/include/sensors/core/pie4ioe5.hpp b/include/sensors/core/pie4ioe5.hpp new file mode 100644 index 000000000..7b886f794 --- /dev/null +++ b/include/sensors/core/pie4ioe5.hpp @@ -0,0 +1,37 @@ +#pragma once +namespace sensors { +namespace pie4ioe4 { +// https://www.diodes.com/assets/Datasheets/PI4IOE5V6408.pdf + +constexpr uint16_t ADDRESS = 0x43 << 1; + +enum class registers : uint8_t { + dev_id_and_ctl = 0x01, // default 1010 0010 + // reserved 0x02 + io_direction = 0x03, // default 0000 0000 + // reserved 0x04 + output_state = 0x05, // default 0000 0000 + // reserved 0x06 + output_high_impedance = 0x07, // default 1111 1111 + // reserved 0x08 + input_default_state = 0x09, // default 0000 0000 + // reserved 0x0A + pull_up_down_enable = 0x0B, // default 1111 1111 + // reserved 0x0C + pull_up_down_select = 0x0D, // default 0000 0000 + // reserved 0x0E + input_status = 0x0F, // default xxxx xxxx + // reserved 0x10 + interrupt_mask = 0x11, // default 0000 0000 + // reserved 0x12 + interrupt_status = 0x13, // default xxxx xxxx +}; + +enum class version_responses : uint8_t { + // right now only version D1.1 of the pipette sensor board responds + // version 0 does not respond + VERSION_1 = 0x01, // Pipette_sensor board D1.1 +}; + +} // namespace pie4ioe4 +} // namespace sensors diff --git a/include/sensors/core/sensor_hardware_interface.hpp b/include/sensors/core/sensor_hardware_interface.hpp index e39db7b76..f56cd8528 100644 --- a/include/sensors/core/sensor_hardware_interface.hpp +++ b/include/sensors/core/sensor_hardware_interface.hpp @@ -5,6 +5,7 @@ #include "can/core/ids.hpp" #include "common/firmware/gpio.hpp" +#include "sensors/core/utils.hpp" namespace sensors { namespace hardware { @@ -41,15 +42,37 @@ static auto get_mask_from_id(can::ids::SensorId sensor) -> uint8_t { } return static_cast(mask_enum); } + +class SensorHardwareVersionSingleton { + public: + SensorHardwareVersionSingleton() = default; + virtual ~SensorHardwareVersionSingleton() = default; + SensorHardwareVersionSingleton(const SensorHardwareVersionSingleton&) = + default; + auto operator=(const SensorHardwareVersionSingleton&) + -> SensorHardwareVersionSingleton& = default; + SensorHardwareVersionSingleton(SensorHardwareVersionSingleton&&) = default; + auto operator=(SensorHardwareVersionSingleton&&) + -> SensorHardwareVersionSingleton& = default; + + void set_board_rev(utils::SensorBoardRev rev) { b_revision = rev; } + + auto get_board_rev() -> utils::SensorBoardRev { return b_revision; } + + private: + utils::SensorBoardRev b_revision = utils::SensorBoardRev::VERSION_0; +}; + /** abstract sensor hardware device for a sync line */ class SensorHardwareBase { public: - SensorHardwareBase() = default; + SensorHardwareBase(SensorHardwareVersionSingleton& version_wrapper) + : version_wrapper{version_wrapper} {} virtual ~SensorHardwareBase() = default; SensorHardwareBase(const SensorHardwareBase&) = default; - auto operator=(const SensorHardwareBase&) -> SensorHardwareBase& = default; + auto operator=(const SensorHardwareBase&) -> SensorHardwareBase& = delete; SensorHardwareBase(SensorHardwareBase&&) = default; - auto operator=(SensorHardwareBase&&) -> SensorHardwareBase& = default; + auto operator=(SensorHardwareBase&&) -> SensorHardwareBase& = delete; virtual auto set_sync() -> void = 0; virtual auto reset_sync() -> void = 0; @@ -114,11 +137,15 @@ class SensorHardwareBase { reset_sync(); } } + auto get_board_rev() -> utils::SensorBoardRev { + return version_wrapper.get_board_rev(); + } private: uint8_t set_sync_required_mask = 0x00; uint8_t set_sync_enabled_mask = 0x00; uint8_t sync_state_mask = 0x00; + SensorHardwareVersionSingleton& version_wrapper; }; struct SensorHardwareContainer { diff --git a/include/sensors/core/tasks/capacitive_sensor_task.hpp b/include/sensors/core/tasks/capacitive_sensor_task.hpp index 824ba72bb..7c62128dc 100644 --- a/include/sensors/core/tasks/capacitive_sensor_task.hpp +++ b/include/sensors/core/tasks/capacitive_sensor_task.hpp @@ -99,6 +99,10 @@ class CapacitiveMessageHandler { } } + void visit(const can::messages::MaxSensorValueRequest &m) { + std::ignore = m; + } + void visit(can::messages::WriteToSensorRequest &m) { LOG("Received request to write data %d to %d sensor", m.data, m.sensor); // FIXME we should send a response message after a write request diff --git a/include/sensors/core/tasks/environmental_sensor_task.hpp b/include/sensors/core/tasks/environmental_sensor_task.hpp index e1694a80b..7a94ab452 100644 --- a/include/sensors/core/tasks/environmental_sensor_task.hpp +++ b/include/sensors/core/tasks/environmental_sensor_task.hpp @@ -81,6 +81,10 @@ class EnvironmentSensorMessageHandler { std::ignore = m; } + void visit(const can::messages::MaxSensorValueRequest &m) { + std::ignore = m; + } + void visit(const can::messages::BindSensorOutputRequest &m) { LOG("Received bind sensor output request from %d sensor", m.sensor); // sync doesn't quite mean the same thing here for us. We should diff --git a/include/sensors/core/tasks/pressure_driver.hpp b/include/sensors/core/tasks/pressure_driver.hpp index 6efc5685c..142cf821f 100644 --- a/include/sensors/core/tasks/pressure_driver.hpp +++ b/include/sensors/core/tasks/pressure_driver.hpp @@ -42,7 +42,6 @@ class MMR920 { CanClient &can_client, OwnQueue &own_queue, sensors::hardware::SensorHardwareBase &hardware, const can::ids::SensorId &id, - const sensors::mmr920::SensorVersion version, std::array *sensor_buffer) : writer(writer), poller(poller), @@ -50,7 +49,6 @@ class MMR920 { own_queue(own_queue), hardware(hardware), sensor_id(id), - sensor_version(version), sensor_buffer(sensor_buffer) {} /** @@ -403,12 +401,12 @@ class MMR920 { save_pressure(shifted_data_store); auto pressure = mmr920::PressureResult::to_pressure( - _registers.pressure_result.reading, sensor_version); + _registers.pressure_result.reading, sensor_version()); if (max_pressure_sync) { bool this_tick_over_threshold = std::fabs(pressure - current_pressure_baseline_pa) >= - mmr920::get_max_pressure_reading(sensor_version); + mmr920::get_max_pressure_reading(sensor_version()); bool over_threshold = false; if (this_tick_over_threshold) { max_pressure_consecutive_readings = @@ -508,7 +506,7 @@ class MMR920 { uint32_t shifted_data_store = temporary_data_store >> 8; auto pressure = mmr920::PressureResult::to_pressure(shifted_data_store, - sensor_version); + sensor_version()); pressure_running_total += pressure; if (!m.id.is_completed_poll) { @@ -578,6 +576,17 @@ class MMR920 { auto get_can_client() -> CanClient & { return can_client; } + auto sensor_version() -> sensors::mmr920::SensorVersion { + utils::SensorBoardRev rev = hardware.get_board_rev(); + switch (rev) { + case utils::SensorBoardRev::VERSION_1: + return sensors::mmr920::SensorVersion::mmr920c10; + case utils::SensorBoardRev::VERSION_0: + default: + return sensors::mmr920::SensorVersion::mmr920c04; + } + } + private: I2CQueueWriter &writer; I2CQueuePoller &poller; @@ -585,7 +594,6 @@ class MMR920 { OwnQueue &own_queue; hardware::SensorHardwareBase &hardware; const can::ids::SensorId &sensor_id; - const sensors::mmr920::SensorVersion sensor_version; mmr920::MMR920RegisterMap _registers{}; mmr920::FilterSetting filter_setting = diff --git a/include/sensors/core/tasks/pressure_sensor_task.hpp b/include/sensors/core/tasks/pressure_sensor_task.hpp index 7c0d72023..fa2b5a0a8 100644 --- a/include/sensors/core/tasks/pressure_sensor_task.hpp +++ b/include/sensors/core/tasks/pressure_sensor_task.hpp @@ -23,10 +23,10 @@ class PressureMessageHandler { CanClient &can_client, OwnQueue &own_queue, sensors::hardware::SensorHardwareBase &hardware, const can::ids::SensorId &id, - const sensors::mmr920::SensorVersion &version, std::array *sensor_buffer) - : driver{i2c_writer, i2c_poller, can_client, own_queue, - hardware, id, version, sensor_buffer} {} + : driver{i2c_writer, i2c_poller, can_client, own_queue, + hardware, id, sensor_buffer}, + sensor_id{id} {} PressureMessageHandler(const PressureMessageHandler &) = delete; PressureMessageHandler(const PressureMessageHandler &&) = delete; auto operator=(const PressureMessageHandler &) @@ -98,6 +98,17 @@ class PressureMessageHandler { } } + void visit(const can::messages::MaxSensorValueRequest &m) { + auto max = mmr920::get_max_pressure_reading(driver.sensor_version()); + auto message = can::messages::ReadFromSensorResponse{ + .message_index = m.message_index, + .sensor = SensorType::pressure, + .sensor_id = sensor_id, + .sensor_data = mmr920::reading_to_fixed_point(max)}; + driver.get_can_client().send_can_message(can::ids::NodeId::host, + message); + } + void visit(const can::messages::WriteToSensorRequest &m) { LOG("Received request to write data %d to %d sensor\n", m.data, m.sensor); @@ -182,6 +193,7 @@ class PressureMessageHandler { } MMR920 driver; + can::ids::SensorId sensor_id; }; /** @@ -209,11 +221,10 @@ class PressureSensorTask { i2c::writer::Writer *writer, i2c::poller::Poller *poller, CanClient *can_client, sensors::hardware::SensorHardwareBase *hardware, - sensors::mmr920::SensorVersion *sensor_version, std::array *sensor_buffer) { auto handler = PressureMessageHandler{ - *writer, *poller, *can_client, get_queue(), - *hardware, sensor_id, *sensor_version, sensor_buffer}; + *writer, *poller, *can_client, get_queue(), + *hardware, sensor_id, sensor_buffer}; handler.initialize(); utils::TaskMessage message{}; for (;;) { diff --git a/include/sensors/core/tasks/read_sensor_board_rev_task.hpp b/include/sensors/core/tasks/read_sensor_board_rev_task.hpp new file mode 100644 index 000000000..457978b01 --- /dev/null +++ b/include/sensors/core/tasks/read_sensor_board_rev_task.hpp @@ -0,0 +1,93 @@ +#pragma once + +#include "sensors/core/pie4ioe5.hpp" +#include "sensors/core/utils.hpp" + +namespace sensors { +namespace tasks { + +using TaskMessage = + std::variant; + +template +class ReadSensorBoardHandler { + public: + explicit ReadSensorBoardHandler(I2CQueueWriter &i2c_writer, + OwnQueue &own_queue) + : i2c_writer{i2c_writer}, task_queue{own_queue} { + // request gpio expander status register + i2c_writer->read( + pie4ioe4::ADDRESS, + static_cast(pie4ioe4::registers::input_status), 1, + task_queue); + } + ReadSensorBoardHandler(const ReadSensorBoardHandler &) = delete; + ReadSensorBoardHandler(const ReadSensorBoardHandler &&) = delete; + auto operator=(const ReadSensorBoardHandler &) + -> ReadSensorBoardHandler & = delete; + auto operator=(const ReadSensorBoardHandler &&) + -> ReadSensorBoardHandler && = delete; + ~ReadSensorBoardHandler() = default; + + void handle_message(const TaskMessage &m) { + std::visit([this](auto o) { this->visit(o); }, m); + } + + auto get_rev() -> utils::SensorBoardRev { return rev; } + + private: + void visit(const std::monostate &) {} + + void visit(i2c::messages::TransactionResponse &m) { + if (m.bytes_read == 1 && + m.read_buffer[0] == + static_cast(pie4ioe4::version_responses::VERSION_1)) { + rev = utils::SensorBoardRev::VERSION_1; + } + } + + utils::SensorBoardRev rev = utils::SensorBoardRev::VERSION_0; + I2CQueueWriter &i2c_writer; + OwnQueue &task_queue; +}; + +/** + * The task type. + */ +template