hdds_micro/transport/hc12/
framing.rs1use crate::error::{Error, Result};
25
26const SYNC_START: u8 = 0xAA;
28
29const SYNC_END: u8 = 0x55;
31
32const MAX_PAYLOAD: usize = 50;
34
35pub const FRAME_OVERHEAD: usize = 6;
37
38const MAX_FRAME_SIZE: usize = MAX_PAYLOAD + FRAME_OVERHEAD;
40
41#[derive(Debug)]
43pub struct FrameEncoder {
44 }
46
47impl FrameEncoder {
48 pub const fn new() -> Self {
50 Self {}
51 }
52
53 pub fn encode(&self, src_node: u8, data: &[u8], buf: &mut [u8]) -> Result<usize> {
65 if data.len() > MAX_PAYLOAD {
66 return Err(Error::BufferTooSmall);
67 }
68
69 let frame_len = data.len() + FRAME_OVERHEAD;
70 if buf.len() < frame_len {
71 return Err(Error::BufferTooSmall);
72 }
73
74 buf[0] = SYNC_START;
76 buf[1] = data.len() as u8;
77 buf[2] = src_node;
78
79 buf[3..3 + data.len()].copy_from_slice(data);
81
82 let crc = crc16_ccitt(&buf[1..3 + data.len()]);
84 buf[3 + data.len()] = (crc >> 8) as u8;
85 buf[4 + data.len()] = (crc & 0xFF) as u8;
86
87 buf[5 + data.len()] = SYNC_END;
89
90 Ok(frame_len)
91 }
92}
93
94impl Default for FrameEncoder {
95 fn default() -> Self {
96 Self::new()
97 }
98}
99
100#[derive(Debug, Clone, Copy, PartialEq, Eq)]
102enum DecoderState {
103 WaitStart,
105 WaitLength,
107 WaitSource,
109 Payload,
111 CrcHigh,
113 CrcLow,
115 WaitEnd,
117}
118
119#[derive(Debug)]
121pub struct FrameDecoder {
122 state: DecoderState,
124
125 buf: [u8; MAX_FRAME_SIZE],
127
128 payload_len: usize,
130
131 src_node: u8,
133
134 pos: usize,
136
137 crc: u16,
139}
140
141impl FrameDecoder {
142 pub const fn new() -> Self {
144 Self {
145 state: DecoderState::WaitStart,
146 buf: [0u8; MAX_FRAME_SIZE],
147 payload_len: 0,
148 src_node: 0,
149 pos: 0,
150 crc: 0,
151 }
152 }
153
154 pub fn reset(&mut self) {
156 self.state = DecoderState::WaitStart;
157 self.pos = 0;
158 self.payload_len = 0;
159 self.src_node = 0;
160 self.crc = 0;
161 }
162
163 pub fn feed(&mut self, byte: u8) -> Result<Option<(u8, &[u8])>> {
169 match self.state {
170 DecoderState::WaitStart => {
171 if byte == SYNC_START {
172 self.state = DecoderState::WaitLength;
173 self.pos = 0;
174 }
175 Ok(None)
176 }
177
178 DecoderState::WaitLength => {
179 if byte > MAX_PAYLOAD as u8 {
180 self.reset();
182 return Ok(None);
183 }
184 self.payload_len = byte as usize;
185 self.buf[0] = byte; self.state = DecoderState::WaitSource;
187 Ok(None)
188 }
189
190 DecoderState::WaitSource => {
191 self.src_node = byte;
192 self.buf[1] = byte; self.pos = 0;
194 if self.payload_len == 0 {
195 self.state = DecoderState::CrcHigh;
196 } else {
197 self.state = DecoderState::Payload;
198 }
199 Ok(None)
200 }
201
202 DecoderState::Payload => {
203 self.buf[2 + self.pos] = byte;
204 self.pos += 1;
205
206 if self.pos >= self.payload_len {
207 self.state = DecoderState::CrcHigh;
208 }
209 Ok(None)
210 }
211
212 DecoderState::CrcHigh => {
213 self.crc = (byte as u16) << 8;
214 self.state = DecoderState::CrcLow;
215 Ok(None)
216 }
217
218 DecoderState::CrcLow => {
219 self.crc |= byte as u16;
220 self.state = DecoderState::WaitEnd;
221 Ok(None)
222 }
223
224 DecoderState::WaitEnd => {
225 if byte == SYNC_END {
226 let expected_crc = crc16_ccitt(&self.buf[..2 + self.payload_len]);
228
229 if self.crc == expected_crc {
230 self.state = DecoderState::WaitStart;
232 let payload_end = 2 + self.payload_len;
233 self.payload_len = 0; self.crc = 0;
235 self.pos = 0;
236 return Ok(Some((self.src_node, &self.buf[2..payload_end])));
237 }
238 }
239
240 self.reset();
242 Ok(None)
243 }
244 }
245 }
246
247 pub const fn is_receiving(&self) -> bool {
249 !matches!(self.state, DecoderState::WaitStart)
250 }
251}
252
253impl Default for FrameDecoder {
254 fn default() -> Self {
255 Self::new()
256 }
257}
258
259fn crc16_ccitt(data: &[u8]) -> u16 {
261 let mut crc: u16 = 0xFFFF;
262
263 for &byte in data {
264 crc ^= (byte as u16) << 8;
265 for _ in 0..8 {
266 if crc & 0x8000 != 0 {
267 crc = (crc << 1) ^ 0x1021;
268 } else {
269 crc <<= 1;
270 }
271 }
272 }
273
274 crc
275}
276
277#[cfg(test)]
278mod tests {
279 use super::*;
280
281 #[test]
282 fn test_encoder_basic() {
283 let encoder = FrameEncoder::new();
284 let mut buf = [0u8; 64];
285
286 let len = encoder.encode(42, b"Hello", &mut buf).unwrap();
287
288 assert_eq!(len, 5 + FRAME_OVERHEAD); assert_eq!(buf[0], SYNC_START);
290 assert_eq!(buf[1], 5); assert_eq!(buf[2], 42); assert_eq!(&buf[3..8], b"Hello");
293 assert_eq!(buf[len - 1], SYNC_END);
294 }
295
296 #[test]
297 fn test_encoder_empty_payload() {
298 let encoder = FrameEncoder::new();
299 let mut buf = [0u8; 64];
300
301 let len = encoder.encode(1, &[], &mut buf).unwrap();
302
303 assert_eq!(len, FRAME_OVERHEAD);
304 assert_eq!(buf[0], SYNC_START);
305 assert_eq!(buf[1], 0); assert_eq!(buf[len - 1], SYNC_END);
307 }
308
309 #[test]
310 fn test_encoder_buffer_too_small() {
311 let encoder = FrameEncoder::new();
312 let mut buf = [0u8; 5]; let result = encoder.encode(1, b"Hello", &mut buf);
315 assert_eq!(result, Err(Error::BufferTooSmall));
316 }
317
318 #[test]
319 fn test_encoder_payload_too_large() {
320 let encoder = FrameEncoder::new();
321 let mut buf = [0u8; 256];
322 let data = [0u8; 60]; let result = encoder.encode(1, &data, &mut buf);
325 assert_eq!(result, Err(Error::BufferTooSmall));
326 }
327
328 #[test]
329 fn test_decoder_basic() {
330 let encoder = FrameEncoder::new();
331 let mut decoder = FrameDecoder::new();
332 let mut buf = [0u8; 64];
333
334 let len = encoder.encode(42, b"Test", &mut buf).unwrap();
336
337 for &byte in &buf[..len - 1] {
339 let result = decoder.feed(byte).unwrap();
340 assert!(result.is_none());
341 }
342
343 let result = decoder.feed(buf[len - 1]).unwrap();
345 assert!(result.is_some());
346
347 let (src, payload) = result.unwrap();
348 assert_eq!(src, 42);
349 assert_eq!(payload, b"Test");
350 }
351
352 #[test]
353 fn test_decoder_empty_payload() {
354 let encoder = FrameEncoder::new();
355 let mut decoder = FrameDecoder::new();
356 let mut buf = [0u8; 64];
357
358 let len = encoder.encode(1, &[], &mut buf).unwrap();
359
360 for &byte in &buf[..len - 1] {
361 assert!(decoder.feed(byte).unwrap().is_none());
362 }
363
364 let result = decoder.feed(buf[len - 1]).unwrap();
365 assert!(result.is_some());
366
367 let (src, payload) = result.unwrap();
368 assert_eq!(src, 1);
369 assert!(payload.is_empty());
370 }
371
372 #[test]
373 fn test_decoder_bad_crc() {
374 let encoder = FrameEncoder::new();
375 let mut decoder = FrameDecoder::new();
376 let mut buf = [0u8; 64];
377
378 let len = encoder.encode(42, b"Test", &mut buf).unwrap();
379
380 buf[5] ^= 0xFF;
382
383 for &byte in &buf[..len] {
385 let _ = decoder.feed(byte);
386 }
387
388 assert!(!decoder.is_receiving());
390 }
391
392 #[test]
393 fn test_decoder_bad_sync() {
394 let mut decoder = FrameDecoder::new();
395
396 for b in &[0x12, 0x34, 0x56, 0x78] {
398 let result = decoder.feed(*b).unwrap();
399 assert!(result.is_none());
400 }
401
402 assert!(!decoder.is_receiving());
403 }
404
405 #[test]
406 fn test_decoder_multiple_frames() {
407 let encoder = FrameEncoder::new();
408 let mut decoder = FrameDecoder::new();
409 let mut buf1 = [0u8; 64];
410 let mut buf2 = [0u8; 64];
411
412 let len1 = encoder.encode(1, b"First", &mut buf1).unwrap();
413 let len2 = encoder.encode(2, b"Second", &mut buf2).unwrap();
414
415 for &byte in &buf1[..len1 - 1] {
417 assert!(decoder.feed(byte).unwrap().is_none());
418 }
419 let result = decoder.feed(buf1[len1 - 1]).unwrap();
420 let (src, payload) = result.unwrap();
421 assert_eq!(src, 1);
422 assert_eq!(payload, b"First");
423
424 for &byte in &buf2[..len2 - 1] {
426 assert!(decoder.feed(byte).unwrap().is_none());
427 }
428 let result = decoder.feed(buf2[len2 - 1]).unwrap();
429 let (src, payload) = result.unwrap();
430 assert_eq!(src, 2);
431 assert_eq!(payload, b"Second");
432 }
433
434 #[test]
435 fn test_crc16_known_values() {
436 assert_eq!(crc16_ccitt(b""), 0xFFFF);
438 assert_eq!(crc16_ccitt(b"123456789"), 0x29B1);
439 }
440
441 #[test]
442 fn test_roundtrip_various_sizes() {
443 let encoder = FrameEncoder::new();
444 let mut decoder = FrameDecoder::new();
445 let mut frame_buf = [0u8; 64];
446 let mut data_buf = [0u8; 50];
447
448 for size in [0usize, 1, 10, 25, 50] {
449 for (i, slot) in data_buf[..size].iter_mut().enumerate() {
451 *slot = i as u8;
452 }
453 let data = &data_buf[..size];
454
455 let len = encoder.encode(42, data, &mut frame_buf).unwrap();
456
457 for &byte in &frame_buf[..len - 1] {
458 assert!(decoder.feed(byte).unwrap().is_none());
459 }
460
461 let result = decoder.feed(frame_buf[len - 1]).unwrap();
462 assert!(result.is_some());
463
464 let (src, payload) = result.unwrap();
465 assert_eq!(src, 42);
466 assert_eq!(payload, data);
467 }
468 }
469}