1use 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
11pub(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
16pub(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
29pub(crate) fn encode_packet(frame: &PacketFrame) -> [f32; 192] {
30 let mut type1 = [0u8; 26]; match frame.counter {
32 PacketFrameCounter::Frame { index } => {
33 type1[0..25].copy_from_slice(&frame.payload);
34 type1[25] = (index as u8) << 2;
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) << 2) | 0x80;
39 }
40 }
41 let type3 = fec::encode(&type1, 206, p_3);
42 interleave_to_dibits(type3, PACKET_SYNC)
43}
44
45pub(crate) fn generate_preamble() -> [f32; 192] {
51 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
60pub(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
68pub(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
83fn 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)]
105mod 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}