leodos_protocols/datalink/framing/sdlp/
tm.rs1use bon::bon;
9use zerocopy::FromBytes;
10use zerocopy::Immutable;
11use zerocopy::IntoBytes;
12use zerocopy::KnownLayout;
13use zerocopy::Unaligned;
14use zerocopy::byteorder::network_endian::U16;
15
16use crate::coding::randomizer::Randomizer;
17use crate::utils::get_bits_u16;
18use crate::utils::set_bits_u16;
19
20#[repr(C, packed)]
60#[derive(IntoBytes, FromBytes, Unaligned, KnownLayout, Immutable)]
61pub struct TelemetryTransferFrame {
62 header: TelemetryTransferFrameHeader,
63 data_field: [u8],
64}
65
66#[repr(C)]
68#[derive(FromBytes, IntoBytes, KnownLayout, Unaligned, Immutable, Debug, Copy, Clone)]
69pub struct TelemetryTransferFrameHeader {
70 version_scid_vcid_and_ocf: U16,
72 mc_frame_count: u8,
74 vc_frame_count: u8,
76 data_field_status: U16,
78}
79
80#[rustfmt::skip]
82pub mod bitmask {
83 pub const VERSION_MASK: u16 = 0b_1100_0000_0000_0000;
85 pub const SCID_MASK: u16 = 0b_0011_1111_1111_0000;
87 pub const VCID_MASK: u16 = 0b_0000_0000_0000_1110;
89 pub const OCF_FLAG_MASK: u16 = 0b_0000_0000_0000_0001;
91
92 pub const FIRST_HEADER_POINTER_MASK: u16 = 0b_0000_0111_1111_1111;
94}
95
96use bitmask::*;
97use crate::ids::{Scid, Vcid};
98
99#[derive(Debug, Copy, Clone, Eq, PartialEq)]
101pub enum BuildError {
102 InvalidScid(Scid),
104 InvalidVcid(Vcid),
106 BufferTooSmall {
108 required_len: usize,
110 provided_len: usize,
112 },
113}
114
115#[derive(Debug, Copy, Clone, Eq, PartialEq)]
117pub enum ParseError {
118 InvalidBufferLength,
121 TooShortForHeader,
123}
124
125#[bon]
126impl TelemetryTransferFrame {
127 pub const HEADER_SIZE: usize = 6;
129
130 pub fn parse<'a>(
135 bytes: &[u8],
136 output_buffer: &'a mut [u8],
137 randomizer: &impl Randomizer,
138 ) -> Result<&'a TelemetryTransferFrame, ParseError> {
139 if bytes.len() < Self::HEADER_SIZE {
140 return Err(ParseError::TooShortForHeader);
141 }
142 if output_buffer.len() < bytes.len() {
143 return Err(ParseError::InvalidBufferLength);
144 }
145 let frame_buf = &mut output_buffer[..bytes.len()];
146 frame_buf.copy_from_slice(bytes);
147
148 randomizer.apply(frame_buf);
149
150 TelemetryTransferFrame::ref_from_bytes(frame_buf)
151 .map_err(|_| ParseError::InvalidBufferLength)
152 }
153
154 pub fn parse_raw(bytes: &[u8]) -> Result<&TelemetryTransferFrame, ParseError> {
159 if bytes.len() < Self::HEADER_SIZE {
160 return Err(ParseError::TooShortForHeader);
161 }
162 TelemetryTransferFrame::ref_from_bytes(bytes)
163 .map_err(|_| ParseError::InvalidBufferLength)
164 }
165
166 pub fn header(&self) -> &TelemetryTransferFrameHeader {
168 &self.header
169 }
170
171 pub fn data_field_mut(&mut self) -> &mut [u8] {
173 &mut self.data_field
174 }
175
176 pub fn data_field(&self) -> &[u8] {
181 &self.data_field
182 }
183
184 #[builder]
186 pub fn new(
187 buffer: &mut [u8],
188 version: u8,
189 scid: Scid,
190 vcid: Vcid,
191 mc_frame_count: u8,
192 vc_frame_count: u8,
193 first_header_pointer: u16,
194 ) -> Result<&mut Self, BuildError> {
195 if buffer.len() < Self::HEADER_SIZE {
196 return Err(BuildError::BufferTooSmall {
197 required_len: Self::HEADER_SIZE,
198 provided_len: buffer.len(),
199 });
200 }
201 if scid.num_bits() > 10 {
202 return Err(BuildError::InvalidScid(scid));
203 }
204 if vcid.num_bits() > 3 {
205 return Err(BuildError::InvalidVcid(vcid));
206 }
207
208 let provided_len = buffer.len();
209 if provided_len < Self::HEADER_SIZE {
210 return Err(BuildError::BufferTooSmall {
211 required_len: Self::HEADER_SIZE,
212 provided_len,
213 });
214 }
215 let data_field_len = provided_len - Self::HEADER_SIZE;
216 let (frame, _) = TelemetryTransferFrame::mut_from_prefix_with_elems(buffer, data_field_len)
217 .map_err(|_| BuildError::BufferTooSmall {
218 required_len: Self::HEADER_SIZE,
219 provided_len,
220 })?;
221
222 frame.header.set_version(version);
223 frame.header.set_scid(scid);
224 frame.header.set_vcid(vcid);
225 frame.header.set_mc_frame_count(mc_frame_count);
226 frame.header.set_vc_frame_count(vc_frame_count);
227 frame.header.set_first_header_pointer(first_header_pointer);
228
229 Ok(frame)
230 }
231}
232
233impl TelemetryTransferFrameHeader {
234 pub fn version(&self) -> u8 {
236 get_bits_u16(self.version_scid_vcid_and_ocf, VERSION_MASK) as u8
237 }
238 pub fn set_version(&mut self, version: u8) {
240 set_bits_u16(
241 &mut self.version_scid_vcid_and_ocf,
242 VERSION_MASK,
243 version as u16,
244 );
245 }
246
247 pub fn scid(&self) -> Scid {
249 Scid::new(get_bits_u16(self.version_scid_vcid_and_ocf, SCID_MASK) as u32)
250 }
251 pub fn set_scid(&mut self, scid: Scid) {
253 set_bits_u16(&mut self.version_scid_vcid_and_ocf, SCID_MASK, scid.get() as u16);
254 }
255
256 pub fn vcid(&self) -> Vcid {
258 Vcid::new(get_bits_u16(self.version_scid_vcid_and_ocf, VCID_MASK) as u32)
259 }
260 pub fn set_vcid(&mut self, vcid: Vcid) {
262 set_bits_u16(&mut self.version_scid_vcid_and_ocf, VCID_MASK, vcid.get() as u16);
263 }
264
265 pub fn mc_frame_count(&self) -> u8 {
267 self.mc_frame_count
268 }
269 pub fn set_mc_frame_count(&mut self, count: u8) {
271 self.mc_frame_count = count;
272 }
273
274 pub fn vc_frame_count(&self) -> u8 {
276 self.vc_frame_count
277 }
278 pub fn set_vc_frame_count(&mut self, count: u8) {
280 self.vc_frame_count = count;
281 }
282
283 pub fn first_header_pointer(&self) -> u16 {
285 get_bits_u16(self.data_field_status, FIRST_HEADER_POINTER_MASK)
286 }
287 pub fn set_first_header_pointer(&mut self, fhp: u16) {
289 set_bits_u16(&mut self.data_field_status, FIRST_HEADER_POINTER_MASK, fhp);
290 }
291}
292
293use super::super::{FrameRead, FrameWrite, PushError};
296
297#[derive(Debug, Clone)]
299pub struct TmFrameWriterConfig {
300 pub scid: Scid,
302 pub vcid: Vcid,
304 pub max_data_field_len: usize,
306}
307
308pub struct TmFrameWriter<const BUF: usize> {
315 config: TmFrameWriterConfig,
316 mc_frame_count: u8,
317 vc_frame_count: u8,
318 data_len: usize,
319 buf: [u8; BUF],
320}
321
322impl<const BUF: usize> TmFrameWriter<BUF> {
323 pub fn new(config: TmFrameWriterConfig) -> Self {
325 Self {
326 config,
327 mc_frame_count: 0,
328 vc_frame_count: 0,
329 data_len: 0,
330 buf: [0u8; BUF],
331 }
332 }
333}
334
335impl<const BUF: usize> TmFrameWriter<BUF> {
336 fn remaining(&self) -> usize {
337 self.config
338 .max_data_field_len
339 .saturating_sub(self.data_len)
340 }
341}
342
343impl<const BUF: usize> FrameWrite for TmFrameWriter<BUF> {
344 type Error = BuildError;
345
346 fn is_empty(&self) -> bool {
347 self.data_len == 0
348 }
349
350 fn push(&mut self, data: &[u8]) -> Result<(), PushError> {
351 if data.len() > self.config.max_data_field_len {
352 return Err(PushError::TooLarge);
353 }
354 if data.len() > self.remaining() {
355 return Err(PushError::Full);
356 }
357 let off =
358 TelemetryTransferFrame::HEADER_SIZE + self.data_len;
359 self.buf[off..off + data.len()].copy_from_slice(data);
360 self.data_len += data.len();
361 Ok(())
362 }
363
364 fn finish(&mut self) -> Result<&[u8], BuildError> {
365 let total =
366 TelemetryTransferFrame::HEADER_SIZE + self.data_len;
367 let mc = self.mc_frame_count;
368 let vc = self.vc_frame_count;
369 self.mc_frame_count =
370 self.mc_frame_count.wrapping_add(1);
371 self.vc_frame_count =
372 self.vc_frame_count.wrapping_add(1);
373
374 TelemetryTransferFrame::builder()
375 .buffer(&mut self.buf[..total])
376 .version(0)
377 .scid(self.config.scid)
378 .vcid(self.config.vcid)
379 .mc_frame_count(mc)
380 .vc_frame_count(vc)
381 .first_header_pointer(0)
382 .build()?;
383
384 self.data_len = 0;
385 Ok(&self.buf[..total])
386 }
387}
388
389pub struct TmFrameReader<const BUF: usize> {
397 buf: [u8; BUF],
398 data_start: usize,
399 data_end: usize,
400}
401
402impl<const BUF: usize> TmFrameReader<BUF> {
403 pub fn new() -> Self {
405 Self {
406 buf: [0u8; BUF],
407 data_start: 0,
408 data_end: 0,
409 }
410 }
411}
412
413impl<const BUF: usize> FrameRead for TmFrameReader<BUF> {
414 type Error = ParseError;
415
416 fn buffer_mut(&mut self) -> &mut [u8] {
417 &mut self.buf
418 }
419
420 fn feed(&mut self, len: usize) -> Result<(), ParseError> {
421 let parsed =
422 TelemetryTransferFrame::parse_raw(&self.buf[..len])?;
423 let data = parsed.data_field();
424 self.data_start =
425 TelemetryTransferFrame::HEADER_SIZE;
426 self.data_end = self.data_start + data.len();
427 Ok(())
428 }
429
430 fn data_field(&self) -> &[u8] {
431 &self.buf[self.data_start..self.data_end]
432 }
433}