Skip to content
Open
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
15 changes: 14 additions & 1 deletion core/include/librmcs/data/datas.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <cstddef>
#include <cstdint>
#include <optional>
#include <span>

#include <librmcs/spec/gpio.hpp>
Expand Down Expand Up @@ -46,6 +47,7 @@ struct UartDataView {

struct GpioDigitalDataView {
bool high;
std::optional<uint32_t> timestamp_quarter_us = std::nullopt;
};

struct GpioAnalogDataView {
Expand All @@ -63,6 +65,7 @@ struct GpioReadConfigView {
bool asap = false;
bool rising_edge = false;
bool falling_edge = false;
bool capture_timestamp = false;
GpioPull pull = GpioPull::kNone;

[[nodiscard]] constexpr bool supported(const spec::GpioDescriptor& gpio) const noexcept {
Expand All @@ -71,20 +74,28 @@ struct GpioReadConfigView {
&& ((!rising_edge && !falling_edge)
|| gpio.supports(spec::GpioCapability::kDigitalReadInterrupt))
&& (pull != GpioPull::kUp || gpio.supports(spec::GpioCapability::kPullUp))
&& (pull != GpioPull::kDown || gpio.supports(spec::GpioCapability::kPullDown));
&& (pull != GpioPull::kDown || gpio.supports(spec::GpioCapability::kPullDown))
&& (!capture_timestamp || gpio.supports(spec::GpioCapability::kTimestampedDigitalRead));
}
};

struct AccelerometerDataView {
int16_t x;
int16_t y;
int16_t z;
uint32_t timestamp_quarter_us;
};

struct GyroscopeDataView {
int16_t x;
int16_t y;
int16_t z;
uint32_t timestamp_quarter_us;
};

struct TemperatureDataView {
uint16_t temperature;
uint32_t timestamp_quarter_us;
};

class DataCallback {
Expand All @@ -110,6 +121,8 @@ class DataCallback {
virtual void accelerometer_receive_callback(const AccelerometerDataView& data) = 0;

virtual void gyroscope_receive_callback(const GyroscopeDataView& data) = 0;

virtual void temperature_receive_callback(const TemperatureDataView& data) = 0;
};

} // namespace librmcs::data
3 changes: 2 additions & 1 deletion core/include/librmcs/spec/gpio.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ enum class GpioCapability : std::uint8_t {
kDigitalReadInterrupt = 1U << 4,
kPullUp = 1U << 5,
kPullDown = 1U << 6,
kTimestampedDigitalRead = 1U << 7,
};

constexpr GpioCapability operator|(GpioCapability a, GpioCapability b) noexcept {
Expand All @@ -31,7 +32,7 @@ constexpr GpioCapability operator~(GpioCapability a) noexcept {
inline constexpr GpioCapability kDigitalCapabilities =
GpioCapability::kDigitalWrite | GpioCapability::kDigitalReadOnce
| GpioCapability::kDigitalReadPeriodic | GpioCapability::kDigitalReadInterrupt
| GpioCapability::kPullUp | GpioCapability::kPullDown;
| GpioCapability::kPullUp | GpioCapability::kPullDown | GpioCapability::kTimestampedDigitalRead;

inline constexpr GpioCapability kPwmCapabilities =
kDigitalCapabilities | GpioCapability::kAnalogWrite;
Expand Down
37 changes: 34 additions & 3 deletions core/src/protocol/deserializer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ coroutine::LifoTask<bool> Deserializer::process_uart_field(FieldId field_id) {
coroutine::LifoTask<bool> Deserializer::process_gpio_field(FieldId) {
GpioHeader::PayloadEnum payload_type;
std::uint8_t channel_index = 0;
data::GpioPull pull = data::GpioPull::kNone;
bool timestamped = false;
{
const auto* header_bytes = co_await peek_bytes(sizeof(GpioHeader));
if (!header_bytes) [[unlikely]]
Expand All @@ -163,7 +163,7 @@ coroutine::LifoTask<bool> Deserializer::process_gpio_field(FieldId) {
auto header = GpioHeader::CRef{header_bytes};
payload_type = header.get<GpioHeader::PayloadType>();
channel_index = header.get<GpioHeader::ChannelIndex>();
pull = header.get<GpioHeader::Pull>();
timestamped = header.get<GpioHeader::Timestamped>();
consume_peeked();
}

Expand All @@ -176,6 +176,8 @@ coroutine::LifoTask<bool> Deserializer::process_gpio_field(FieldId) {
break;
}
case GpioHeader::PayloadEnum::kAnalogWrite: {
if (timestamped) [[unlikely]]
co_return false;
const auto* payload_bytes = co_await peek_bytes(sizeof(GpioAnalogPayload));
if (!payload_bytes) [[unlikely]]
co_return false;
Expand All @@ -199,8 +201,9 @@ coroutine::LifoTask<bool> Deserializer::process_gpio_field(FieldId) {
data_view.asap = payload.get<GpioReadConfigPayload::Asap>();
data_view.rising_edge = payload.get<GpioReadConfigPayload::RisingEdge>();
data_view.falling_edge = payload.get<GpioReadConfigPayload::FallingEdge>();
data_view.capture_timestamp = timestamped;
data_view.pull = payload.get<GpioReadConfigPayload::Pull>();
data_view.period_ms = payload.get<GpioReadConfigPayload::PeriodMs>();
data_view.pull = pull;
consume_peeked();

if (data_view.pull != data::GpioPull::kNone && data_view.pull != data::GpioPull::kUp
Expand All @@ -210,6 +213,8 @@ coroutine::LifoTask<bool> Deserializer::process_gpio_field(FieldId) {
if (payload_type == GpioHeader::PayloadEnum::kDigitalRead) {
callback_.gpio_digital_read_config_deserialized_callback(channel_index, data_view);
} 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;
Expand All @@ -218,10 +223,22 @@ coroutine::LifoTask<bool> Deserializer::process_gpio_field(FieldId) {
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]]
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;
Expand Down Expand Up @@ -262,6 +279,7 @@ coroutine::LifoTask<bool> Deserializer::process_imu_field(FieldId) {
data_view.x = payload.get<ImuAccelerometerPayload::X>();
data_view.y = payload.get<ImuAccelerometerPayload::Y>();
data_view.z = payload.get<ImuAccelerometerPayload::Z>();
data_view.timestamp_quarter_us = payload.get<ImuAccelerometerPayload::TimestampQuarterUs>();
consume_peeked();
callback_.accelerometer_deserialized_callback(data_view);
break;
Expand All @@ -275,10 +293,23 @@ coroutine::LifoTask<bool> Deserializer::process_imu_field(FieldId) {
data_view.x = payload.get<ImuGyroscopePayload::X>();
data_view.y = payload.get<ImuGyroscopePayload::Y>();
data_view.z = payload.get<ImuGyroscopePayload::Z>();
data_view.timestamp_quarter_us = payload.get<ImuGyroscopePayload::TimestampQuarterUs>();
consume_peeked();
callback_.gyroscope_deserialized_callback(data_view);
break;
}
case ImuHeader::PayloadEnum::kTemperature: {
data::TemperatureDataView data_view{};
const auto* payload_bytes = co_await peek_bytes(sizeof(ImuTemperaturePayload));
if (!payload_bytes) [[unlikely]]
co_return false;
auto payload = ImuTemperaturePayload::CRef{payload_bytes};
data_view.temperature = payload.get<ImuTemperaturePayload::Temperature>();
data_view.timestamp_quarter_us = payload.get<ImuTemperaturePayload::TimestampQuarterUs>();
consume_peeked();
callback_.temperature_deserialized_callback(data_view);
break;
}
default: co_return false;
}
co_return true;
Expand Down
2 changes: 2 additions & 0 deletions core/src/protocol/deserializer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ class DeserializeCallback {

virtual void gyroscope_deserialized_callback(const data::GyroscopeDataView& data) = 0;

virtual void temperature_deserialized_callback(const data::TemperatureDataView& data) = 0;

virtual void error_callback() = 0;
};

Expand Down
23 changes: 18 additions & 5 deletions core/src/protocol/protocol.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,19 @@ struct GpioHeader : utility::Bitfield<2> {

using PayloadType = utility::BitfieldMember<4, 4, PayloadEnum>;
using ChannelIndex = utility::BitfieldMember<8, 6>;
using Pull = utility::BitfieldMember<14, 2, data::GpioPull>;
using Timestamped = utility::BitfieldMember<15, 1>;
};

struct GpioReadConfigPayload : utility::Bitfield<2> {
struct GpioReadConfigPayload : utility::Bitfield<3> {
using Asap = utility::BitfieldMember<0, 1>;
using RisingEdge = utility::BitfieldMember<1, 1>;
using FallingEdge = utility::BitfieldMember<2, 1>;
using PeriodMs = utility::BitfieldMember<3, 13, uint16_t>;
using Pull = utility::BitfieldMember<4, 2, data::GpioPull>;
using PeriodMs = utility::BitfieldMember<8, 16, uint16_t>;
};

struct GpioDigitalReadTimestampPayload : utility::Bitfield<4> {
using TimestampQuarterUs = utility::BitfieldMember<0, 32, uint32_t>;
};

struct GpioAnalogPayload : utility::Bitfield<2> {
Expand All @@ -114,20 +119,28 @@ struct ImuHeader : utility::Bitfield<1> {
enum class PayloadEnum : uint8_t {
kAccelerometer = 0,
kGyroscope = 1,
kTemperature = 2,
};
using PayloadType = utility::BitfieldMember<4, 4, PayloadEnum>;
};

struct ImuAccelerometerPayload : utility::Bitfield<6> {
struct ImuAccelerometerPayload : utility::Bitfield<10> {
using X = utility::BitfieldMember<0, 16, int16_t>;
using Y = utility::BitfieldMember<16, 16, int16_t>;
using Z = utility::BitfieldMember<32, 16, int16_t>;
using TimestampQuarterUs = utility::BitfieldMember<48, 32, uint32_t>;
};

struct ImuGyroscopePayload : utility::Bitfield<6> {
struct ImuGyroscopePayload : utility::Bitfield<10> {
using X = utility::BitfieldMember<0, 16, int16_t>;
using Y = utility::BitfieldMember<16, 16, int16_t>;
using Z = utility::BitfieldMember<32, 16, int16_t>;
using TimestampQuarterUs = utility::BitfieldMember<48, 32, uint32_t>;
};

struct ImuTemperaturePayload : utility::Bitfield<6> {
using Temperature = utility::BitfieldMember<0, 16, uint16_t>;
using TimestampQuarterUs = utility::BitfieldMember<16, 32, uint32_t>;
};

} // namespace librmcs::core::protocol
Loading
Loading