Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 26 additions & 50 deletions core/src/protocol/deserializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,7 @@ coroutine::LifoTask<bool> Deserializer::process_can_field(FieldId field_id) {
data_view.can_data = std::span<const std::byte>{};
}

callback_.can_deserialized_callback(field_id, data_view);

co_return true;
co_return callback_.can_deserialized_callback(field_id, data_view);
}

coroutine::LifoTask<bool> Deserializer::process_uart_field(FieldId field_id) {
Expand Down Expand Up @@ -147,9 +145,7 @@ coroutine::LifoTask<bool> Deserializer::process_uart_field(FieldId field_id) {
data_view.uart_data = std::span<const std::byte>{};
}

callback_.uart_deserialized_callback(field_id, data_view);

co_return true;
co_return callback_.uart_deserialized_callback(field_id, data_view);
}

coroutine::LifoTask<bool> Deserializer::process_gpio_field(FieldId) {
Expand All @@ -169,16 +165,25 @@ coroutine::LifoTask<bool> 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<GpioDigitalReadTimestampPayload::TimestampQuarterUs>();
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));
Expand All @@ -190,11 +195,12 @@ coroutine::LifoTask<bool> Deserializer::process_gpio_field(FieldId) {
data_view.value = payload.get<GpioAnalogPayload::Value>();
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;
Expand All @@ -213,45 +219,15 @@ coroutine::LifoTask<bool> 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<GpioDigitalReadTimestampPayload::TimestampQuarterUs>();
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<GpioAnalogPayload::Value>();
consume_peeked();

callback_.gpio_analog_data_deserialized_callback(channel_index, data_view);
break;
}
default: co_return false;
Expand Down
14 changes: 8 additions & 6 deletions core/src/protocol/deserializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
13 changes: 5 additions & 8 deletions core/src/protocol/protocol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>;
Expand Down
110 changes: 25 additions & 85 deletions core/src/protocol/serializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -141,7 +140,14 @@ class Serializer {
cursor += sizeof(GpioHeader);
header.set<GpioHeader::PayloadType>(payload_type);
header.set<GpioHeader::ChannelIndex>(channel_index);
header.set<GpioHeader::Timestamped>(false);
header.set<GpioHeader::Timestamped>(view.timestamp_quarter_us.has_value());

if (view.timestamp_quarter_us) {
auto payload = GpioDigitalReadTimestampPayload::Ref(cursor);
cursor += sizeof(GpioDigitalReadTimestampPayload);
payload.set<GpioDigitalReadTimestampPayload::TimestampQuarterUs>(
*view.timestamp_quarter_us);
}

utility::assert_debug(cursor == dst.data() + dst.size());
return SerializeResult::kSuccess;
Expand All @@ -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);
Expand All @@ -163,7 +169,7 @@ class Serializer {

auto header = GpioHeader::Ref(cursor);
cursor += sizeof(GpioHeader);
header.set<GpioHeader::PayloadType>(GpioHeader::PayloadEnum::kDigitalRead);
header.set<GpioHeader::PayloadType>(GpioHeader::PayloadEnum::kDigitalReadConfig);
header.set<GpioHeader::ChannelIndex>(channel_index);
header.set<GpioHeader::Timestamped>(view.capture_timestamp);

Expand All @@ -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);
Expand All @@ -195,7 +201,7 @@ class Serializer {

auto header = GpioHeader::Ref(cursor);
cursor += sizeof(GpioHeader);
header.set<GpioHeader::PayloadType>(GpioHeader::PayloadEnum::kAnalogWrite);
header.set<GpioHeader::PayloadType>(GpioHeader::PayloadEnum::kAnalog);
header.set<GpioHeader::ChannelIndex>(channel_index);
header.set<GpioHeader::Timestamped>(false);

Expand All @@ -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);
Expand All @@ -227,7 +233,7 @@ class Serializer {

auto header = GpioHeader::Ref(cursor);
cursor += sizeof(GpioHeader);
header.set<GpioHeader::PayloadType>(GpioHeader::PayloadEnum::kAnalogRead);
header.set<GpioHeader::PayloadType>(GpioHeader::PayloadEnum::kAnalogReadConfig);
header.set<GpioHeader::ChannelIndex>(channel_index);
header.set<GpioHeader::Timestamped>(false);

Expand All @@ -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<GpioHeader::PayloadType>(payload_type);
header.set<GpioHeader::ChannelIndex>(channel_index);
header.set<GpioHeader::Timestamped>(view.timestamp_quarter_us.has_value());

if (view.timestamp_quarter_us) {
auto payload = GpioDigitalReadTimestampPayload::Ref(cursor);
cursor += sizeof(GpioDigitalReadTimestampPayload);
payload.set<GpioDigitalReadTimestampPayload::TimestampQuarterUs>(
*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::PayloadType>(GpioHeader::PayloadEnum::kAnalogReadResult);
header.set<GpioHeader::ChannelIndex>(channel_index);
header.set<GpioHeader::Timestamped>(false);

auto payload = GpioAnalogPayload::Ref(cursor);
cursor += sizeof(GpioAnalogPayload);
payload.set<GpioAnalogPayload::Value>(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);
Expand Down Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion firmware/c_board/app/src/gpio/gpio.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
Loading
Loading