]>
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
, END_OF_TRANSMISSION
,
7 LSF_SYNC
, PACKET_SYNC
, PREAMBLE
, STREAM_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
{
41 pub(crate) fn target(&self) -> [i8; 8] {
43 Self::Lsf
=> LSF_SYNC
,
44 Self::Bert
=> BERT_SYNC
,
45 Self::Stream
=> STREAM_SYNC
,
46 Self::Packet
=> PACKET_SYNC
,
47 Self::Preamble
=> PREAMBLE
,
48 Self::EndOfTransmission
=> END_OF_TRANSMISSION
,
53 const SYNC_MIN_GAIN
: f32 = 16.0;
54 const SYNC_BIT_THRESHOLD
: f32 = 0.3;
55 pub const SYNC_THRESHOLD
: f32 = 100.0;
57 pub(crate) fn sync_burst_correlation(target
: [i8; 8], samples
: &[f32]) -> (f32, f32, f32) {
58 let mut pos_max
: f32 = f32::MIN
;
59 let mut neg_max
: f32 = f32::MAX
;
61 pos_max
= pos_max
.max(samples
[i
]);
62 neg_max
= neg_max
.min(samples
[i
]);
64 let gain
= (pos_max
- neg_max
) / 2.0;
65 let shift
= pos_max
+ neg_max
;
66 if gain
< SYNC_MIN_GAIN
{
67 return (f32::MAX
, gain
, shift
);
72 let sym_diff
= (((samples
[i
] - shift
) / gain
) - target
[i
] as f32).abs();
73 if sym_diff
> SYNC_BIT_THRESHOLD
{
74 return (f32::MAX
, gain
, shift
);
81 /// Decode frame and return contents after the sync burst
82 pub(crate) fn frame_initial_decode(frame
: &[f32] /* length 192 */) -> [u8; 46] {
83 let mut decoded
= [0u8; 48];
84 let mut decoded_bits
= BitsMut
::new(&mut decoded
);
85 for (idx
, s
) in frame
.iter
().enumerate() {
86 let dibits
= decode_sample(*s
);
87 decoded_bits
.set_bit(idx
* 2, dibits
[0]);
88 decoded_bits
.set_bit(idx
* 2 + 1, dibits
[1]);
90 random_xor(&mut decoded
[2..]);
91 interleave(&decoded
[2..])
94 pub(crate) fn parse_lsf(frame
: &[f32] /* length 192 */) -> Option
<LsfFrame
> {
95 let deinterleaved
= frame_initial_decode(frame
);
96 debug
!("deinterleaved: {:?}", deinterleaved
);
97 let lsf
= match fec
::decode(&deinterleaved
, 240, p_1
) {
98 Some(lsf
) => LsfFrame(lsf
),
101 debug
!("full lsf: {:?}", lsf
.0);
102 let crc
= lsf
.check_crc();
103 debug
!("recv crc: {:04X}", crc
);
104 debug
!("destination: {:?}", lsf
.destination());
105 debug
!("source: {:?}", lsf
.source());
106 debug
!("mode: {:?}", lsf
.mode());
107 debug
!("data type: {:?}", lsf
.data_type());
108 debug
!("encryption type: {:?}", lsf
.encryption_type());
109 debug
!("can: {}", lsf
.channel_access_number());
110 debug
!("meta: {:?}", lsf
.meta());
114 pub(crate) fn parse_stream(frame
: &[f32] /* length 192 */) -> Option
<StreamFrame
> {
115 let deinterleaved
= frame_initial_decode(frame
);
116 let stream_part
= &deinterleaved
[12..];
117 let stream
= match fec
::decode(stream_part
, 144, p_2
) {
118 Some(stream
) => stream
,
121 let frame_num
= u16::from_be_bytes([stream
[0], stream
[1]]);
122 let eos
= (frame_num
& 0x8000) > 0;
123 let frame_num
= frame_num
& 0x7fff; // higher layer has to handle wraparound
124 debug
!("frame number: {frame_num}, codec2: {:?}", &stream
[2..18]);
126 if let Some((counter
, part
)) = decode_lich(&deinterleaved
[0..12]) {
128 "LICH: received part {counter} part {part:?} from raw {:?}",
129 &deinterleaved
[0..12]
134 frame_number
: frame_num
,
136 stream_data
: stream
[2..18].try_into().unwrap
(),
143 pub(crate) fn parse_packet(frame
: &[f32] /* length 192 */) -> Option
<PacketFrame
> {
144 let deinterleaved
= frame_initial_decode(frame
);
145 let packet
= match fec
::decode(&deinterleaved
, 206, p_3
) {
146 Some(packet
) => packet
,
149 // TODO: the spec is inconsistent about which bit in packet[25] is EOF
150 // https://github.com/M17-Project/M17_spec/issues/147
151 let final_frame
= (packet
[25] & 0x80) > 0;
152 let number
= (packet
[25] >> 2) & 0x1f;
153 let counter
= if final_frame
{
154 PacketFrameCounter
::FinalFrame
{
155 payload_len
: number
as usize,
158 PacketFrameCounter
::Frame
{
159 index
: number
as usize,
163 payload
: packet
[0..25].try_into().unwrap
(),
168 pub(crate) fn decode_lich(type2_bits
: &[u8]) -> Option
<(u8, [u8; 5])> {
169 let mut decoded
= 0u64;
170 for (input_idx
, input_bytes
) in type2_bits
.chunks(3).enumerate() {
171 let mut input
: u32 = 0;
172 for (idx
, byte
) in input_bytes
.iter
().enumerate() {
173 input
|= (*byte
as u32) << (16 - (8 * idx
));
175 let (val
, _dist
) = cai_golay
::extended
::decode(input
)?
;
176 decoded
|= (val
as u64) << ((3 - input_idx
) * 12);
178 let b
= decoded
.to_be_bytes();
179 Some((b
[7] >> 5, [b
[2], b
[3], b
[4], b
[5], b
[6]]))
187 fn test_lich_decode() {
188 let input
= [221, 82, 162, 16, 85, 200, 5, 14, 254, 4, 13, 153];
189 let expected_counter
= 2;
190 let expected_part
= [221, 81, 5, 5, 0];
191 assert_eq
!(decode_lich(&input
), Some((expected_counter
, expected_part
)));