1#[derive(PartialEq, Eq, Copy, Clone, Debug)]
2pub enum GpsFix {
3 Old,
4 Current,
5}
6
7impl From<bool> for GpsFix {
8 fn from(bit: bool) -> Self {
9 match bit {
10 false => GpsFix::Old,
11 true => GpsFix::Current,
12 }
13 }
14}
15
16impl From<GpsFix> for bool {
17 fn from(fix: GpsFix) -> bool {
18 match fix {
19 GpsFix::Old => false,
20 GpsFix::Current => true,
21 }
22 }
23}
24
25#[derive(PartialEq, Eq, Copy, Clone, Debug)]
26pub enum NmeaSource {
27 Other,
28 Gll,
29 Gga,
30 Rmc,
31}
32
33impl From<(bool, bool)> for NmeaSource {
34 fn from(bits: (bool, bool)) -> Self {
35 match bits {
36 (false, false) => NmeaSource::Other,
37 (false, true) => NmeaSource::Gll,
38 (true, false) => NmeaSource::Gga,
39 (true, true) => NmeaSource::Rmc,
40 }
41 }
42}
43
44impl From<NmeaSource> for (bool, bool) {
45 fn from(source: NmeaSource) -> Self {
46 match source {
47 NmeaSource::Other => (false, false),
48 NmeaSource::Gll => (false, true),
49 NmeaSource::Gga => (true, false),
50 NmeaSource::Rmc => (true, true),
51 }
52 }
53}
54
55#[derive(PartialEq, Eq, Copy, Clone, Debug)]
56pub enum Origin {
57 Compressed,
58 TncBText,
59 Software,
60 Tbd,
61 Kpc3,
62 Pico,
63 Other,
64 Digipeater,
65}
66
67impl From<(bool, bool, bool)> for Origin {
68 fn from(bits: (bool, bool, bool)) -> Self {
69 match bits {
70 (false, false, false) => Origin::Compressed,
71 (false, false, true) => Origin::TncBText,
72 (false, true, false) => Origin::Software,
73 (false, true, true) => Origin::Tbd,
74 (true, false, false) => Origin::Kpc3,
75 (true, false, true) => Origin::Pico,
76 (true, true, false) => Origin::Other,
77 (true, true, true) => Origin::Digipeater,
78 }
79 }
80}
81
82impl From<Origin> for (bool, bool, bool) {
83 fn from(origin: Origin) -> Self {
84 match origin {
85 Origin::Compressed => (false, false, false),
86 Origin::TncBText => (false, false, true),
87 Origin::Software => (false, true, false),
88 Origin::Tbd => (false, true, true),
89 Origin::Kpc3 => (true, false, false),
90 Origin::Pico => (true, false, true),
91 Origin::Other => (true, true, false),
92 Origin::Digipeater => (true, true, true),
93 }
94 }
95}
96
97#[derive(PartialEq, Eq, Copy, Clone, Debug)]
98pub struct AprsCompressionType {
99 pub gps_fix: GpsFix,
100 pub nmea_source: NmeaSource,
101 pub origin: Origin,
102}
103
104impl From<u8> for AprsCompressionType {
105 fn from(byte: u8) -> Self {
106 let gps_fix = (byte & (1 << 5)) != 0;
107 let nmea_source = (byte & (1 << 4) != 0, byte & (1 << 3) != 0);
108 let origin = (
109 byte & (1 << 2) != 0,
110 byte & (1 << 1) != 0,
111 byte & (1 << 0) != 0,
112 );
113
114 Self {
115 gps_fix: gps_fix.into(),
116 nmea_source: nmea_source.into(),
117 origin: origin.into(),
118 }
119 }
120}
121
122impl From<AprsCompressionType> for u8 {
123 fn from(t: AprsCompressionType) -> u8 {
124 let b5: bool = t.gps_fix.into();
125 let (b4, b3) = t.nmea_source.into();
126 let (b2, b1, b0) = t.origin.into();
127
128 (u8::from(b5) << 5)
129 + (u8::from(b4) << 4)
130 + (u8::from(b3) << 3)
131 + (u8::from(b2) << 2)
132 + (u8::from(b1) << 1)
133 + (u8::from(b0))
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140
141 #[test]
142 fn encode_works() {
143 let byte: u8 = 0b00111010;
144 let expected = AprsCompressionType {
145 gps_fix: GpsFix::Current,
146 nmea_source: NmeaSource::Rmc,
147 origin: Origin::Software,
148 };
149
150 assert_eq!(expected, byte.into());
151 }
152
153 #[test]
154 fn decode_works() {
155 let expected: u8 = 0b00111010;
156 let ctype = AprsCompressionType {
157 gps_fix: GpsFix::Current,
158 nmea_source: NmeaSource::Rmc,
159 origin: Origin::Software,
160 };
161
162 assert_eq!(expected, ctype.into());
163 }
164}