]>
code.octet-stream.net Git - m17rt/blob - m17core/src/decode.rs
115ff63fbf9101c9507143f38ff91ac1a01e5da2
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
);
68 let sym_diff
= (((samples
[i
* 10] - shift
) / gain
) - target
[i
] as f32).abs();
69 if sym_diff
> SYNC_BIT_THRESHOLD
{
70 return (f32::MAX
, gain
, shift
);
77 /// Decode frame and return contents after the sync burst
78 pub(crate) fn frame_initial_decode(frame
: &[f32] /* length 192 */) -> [u8; 46] {
79 let mut decoded
= [0u8; 48];
80 let mut decoded_bits
= BitsMut
::new(&mut decoded
);
81 for (idx
, s
) in frame
.iter
().enumerate() {
82 let dibits
= decode_sample(*s
);
83 decoded_bits
.set_bit(idx
* 2, dibits
[0]);
84 decoded_bits
.set_bit(idx
* 2 + 1, dibits
[1]);
86 random_xor(&mut decoded
[2..]);
87 interleave(&decoded
[2..])
90 pub(crate) fn parse_lsf(frame
: &[f32] /* length 192 */) -> Option
<LsfFrame
> {
91 let deinterleaved
= frame_initial_decode(frame
);
92 debug
!("deinterleaved: {:?}", deinterleaved
);
93 let lsf
= match fec
::decode(&deinterleaved
, 240, p_1
) {
94 Some(lsf
) => LsfFrame(lsf
),
97 debug
!("full lsf: {:?}", lsf
.0);
98 let crc
= lsf
.check_crc();
99 debug
!("recv crc: {:04X}", crc
);
100 debug
!("destination: {:?}", lsf
.destination());
101 debug
!("source: {:?}", lsf
.source());
102 debug
!("mode: {:?}", lsf
.mode());
103 debug
!("data type: {:?}", lsf
.data_type());
104 debug
!("encryption type: {:?}", lsf
.encryption_type());
105 debug
!("can: {}", lsf
.channel_access_number());
106 debug
!("meta: {:?}", lsf
.meta());
110 pub(crate) fn parse_stream(frame
: &[f32] /* length 192 */) -> Option
<StreamFrame
> {
111 let deinterleaved
= frame_initial_decode(frame
);
112 let stream_part
= &deinterleaved
[12..];
113 let stream
= match fec
::decode(stream_part
, 144, p_2
) {
114 Some(stream
) => stream
,
117 let frame_num
= u16::from_be_bytes([stream
[0], stream
[1]]);
118 let eos
= (frame_num
& 0x8000) > 0;
119 let frame_num
= frame_num
& 0x7fff; // higher layer has to handle wraparound
120 debug
!("frame number: {frame_num}, codec2: {:?}", &stream
[2..18]);
122 if let Some((counter
, part
)) = decode_lich(&deinterleaved
[0..12]) {
124 "LICH: received part {counter} part {part:?} from raw {:?}",
125 &deinterleaved
[0..12]
130 frame_number
: frame_num
,
132 stream_data
: stream
[2..18].try_into().unwrap
(),
139 pub(crate) fn parse_packet(frame
: &[f32] /* length 192 */) -> Option
<PacketFrame
> {
140 let deinterleaved
= frame_initial_decode(frame
);
141 let packet
= match fec
::decode(&deinterleaved
, 206, p_3
) {
142 Some(packet
) => packet
,
145 // TODO: the spec is inconsistent about which bit in packet[25] is EOF
146 // https://github.com/M17-Project/M17_spec/issues/147
147 let final_frame
= (packet
[25] & 0x04) > 0;
148 let number
= packet
[25] >> 3;
149 let counter
= if final_frame
{
150 PacketFrameCounter
::FinalFrame
{
151 payload_len
: number
as usize,
154 PacketFrameCounter
::Frame
{
155 index
: number
as usize,
159 payload
: packet
[0..25].try_into().unwrap
(),
164 pub(crate) fn decode_lich(type2_bits
: &[u8]) -> Option
<(u8, [u8; 5])> {
165 let mut decoded
= 0u64;
166 for (input_idx
, input_bytes
) in type2_bits
.chunks(3).enumerate() {
167 let mut input
: u32 = 0;
168 for (idx
, byte
) in input_bytes
.iter
().enumerate() {
169 input
|= (*byte
as u32) << (16 - (8 * idx
));
171 let (val
, _dist
) = cai_golay
::extended
::decode(input
)?
;
172 decoded
|= (val
as u64) << ((3 - input_idx
) * 12);
174 let b
= decoded
.to_be_bytes();
175 Some((b
[7] >> 5, [b
[2], b
[3], b
[4], b
[5], b
[6]]))
183 fn test_lich_decode() {
184 let input
= [221, 82, 162, 16, 85, 200, 5, 14, 254, 4, 13, 153];
185 let expected_counter
= 2;
186 let expected_part
= [221, 81, 5, 5, 0];
187 assert_eq
!(decode_lich(&input
), Some((expected_counter
, expected_part
)));