]> code.octet-stream.net Git - m17rt/blob - m17core/src/encode.rs
Integrating modulator
[m17rt] / m17core / src / encode.rs
1 use crate::{
2 bits::Bits,
3 fec::{self, p_1, p_2, p_3},
4 interleave::interleave,
5 protocol::{
6 LsfFrame, PacketFrame, PacketFrameCounter, StreamFrame, LSF_SYNC, PACKET_SYNC, STREAM_SYNC,
7 },
8 random::random_xor,
9 };
10
11 pub(crate) fn encode_lsf(frame: &LsfFrame) -> [f32; 192] {
12 let type3 = fec::encode(&frame.0, 240, p_1);
13 interleave_to_dibits(type3, LSF_SYNC)
14 }
15
16 pub(crate) fn encode_stream(frame: &StreamFrame) -> [f32; 192] {
17 let lich = encode_lich(frame.lich_idx, &frame.lich_part);
18 let mut type1 = [0u8; 18];
19 let frame_number = frame.frame_number | if frame.end_of_stream { 0x8000 } else { 0x0000 };
20 type1[0..2].copy_from_slice(&frame_number.to_be_bytes());
21 type1[2..18].copy_from_slice(&frame.stream_data);
22 let type3 = fec::encode(&type1, 144, p_2);
23 let mut combined = [0u8; 46];
24 combined[0..12].copy_from_slice(&lich);
25 combined[12..46].copy_from_slice(&type3[0..34]);
26 interleave_to_dibits(combined, STREAM_SYNC)
27 }
28
29 pub(crate) fn encode_packet(frame: &PacketFrame) -> [f32; 192] {
30 let mut type1 = [0u8; 26]; // only 206 out of 208 bits filled
31 match frame.counter {
32 PacketFrameCounter::Frame { index } => {
33 type1[0..25].copy_from_slice(&frame.payload);
34 type1[25] = (index as u8) << 3;
35 }
36 PacketFrameCounter::FinalFrame { payload_len } => {
37 type1[0..payload_len].copy_from_slice(&frame.payload[0..payload_len]);
38 type1[25] = (payload_len as u8) << 3 | 0x04;
39 }
40 }
41 let type3 = fec::encode(&type1, 206, p_3);
42 interleave_to_dibits(type3, PACKET_SYNC)
43 }
44
45 /// Generate a preamble suitable for placement before an LSF frame.
46 ///
47 /// Polarity needs to be flipped for BERT, however we don't support this yet.
48 /// STREAM and PACKET don't need to be considered as they are an invalid way to
49 /// begin a transmission.
50 pub(crate) fn generate_preamble() -> [f32; 192] {
51 // TODO: should all these encode/generate functions return owning iterators?
52 // Then I could avoid making this array which I'm just going to have to copy anyway
53 let mut out = [1.0f32; 192];
54 for n in out.iter_mut().skip(1).step_by(2) {
55 *n = -1.0;
56 }
57 out
58 }
59
60 pub(crate) fn generate_end_of_transmission() -> [f32; 192] {
61 let mut out = [1.0f32; 192];
62 for n in out.iter_mut().skip(6).step_by(8) {
63 *n = -1.0;
64 }
65 out
66 }
67
68 pub(crate) fn encode_lich(counter: u8, part: &[u8; 5]) -> [u8; 12] {
69 let mut out = [0u8; 12];
70 let to_encode = [
71 ((part[0] as u16) << 4) | ((part[1] as u16) >> 4),
72 ((part[1] as u16 & 0x000f) << 8) | part[2] as u16,
73 ((part[3] as u16) << 4) | ((part[4] as u16) >> 4),
74 ((part[4] as u16 & 0x000f) << 8) | ((counter as u16) << 5),
75 ];
76 for (i, o) in to_encode.into_iter().zip(out.chunks_mut(3)) {
77 let encoded = cai_golay::extended::encode(i).to_be_bytes();
78 o[0..3].copy_from_slice(&encoded[1..4]);
79 }
80 out
81 }
82
83 fn interleave_to_dibits(combined: [u8; 46], sync_burst: [i8; 8]) -> [f32; 192] {
84 let mut interleaved = interleave(&combined);
85 random_xor(&mut interleaved);
86 let mut out = [0f32; 192];
87 for (val, o) in sync_burst.iter().zip(out.iter_mut()) {
88 *o = *val as f32;
89 }
90 let bits = Bits::new(&interleaved);
91 let mut out_bits = bits.iter();
92 for o in out[8..].iter_mut() {
93 *o = match (out_bits.next().unwrap(), out_bits.next().unwrap()) {
94 (0, 1) => 1.0,
95 (0, 0) => 1.0 / 3.0,
96 (1, 0) => -1.0 / 3.0,
97 (1, 1) => -1.0,
98 _ => unreachable!(),
99 };
100 }
101 out
102 }
103
104 #[cfg(test)]
105 mod tests {
106 use super::*;
107
108 #[test]
109 fn lsf_round_trip() {
110 let lsf = LsfFrame([
111 255, 255, 255, 255, 255, 255, 0, 0, 0, 159, 221, 81, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0,
112 0, 0, 0, 0, 0, 131, 53,
113 ]);
114 let encoded = encode_lsf(&lsf);
115 let decoded = crate::decode::parse_lsf(&encoded);
116 assert_eq!(decoded, Some(lsf));
117 }
118
119 #[test]
120 fn stream_round_trip() {
121 let stream = StreamFrame {
122 lich_idx: 5,
123 lich_part: [1, 2, 3, 4, 5],
124 frame_number: 50,
125 end_of_stream: false,
126 stream_data: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16],
127 };
128 let encoded = encode_stream(&stream);
129 let decoded = crate::decode::parse_stream(&encoded);
130 assert_eq!(decoded, Some(stream));
131 }
132
133 #[test]
134 fn packet_round_trip() {
135 let packet = PacketFrame {
136 payload: [41u8; 25],
137 counter: PacketFrameCounter::Frame { index: 3 },
138 };
139 let encoded = encode_packet(&packet);
140 let decoded = crate::decode::parse_packet(&encoded);
141 assert_eq!(decoded, Some(packet));
142
143 let packet = PacketFrame {
144 payload: [0u8; 25],
145 counter: PacketFrameCounter::FinalFrame { payload_len: 10 },
146 };
147 let encoded = encode_packet(&packet);
148 let decoded = crate::decode::parse_packet(&encoded);
149 assert_eq!(decoded, Some(packet));
150 }
151
152 #[test]
153 fn lich_encode() {
154 let input = [221, 81, 5, 5, 0];
155 let counter = 2;
156 let expected_output = [221, 82, 162, 16, 85, 200, 5, 14, 254, 4, 13, 153];
157 assert_eq!(encode_lich(counter, &input), expected_output);
158 }
159
160 #[test]
161 fn lich_round_trip() {
162 let input = [1, 255, 0, 90, 10];
163 let counter = 0;
164 assert_eq!(
165 crate::decode::decode_lich(&encode_lich(counter, &input)),
166 Some((counter, input))
167 );
168 }
169 }