2021-01-03 03:59:59 +00:00
|
|
|
// Copyright 2020-2021 Rob Riggs <rob@mobilinkd.com>
|
|
|
|
// All rights reserved.
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
#include "Demodulator.hpp"
|
|
|
|
#include "AfskDemodulator.hpp"
|
|
|
|
#include "FirFilter.hpp"
|
|
|
|
#include "FilterCoefficients.hpp"
|
|
|
|
#include "KissHardware.hpp"
|
|
|
|
#include "HdlcFrame.hpp"
|
|
|
|
|
|
|
|
namespace mobilinkd { namespace tnc {
|
|
|
|
|
|
|
|
struct Afsk1200Demodulator : IDemodulator
|
|
|
|
{
|
|
|
|
/*
|
|
|
|
* Generated with Scipy Filter, 152 coefficients, 1100-2300Hz bandpass,
|
|
|
|
* Hann window, starting and ending 0 value coefficients removed.
|
|
|
|
*
|
|
|
|
* np.array(
|
|
|
|
* firwin2(152,
|
|
|
|
* [
|
|
|
|
* 0.0,
|
|
|
|
* 1000.0/(sample_rate/2),
|
|
|
|
* 1100.0/(sample_rate/2),
|
|
|
|
* 2350.0/(sample_rate/2),
|
|
|
|
* 2500.0/(sample_rate/2),
|
|
|
|
* 1.0
|
|
|
|
* ],
|
|
|
|
* [0,0,1,1,0,0],
|
|
|
|
* antisymmetric = False,
|
|
|
|
* window='hann') * 32768,
|
|
|
|
* dtype=int)[10:-10]
|
|
|
|
*/
|
|
|
|
static constexpr size_t FILTER_TAP_NUM = 132;
|
|
|
|
static constexpr uint32_t ADC_BLOCK_SIZE = afsk1200::ADC_BUFFER_SIZE;
|
|
|
|
static_assert(audio::ADC_BUFFER_SIZE >= ADC_BLOCK_SIZE);
|
|
|
|
|
|
|
|
static constexpr uint32_t SAMPLE_RATE = 26400;
|
|
|
|
static constexpr uint16_t VREF = 16383;
|
|
|
|
|
|
|
|
using audio_filter_t = Q15FirFilter<ADC_BLOCK_SIZE, FILTER_TAP_NUM>;
|
|
|
|
|
|
|
|
static const q15_t bpf_coeffs[FILTER_TAP_NUM];
|
|
|
|
|
|
|
|
static afsk1200::emphasis_filter_type filter_1;
|
|
|
|
static afsk1200::emphasis_filter_type filter_2;
|
|
|
|
static afsk1200::emphasis_filter_type filter_3;
|
|
|
|
|
|
|
|
static afsk1200::Demodulator demod1;
|
|
|
|
static afsk1200::Demodulator demod2;
|
|
|
|
static afsk1200::Demodulator demod3;
|
|
|
|
|
|
|
|
audio_filter_t demod_filter;
|
|
|
|
uint16_t last_fcs{0};
|
|
|
|
uint32_t last_counter{0};
|
|
|
|
uint32_t counter{0};
|
|
|
|
bool locked_{false};
|
|
|
|
|
|
|
|
virtual ~Afsk1200Demodulator() {}
|
|
|
|
|
|
|
|
void start() override
|
|
|
|
{
|
|
|
|
INFO("Setting 48MHz SysClock.");
|
|
|
|
SysClock48();
|
|
|
|
|
|
|
|
// rx_twist is 6dB for discriminator input and 0db for de-emphasized input.
|
|
|
|
auto twist = kiss::settings().rx_twist;
|
|
|
|
|
2021-07-01 01:16:15 +00:00
|
|
|
filter_1.init(filter::fir::AfskFilters[twist + 3]->taps);
|
|
|
|
filter_2.init(filter::fir::AfskFilters[twist + 6]->taps);
|
|
|
|
filter_3.init(filter::fir::AfskFilters[twist + 9]->taps);
|
2021-01-03 03:59:59 +00:00
|
|
|
|
|
|
|
last_fcs = 0;
|
|
|
|
last_counter = 0;
|
|
|
|
counter = 0;
|
|
|
|
|
|
|
|
demod_filter.init(bpf_coeffs);
|
|
|
|
passall(kiss::settings().options & KISS_OPTION_PASSALL);
|
|
|
|
|
|
|
|
hadc1.Init.OversamplingMode = ENABLE;
|
|
|
|
if (HAL_ADC_Init(&hadc1) != HAL_OK)
|
|
|
|
{
|
|
|
|
CxxErrorHandler();
|
|
|
|
}
|
|
|
|
|
|
|
|
ADC_ChannelConfTypeDef sConfig;
|
|
|
|
|
|
|
|
sConfig.Channel = AUDIO_IN;
|
|
|
|
sConfig.Rank = ADC_REGULAR_RANK_1;
|
|
|
|
sConfig.SingleDiff = ADC_SINGLE_ENDED;
|
2021-06-22 01:58:26 +00:00
|
|
|
sConfig.SamplingTime = ADC_SAMPLETIME_24CYCLES_5;
|
2021-01-03 03:59:59 +00:00
|
|
|
sConfig.OffsetNumber = ADC_OFFSET_NONE;
|
|
|
|
sConfig.Offset = 0;
|
|
|
|
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
|
|
|
|
CxxErrorHandler();
|
|
|
|
startADC(1817, ADC_BLOCK_SIZE);
|
|
|
|
}
|
|
|
|
|
|
|
|
void stop() override
|
|
|
|
{
|
|
|
|
stopADC();
|
|
|
|
locked_ = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
hdlc::IoFrame* operator()(const q15_t* samples) override;
|
|
|
|
|
|
|
|
float readTwist() override;
|
|
|
|
|
|
|
|
uint32_t readBatteryLevel() override;
|
|
|
|
|
|
|
|
bool locked() const override
|
|
|
|
{
|
|
|
|
return locked_;
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t size() const override
|
|
|
|
{
|
|
|
|
return ADC_BLOCK_SIZE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void passall(bool enabled) override
|
|
|
|
{
|
|
|
|
demod1.hdlc_decoder_.setPassall(enabled);
|
|
|
|
demod2.hdlc_decoder_.setPassall(enabled);
|
|
|
|
demod3.hdlc_decoder_.setPassall(enabled);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
}} // mobilinkd::tnc
|