Skip to content

Commit aae15b6

Browse files
committed
protocol task now uses sansio
1 parent b8ca76c commit aae15b6

File tree

5 files changed

+95
-120
lines changed

5 files changed

+95
-120
lines changed

firmware/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ fn main() -> ! {
6060

6161
static EXECUTOR: StaticCell<Executor> = StaticCell::new();
6262
EXECUTOR.init(Executor::new()).run(move |s| {
63-
s.spawn(crate::networking::protocol::control_task(packets, quat))
63+
s.spawn(crate::networking::protocol::protocol_task(packets, quat))
6464
.unwrap();
6565
s.spawn(crate::networking::network_task(packets)).unwrap();
6666
s.spawn(crate::imu::imu_task(quat, p.i2c, p.delay)).unwrap();

firmware/src/networking/protocol/mod.rs

Lines changed: 36 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -7,88 +7,59 @@ use defmt::debug;
77
use embassy_executor::task;
88
use embassy_futures::select::select;
99
use firmware_protocol::{
10-
BoardType, CbPacket, ImuType, McuType, SbPacket, SensorDataType, SensorStatus,
10+
sansio::{self, SbBuf},
11+
CbPacket, SlimeQuaternion,
1112
};
1213

1314
use crate::imu::Quat;
14-
use crate::utils::Unreliable;
15-
16-
#[allow(dead_code)]
17-
mod v2;
15+
use crate::utils::{Reliable, Unreliable};
1816

1917
#[task]
20-
pub async fn control_task(
18+
pub async fn protocol_task(
2119
packets: &'static Packets,
2220
quat: &'static Unreliable<Quat>,
2321
) -> ! {
2422
debug!("Control task!");
2523
async {
24+
let mut proto_state = sansio::State::new();
25+
let mut sb_buf = SbBuf::new();
2626
loop {
27-
do_work(packets, quat).await;
27+
proto_state = match proto_state {
28+
sansio::State::Disconnected(s) => {
29+
while_disconnected(s, &mut sb_buf, &packets.clientbound).await
30+
}
31+
sansio::State::Connected(s) => {
32+
while_connected(s, &mut sb_buf, &packets.clientbound, quat).await
33+
}
34+
};
35+
while !sb_buf.is_empty() {
36+
let sb = sb_buf.pop().unwrap();
37+
packets.serverbound.send(sb).await;
38+
}
2839
}
2940
}
3041
.await
3142
}
3243

33-
async fn do_work(packets: &Packets, quat: &Unreliable<Quat>) {
34-
let event = select(packets.clientbound.recv(), quat.wait()).await;
44+
async fn while_disconnected(
45+
state: sansio::Disconnected,
46+
sb_buf: &mut SbBuf,
47+
cb: &Reliable<CbPacket>,
48+
) -> sansio::State {
49+
let cb_msg = cb.recv().await;
50+
state.received_msg(cb_msg, sb_buf)
51+
}
52+
53+
async fn while_connected(
54+
state: sansio::Connected,
55+
sb_buf: &mut SbBuf,
56+
cb: &Reliable<CbPacket>,
57+
quat: &Unreliable<Quat>,
58+
) -> sansio::State {
59+
let event = select(cb.recv(), quat.wait()).await;
3560
use embassy_futures::select::Either;
3661
match event {
37-
Either::First(cb_packet) => todo!(),
38-
Either::Second(quat) => todo!(),
39-
}
40-
41-
match packets.clientbound.recv().await {
42-
// Identify ourself when discovery packet is received
43-
CbPacket::Discovery => {
44-
packets
45-
.serverbound
46-
.send(SbPacket::Handshake {
47-
// TODO: Compile time constants for board and MCU
48-
board: BoardType::Custom,
49-
// Should this IMU type be whatever the first IMU of the system is?
50-
imu: ImuType::Unknown(0xFF),
51-
mcu: McuType::Esp32,
52-
imu_info: (0, 0, 0), // These appear to be inert
53-
// Needs to be >=9 to use newer protocol, this is hard-coded in
54-
// the java server :(
55-
build: 10,
56-
firmware: "SlimeVR-Rust".into(),
57-
mac_address: [0; 6],
58-
})
59-
.await;
60-
debug!("Handshake");
61-
62-
// After handshake, we are supposed to send `SensorInfo` only once.
63-
packets
64-
.serverbound
65-
.send(SbPacket::SensorInfo {
66-
sensor_id: 0, // First sensor (of two)
67-
sensor_status: SensorStatus::Ok,
68-
sensor_type: ImuType::Unknown(0xFF),
69-
})
70-
.await;
71-
debug!("SensorInfo");
72-
}
73-
// When heartbeat is received, we should reply with heartbeat 0 aka Discovery
74-
// The protocol is asymmetric so its a bit unintuitive.
75-
CbPacket::Heartbeat => {
76-
packets.serverbound.send(SbPacket::Heartbeat).await;
77-
}
78-
// Pings are basically like heartbeats, just echo data back
79-
CbPacket::Ping { challenge } => {
80-
packets.serverbound.send(SbPacket::Ping { challenge }).await;
81-
}
82-
_ => (),
62+
Either::First(cb_msg) => state.received_msg(cb_msg, sb_buf),
63+
Either::Second(quat) => state.send_imu(0, SlimeQuaternion::from(quat), sb_buf),
8364
}
84-
85-
packets
86-
.serverbound
87-
.send(SbPacket::RotationData {
88-
sensor_id: 0, // First sensor
89-
data_type: SensorDataType::Normal, // Rotation data without magnetometer correction.
90-
quat: quat.wait().await.into_inner().into(),
91-
calibration_info: 0,
92-
})
93-
.await;
9465
}

networking/firmware_protocol/src/lib.rs

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ extern crate alloc;
44

55
mod clientbound;
66
pub mod sansio;
7+
mod serialization;
78
mod serverbound;
89

910
pub use clientbound::*;
@@ -27,47 +28,50 @@ pub struct SlimeQuaternion {
2728
pub w: f32,
2829
}
2930

30-
#[cfg(any(test, feature = "nalgebra031"))]
31-
mod nalgebra031_impls {
32-
use super::*;
33-
use nalgebra031::Quaternion;
31+
macro_rules! impl_from {
32+
($nalg_mod:path) => {
33+
use $nalg_mod::{Quaternion, UnitQuaternion};
3434

35-
impl From<Quaternion<f32>> for SlimeQuaternion {
36-
fn from(q: Quaternion<f32>) -> Self {
37-
Self {
38-
i: q.i as _,
39-
j: q.j as _,
40-
k: q.k as _,
41-
w: q.w as _,
35+
impl From<Quaternion<f32>> for SlimeQuaternion {
36+
fn from(q: Quaternion<f32>) -> Self {
37+
Self {
38+
x: q.i,
39+
y: q.j,
40+
z: q.k,
41+
w: q.w,
42+
}
4243
}
4344
}
44-
}
45-
impl From<SlimeQuaternion> for Quaternion<f32> {
46-
fn from(q: SlimeQuaternion) -> Self {
47-
Self::new(q.w as _, q.i as _, q.j as _, q.k as _)
45+
impl From<SlimeQuaternion> for Quaternion<f32> {
46+
fn from(q: SlimeQuaternion) -> Self {
47+
Self::new(q.w as _, q.x as _, q.y as _, q.z as _)
48+
}
4849
}
49-
}
50+
51+
impl From<UnitQuaternion<f32>> for SlimeQuaternion {
52+
fn from(q: UnitQuaternion<f32>) -> Self {
53+
Self {
54+
x: q.i,
55+
y: q.j,
56+
z: q.k,
57+
w: q.w,
58+
}
59+
}
60+
}
61+
};
62+
}
63+
64+
#[cfg(any(test, feature = "nalgebra031"))]
65+
mod nalgebra031_impls {
66+
use super::*;
67+
68+
impl_from!(::nalgebra031);
5069
}
5170
#[cfg(any(test, feature = "nalgebra030"))]
5271
mod nalgebra030_impls {
5372
use super::*;
54-
use nalgebra030::Quaternion;
5573

56-
impl From<Quaternion<f32>> for SlimeQuaternion {
57-
fn from(q: Quaternion<f32>) -> Self {
58-
Self {
59-
i: q.i as _,
60-
j: q.j as _,
61-
k: q.k as _,
62-
w: q.w as _,
63-
}
64-
}
65-
}
66-
impl From<SlimeQuaternion> for Quaternion<f32> {
67-
fn from(q: SlimeQuaternion) -> Self {
68-
Self::new(q.w as _, q.i as _, q.j as _, q.k as _)
69-
}
70-
}
74+
impl_from!(::nalgebra030);
7175
}
7276

7377
#[derive(PartialEq, Eq, Debug, DekuRead, DekuWrite)]

networking/firmware_protocol/src/sansio/mod.rs

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@ use crate::{
1111

1212
use replace_with::replace_with;
1313

14-
mod serialization;
15-
1614
/// A buffer of `SbPacket` that *must all be sent* before other functions on the
1715
/// protocol are invoked.
1816
#[derive(Debug)]
@@ -53,17 +51,16 @@ macro_rules! assert_empty {
5351
}
5452

5553
#[derive(Debug, derive_more::From)]
56-
pub enum ProtocolState {
54+
pub enum State {
5755
Disconnected(Disconnected),
5856
Connected(Connected),
5957
}
60-
impl ProtocolState {
58+
impl State {
6159
pub const fn new() -> Self {
6260
Self::Disconnected(Disconnected)
6361
}
6462

65-
/// Process a newly received message. This will update (and possibly transition) to
66-
/// a new state, while enqueueing any serverbound packets that should be sent into
63+
/// Process a newly received message, enqueueing any serverbound messages in
6764
/// `sb_buf`.
6865
///
6966
/// # Panics
@@ -81,8 +78,8 @@ impl ProtocolState {
8178
|taken| {
8279
// Now we can use the owned value in functions that expect an owned type.
8380
match taken {
84-
ProtocolState::Disconnected(s) => s.received_msg(cb, sb_buf),
85-
ProtocolState::Connected(s) => s.received_msg(cb, sb_buf),
81+
State::Disconnected(s) => s.received_msg(cb, sb_buf),
82+
State::Connected(s) => s.received_msg(cb, sb_buf),
8683
}
8784
},
8885
);
@@ -92,18 +89,13 @@ impl ProtocolState {
9289
#[derive(Debug)]
9390
pub struct Disconnected;
9491
impl Disconnected {
95-
/// Process a newly received message. This will update (and possibly transition) to
96-
/// a new state, while pushing any serverbound packets that should be sent to
92+
/// Process a newly received message, enqueueing any serverbound messages in
9793
/// `sb_buf`.
9894
///
9995
/// # Panics
10096
/// Panics if `!sb_buf.is_empty()`. You are only supposed to call this function when
10197
/// all serverbound packets have already been sent.
102-
pub fn received_msg<'b>(
103-
self,
104-
cb: CbPacket,
105-
sb_buf: &'b mut SbBuf,
106-
) -> ProtocolState {
98+
pub fn received_msg<'b>(self, cb: CbPacket, sb_buf: &'b mut SbBuf) -> State {
10799
assert_empty!(sb_buf);
108100
match cb {
109101
CbPacket::Discovery => {
@@ -137,11 +129,13 @@ impl Disconnected {
137129
#[derive(Debug)]
138130
pub struct Connected {}
139131
impl Connected {
140-
pub fn received_msg<'b>(
141-
self,
142-
cb: CbPacket,
143-
sb_buf: &'b mut SbBuf,
144-
) -> ProtocolState {
132+
/// Process a newly received message, enqueueing any serverbound messages in
133+
/// `sb_buf`.
134+
///
135+
/// # Panics
136+
/// Panics if `!sb_buf.is_empty()`. You are only supposed to call this function when
137+
/// all serverbound packets have already been sent.
138+
pub fn received_msg<'b>(self, cb: CbPacket, sb_buf: &'b mut SbBuf) -> State {
145139
assert_empty!(sb_buf);
146140
match cb {
147141
// When heartbeat is received, we should reply with another heartbeat.
@@ -158,18 +152,24 @@ impl Connected {
158152
}
159153
}
160154

155+
/// Enqueues an imu update in `SbBuf`.
156+
///
157+
/// # Panics
158+
/// Panics if `!sb_buf.is_empty()`. You are only supposed to call this function when
159+
/// all serverbound packets have already been sent.
161160
pub fn send_imu(
162-
&mut self,
161+
self,
163162
sensor_id: u8,
164163
quat: SlimeQuaternion,
165164
sb_buf: &mut SbBuf,
166-
) {
165+
) -> State {
167166
assert_empty!(sb_buf);
168167
sb_buf.push(SbPacket::RotationData {
169168
sensor_id,
170169
data_type: SensorDataType::Normal,
171170
quat,
172171
calibration_info: 0,
173172
});
173+
self.into()
174174
}
175175
}

0 commit comments

Comments
 (0)