]>
code.octet-stream.net Git - m17rt/blob - m17core/src/modem.rs
1 use crate::decode
::{parse_lsf
, parse_stream
, sync_burst_correlation
, SyncBurst
, SYNC_THRESHOLD
};
2 use crate::protocol
::Frame
;
3 use crate::shaping
::RRC_48K
;
6 pub trait Demodulator
{
7 fn demod(&mut self, sample
: i16) -> Option
<Frame
>;
8 fn data_carrier_detect(&self) -> bool
;
11 /// Converts a sequence of samples into frames.
12 pub struct SoftDemodulator
{
13 /// Circular buffer of incoming samples for calculating the RRC filtered value
14 filter_win
: [i16; 81],
15 /// Current position in filter_win
17 /// Circular buffer of shaped samples for performing decodes based on the last 192 symbols
19 /// Current position in rx_cursor
21 /// A position that we are considering decoding due to decent sync
22 candidate
: Option
<DecodeCandidate
>,
23 /// How many samples have we received?
25 /// Remaining samples to ignore so once we already parse a frame we flush it out in full
29 impl SoftDemodulator
{
30 pub fn new() -> Self {
32 filter_win
: [0i16; 81],
43 impl Demodulator
for SoftDemodulator
{
44 fn demod(&mut self, sample
: i16) -> Option
<Frame
> {
45 self.filter
_w
in
[self.filter
_c
ursor
] = sample
;
46 self.filter
_c
ursor
= (self.filter
_c
ursor
+ 1) % 81;
47 let mut out
: f32 = 0.0;
49 let filter_idx
= (self.filter
_c
ursor
+ i
) % 81;
50 out
+= RRC_48K
[i
] * self.filter
_w
in
[filter_idx
] as f32;
53 self.rx_win
[self.rx_cursor
] = out
;
54 self.rx_cursor
= (self.rx_cursor
+ 1) % 1920;
58 if self.suppress
> 0 {
63 let mut burst_window
= [0f32; 71];
65 let c
= (self.rx_cursor
+ i
) % 1920;
66 burst_window
[i
] = self.rx_win
[c
];
75 let (diff
, max
, shift
) = sync_burst_correlation(burst
.target(), &burst_window
);
76 if diff
< SYNC_THRESHOLD
{
77 let mut new_candidate
= true;
78 if let Some(c
) = self.candidate
.as_mut() {
81 new_candidate
= false;
85 self.candidate
= Some(DecodeCandidate
{
94 if diff
>= SYNC_THRESHOLD
98 .map(|c
| c
.burst
== burst
)
101 if let Some(c
) = self.candidate
.take() {
102 let start_idx
= self.rx_cursor
+ 1920 - (c
.age
as usize);
103 let start_sample
= self.sample
- c
.age
as u64;
104 let mut pkt_samples
= [0f32; 192];
106 let rx_idx
= (start_idx
+ i
* 10) % 1920;
107 pkt_samples
[i
] = (self.rx_win
[rx_idx
] - c
.shift
) / c
.gain
;
112 "Found LSF at sample {} diff {} max {} shift {}",
113 start_sample
, c
.diff
, c
.gain
, c
.shift
115 if let Some(frame
) = parse_lsf(&pkt_samples
) {
116 self.suppress
= 191 * 10;
117 return Some(Frame
::Lsf(frame
));
121 debug
!("Found BERT at sample {} diff {}", start_sample
, c
.diff
);
123 SyncBurst
::Stream
=> {
125 "Found STREAM at sample {} diff {} max {} shift {}",
126 start_sample
, c
.diff
, c
.gain
, c
.shift
128 if let Some(frame
) = parse_stream(&pkt_samples
) {
129 self.suppress
= 191 * 10;
130 return Some(Frame
::Stream(frame
));
133 SyncBurst
::Packet
=> {
134 debug
!("Found PACKET at sample {} diff {}", start_sample
, c
.diff
)
144 fn data_carrier_detect(&self) -> bool
{
149 impl Default
for SoftDemodulator
{
150 fn default() -> Self {
156 pub(crate) struct DecodeCandidate
{