]>
code.octet-stream.net Git - m17rt/blob - m17core/src/modem.rs
2 parse_lsf
, parse_packet
, parse_stream
, sync_burst_correlation
, SyncBurst
, SYNC_THRESHOLD
,
4 use crate::protocol
::Frame
;
5 use crate::shaping
::RRC_48K
;
8 pub trait Demodulator
{
9 fn demod(&mut self, sample
: i16) -> Option
<Frame
>;
10 fn data_carrier_detect(&self) -> bool
;
13 /// Converts a sequence of samples into frames.
14 pub struct SoftDemodulator
{
15 /// Circular buffer of incoming samples for calculating the RRC filtered value
16 filter_win
: [i16; 81],
17 /// Current position in filter_win
19 /// Circular buffer of shaped samples for performing decodes based on the last 192 symbols
21 /// Current position in rx_cursor
23 /// A position that we are considering decoding due to decent sync
24 candidate
: Option
<DecodeCandidate
>,
25 /// How many samples have we received?
27 /// Remaining samples to ignore so once we already parse a frame we flush it out in full
31 impl SoftDemodulator
{
32 pub fn new() -> Self {
34 filter_win
: [0i16; 81],
45 impl Demodulator
for SoftDemodulator
{
46 fn demod(&mut self, sample
: i16) -> Option
<Frame
> {
47 self.filter
_w
in
[self.filter
_c
ursor
] = sample
;
48 self.filter
_c
ursor
= (self.filter
_c
ursor
+ 1) % 81;
49 let mut out
: f32 = 0.0;
51 let filter_idx
= (self.filter
_c
ursor
+ i
) % 81;
52 out
+= RRC_48K
[i
] * self.filter
_w
in
[filter_idx
] as f32;
55 self.rx_win
[self.rx_cursor
] = out
;
56 self.rx_cursor
= (self.rx_cursor
+ 1) % 1920;
60 if self.suppress
> 0 {
65 let mut burst_window
= [0f32; 71];
67 let c
= (self.rx_cursor
+ i
) % 1920;
68 burst_window
[i
] = self.rx_win
[c
];
77 let (diff
, max
, shift
) = sync_burst_correlation(burst
.target(), &burst_window
);
78 if diff
< SYNC_THRESHOLD
{
79 let mut new_candidate
= true;
80 if let Some(c
) = self.candidate
.as_mut() {
83 new_candidate
= false;
87 self.candidate
= Some(DecodeCandidate
{
96 if diff
>= SYNC_THRESHOLD
100 .map(|c
| c
.burst
== burst
)
103 if let Some(c
) = self.candidate
.take() {
104 let start_idx
= self.rx_cursor
+ 1920 - (c
.age
as usize);
105 let start_sample
= self.sample
- c
.age
as u64;
106 let mut pkt_samples
= [0f32; 192];
108 let rx_idx
= (start_idx
+ i
* 10) % 1920;
109 pkt_samples
[i
] = (self.rx_win
[rx_idx
] - c
.shift
) / c
.gain
;
114 "Found LSF at sample {} diff {} max {} shift {}",
115 start_sample
, c
.diff
, c
.gain
, c
.shift
117 if let Some(frame
) = parse_lsf(&pkt_samples
) {
118 self.suppress
= 191 * 10;
119 return Some(Frame
::Lsf(frame
));
123 debug
!("Found BERT at sample {} diff {}", start_sample
, c
.diff
);
125 SyncBurst
::Stream
=> {
127 "Found STREAM at sample {} diff {} max {} shift {}",
128 start_sample
, c
.diff
, c
.gain
, c
.shift
130 if let Some(frame
) = parse_stream(&pkt_samples
) {
131 self.suppress
= 191 * 10;
132 return Some(Frame
::Stream(frame
));
135 SyncBurst
::Packet
=> {
136 debug
!("Found PACKET at sample {} diff {}", start_sample
, c
.diff
);
137 if let Some(frame
) = parse_packet(&pkt_samples
) {
138 self.suppress
= 191 * 10;
139 return Some(Frame
::Packet(frame
));
150 fn data_carrier_detect(&self) -> bool
{
155 impl Default
for SoftDemodulator
{
156 fn default() -> Self {
162 pub(crate) struct DecodeCandidate
{