1pub const DEFAULT_LINK_ID: u32 = 7_669_206;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8pub enum RadioPort {
9 Video,
10 MavlinkRx,
11 MavlinkTx,
12 DataRx,
13 Custom(u8),
14}
15
16impl RadioPort {
17 pub const fn as_u8(self) -> u8 {
18 match self {
19 Self::Video => 0,
20 Self::MavlinkRx => 0x10,
21 Self::MavlinkTx => 160,
22 Self::DataRx => 32,
23 Self::Custom(value) => value,
24 }
25 }
26}
27
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
29pub struct ChannelId(u32);
30
31impl ChannelId {
32 pub const fn new(raw: u32) -> Self {
33 Self(raw)
34 }
35
36 pub const fn from_link_port(link_id: u32, port: RadioPort) -> Self {
37 Self((link_id << 8) | port.as_u8() as u32)
38 }
39
40 pub const fn default_video() -> Self {
41 Self::from_link_port(DEFAULT_LINK_ID, RadioPort::Video)
42 }
43
44 pub const fn raw(self) -> u32 {
45 self.0
46 }
47
48 pub const fn to_be_bytes(self) -> [u8; 4] {
49 self.0.to_be_bytes()
50 }
51}
52
53#[cfg(test)]
54mod tests {
55 use super::*;
56
57 #[test]
58 fn default_video_channel_matches_reference_value() {
59 let id = ChannelId::default_video();
60 assert_eq!(id.raw(), (DEFAULT_LINK_ID << 8));
61 assert_eq!(id.to_be_bytes(), id.raw().to_be_bytes());
62 }
63
64 #[test]
65 fn radio_ports_match_openipc_ground_station_conventions() {
66 assert_eq!(RadioPort::Video.as_u8(), 0x00);
67 assert_eq!(RadioPort::MavlinkRx.as_u8(), 0x10);
68 assert_eq!(RadioPort::DataRx.as_u8(), 0x20);
69 assert_eq!(RadioPort::MavlinkTx.as_u8(), 0xa0);
70 }
71}