]>
code.octet-stream.net Git - m17rt/blob - m17core/src/decode.rs
3 fec
::{self, p_1
, p_2
, p_3
},
4 interleave
::interleave
,
6 LsfFrame
, PacketFrame
, PacketFrameCounter
, StreamFrame
, BERT_SYNC
, LSF_SYNC
, PACKET_SYNC
,
13 const PLUS_THREE
: [u8; 2] = [0, 1];
14 const PLUS_ONE
: [u8; 2] = [0, 0];
15 const MINUS_ONE
: [u8; 2] = [1, 0];
16 const MINUS_THREE
: [u8; 2] = [1, 1];
18 fn decode_sample(sample
: f32) -> [u8; 2] {
21 } else if sample
> 0.0 {
23 } else if sample
> -0.667 {
30 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
31 pub(crate) enum SyncBurst
{
39 pub(crate) fn target(&self) -> [i8; 8] {
41 Self::Lsf
=> LSF_SYNC
,
42 Self::Bert
=> BERT_SYNC
,
43 Self::Stream
=> STREAM_SYNC
,
44 Self::Packet
=> PACKET_SYNC
,
49 const SYNC_MIN_GAIN
: f32 = 16.0;
50 const SYNC_BIT_THRESHOLD
: f32 = 0.3;
51 pub const SYNC_THRESHOLD
: f32 = 100.0;
53 pub(crate) fn sync_burst_correlation(target
: [i8; 8], samples
: &[f32]) -> (f32, f32, f32) {
54 let mut pos_max
: f32 = f32::MIN
;
55 let mut neg_max
: f32 = f32::MAX
;
57 pos_max
= pos_max
.max(samples
[i
* 10]);
58 neg_max
= neg_max
.min(samples
[i
* 10]);
60 let gain
= (pos_max
- neg_max
) / 2.0;
61 let shift
= pos_max
+ neg_max
;
62 if gain
< SYNC_MIN_GAIN
{
63 return (f32::MAX
, gain
, shift
);
67 let sym_diff
= (((samples
[i
* 10] - shift
) / gain
) - target
[i
] as f32).abs();
68 if sym_diff
> SYNC_BIT_THRESHOLD
{
69 return (f32::MAX
, gain
, shift
);
76 /// Decode frame and return contents after the sync burst
77 pub(crate) fn frame_initial_decode(frame
: &[f32] /* length 192 */) -> [u8; 46] {
78 let mut decoded
= [0u8; 48];
79 let mut decoded_bits
= BitsMut
::new(&mut decoded
);
80 for (idx
, s
) in frame
.iter
().enumerate() {
81 let dibits
= decode_sample(*s
);
82 decoded_bits
.set_bit(idx
* 2, dibits
[0]);
83 decoded_bits
.set_bit(idx
* 2 + 1, dibits
[1]);
85 random_xor(&mut decoded
[2..]);
86 interleave(&decoded
[2..])
89 pub(crate) fn parse_lsf(frame
: &[f32] /* length 192 */) -> Option
<LsfFrame
> {
90 let deinterleaved
= frame_initial_decode(frame
);
91 debug
!("deinterleaved: {:?}", deinterleaved
);
92 let lsf
= match fec
::decode(&deinterleaved
, 240, p_1
) {
93 Some(lsf
) => LsfFrame(lsf
),
96 debug
!("full lsf: {:?}", lsf
.0);
97 let crc
= lsf
.check_crc();
98 debug
!("recv crc: {:04X}", crc
);
99 debug
!("destination: {:?}", lsf
.destination());
100 debug
!("source: {:?}", lsf
.source());
101 debug
!("mode: {:?}", lsf
.mode());
102 debug
!("data type: {:?}", lsf
.data_type());
103 debug
!("encryption type: {:?}", lsf
.encryption_type());
104 debug
!("can: {}", lsf
.channel_access_number());
105 debug
!("meta: {:?}", lsf
.meta());
109 pub(crate) fn parse_stream(frame
: &[f32] /* length 192 */) -> Option
<StreamFrame
> {
110 let deinterleaved
= frame_initial_decode(frame
);
111 let stream_part
= &deinterleaved
[12..];
112 let stream
= match fec
::decode(stream_part
, 144, p_2
) {
113 Some(stream
) => stream
,
116 let frame_num
= u16::from_be_bytes([stream
[0], stream
[1]]);
117 let eos
= (frame_num
& 0x8000) > 0;
118 let frame_num
= frame_num
& 0x7fff; // higher layer has to handle wraparound
119 debug
!("frame number: {frame_num}, codec2: {:?}", &stream
[2..18]);
121 if let Some((counter
, part
)) = decode_lich(&deinterleaved
[0..12]) {
123 "LICH: received part {counter} part {part:?} from raw {:?}",
124 &deinterleaved
[0..12]
129 frame_number
: frame_num
,
131 stream_data
: stream
[2..18].try_into().unwrap
(),
138 pub(crate) fn parse_packet(frame
: &[f32] /* length 192 */) -> Option
<PacketFrame
> {
139 let deinterleaved
= frame_initial_decode(frame
);
140 let packet
= match fec
::decode(&deinterleaved
, 206, p_3
) {
141 Some(packet
) => packet
,
144 // TODO: the spec is inconsistent about which bit in packet[25] is EOF
145 // https://github.com/M17-Project/M17_spec/issues/147
146 let final_frame
= (packet
[25] & 0x04) > 0;
147 let number
= packet
[25] >> 3;
148 let counter
= if final_frame
{
149 PacketFrameCounter
::FinalFrame
{
150 payload_len
: number
as usize,
153 PacketFrameCounter
::Frame
{
154 index
: number
as usize,
158 payload
: packet
[0..25].try_into().unwrap
(),
163 pub(crate) fn decode_lich(type2_bits
: &[u8]) -> Option
<(u8, [u8; 5])> {
164 let mut decoded
= 0u64;
165 for (input_idx
, input_bytes
) in type2_bits
.chunks(3).enumerate() {
166 let mut input
: u32 = 0;
167 for (idx
, byte
) in input_bytes
.iter
().enumerate() {
168 input
|= (*byte
as u32) << (16 - (8 * idx
));
170 let (val
, _dist
) = cai_golay
::extended
::decode(input
)?
;
171 decoded
|= (val
as u64) << ((3 - input_idx
) * 12);
173 let b
= decoded
.to_be_bytes();
174 Some((b
[7] >> 5, [b
[2], b
[3], b
[4], b
[5], b
[6]]))
182 fn test_lich_decode() {
183 let input
= [221, 82, 162, 16, 85, 200, 5, 14, 254, 4, 13, 153];
184 let expected_counter
= 2;
185 let expected_part
= [221, 81, 5, 5, 0];
186 assert_eq
!(decode_lich(&input
), Some((expected_counter
, expected_part
)));