kopia lustrzana https://github.com/mobilinkd/tnc3-firmware
Add passall setter. Move battery level code to demodulators because they own the ADC.
rodzic
32111251f8
commit
5503b329e8
|
@ -4,6 +4,7 @@
|
|||
#include "Afsk1200Demodulator.hpp"
|
||||
#include "Goertzel.h"
|
||||
#include "AudioInput.hpp"
|
||||
#include "GPIO.hpp"
|
||||
|
||||
namespace mobilinkd { namespace tnc {
|
||||
|
||||
|
@ -85,7 +86,6 @@ hdlc::IoFrame* Afsk1200Demodulator::operator()(const q15_t* samples)
|
|||
float Afsk1200Demodulator::readTwist()
|
||||
{
|
||||
DEBUG("enter Afsk1200Demodulator::readTwist");
|
||||
constexpr uint32_t channel = AUDIO_IN;
|
||||
|
||||
float g1200 = 0.0f;
|
||||
float g2200 = 0.0f;
|
||||
|
@ -137,6 +137,78 @@ float Afsk1200Demodulator::readTwist()
|
|||
return result;
|
||||
}
|
||||
|
||||
uint32_t Afsk1200Demodulator::readBatteryLevel()
|
||||
{
|
||||
DEBUG("enter Afsk1200Demodulator::readBatteryLevel");
|
||||
|
||||
ADC_ChannelConfTypeDef sConfig;
|
||||
|
||||
sConfig.Channel = ADC_CHANNEL_VREFINT;
|
||||
sConfig.Rank = ADC_REGULAR_RANK_1;
|
||||
sConfig.SingleDiff = ADC_SINGLE_ENDED;
|
||||
sConfig.SamplingTime = ADC_SAMPLETIME_92CYCLES_5;
|
||||
sConfig.OffsetNumber = ADC_OFFSET_NONE;
|
||||
sConfig.Offset = 0;
|
||||
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
|
||||
CxxErrorHandler();
|
||||
|
||||
htim6.Init.Period = 48000;
|
||||
if (HAL_TIM_Base_Init(&htim6) != HAL_OK) CxxErrorHandler();
|
||||
|
||||
if (HAL_TIM_Base_Start(&htim6) != HAL_OK)
|
||||
CxxErrorHandler();
|
||||
|
||||
if (HAL_ADC_Start(&hadc1) != HAL_OK) CxxErrorHandler();
|
||||
if (HAL_ADC_PollForConversion(&hadc1, 3) != HAL_OK) CxxErrorHandler();
|
||||
auto vrefint = HAL_ADC_GetValue(&hadc1);
|
||||
if (HAL_ADC_Stop(&hadc1) != HAL_OK) CxxErrorHandler();
|
||||
|
||||
// Disable battery charging while measuring battery voltage.
|
||||
auto usb_ce = gpio::USB_CE::get();
|
||||
gpio::USB_CE::on();
|
||||
|
||||
gpio::BAT_DIVIDER::off();
|
||||
HAL_Delay(1);
|
||||
|
||||
sConfig.Channel = ADC_CHANNEL_15;
|
||||
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
|
||||
CxxErrorHandler();
|
||||
|
||||
uint32_t vbat = 0;
|
||||
if (HAL_ADC_Start(&hadc1) != HAL_OK) CxxErrorHandler();
|
||||
for (size_t i = 0; i != 8; ++i)
|
||||
{
|
||||
if (HAL_ADC_PollForConversion(&hadc1, 1) != HAL_OK) CxxErrorHandler();
|
||||
vbat += HAL_ADC_GetValue(&hadc1);
|
||||
}
|
||||
|
||||
vbat /= 8;
|
||||
|
||||
if (HAL_ADC_Stop(&hadc1) != HAL_OK) CxxErrorHandler();
|
||||
if (HAL_TIM_Base_Stop(&htim6) != HAL_OK)
|
||||
CxxErrorHandler();
|
||||
|
||||
gpio::BAT_DIVIDER::on();
|
||||
|
||||
// Restore battery charging state.
|
||||
if (!usb_ce) gpio::USB_CE::off();
|
||||
|
||||
INFO("Vref = %lu", vrefint);
|
||||
INFO("Vbat = %lu (raw)", vbat);
|
||||
|
||||
// Order of operations is important to avoid underflow.
|
||||
vbat *= 6600;
|
||||
vbat /= (vrefint + 1);
|
||||
|
||||
uint32_t vref = (vrefint * 3300) + (VREF / 2) / VREF;
|
||||
|
||||
INFO("Vref = %lumV", vref)
|
||||
INFO("Vbat = %lumV", vbat);
|
||||
|
||||
DEBUG("exit Afsk1200Demodulator::readBatteryLevel");
|
||||
return vbat;
|
||||
}
|
||||
|
||||
const q15_t Afsk1200Demodulator::bpf_coeffs[FILTER_TAP_NUM] = {
|
||||
4, 0, -5, -10, -13, -12, -9, -4, -2, -4, -12, -26,
|
||||
-41, -52, -51, -35, -3, 39, 83, 117, 131, 118, 83, 36,
|
||||
|
|
|
@ -109,6 +109,8 @@ struct Afsk1200Demodulator : IDemodulator
|
|||
|
||||
float readTwist() override;
|
||||
|
||||
uint32_t readBatteryLevel() override;
|
||||
|
||||
bool locked() const override
|
||||
{
|
||||
return locked_;
|
||||
|
@ -119,11 +121,11 @@ struct Afsk1200Demodulator : IDemodulator
|
|||
return ADC_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
void passall(bool enable) override
|
||||
void passall(bool enabled) override
|
||||
{
|
||||
demod1.hdlc_decoder_.passall = enable;
|
||||
demod2.hdlc_decoder_.passall = enable;
|
||||
demod3.hdlc_decoder_.passall = enable;
|
||||
demod1.hdlc_decoder_.setPassall(enabled);
|
||||
demod2.hdlc_decoder_.setPassall(enabled);
|
||||
demod3.hdlc_decoder_.setPassall(enabled);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "PortInterface.hpp"
|
||||
#include "Goertzel.h"
|
||||
#include "DCD.h"
|
||||
#include "ModulatorTask.hpp"
|
||||
|
||||
#include "arm_math.h"
|
||||
#include "stm32l4xx_hal.h"
|
||||
|
@ -113,6 +114,7 @@ extern "C" void startAudioInputTask(void const*) {
|
|||
case UPDATE_SETTINGS:
|
||||
DEBUG("UPDATE_SETTINGS");
|
||||
setAudioInputLevels();
|
||||
updateModulator();
|
||||
break;
|
||||
case IDLE:
|
||||
DEBUG("IDLE");
|
||||
|
@ -126,9 +128,9 @@ extern "C" void startAudioInputTask(void const*) {
|
|||
namespace mobilinkd { namespace tnc { namespace audio {
|
||||
|
||||
uint32_t adc_buffer[ADC_BUFFER_SIZE]; // Two samples per element.
|
||||
uint32_t adc_block_size = ADC_BUFFER_SIZE; // Based on demodulator.
|
||||
uint32_t dma_transfer_size = adc_block_size * 2; // Transfer size in bytes.
|
||||
uint32_t half_buffer_size = adc_block_size / 2; // Transfer size in words / 2.
|
||||
volatile uint32_t adc_block_size = ADC_BUFFER_SIZE; // Based on demodulator.
|
||||
volatile uint32_t dma_transfer_size = adc_block_size * 2; // Transfer size in bytes.
|
||||
volatile uint32_t half_buffer_size = adc_block_size / 2; // Transfer size in words / 2.
|
||||
adc_pool_type adcPool;
|
||||
|
||||
void set_adc_block_size(uint32_t block_size)
|
||||
|
@ -208,7 +210,7 @@ void demodulatorTask() {
|
|||
}
|
||||
|
||||
|
||||
void streamLevels(uint32_t channel, uint8_t cmd) {
|
||||
void streamLevels(uint8_t cmd) {
|
||||
|
||||
// Stream out Vpp, Vavg, Vmin, Vmax as four 16-bit values, left justified.
|
||||
|
||||
|
@ -307,7 +309,7 @@ levels_type readLevels(uint32_t)
|
|||
|
||||
uint16_t pp = vmax - vmin;
|
||||
uint16_t avg = iaccum / BLOCKS;
|
||||
DEBUG("exit readLevels");
|
||||
INFO("exit readLevels");
|
||||
|
||||
return levels_type(pp, avg, vmin, vmax);
|
||||
}
|
||||
|
@ -352,7 +354,6 @@ float readTwist()
|
|||
void pollInputTwist()
|
||||
{
|
||||
DEBUG("enter pollInputTwist");
|
||||
constexpr uint32_t channel = AUDIO_IN;
|
||||
|
||||
float g1200 = 0.0f;
|
||||
float g2200 = 0.0f;
|
||||
|
@ -411,7 +412,7 @@ void pollInputTwist()
|
|||
|
||||
void streamAmplifiedInputLevels() {
|
||||
DEBUG("enter streamAmplifiedInputLevels");
|
||||
streamLevels(AUDIO_IN, kiss::hardware::POLL_INPUT_LEVEL);
|
||||
streamLevels(kiss::hardware::POLL_INPUT_LEVEL);
|
||||
DEBUG("exit streamAmplifiedInputLevels");
|
||||
}
|
||||
|
||||
|
@ -441,72 +442,9 @@ void pollAmplifiedInputLevel() {
|
|||
DEBUG("exit pollAmplifiedInputLevel");
|
||||
}
|
||||
|
||||
void pollBatteryLevel() {
|
||||
DEBUG("enter pollBatteryLevel");
|
||||
|
||||
ADC_ChannelConfTypeDef sConfig;
|
||||
|
||||
sConfig.Channel = ADC_CHANNEL_VREFINT;
|
||||
sConfig.Rank = ADC_REGULAR_RANK_1;
|
||||
sConfig.SingleDiff = ADC_SINGLE_ENDED;
|
||||
sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5;
|
||||
sConfig.OffsetNumber = ADC_OFFSET_NONE;
|
||||
sConfig.Offset = 0;
|
||||
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
|
||||
CxxErrorHandler();
|
||||
|
||||
htim6.Init.Period = 48000;
|
||||
if (HAL_TIM_Base_Init(&htim6) != HAL_OK) CxxErrorHandler();
|
||||
|
||||
if (HAL_TIM_Base_Start(&htim6) != HAL_OK)
|
||||
CxxErrorHandler();
|
||||
|
||||
if (HAL_ADC_Start(&hadc1) != HAL_OK) CxxErrorHandler();
|
||||
if (HAL_ADC_PollForConversion(&hadc1, 3) != HAL_OK) CxxErrorHandler();
|
||||
auto vrefint = HAL_ADC_GetValue(&hadc1);
|
||||
if (HAL_ADC_Stop(&hadc1) != HAL_OK) CxxErrorHandler();
|
||||
|
||||
// Disable battery charging while measuring battery voltage.
|
||||
auto usb_ce = gpio::USB_CE::get();
|
||||
gpio::USB_CE::on();
|
||||
|
||||
gpio::BAT_DIVIDER::off();
|
||||
HAL_Delay(1);
|
||||
|
||||
sConfig.Channel = ADC_CHANNEL_15;
|
||||
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
|
||||
CxxErrorHandler();
|
||||
|
||||
uint32_t vbat = 0;
|
||||
if (HAL_ADC_Start(&hadc1) != HAL_OK) CxxErrorHandler();
|
||||
for (size_t i = 0; i != 8; ++i)
|
||||
{
|
||||
if (HAL_ADC_PollForConversion(&hadc1, 1) != HAL_OK) CxxErrorHandler();
|
||||
vbat += HAL_ADC_GetValue(&hadc1);
|
||||
}
|
||||
|
||||
vbat /= 8;
|
||||
|
||||
if (HAL_ADC_Stop(&hadc1) != HAL_OK) CxxErrorHandler();
|
||||
if (HAL_TIM_Base_Stop(&htim6) != HAL_OK)
|
||||
CxxErrorHandler();
|
||||
|
||||
htim6.Init.Period = 1817;
|
||||
if (HAL_TIM_Base_Init(&htim6) != HAL_OK) CxxErrorHandler();
|
||||
|
||||
HAL_Delay(1);
|
||||
|
||||
gpio::BAT_DIVIDER::on();
|
||||
if (!usb_ce) gpio::USB_CE::off(); // Restore battery charging state.
|
||||
|
||||
INFO("Vref = %lu", vrefint);
|
||||
INFO("Vbat = %lu (raw)", vbat);
|
||||
|
||||
// Order of operations is important to avoid underflow.
|
||||
vbat *= 6600;
|
||||
vbat /= (vref + 1);
|
||||
|
||||
INFO("Vbat = %lumV", vbat);
|
||||
void pollBatteryLevel()
|
||||
{
|
||||
auto vbat = getDemodulator()->readBatteryLevel();
|
||||
|
||||
uint8_t data[3];
|
||||
data[0] = kiss::hardware::GET_BATTERY_LEVEL;
|
||||
|
@ -514,7 +452,6 @@ void pollBatteryLevel() {
|
|||
data[2] = (vbat & 0xFF);
|
||||
|
||||
ioport->write(data, 3, 6, 10);
|
||||
DEBUG("exit pollBatteryLevel");
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
|
|
@ -87,9 +87,9 @@ enum AdcState {
|
|||
|
||||
const size_t ADC_BUFFER_SIZE = 384;
|
||||
extern uint32_t adc_buffer[]; // Two int16_t samples per element.
|
||||
extern uint32_t adc_block_size;
|
||||
extern uint32_t dma_transfer_size;
|
||||
extern uint32_t half_buffer_size;
|
||||
extern volatile uint32_t adc_block_size;
|
||||
extern volatile uint32_t dma_transfer_size;
|
||||
extern volatile uint32_t half_buffer_size;
|
||||
|
||||
// 1kB
|
||||
typedef memory::Pool<8, ADC_BUFFER_SIZE * 2> adc_pool_type;
|
||||
|
|
|
@ -23,7 +23,6 @@ void IDemodulator::startADC(uint32_t period, uint32_t block_size)
|
|||
audio::set_adc_block_size(block_size);
|
||||
|
||||
htim6.Init.Period = period;
|
||||
htim6.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||
if (HAL_TIM_Base_Init(&htim6) != HAL_OK)
|
||||
{
|
||||
CxxErrorHandler();
|
||||
|
@ -35,7 +34,7 @@ void IDemodulator::startADC(uint32_t period, uint32_t block_size)
|
|||
}
|
||||
|
||||
if (HAL_ADC_Start_DMA(&hadc1, audio::adc_buffer,
|
||||
block_size * 2) != HAL_OK)
|
||||
audio::dma_transfer_size) != HAL_OK)
|
||||
{
|
||||
CxxErrorHandler();
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ struct IDemodulator
|
|||
virtual void stop() = 0;
|
||||
virtual hdlc::IoFrame* operator()(const q15_t* samples) = 0;
|
||||
virtual float readTwist() = 0;
|
||||
virtual uint32_t readBatteryLevel() = 0;
|
||||
|
||||
virtual bool locked() const = 0;
|
||||
virtual size_t size() const = 0;
|
||||
|
@ -33,10 +34,10 @@ struct IDemodulator
|
|||
* are frames which consist of an even multiple of eight bits and are
|
||||
* up to 330 bytes, but which do not have a valid checksum.
|
||||
*
|
||||
* @param enable is true when enabled and false when disabled. The
|
||||
* @param enabled is true when enabled and false when disabled. The
|
||||
* default state is disabled.
|
||||
*/
|
||||
virtual void passall(bool enable) = 0;
|
||||
virtual void passall(bool enabled) = 0;
|
||||
|
||||
virtual ~IDemodulator() {}
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include "Fsk9600Demodulator.hpp"
|
||||
#include "Goertzel.h"
|
||||
#include "AudioInput.hpp"
|
||||
#include "GPIO.hpp"
|
||||
|
||||
namespace mobilinkd { namespace tnc {
|
||||
|
||||
|
@ -45,7 +46,6 @@ hdlc::IoFrame* Fsk9600Demodulator::operator()(const q15_t* samples)
|
|||
float Fsk9600Demodulator::readTwist()
|
||||
{
|
||||
DEBUG("enter Fsk9600Demodulator::readTwist");
|
||||
constexpr uint32_t channel = AUDIO_IN;
|
||||
|
||||
float g120 = 0.0f;
|
||||
float g4800 = 0.0f;
|
||||
|
@ -97,6 +97,77 @@ float Fsk9600Demodulator::readTwist()
|
|||
return result;
|
||||
}
|
||||
|
||||
uint32_t Fsk9600Demodulator::readBatteryLevel()
|
||||
{
|
||||
DEBUG("enter Fsk9600Demodulator::readBatteryLevel");
|
||||
|
||||
ADC_ChannelConfTypeDef sConfig;
|
||||
|
||||
sConfig.Channel = ADC_CHANNEL_VREFINT;
|
||||
sConfig.Rank = ADC_REGULAR_RANK_1;
|
||||
sConfig.SingleDiff = ADC_SINGLE_ENDED;
|
||||
sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5;
|
||||
sConfig.OffsetNumber = ADC_OFFSET_NONE;
|
||||
sConfig.Offset = 0;
|
||||
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
|
||||
CxxErrorHandler();
|
||||
|
||||
htim6.Init.Period = 48000;
|
||||
if (HAL_TIM_Base_Init(&htim6) != HAL_OK) CxxErrorHandler();
|
||||
|
||||
if (HAL_TIM_Base_Start(&htim6) != HAL_OK)
|
||||
CxxErrorHandler();
|
||||
|
||||
if (HAL_ADC_Start(&hadc1) != HAL_OK) CxxErrorHandler();
|
||||
if (HAL_ADC_PollForConversion(&hadc1, 3) != HAL_OK) CxxErrorHandler();
|
||||
auto vrefint = HAL_ADC_GetValue(&hadc1);
|
||||
if (HAL_ADC_Stop(&hadc1) != HAL_OK) CxxErrorHandler();
|
||||
|
||||
// Disable battery charging while measuring battery voltage.
|
||||
auto usb_ce = gpio::USB_CE::get();
|
||||
gpio::USB_CE::on();
|
||||
|
||||
gpio::BAT_DIVIDER::off();
|
||||
HAL_Delay(1);
|
||||
|
||||
sConfig.Channel = ADC_CHANNEL_15;
|
||||
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
|
||||
CxxErrorHandler();
|
||||
|
||||
uint32_t vbat = 0;
|
||||
if (HAL_ADC_Start(&hadc1) != HAL_OK) CxxErrorHandler();
|
||||
for (size_t i = 0; i != 8; ++i)
|
||||
{
|
||||
if (HAL_ADC_PollForConversion(&hadc1, 1) != HAL_OK) CxxErrorHandler();
|
||||
vbat += HAL_ADC_GetValue(&hadc1);
|
||||
}
|
||||
|
||||
vbat /= 8;
|
||||
|
||||
if (HAL_ADC_Stop(&hadc1) != HAL_OK) CxxErrorHandler();
|
||||
if (HAL_TIM_Base_Stop(&htim6) != HAL_OK)
|
||||
CxxErrorHandler();
|
||||
|
||||
gpio::BAT_DIVIDER::on();
|
||||
|
||||
// Restore battery charging state.
|
||||
if (!usb_ce) gpio::USB_CE::off();
|
||||
|
||||
INFO("Vref = %lu", vrefint);
|
||||
INFO("Vbat = %lu (raw)", vbat);
|
||||
|
||||
// Order of operations is important to avoid underflow.
|
||||
vbat *= 6600;
|
||||
vbat /= (vrefint + 1);
|
||||
|
||||
uint32_t vref = (vrefint * 3300) + (VREF / 2) / VREF;
|
||||
|
||||
INFO("Vref = %lumV", vref)
|
||||
INFO("Vbat = %lumV", vbat);
|
||||
|
||||
DEBUG("exit Fsk9600Demodulator::readBatteryLevel");
|
||||
return vbat;
|
||||
}
|
||||
|
||||
const Fsk9600Demodulator::bpf_bank_type Fsk9600Demodulator::bpf_bank = {{
|
||||
// -3dB
|
||||
|
|
|
@ -29,9 +29,11 @@ struct Fsk9600Demodulator : IDemodulator
|
|||
{
|
||||
static constexpr size_t FILTER_TAP_NUM = 132;
|
||||
static constexpr uint32_t ADC_BLOCK_SIZE = 384;
|
||||
static constexpr uint32_t SAMPLE_RATE = 192000;
|
||||
static_assert(audio::ADC_BUFFER_SIZE >= ADC_BLOCK_SIZE);
|
||||
|
||||
static constexpr uint32_t SAMPLE_RATE = 192000;
|
||||
static constexpr uint16_t VREF = 16383;
|
||||
|
||||
using bpf_coeffs_type = std::array<int16_t, FILTER_TAP_NUM>;
|
||||
using bpf_bank_type = std::array<bpf_coeffs_type, 13>;
|
||||
using audio_filter_t = Q15FirFilter<ADC_BLOCK_SIZE, FILTER_TAP_NUM>;
|
||||
|
@ -80,13 +82,13 @@ struct Fsk9600Demodulator : IDemodulator
|
|||
void stop() override
|
||||
{
|
||||
stopADC();
|
||||
// INFO("Setting 4MHz SysClock.");
|
||||
// SysClock48();
|
||||
locked_ = false;
|
||||
}
|
||||
|
||||
float readTwist() override;
|
||||
|
||||
uint32_t readBatteryLevel() override;
|
||||
|
||||
hdlc::IoFrame* operator()(const q15_t* samples) override;
|
||||
|
||||
bool locked() const override
|
||||
|
@ -99,9 +101,9 @@ struct Fsk9600Demodulator : IDemodulator
|
|||
return ADC_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
void passall(bool enable) override
|
||||
void passall(bool enabled) override
|
||||
{
|
||||
hdlc_decoder_.passall = enable;
|
||||
hdlc_decoder_.setPassall(enabled);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -54,6 +54,10 @@ struct NewDecoder
|
|||
|
||||
optional_result_type operator()(bool input, bool pll_lock);
|
||||
uint8_t process(bool input, bool pll_lock);
|
||||
void setPassall(bool enabled)
|
||||
{
|
||||
passall = enabled;
|
||||
}
|
||||
};
|
||||
|
||||
}}} // mobilinkd::tnc::hdlc
|
||||
|
|
Ładowanie…
Reference in New Issue