Add get_adc_exponent() to demodulator interface. Update battery level code in 9600 baud and M17 demodulators. Clean up code. Remove unused code. Suppress some CMSIS-OS and Blaze warnings.

build_system v2.5.0
Rob Riggs 2024-09-06 12:16:09 -07:00
rodzic a2606c4bf5
commit 4a8d16564c
14 zmienionych plików z 51 dodań i 207 usunięć

Wyświetl plik

@ -12,12 +12,8 @@ void AFSKModulator::init(const kiss::Hardware& hw)
SysClock48();
// Configure 48MHz clock for 26.4ksps.
htim7.Init.Period = 1817;
if (HAL_TIM_Base_Init(&htim7) != HAL_OK)
{
ERROR("htim7 init failed");
CxxErrorHandler();
}
__HAL_TIM_SET_AUTORELOAD(&htim7, 1817);
__HAL_TIM_SET_PRESCALER(&htim7, 0);
DAC_ChannelConfTypeDef sConfig;
@ -26,11 +22,7 @@ void AFSKModulator::init(const kiss::Hardware& hw)
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
sConfig.DAC_ConnectOnChipPeripheral = DAC_CHIPCONNECT_ENABLE;
sConfig.DAC_UserTrimming = DAC_TRIMMING_FACTORY;
if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1) != HAL_OK)
{
CxxErrorHandler();
}
if (HAL_DAC_ConfigChannel(&hdac1, &sConfig, DAC_CHANNEL_1) != HAL_OK) CxxErrorHandler();
if (HAL_DAC_SetValue(&hdac1, DAC_CHANNEL_1, DAC_ALIGN_12B_R, 2048) != HAL_OK) CxxErrorHandler();
if (HAL_DAC_Start(&hdac1, DAC_CHANNEL_1) != HAL_OK) CxxErrorHandler();
}

Wyświetl plik

