diff --git a/core/src/protocol/deserializer.cpp b/core/src/protocol/deserializer.cpp index f746abb..f0b9ff2 100644 --- a/core/src/protocol/deserializer.cpp +++ b/core/src/protocol/deserializer.cpp @@ -108,9 +108,7 @@ coroutine::LifoTask Deserializer::process_can_field(FieldId field_id) { data_view.can_data = std::span{}; } - callback_.can_deserialized_callback(field_id, data_view); - - co_return true; + co_return callback_.can_deserialized_callback(field_id, data_view); } coroutine::LifoTask Deserializer::process_uart_field(FieldId field_id) { @@ -147,9 +145,7 @@ coroutine::LifoTask Deserializer::process_uart_field(FieldId field_id) { data_view.uart_data = std::span{}; } - callback_.uart_deserialized_callback(field_id, data_view); - - co_return true; + co_return callback_.uart_deserialized_callback(field_id, data_view); } coroutine::LifoTask Deserializer::process_gpio_field(FieldId) { @@ -169,16 +165,25 @@ coroutine::LifoTask Deserializer::process_gpio_field(FieldId) { } switch (payload_type) { - case GpioHeader::PayloadEnum::kDigitalWriteLow: - case GpioHeader::PayloadEnum::kDigitalWriteHigh: { - if (timestamped) [[unlikely]] - co_return false; + case GpioHeader::PayloadEnum::kDigitalLow: + case GpioHeader::PayloadEnum::kDigitalHigh: { data::GpioDigitalDataView data_view{}; - data_view.high = payload_type == GpioHeader::PayloadEnum::kDigitalWriteHigh; - callback_.gpio_digital_data_deserialized_callback(channel_index, data_view); + data_view.high = payload_type == GpioHeader::PayloadEnum::kDigitalHigh; + if (timestamped) { + const auto* payload_bytes = + co_await peek_bytes(sizeof(GpioDigitalReadTimestampPayload)); + if (!payload_bytes) [[unlikely]] + co_return false; + auto payload = GpioDigitalReadTimestampPayload::CRef{payload_bytes}; + data_view.timestamp_quarter_us = + payload.get(); + consume_peeked(); + } + if (!callback_.gpio_digital_data_deserialized_callback(channel_index, data_view)) + co_return false; break; } - case GpioHeader::PayloadEnum::kAnalogWrite: { + case GpioHeader::PayloadEnum::kAnalog: { if (timestamped) [[unlikely]] co_return false; const auto* payload_bytes = co_await peek_bytes(sizeof(GpioAnalogPayload)); @@ -190,11 +195,12 @@ coroutine::LifoTask Deserializer::process_gpio_field(FieldId) { data_view.value = payload.get(); consume_peeked(); - callback_.gpio_analog_data_deserialized_callback(channel_index, data_view); + if (!callback_.gpio_analog_data_deserialized_callback(channel_index, data_view)) + co_return false; break; } - case GpioHeader::PayloadEnum::kDigitalRead: - case GpioHeader::PayloadEnum::kAnalogRead: { + case GpioHeader::PayloadEnum::kDigitalReadConfig: + case GpioHeader::PayloadEnum::kAnalogReadConfig: { const auto* payload_bytes = co_await peek_bytes(sizeof(GpioReadConfigPayload)); if (!payload_bytes) [[unlikely]] co_return false; @@ -213,45 +219,15 @@ coroutine::LifoTask Deserializer::process_gpio_field(FieldId) { && data_view.pull != data::GpioPull::kDown) co_return false; - if (payload_type == GpioHeader::PayloadEnum::kDigitalRead) { - callback_.gpio_digital_read_config_deserialized_callback(channel_index, data_view); + if (payload_type == GpioHeader::PayloadEnum::kDigitalReadConfig) { + if (!callback_.gpio_digital_read_config_deserialized_callback(channel_index, data_view)) + co_return false; } else { if (data_view.capture_timestamp || data_view.rising_edge || data_view.falling_edge) co_return false; - callback_.gpio_analog_read_config_deserialized_callback(channel_index, data_view); - } - break; - } - case GpioHeader::PayloadEnum::kDigitalReadResultLow: - case GpioHeader::PayloadEnum::kDigitalReadResultHigh: { - data::GpioDigitalDataView data_view{}; - data_view.high = payload_type == GpioHeader::PayloadEnum::kDigitalReadResultHigh; - if (timestamped) { - const auto* payload_bytes = - co_await peek_bytes(sizeof(GpioDigitalReadTimestampPayload)); - if (!payload_bytes) [[unlikely]] + if (!callback_.gpio_analog_read_config_deserialized_callback(channel_index, data_view)) co_return false; - auto payload = GpioDigitalReadTimestampPayload::CRef{payload_bytes}; - data_view.timestamp_quarter_us = - payload.get(); - consume_peeked(); } - callback_.gpio_digital_data_deserialized_callback(channel_index, data_view); - break; - } - case GpioHeader::PayloadEnum::kAnalogReadResult: { - if (timestamped) [[unlikely]] - co_return false; - const auto* payload_bytes = co_await peek_bytes(sizeof(GpioAnalogPayload)); - if (!payload_bytes) [[unlikely]] - co_return false; - - auto payload = GpioAnalogPayload::CRef{payload_bytes}; - data::GpioAnalogDataView data_view{}; - data_view.value = payload.get(); - consume_peeked(); - - callback_.gpio_analog_data_deserialized_callback(channel_index, data_view); break; } default: co_return false; diff --git a/core/src/protocol/deserializer.hpp b/core/src/protocol/deserializer.hpp index 4e346a0..263a56f 100644 --- a/core/src/protocol/deserializer.hpp +++ b/core/src/protocol/deserializer.hpp @@ -24,20 +24,22 @@ class DeserializeCallback { DeserializeCallback& operator=(DeserializeCallback&&) = delete; virtual ~DeserializeCallback() = default; - virtual void can_deserialized_callback(FieldId id, const data::CanDataView& data) = 0; + [[nodiscard]] virtual bool + can_deserialized_callback(FieldId id, const data::CanDataView& data) = 0; - virtual void uart_deserialized_callback(FieldId id, const data::UartDataView& data) = 0; + [[nodiscard]] virtual bool + uart_deserialized_callback(FieldId id, const data::UartDataView& data) = 0; - virtual void gpio_digital_data_deserialized_callback( + [[nodiscard]] virtual bool gpio_digital_data_deserialized_callback( uint8_t channel_index, const data::GpioDigitalDataView& data) = 0; - virtual void gpio_analog_data_deserialized_callback( + [[nodiscard]] virtual bool gpio_analog_data_deserialized_callback( uint8_t channel_index, const data::GpioAnalogDataView& data) = 0; - virtual void gpio_digital_read_config_deserialized_callback( + [[nodiscard]] virtual bool gpio_digital_read_config_deserialized_callback( uint8_t channel_index, const data::GpioReadConfigView& data) = 0; - virtual void gpio_analog_read_config_deserialized_callback( + [[nodiscard]] virtual bool gpio_analog_read_config_deserialized_callback( uint8_t channel_index, const data::GpioReadConfigView& data) = 0; virtual void accelerometer_deserialized_callback(const data::AccelerometerDataView& data) = 0; diff --git a/core/src/protocol/protocol.hpp b/core/src/protocol/protocol.hpp index 2fb690d..fe7960c 100644 --- a/core/src/protocol/protocol.hpp +++ b/core/src/protocol/protocol.hpp @@ -93,14 +93,11 @@ struct SessionHeader struct GpioHeader : utility::Bitfield<2> { enum class PayloadEnum : uint8_t { - kDigitalWriteLow = 0b0000, - kDigitalWriteHigh = 0b0001, - kAnalogWrite = 0b0010, - kDigitalRead = 0b0100, - kAnalogRead = 0b0110, - kDigitalReadResultLow = 0b1000, - kDigitalReadResultHigh = 0b1001, - kAnalogReadResult = 0b1010, + kDigitalLow = 0b0000, + kDigitalHigh = 0b0001, + kAnalog = 0b0010, + kDigitalReadConfig = 0b0100, + kAnalogReadConfig = 0b0110, }; using PayloadType = utility::BitfieldMember<4, 4, PayloadEnum>; diff --git a/core/src/protocol/serializer.hpp b/core/src/protocol/serializer.hpp index db85988..b213f7b 100644 --- a/core/src/protocol/serializer.hpp +++ b/core/src/protocol/serializer.hpp @@ -120,14 +120,13 @@ class Serializer { return SerializeResult::kSuccess; } - SerializeResult write_gpio_digital_data( + SerializeResult write_gpio_digital_value( uint8_t channel_index, const data::GpioDigitalDataView& view) noexcept { utility::assert_debug(channel_index < (1U << GpioHeader::ChannelIndex::kBitWidth)); - LIBRMCS_VERIFY_LIKELY( - !view.timestamp_quarter_us.has_value(), SerializeResult::kInvalidArgument); - const auto payload_type = view.high ? GpioHeader::PayloadEnum::kDigitalWriteHigh - : GpioHeader::PayloadEnum::kDigitalWriteLow; - const std::size_t required = required_gpio_size(FieldId::kGpio, payload_type); + const auto payload_type = view.high ? GpioHeader::PayloadEnum::kDigitalHigh + : GpioHeader::PayloadEnum::kDigitalLow; + const std::size_t required = + required_gpio_size(FieldId::kGpio, payload_type, view.timestamp_quarter_us.has_value()); LIBRMCS_VERIFY_LIKELY(required, SerializeResult::kInvalidArgument); auto dst = buffer_.allocate(required); @@ -141,7 +140,14 @@ class Serializer { cursor += sizeof(GpioHeader); header.set(payload_type); header.set(channel_index); - header.set(false); + header.set(view.timestamp_quarter_us.has_value()); + + if (view.timestamp_quarter_us) { + auto payload = GpioDigitalReadTimestampPayload::Ref(cursor); + cursor += sizeof(GpioDigitalReadTimestampPayload); + payload.set( + *view.timestamp_quarter_us); + } utility::assert_debug(cursor == dst.data() + dst.size()); return SerializeResult::kSuccess; @@ -151,7 +157,7 @@ class Serializer { uint8_t channel_index, const data::GpioReadConfigView& view) noexcept { utility::assert_debug(channel_index < (1U << GpioHeader::ChannelIndex::kBitWidth)); const std::size_t required = - required_gpio_size(FieldId::kGpio, GpioHeader::PayloadEnum::kDigitalRead); + required_gpio_size(FieldId::kGpio, GpioHeader::PayloadEnum::kDigitalReadConfig); LIBRMCS_VERIFY_LIKELY(required, SerializeResult::kInvalidArgument); auto dst = buffer_.allocate(required); @@ -163,7 +169,7 @@ class Serializer { auto header = GpioHeader::Ref(cursor); cursor += sizeof(GpioHeader); - header.set(GpioHeader::PayloadEnum::kDigitalRead); + header.set(GpioHeader::PayloadEnum::kDigitalReadConfig); header.set(channel_index); header.set(view.capture_timestamp); @@ -179,11 +185,11 @@ class Serializer { return SerializeResult::kSuccess; } - SerializeResult write_gpio_analog_data( + SerializeResult write_gpio_analog_value( uint8_t channel_index, const data::GpioAnalogDataView& view) noexcept { utility::assert_debug(channel_index < (1U << GpioHeader::ChannelIndex::kBitWidth)); const std::size_t required = - required_gpio_size(FieldId::kGpio, GpioHeader::PayloadEnum::kAnalogWrite); + required_gpio_size(FieldId::kGpio, GpioHeader::PayloadEnum::kAnalog); LIBRMCS_VERIFY_LIKELY(required, SerializeResult::kInvalidArgument); auto dst = buffer_.allocate(required); @@ -195,7 +201,7 @@ class Serializer { auto header = GpioHeader::Ref(cursor); cursor += sizeof(GpioHeader); - header.set(GpioHeader::PayloadEnum::kAnalogWrite); + header.set(GpioHeader::PayloadEnum::kAnalog); header.set(channel_index); header.set(false); @@ -215,7 +221,7 @@ class Serializer { LIBRMCS_VERIFY_LIKELY(!view.capture_timestamp, SerializeResult::kInvalidArgument); const std::size_t required = - required_gpio_size(FieldId::kGpio, GpioHeader::PayloadEnum::kAnalogRead); + required_gpio_size(FieldId::kGpio, GpioHeader::PayloadEnum::kAnalogReadConfig); LIBRMCS_VERIFY_LIKELY(required, SerializeResult::kInvalidArgument); auto dst = buffer_.allocate(required); @@ -227,7 +233,7 @@ class Serializer { auto header = GpioHeader::Ref(cursor); cursor += sizeof(GpioHeader); - header.set(GpioHeader::PayloadEnum::kAnalogRead); + header.set(GpioHeader::PayloadEnum::kAnalogReadConfig); header.set(channel_index); header.set(false); @@ -243,67 +249,6 @@ class Serializer { return SerializeResult::kSuccess; } - SerializeResult write_gpio_digital_read_result( - uint8_t channel_index, const data::GpioDigitalDataView& view) noexcept { - utility::assert_debug(channel_index < (1U << GpioHeader::ChannelIndex::kBitWidth)); - const auto payload_type = view.high ? GpioHeader::PayloadEnum::kDigitalReadResultHigh - : GpioHeader::PayloadEnum::kDigitalReadResultLow; - const std::size_t required = - required_gpio_size(FieldId::kGpio, payload_type, view.timestamp_quarter_us.has_value()); - LIBRMCS_VERIFY_LIKELY(required, SerializeResult::kInvalidArgument); - - auto dst = buffer_.allocate(required); - LIBRMCS_VERIFY_LIKELY(!dst.empty(), SerializeResult::kBadAlloc); - utility::assert_debug(dst.size() == required); - std::byte* cursor = dst.data(); - - write_field_header(cursor, FieldId::kGpio); - - auto header = GpioHeader::Ref(cursor); - cursor += sizeof(GpioHeader); - header.set(payload_type); - header.set(channel_index); - header.set(view.timestamp_quarter_us.has_value()); - - if (view.timestamp_quarter_us) { - auto payload = GpioDigitalReadTimestampPayload::Ref(cursor); - cursor += sizeof(GpioDigitalReadTimestampPayload); - payload.set( - *view.timestamp_quarter_us); - } - - utility::assert_debug(cursor == dst.data() + dst.size()); - return SerializeResult::kSuccess; - } - - SerializeResult write_gpio_analog_read_result( - uint8_t channel_index, const data::GpioAnalogDataView& view) noexcept { - utility::assert_debug(channel_index < (1U << GpioHeader::ChannelIndex::kBitWidth)); - const std::size_t required = - required_gpio_size(FieldId::kGpio, GpioHeader::PayloadEnum::kAnalogReadResult); - LIBRMCS_VERIFY_LIKELY(required, SerializeResult::kInvalidArgument); - - auto dst = buffer_.allocate(required); - LIBRMCS_VERIFY_LIKELY(!dst.empty(), SerializeResult::kBadAlloc); - utility::assert_debug(dst.size() == required); - std::byte* cursor = dst.data(); - - write_field_header(cursor, FieldId::kGpio); - - auto header = GpioHeader::Ref(cursor); - cursor += sizeof(GpioHeader); - header.set(GpioHeader::PayloadEnum::kAnalogReadResult); - header.set(channel_index); - header.set(false); - - auto payload = GpioAnalogPayload::Ref(cursor); - cursor += sizeof(GpioAnalogPayload); - payload.set(view.value); - - utility::assert_debug(cursor == dst.data() + dst.size()); - return SerializeResult::kSuccess; - } - SerializeResult write_imu_accelerometer(const data::AccelerometerDataView& view) noexcept { const std::size_t required = required_imu_size(FieldId::kImu, ImuPayload::kAccelerometer); LIBRMCS_VERIFY_LIKELY(required, SerializeResult::kInvalidArgument); @@ -466,20 +411,15 @@ class Serializer { const std::size_t gpio_header_bytes = sizeof(GpioHeader); std::size_t payload_bytes = 0; switch (payload) { - case GpioHeader::PayloadEnum::kDigitalWriteLow: - case GpioHeader::PayloadEnum::kDigitalWriteHigh: payload_bytes = 0; break; - case GpioHeader::PayloadEnum::kDigitalReadResultLow: - case GpioHeader::PayloadEnum::kDigitalReadResultHigh: + case GpioHeader::PayloadEnum::kDigitalLow: + case GpioHeader::PayloadEnum::kDigitalHigh: payload_bytes = timestamped ? sizeof(GpioDigitalReadTimestampPayload) : 0; break; - case GpioHeader::PayloadEnum::kDigitalRead: - case GpioHeader::PayloadEnum::kAnalogRead: + case GpioHeader::PayloadEnum::kDigitalReadConfig: + case GpioHeader::PayloadEnum::kAnalogReadConfig: payload_bytes = sizeof(GpioReadConfigPayload); break; - case GpioHeader::PayloadEnum::kAnalogWrite: - case GpioHeader::PayloadEnum::kAnalogReadResult: - payload_bytes = sizeof(GpioAnalogPayload); - break; + case GpioHeader::PayloadEnum::kAnalog: payload_bytes = sizeof(GpioAnalogPayload); break; default: return 0; } diff --git a/firmware/c_board/app/src/gpio/gpio.hpp b/firmware/c_board/app/src/gpio/gpio.hpp index 96cd189..a5540e8 100644 --- a/firmware/c_board/app/src/gpio/gpio.hpp +++ b/firmware/c_board/app/src/gpio/gpio.hpp @@ -211,7 +211,7 @@ class Gpio : private core::utility::Immovable { auto& serializer = usb::get_serializer(); core::utility::assert_debug( - serializer.write_gpio_digital_read_result( + serializer.write_gpio_digital_value( channel_index, {.high = high, .timestamp_quarter_us = timestamp_to_publish}) != core::protocol::Serializer::SerializeResult::kInvalidArgument); } diff --git a/firmware/c_board/app/src/usb/vendor.hpp b/firmware/c_board/app/src/usb/vendor.hpp index b8ac443..1e9051c 100644 --- a/firmware/c_board/app/src/usb/vendor.hpp +++ b/firmware/c_board/app/src/usb/vendor.hpp @@ -106,74 +106,82 @@ class Vendor session_established_ = true; } - void can_deserialized_callback( + bool can_deserialized_callback( core::protocol::FieldId id, const data::CanDataView& data) override { if (!session_established_) - return; + return true; switch (id) { - case data::DataId::kCan1: can::can1->handle_downlink(data); break; - case data::DataId::kCan2: can::can2->handle_downlink(data); break; - default: core::utility::assert_failed_always(); + case data::DataId::kCan1: can::can1->handle_downlink(data); return true; + case data::DataId::kCan2: can::can2->handle_downlink(data); return true; + default: return false; } } - void uart_deserialized_callback( + bool uart_deserialized_callback( core::protocol::FieldId id, const data::UartDataView& data) override { if (!session_established_) - return; + return true; switch (id) { - case data::DataId::kUart1: uart::uart1->handle_downlink(data); break; - case data::DataId::kUart2: uart::uart2->handle_downlink(data); break; - default: core::utility::assert_failed_always(); + case data::DataId::kUart1: uart::uart1->handle_downlink(data); return true; + case data::DataId::kUart2: uart::uart2->handle_downlink(data); return true; + default: return false; } } - void gpio_digital_data_deserialized_callback( + bool gpio_digital_data_deserialized_callback( uint8_t channel_index, const data::GpioDigitalDataView& data) override { if (!session_established_) - return; + return true; + if (data.timestamp_quarter_us.has_value()) + return false; if (channel_index >= kGpioChannelCount) - return; + return false; const auto& gpio = spec::c_board::kGpioDescriptors[channel_index]; if (!gpio.supports(spec::GpioCapability::kDigitalWrite)) - return; + return false; gpio::gpio->handle_digital_write(channel_index, data); + return true; } - void gpio_analog_data_deserialized_callback( + bool gpio_analog_data_deserialized_callback( uint8_t channel_index, const data::GpioAnalogDataView& data) override { if (!session_established_) - return; + return true; if (channel_index >= kGpioChannelCount) - return; + return false; const auto& gpio = spec::c_board::kGpioDescriptors[channel_index]; if (!gpio.supports(spec::GpioCapability::kAnalogWrite)) - return; + return false; gpio::gpio->handle_analog_write(channel_index, data); + return true; } - void gpio_digital_read_config_deserialized_callback( + bool gpio_digital_read_config_deserialized_callback( uint8_t channel_index, const data::GpioReadConfigView& data) override { if (!session_established_) - return; + return true; if (channel_index >= kGpioChannelCount) - return; + return false; const auto& gpio = spec::c_board::kGpioDescriptors[channel_index]; if (!data.supported(gpio)) - return; + return false; gpio::gpio->handle_digital_read(channel_index, data); + return true; } - void gpio_analog_read_config_deserialized_callback( + bool gpio_analog_read_config_deserialized_callback( uint8_t channel_index, const data::GpioReadConfigView& data) override { + if (!session_established_) + return true; (void)channel_index; (void)data; + return false; } void accelerometer_deserialized_callback(const data::AccelerometerDataView& data) override { diff --git a/firmware/rmcs_board/app/src/gpio/gpio.hpp b/firmware/rmcs_board/app/src/gpio/gpio.hpp index 3750ce5..0f9af26 100644 --- a/firmware/rmcs_board/app/src/gpio/gpio.hpp +++ b/firmware/rmcs_board/app/src/gpio/gpio.hpp @@ -309,7 +309,7 @@ class Gpio : private core::utility::Immovable { auto& serializer = usb::get_serializer(); core::utility::assert_debug( - serializer.write_gpio_digital_read_result( + serializer.write_gpio_digital_value( channel_index, {.high = high, .timestamp_quarter_us = timestamp_to_publish}) != core::protocol::Serializer::SerializeResult::kInvalidArgument); } diff --git a/firmware/rmcs_board/app/src/usb/vendor.hpp b/firmware/rmcs_board/app/src/usb/vendor.hpp index 9a11d4b..23db42d 100644 --- a/firmware/rmcs_board/app/src/usb/vendor.hpp +++ b/firmware/rmcs_board/app/src/usb/vendor.hpp @@ -111,82 +111,90 @@ class Vendor session_established_ = true; } - void can_deserialized_callback( + bool can_deserialized_callback( core::protocol::FieldId id, const data::CanDataView& data) override { if (!session_established_) - return; + return true; switch (id) { - case data::DataId::kCan0: can::can_array[0]->handle_downlink(data); break; - case data::DataId::kCan1: can::can_array[1]->handle_downlink(data); break; - case data::DataId::kCan2: can::can_array[2]->handle_downlink(data); break; - case data::DataId::kCan3: can::can_array[3]->handle_downlink(data); break; - default: core::utility::assert_failed_always(); + case data::DataId::kCan0: can::can_array[0]->handle_downlink(data); return true; + case data::DataId::kCan1: can::can_array[1]->handle_downlink(data); return true; + case data::DataId::kCan2: can::can_array[2]->handle_downlink(data); return true; + case data::DataId::kCan3: can::can_array[3]->handle_downlink(data); return true; + default: return false; } } - void uart_deserialized_callback( + bool uart_deserialized_callback( core::protocol::FieldId id, const data::UartDataView& data) override { if (!session_established_) - return; + return true; switch (id) { - case data::DataId::kUart0: uart::uart_array[0]->handle_downlink(data); break; - case data::DataId::kUart1: uart::uart_array[1]->handle_downlink(data); break; + case data::DataId::kUart0: uart::uart_array[0]->handle_downlink(data); return true; + case data::DataId::kUart1: uart::uart_array[1]->handle_downlink(data); return true; #ifdef BOARD_UART2 - case data::DataId::kUart2: uart::uart_array[2]->handle_downlink(data); break; + case data::DataId::kUart2: uart::uart_array[2]->handle_downlink(data); return true; #endif #ifdef BOARD_UART3 - case data::DataId::kUart3: uart::uart_array[3]->handle_downlink(data); break; + case data::DataId::kUart3: uart::uart_array[3]->handle_downlink(data); return true; #endif - default: core::utility::assert_failed_always(); + default: return false; } } - void gpio_digital_data_deserialized_callback( + bool gpio_digital_data_deserialized_callback( uint8_t channel_index, const data::GpioDigitalDataView& data) override { if (!session_established_) - return; + return true; + if (data.timestamp_quarter_us.has_value()) + return false; if (channel_index >= board::spec::kGpioDescriptors.size()) - return; + return false; const auto& gpio_descriptor = board::spec::kGpioDescriptors[channel_index]; if (!gpio_descriptor.supports(spec::GpioCapability::kDigitalWrite)) - return; + return false; gpio::gpio->handle_digital_write(channel_index, data); + return true; } - void gpio_analog_data_deserialized_callback( + bool gpio_analog_data_deserialized_callback( uint8_t channel_index, const data::GpioAnalogDataView& data) override { if (!session_established_) - return; + return true; if (channel_index >= board::spec::kGpioDescriptors.size()) - return; + return false; const auto& gpio_descriptor = board::spec::kGpioDescriptors[channel_index]; if (!gpio_descriptor.supports(spec::GpioCapability::kAnalogWrite)) - return; + return false; gpio::gpio->handle_analog_write(channel_index, data); + return true; } - void gpio_digital_read_config_deserialized_callback( + bool gpio_digital_read_config_deserialized_callback( uint8_t channel_index, const data::GpioReadConfigView& data) override { if (!session_established_) - return; + return true; if (channel_index >= board::spec::kGpioDescriptors.size()) - return; + return false; const auto& gpio_descriptor = board::spec::kGpioDescriptors[channel_index]; if (!data.supported(gpio_descriptor)) - return; + return false; gpio::gpio->handle_digital_read(channel_index, data); + return true; } - void gpio_analog_read_config_deserialized_callback( + bool gpio_analog_read_config_deserialized_callback( uint8_t channel_index, const data::GpioReadConfigView& data) override { + if (!session_established_) + return true; (void)channel_index; (void)data; + return false; } void accelerometer_deserialized_callback(const data::AccelerometerDataView& data) override { diff --git a/host/src/protocol/handler.cpp b/host/src/protocol/handler.cpp index 123f8a4..1ccf116 100644 --- a/host/src/protocol/handler.cpp +++ b/host/src/protocol/handler.cpp @@ -61,52 +61,70 @@ class Handler::Impl : public core::protocol::DeserializeCallback { PacketBuilder start_transmit() { return PacketBuilder{transport_.get()}; } - void can_deserialized_callback( + bool can_deserialized_callback( core::protocol::FieldId id, const data::CanDataView& data) override { if (!session_established()) - return; - if (!callback_.can_receive_callback(id, data)) + return true; + if (!callback_.can_receive_callback(id, data)) { logging::get_logger().error("Unexpected can field id: ", static_cast(id)); + return false; + } + return true; } - void uart_deserialized_callback( + bool uart_deserialized_callback( core::protocol::FieldId id, const data::UartDataView& data) override { if (!session_established()) - return; - if (!callback_.uart_receive_callback(id, data)) + return true; + if (!callback_.uart_receive_callback(id, data)) { logging::get_logger().error("Unexpected uart field id: ", static_cast(id)); + return false; + } + return true; } - void gpio_digital_data_deserialized_callback( + bool gpio_digital_data_deserialized_callback( uint8_t channel_index, const data::GpioDigitalDataView& data) override { if (!session_established()) - return; - if (!callback_.gpio_digital_read_result_callback(channel_index, data)) + return true; + if (!callback_.gpio_digital_read_result_callback(channel_index, data)) { logging::get_logger().error( "Unexpected gpio channel index: ", static_cast(channel_index)); + return false; + } + return true; } - void gpio_analog_data_deserialized_callback( + bool gpio_analog_data_deserialized_callback( uint8_t channel_index, const data::GpioAnalogDataView& data) override { if (!session_established()) - return; - if (!callback_.gpio_analog_read_result_callback(channel_index, data)) + return true; + if (!callback_.gpio_analog_read_result_callback(channel_index, data)) { logging::get_logger().error( "Unexpected gpio channel index: ", static_cast(channel_index)); + return false; + } + return true; } - void gpio_digital_read_config_deserialized_callback( + bool gpio_digital_read_config_deserialized_callback( uint8_t channel_index, const data::GpioReadConfigView& data) override { + if (!session_established()) + return true; (void)channel_index; (void)data; logging::get_logger().error("Unexpected gpio digital read config field in uplink"); + return false; } - void gpio_analog_read_config_deserialized_callback( + bool gpio_analog_read_config_deserialized_callback( uint8_t channel_index, const data::GpioReadConfigView& data) override { + if (!session_established()) + return true; (void)channel_index; (void)data; logging::get_logger().error("Unexpected gpio analog read config field in uplink"); + return false; } void accelerometer_deserialized_callback(const data::AccelerometerDataView& data) override { @@ -295,7 +313,9 @@ struct PacketBuilderImpl { [[nodiscard]] bool write_gpio_digital_data( uint8_t channel_index, const data::GpioDigitalDataView& view) noexcept { - return process_result(serializer_.write_gpio_digital_data(channel_index, view)); + if (view.timestamp_quarter_us.has_value()) [[unlikely]] + return false; + return process_result(serializer_.write_gpio_digital_value(channel_index, view)); } [[nodiscard]] bool write_gpio_digital_read_config( @@ -305,7 +325,7 @@ struct PacketBuilderImpl { [[nodiscard]] bool write_gpio_analog_data( uint8_t channel_index, const data::GpioAnalogDataView& view) noexcept { - return process_result(serializer_.write_gpio_analog_data(channel_index, view)); + return process_result(serializer_.write_gpio_analog_value(channel_index, view)); } [[nodiscard]] bool write_imu_accelerometer(const data::AccelerometerDataView& view) noexcept {