]>
code.octet-stream.net Git - m17rt/blob - m17core/src/fec.rs
   1 use crate::bits
::{Bits
, BitsMut
}; 
  10 static TRANSITIONS
: [Transition
; 32] = [ 
 173 pub(crate) fn p_1(step
: usize) -> (bool
, bool
) { 
 174     let mod61 
= step 
% 61; 
 175     let is_even 
= mod61 
% 2 == 0; 
 176     (mod61 
> 30 || is_even
, mod61 
< 30 || is_even
) 
 179 pub(crate) fn p_2(step
: usize) -> (bool
, bool
) { 
 184 pub(crate) fn p_3(step
: usize) -> (bool
, bool
) { 
 189 fn best_previous(table
: &[[u8; 32]; 244], step
: usize, state
: usize) -> u8 { 
 197     let prev1 
= table
[step 
- 1][state 
* 2]; 
 198     let prev2 
= table
[step 
- 1][state 
* 2 + 1]; 
 202 fn hamming_distance(first
: &[u8], second
: &[u8]) -> u8 { 
 206         .map(|(x
, y
)| if *x 
== *y 
{ 0 } else { 1 }) 
 210 // maximum 368 type 3 bits, maximum 240 type 1 bits, 4 flush bits 
 211 pub(crate) fn decode( 
 212     type3
: &[u8], // up to len 46 
 214     puncture
: fn(usize) -> (bool
, bool
), 
 215 ) -> Option
<[u8; 30]> { 
 216     let type3_bits 
= Bits
::new(type3
); 
 217     let mut type3_iter 
= type3_bits
.iter
(); 
 218     let mut table 
= [[0u8; 32]; 244]; 
 219     for step 
in 0..(input_len 
+ 4) { 
 220         let (use_g1
, use_g2
) = puncture(step
); 
 221         let split_idx 
= if use_g1 
&& use_g2 
{ 2 } else { 1 }; 
 222         let mut input_bits 
= [0u8; 2]; 
 223         input_bits
[0] = type3_iter
.next().unwrap
(); 
 224         let step_input 
= if split_idx 
== 1 { 
 227             input_bits
[1] = type3_iter
.next().unwrap
(); 
 230         for (t_idx
, t
) in TRANSITIONS
.iter
().enumerate() { 
 231             let t_offer 
= if use_g1 
&& use_g2 
{ 
 238             let step_dist 
= hamming_distance(step_input
, t_offer
); 
 239             table
[step
][t_idx
] = best_previous(&table
, step
, t
.source
).saturating_add(step_dist
); 
 242     let (mut best_idx
, best
) = table
[input_len 
+ 3] 
 245         .min_by_key(|(_
, i
)| *i
) 
 247     debug
!("Best score is {best}, transition {best_idx}"); 
 251         let mut out 
= [0u8; 30]; 
 252         let mut out_bits 
= BitsMut
::new(&mut out
); 
 253         for step 
in (0..(input_len 
+ 4)).rev() { 
 254             let input 
= TRANSITIONS
[best_idx
].inp
ut
; 
 255             if step 
< input_len 
{ 
 256                 out_bits
.set_bit(step
, input
); 
 259                 let state 
= TRANSITIONS
[best_idx
].source
; 
 260                 let prev1 
= table
[step 
- 1][state 
* 2]; 
 261                 let prev2 
= table
[step 
- 1][state 
* 2 + 1]; 
 262                 best_idx 
= if prev1 
< prev2 
{ 
 273 /// Perform convolutional encoding on payload. 
 275 /// Four flush bits will be appended automatically. 
 278 /// * `type1`: Type 1 bits, maximum length 30 bytes 
 279 /// * `input_len`: Number of type 1 bits, up to 240 
 280 /// * `puncture`: Puncturing scheme - `p_1`, `p_2` or `p_3` 
 282 /// Returns up to 368 type 3 bits. Caller is responsible for knowing the number of 
 283 /// filled bits in the returned array, which is known statically by the type of 
 284 /// payload and puncturing scheme in use. 
 285 pub(crate) fn encode( 
 288     puncture
: fn(usize) -> (bool
, bool
), 
 290     let mut out 
= [0u8; 46]; 
 291     let bits 
= Bits
::new(type1
); 
 293     let mut out_bits 
= BitsMut
::new(&mut out
); 
 294     let mut state
: u8 = 0; 
 295     for (t1_idx
, b
) in bits
 
 298         .chain(core
::iter
::repeat_n(0, 4)) 
 301         let (use_g1
, use_g2
) = puncture(t1_idx
); 
 303             let g1 
= (b 
+ ((state 
& 0x02) >> 1) + (state 
& 0x01)) & 0x01; 
 304             out_bits
.set_bit(out_idx
, g1
); 
 308             let g2 
= (b 
+ ((state 
& 0x08) >> 3) + ((state 
& 0x04) >> 2) + (state 
& 0x01)) & 0x01; 
 309             out_bits
.set_bit(out_idx
, g2
); 
 312         state 
= (state 
>> 1) | (b 
<< 3); 
 322     fn lsf_fec_round_trip() { 
 324             255, 255, 255, 255, 255, 255, 0, 0, 0, 159, 221, 81, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 325             0, 0, 0, 0, 0, 131, 53, 
 327         let expected_encoded 
= [ 
 328             222, 73, 36, 146, 73, 37, 182, 219, 109, 76, 0, 0, 0, 5, 191, 47, 25, 186, 30, 214, 
 329             237, 110, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 42, 153, 208, 
 332         let encoded 
= encode(&lsf
, 240, p_1
); 
 333         assert_eq
!(encoded
, expected_encoded
); 
 334         let decoded 
= decode(&encoded
, 240, p_1
); 
 335         assert_eq
!(decoded
, Some(lsf
)); 
 341             255, 255, 255, 255, 255, 255, 0, 0, 0, 159, 221, 81, 5, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
 342             0, 0, 0, 0, 0, 131, 53, 
 344         let mut encoded 
= encode(&lsf
, 240, p_1
); 
 346         // progressively flip more bits 
 347         for idx 
in [50, 90, 51, 200, 15, 7, 100] { 
 348             let mut bits 
= BitsMut
::new(&mut encoded
); 
 349             let bit 
= bits
.get_bit(idx
); 
 350             bits
.set_bit(idx
, if bit 
== 1 { 0 } else { 1 }); 
 351             let decoded 
= decode(&encoded
, 240, p_1
); 
 353                 assert_eq
!(decoded
, None
); // 7 bits is too much damage 
 355                 assert_eq
!(decoded
, Some(lsf
)); // recovered from errors