A start
This commit is contained in:
parent
d116ed9e26
commit
eb5befa55c
12
Cargo.toml
12
Cargo.toml
@ -1,10 +1,13 @@
|
||||
[package]
|
||||
name = "lib-rs"
|
||||
name = "crsf-rs"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
description = "library template"
|
||||
license_file = "MIT OR Apache-2.0"
|
||||
description = "This crate provides a #[no_std] parser for the crossfire protocol"
|
||||
license = "MIT OR Apache-2.0"
|
||||
repository = "https://git.mkaenner.de/max/lib-rs"
|
||||
keywords = ["crsf", "crossfire"]
|
||||
categories = ["embedded"]
|
||||
authors = ["Max Känner <max.kaenner@gmail.com>"]
|
||||
|
||||
[lints.rust]
|
||||
unsafe_code = "forbid"
|
||||
@ -19,3 +22,6 @@ cargo = "warn"
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
num_enum = { version = "=0.5", default-features = false }
|
||||
bitfield = { version = "=0.13" }
|
||||
heapless = { version = "=0.7" }
|
||||
|
@ -1,3 +1,3 @@
|
||||
# lib-rs
|
||||
# crsf-rs
|
||||
|
||||
Template for rust libraries
|
||||
A library for decoding crossfire packages. This library is fully #[no_std] compatible
|
||||
|
129
src/lib.rs
129
src/lib.rs
@ -1,2 +1,131 @@
|
||||
#![cfg_attr(not(test), no_std)]
|
||||
|
||||
use bitfield::bitfield;
|
||||
use heapless::HistoryBuffer;
|
||||
use num_enum::{IntoPrimitive, TryFromPrimitive, TryFromPrimitiveError};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
||||
#[repr(u8)]
|
||||
pub enum FrameType {
|
||||
Gps = 0x02,
|
||||
Vario = 0x07,
|
||||
BatterySensor = 0x08,
|
||||
BaroAltitude = 0x09,
|
||||
LinkStatistics = 0x14,
|
||||
OpenTxSync = 0x10,
|
||||
RadioId = 0x3A,
|
||||
RcChannelsPacked = 0x16,
|
||||
Attitude = 0x1E,
|
||||
FlightMode = 0x21,
|
||||
// Extended Header Frames
|
||||
DevicePing = 0x28,
|
||||
DeviceInfo = 0x29,
|
||||
ParameterSettingsEntry = 0x2B,
|
||||
ParameterRead = 0x2C,
|
||||
ParameterWrite = 0x2D,
|
||||
ELRSStatus = 0x2E,
|
||||
Command = 0x32,
|
||||
// KISS frames
|
||||
KissReq = 0x78,
|
||||
KissResp = 0x79,
|
||||
// MSP commands
|
||||
MspReq = 0x7A,
|
||||
MspResp = 0x7B,
|
||||
MspWrite = 0x7C,
|
||||
// Ardupilot frames
|
||||
ArdupilotResp = 0x80,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy, IntoPrimitive, TryFromPrimitive)]
|
||||
#[repr(u8)]
|
||||
pub enum Address {
|
||||
Broadcast = 0x00,
|
||||
Usb = 0x10,
|
||||
TbsCorePnpPro = 0x80,
|
||||
Reserved1 = 0x8A,
|
||||
CurrentSensor = 0xC0,
|
||||
Gps = 0xC2,
|
||||
TbsBlackbox = 0xC4,
|
||||
FlightController = 0xC8,
|
||||
Reserved2 = 0xCA,
|
||||
RaceTag = 0xCC,
|
||||
RadioTransmitter = 0xEA,
|
||||
CrsfReceiver = 0xEC,
|
||||
CrsfTrasmitter = 0xEE,
|
||||
ElrsLua = 0xEF,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
|
||||
struct Header {
|
||||
address: Address,
|
||||
size: u8,
|
||||
frame_type: FrameType,
|
||||
}
|
||||
|
||||
impl Header {
|
||||
fn try_from_bytes(bytes: [u8; 3]) -> Result<Self, u8> {
|
||||
Ok(Self {
|
||||
address: bytes[0]
|
||||
.try_into()
|
||||
.map_err(|TryFromPrimitiveError { number }| number)?,
|
||||
size: bytes[1],
|
||||
frame_type: bytes[2]
|
||||
.try_into()
|
||||
.map_err(|TryFromPrimitiveError { number }| number)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
bitfield! {
|
||||
struct RcChannels([u8]);
|
||||
impl Debug;
|
||||
u16;
|
||||
ch1, set_ch1: Self::upper(1), Self::lower(1);
|
||||
ch2, set_ch2: Self::upper(2), Self::lower(2);
|
||||
ch3, set_ch3: Self::upper(3), Self::lower(3);
|
||||
ch4, set_ch4: Self::upper(4), Self::lower(4);
|
||||
ch5, set_ch5: Self::upper(5), Self::lower(5);
|
||||
ch6, set_ch6: Self::upper(6), Self::lower(6);
|
||||
ch7, set_ch7: Self::upper(7), Self::lower(7);
|
||||
ch8, set_ch8: Self::upper(8), Self::lower(8);
|
||||
ch9, set_ch9: Self::upper(9), Self::lower(9);
|
||||
ch10, set_ch10: Self::upper(10), Self::lower(10);
|
||||
ch11, set_ch11: Self::upper(11), Self::lower(11);
|
||||
ch12, set_ch12: Self::upper(12), Self::lower(12);
|
||||
ch13, set_ch13: Self::upper(13), Self::lower(13);
|
||||
ch14, set_ch14: Self::upper(14), Self::lower(14);
|
||||
ch15, set_ch15: Self::upper(15), Self::lower(15);
|
||||
ch16, set_ch16: Self::upper(16), Self::lower(16);
|
||||
}
|
||||
|
||||
impl<T> RcChannels<T> {
|
||||
const BITS_PER_CHANNEL: usize = 11;
|
||||
|
||||
const fn upper(ch: usize) -> usize {
|
||||
Self::lower(ch) + Self::BITS_PER_CHANNEL - 1
|
||||
}
|
||||
|
||||
const fn lower(ch: usize) -> usize {
|
||||
Self::BITS_PER_CHANNEL * (ch - 1)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CrsfParser {
|
||||
buffer: HistoryBuffer<u8, { Self::MAX_PACKET_SIZE }>,
|
||||
}
|
||||
|
||||
impl CrsfParser {
|
||||
const MAX_PACKET_SIZE: usize = 64;
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#[test]
|
||||
fn rc_channels() {
|
||||
let input = [
|
||||
0xc8, 0x18, 0x16, 0xe0, 0x3, 0x1f, 0xb3, 0xc0, 0xf7, 0xb, 0xee, 0x69, 0x8f, 0x15, 0xe0,
|
||||
0x3, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x78, 0xd9, 0xdb, 0xb4, 0xc8,
|
||||
];
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user