]>
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