@ -140,7 +140,6 @@ struct AFSKModulator : Modulator
void fill(uint16_t* buffer, bool bit)
{
HAL_IWDG_Refresh(&hiwdg);
for (size_t i = 0; i != BIT_LEN; i++)
{
int s = sin_table[pos_];
@ -191,7 +190,6 @@ struct AFSKModulator : Modulator
void empty()
{
HAL_IWDG_Refresh(&hiwdg);
switch (running_) {
case 1:
running_ = 0;

Wyświetl plik

@ -86,7 +86,7 @@ hdlc::IoFrame* Afsk1200Demodulator::operator()(const q15_t* samples)
*/
float Afsk1200Demodulator::readTwist()
{
INFO("enter Afsk1200Demodulator::readTwist");
TNC_DEBUG("enter Afsk1200Demodulator::readTwist");
float g1200 = 0.0f;
float g2200 = 0.0f;

Wyświetl plik

@ -93,7 +93,7 @@ struct Afsk1200Demodulator : IDemodulator
sConfig.SamplingTime = ADC_SAMPLETIME_24CYCLES_5;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
if (HAL_ADC_ConfigChannel(&DEMODULATOR_ADC_HANDLE, &sConfig) != HAL_OK)
CxxErrorHandler();
startADC(1817, ADC_BLOCK_SIZE);
}

Wyświetl plik

@ -1,8 +1,7 @@
// Copyright 2015-2019 Mobilinkd LLC <rob@mobilinkd.com>
// Copyright 2015-2024 Mobilinkd LLC <rob@mobilinkd.com>
// All rights reserved.
#ifndef MOBILINKD__AFSK_DEMODULATOR_HPP_
#define MOBILINKD__AFSK_DEMODULATOR_HPP_
#pragma once
#include "DelayLine.hpp"
#include "AudioInput.hpp"
@ -74,6 +73,3 @@ struct Demodulator {
}}} // mobilinkd::tnc::afsk1200
#endif // MOBILINKD__AFSK_DEMODULATOR_HPP_

Wyświetl plik

@ -116,8 +116,8 @@ extern "C" void startAudioInputTask(void const*) {
break;
case UPDATE_SETTINGS:
TNC_DEBUG("UPDATE_SETTINGS");
setAudioInputLevels();
updateModulator();
setAudioInputLevels(); // Update the input levels.
updateModulator(); // Update the modulator and PTT config.
break;
case IDLE:
INFO("IDLE");
@ -206,8 +206,6 @@ void demodulatorTask() {
continue;
}
HAL_IWDG_Refresh(&hiwdg);
auto block = (adc_pool_type::chunk_type*) evt.value.p;
auto samples = (int16_t*) block->buffer;
@ -245,22 +243,25 @@ void streamLevels(uint8_t cmd) {
// Stream out Vpp, Vavg, Vmin, Vmax as four 16-bit values, left justified.
constexpr uint32_t BLOCKS = 30;
uint8_t data[9];
INFO("streamLevels: start");
auto demodulator = getDemodulator();
demodulator->start();
const size_t audio_exponent = demodulator->get_adc_exponent();
while (true) {
osEvent peek = osMessagePeek(audioInputQueueHandle, 0);
if (peek.status == osEventMessage) break;
uint16_t count = 0;
uint32_t count = 0;
uint32_t accum = 0;
uint16_t vmin = std::numeric_limits<uint16_t>::max();
uint16_t vmax = std::numeric_limits<uint16_t>::min();
while (count < demodulator->size() * 30) {
for (size_t i = 0; i != BLOCKS; ++i) {
osEvent evt = osMessageGet(adcInputQueueHandle, osWaitForever);
if (evt.status != osEventMessage) continue;
@ -277,10 +278,10 @@ void streamLevels(uint8_t cmd) {
adcPool.deallocate(block);
}
uint16_t pp = (vmax - vmin) << 4;
uint16_t avg = (accum / count) << 4;
vmin <<= 4;
vmax <<= 4;
uint16_t pp = (vmax - vmin) << audio_exponent;
uint16_t avg = (accum / count) << audio_exponent;
vmin <<= audio_exponent;
vmax <<= audio_exponent;
data[0] = cmd;
data[1] = (pp >> 8) & 0xFF; // Vpp
@ -337,6 +338,8 @@ levels_type readLevels(uint32_t)
}
demodulator->stop();
auto status = osMessagePut(ioEventQueueHandle, CMD_RESTORE_SYSCLK, 100);
if (status != osOK) CxxErrorHandler2(HAL_TIMEOUT);
uint16_t pp = vmax - vmin;
uint16_t avg = iaccum / BLOCKS;
@ -418,7 +421,7 @@ void pollInputTwist()
IDemodulator::stopADC();
INFO("pollInputTwist: MARK=%d, SPACE=%d (x100)",
TNC_DEBUG("pollInputTwist: MARK=%d, SPACE=%d (x100)",
int(g1200 * 100.0 / AVG_SAMPLES), int(g2200 * 100.0 / AVG_SAMPLES));
int16_t g1200i = int16_t(g1200 * 256 / AVG_SAMPLES);
@ -433,7 +436,7 @@ void pollInputTwist()
ioport->write(buffer, 5, 6, 10);
INFO("exit pollInputTwist");
TNC_DEBUG("exit pollInputTwist");
}
void streamAmplifiedInputLevels() {
@ -448,10 +451,12 @@ void pollAmplifiedInputLevel() {
uint16_t Vpp, Vavg, Vmin, Vmax;
std::tie(Vpp, Vavg, Vmin, Vmax) = readLevels(AUDIO_IN);
Vpp <<= 4;
Vavg <<= 4;
Vmin <<= 4;
Vmax <<= 4;
const size_t audio_exponent = getDemodulator()->get_adc_exponent();
Vpp <<= audio_exponent;
Vavg <<= audio_exponent;
Vmin <<= audio_exponent;
Vmax <<= audio_exponent;
uint8_t data[9];
data[0] = kiss::hardware::POLL_INPUT_LEVEL;
@ -482,34 +487,4 @@ void pollBatteryLevel()
}
#endif
#if 0
void stop() {
osDelay(100);
auto restore = SysTick->CTRL;
kiss::settings().input_offset += 6;
setAudioInputLevels();
kiss::settings().input_offset -= 6;
TNC_DEBUG("Stop");
// __disable_irq();
vTaskSuspendAll();
SysTick->CTRL = 0;
HAL_COMP_Init(&hcomp1);
HAL_COMP_Start_IT(&hcomp1);
while (adcState == STOPPED) {
// PWR_MAINREGULATOR_ON / PWR_LOWPOWERREGULATOR_ON
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
}
SystemClock_Config();
SysTick->CTRL = restore;
// __enable_irq();
HAL_COMP_Stop_IT(&hcomp1);
HAL_COMP_DeInit(&hcomp1);
xTaskResumeAll();
setAudioInputLevels();
// adcState = DEMODULATOR;
TNC_DEBUG("Wake");
}
#endif
}}} // mobilinkd::tnc::audio

Wyświetl plik

@ -33,7 +33,7 @@ void IDemodulator::startADC(uint32_t period, uint32_t block_size)
status = HAL_TIM_Base_Start(&htim6);
if (status != HAL_OK) CxxErrorHandler2(status);
status = HAL_ADC_Start_DMA(&hadc1, audio::adc_buffer, audio::dma_transfer_size);
status = HAL_ADC_Start_DMA(&DEMODULATOR_ADC_HANDLE, audio::adc_buffer, audio::dma_transfer_size);
if (status != HAL_OK) CxxErrorHandler2(status);
}
@ -41,7 +41,7 @@ void IDemodulator::stopADC()
{
HAL_StatusTypeDef status;
status = HAL_ADC_Stop_DMA(&hadc1);
status = HAL_ADC_Stop_DMA(&DEMODULATOR_ADC_HANDLE);
if (status != HAL_OK) CxxErrorHandler2(status);
status = HAL_TIM_Base_Stop(&htim6);

Wyświetl plik

@ -29,6 +29,9 @@ struct IDemodulator
virtual bool locked() const = 0;
virtual size_t size() const = 0;
/// Shift value required to normalize ADC values to uint16_t.
virtual size_t get_adc_exponent() const { return 2; } // By default, 14-bit oversampled input.
/**
* Tell the demodulator to return all "passable" HDLC frames. These
* are frames which consist of an even multiple of eight bits and are

Wyświetl plik

@ -6,6 +6,7 @@
#include "AudioInput.hpp"
#include "GPIO.hpp"
#include "Log.h"
#include "power.h"
namespace mobilinkd { namespace tnc {
@ -124,74 +125,7 @@ float Fsk9600Demodulator::readTwist()
uint32_t Fsk9600Demodulator::readBatteryLevel()
{
#ifndef NUCLEOTNC
TNC_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 = BATTERY_ADC_CHANNEL;
if (HAL_ADC_ConfigChannel(&BATTERY_ADC_HANDLE, &sConfig) != HAL_OK)
CxxErrorHandler();
uint32_t vbat = 0;
if (HAL_ADC_Start(&BATTERY_ADC_HANDLE) != HAL_OK) CxxErrorHandler();
for (size_t i = 0; i != 8; ++i)
{
if (HAL_ADC_PollForConversion(&BATTERY_ADC_HANDLE, 1) != HAL_OK) CxxErrorHandler();
vbat += HAL_ADC_GetValue(&BATTERY_ADC_HANDLE);
}
vbat /= 8;
if (HAL_ADC_Stop(&BATTERY_ADC_HANDLE) != 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 /= (VREF + 1);
uint32_t vref = ((vrefint * 3300) + (VREF / 2)) / VREF;
INFO("Vref = %lumV", vref)
INFO("Vbat = %lumV", vbat);
TNC_DEBUG("exit Fsk9600Demodulator::readBatteryLevel");
return vbat;
return read_battery_level();
#else
return 0;
#endif

Wyświetl plik

@ -31,7 +31,6 @@ extern osMessageQId hdlcOutputQueueHandle;
extern osThreadId modulatorTaskHandle;
extern osThreadId audioInputTaskHandle;
extern "C" void shutdown(void const *);
extern I2C_HandleTypeDef hi2c1;
extern UART_HandleTypeDef huart3;
@ -341,6 +340,8 @@ void startIOEventTask(void const*)
// Normal startup.
hardware.debug();
// On TNC3, power monitor must be started before initializing audio
// because ADC is used.
init_power_monitor();
start_power_monitor();

Wyświetl plik

@ -18,6 +18,7 @@
#include "M17Framer.h"
#include "Modulator.hpp"
#include "ModulatorTask.hpp"
#include "power.h"
#include "Util.h"
#include <arm_math.h>
@ -145,74 +146,7 @@ struct M17Demodulator : IDemodulator
uint32_t readBatteryLevel() override
{
#ifndef NUCLEOTNC
TNC_DEBUG("enter M17Demodulator::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 = BATTERY_ADC_CHANNEL;
if (HAL_ADC_ConfigChannel(&BATTERY_ADC_HANDLE, &sConfig) != HAL_OK)
CxxErrorHandler();
uint32_t vbat = 0;
if (HAL_ADC_Start(&BATTERY_ADC_HANDLE) != HAL_OK) CxxErrorHandler();
for (size_t i = 0; i != 8; ++i)
{
if (HAL_ADC_PollForConversion(&BATTERY_ADC_HANDLE, 1) != HAL_OK) CxxErrorHandler();
vbat += HAL_ADC_GetValue(&BATTERY_ADC_HANDLE);
}
vbat /= 8;
if (HAL_ADC_Stop(&BATTERY_ADC_HANDLE) != 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 /= (VREF + 1);
uint32_t vref = ((vrefint * 3300) + (VREF / 2)) / VREF;
INFO("Vref = %lumV", vref)
INFO("Vbat = %lumV", vbat);
TNC_DEBUG("exit M17Demodulator::readBatteryLevel");
return vbat;
return read_battery_level();
#else
return 0;
#endif

Wyświetl plik

@ -318,6 +318,9 @@ osStaticMessageQDef_t serialQueueControlBlock __attribute__((section(".bss3")));
osMutexDef(serialMutex);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wwrite-strings" // cmsis-os is not const-correct.
void SerialPort::init()
{
if (serialTaskHandle_) return;
@ -333,6 +336,8 @@ void SerialPort::init()
serialTaskHandle_ = osThreadCreate(osThread(serialTask), this);
}
#pragma GCC diagnostic pop
bool SerialPort::open()
{
if (open_ or !serialTaskHandle_) return open_;

Wyświetl plik

@ -141,6 +141,9 @@ osStaticThreadDef_t cdcTaskControlBlock;
uint8_t cdcQueueBuffer[ 4 * sizeof( void* ) ];
osStaticMessageQDef_t cdcQueueControlBlock;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wwrite-strings" // cmsis-os is not const-correct.
void UsbPort::init()
{
if (cdcTaskHandle_) return;
@ -155,6 +158,8 @@ void UsbPort::init()
cdcTaskHandle_ = osThreadCreate(osThread(cdcTask), this);
}
#pragma GCC diagnostic pop
bool UsbPort::open()
{
if (open_ or !cdcTaskHandle_) return open_;

Wyświetl plik

@ -31,6 +31,7 @@ set(C_WARNING_FLAGS "-Wall -Wextra -Wno-unused-parameter")
set(CXX_WARNING_FLAGS "${C_WARNING_FLAGS} -Wno-psabi -Wno-dangling-reference")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TARGET_FLAGS} ${C_WARNING_FLAGS}")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${TARGET_FLAGS} ${C_WARNING_FLAGS} ${CXX_WARNING_FLAGS}")
set(CMAKE_C_FLAGS_DEBUG "-O2 -g3")
set(CMAKE_C_FLAGS_RELEASE "-O2 -g3 -DNDEBUG")
@ -41,7 +42,7 @@ set(CMAKE_CXX_FLAGS_RELEASE "-O3 -g3 -DNDEBUG")
set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "-O3 -g3 -DNDEBUG")
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS} -x assembler-with-cpp -MMD -MP")
set(CMAKE_CXX_FLAGS "${CMAKE_C_FLAGS} -fno-rtti -fno-exceptions -fno-threadsafe-statics")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions -fno-threadsafe-statics")
set(CMAKE_C_LINK_FLAGS "${TARGET_FLAGS}")
set(CMAKE_C_LINK_FLAGS "${CMAKE_C_LINK_FLAGS} -T \"${CMAKE_SOURCE_DIR}/TNC3.ld\"")