From c1abeefd670c10c50578dde0e32993c4da1d6a51 Mon Sep 17 00:00:00 2001 From: Silvano Seva Date: Mon, 15 Mar 2021 15:24:42 +0100 Subject: [PATCH] Implemented volume control for audio coming from radio stage on MD-UV3x0 and fixed a compilation warning regarding non-const access to a const variable --- meson.build | 2 +- openrtx/src/rtx.c | 25 +++++++++++++++++++++ platform/drivers/baseband/HR_C6000.c | 2 +- platform/drivers/baseband/HR_C6000.h | 6 +++-- platform/drivers/baseband/HR_C6000_UV3x0.c | 13 +++++------ platform/drivers/baseband/radio_UV3x0.c | 26 +++++++++++++--------- 6 files changed, 53 insertions(+), 21 deletions(-) diff --git a/meson.build b/meson.build index f6a9af4c..6e2268b9 100644 --- a/meson.build +++ b/meson.build @@ -179,7 +179,7 @@ mduv380_src = src + stm32f405_src + ['platform/drivers/display/HX8353_MDx.cpp', 'platform/drivers/ADC/ADC1_MDx.c', 'platform/drivers/tones/toneGenerator_MDx.c', 'platform/drivers/baseband/radio_UV3x0.c', - 'platform/drivers/GPS/GPS_MDx.c', + 'platform/drivers/GPS/GPS_MDx.cpp', 'platform/targets/MD-UV380/platform.c', 'platform/drivers/baseband/AT1846S_UV3x0.c', 'platform/drivers/baseband/HR_C6000_UV3x0.c', diff --git a/openrtx/src/rtx.c b/openrtx/src/rtx.c index 4603fe69..b04ecc20 100644 --- a/openrtx/src/rtx.c +++ b/openrtx/src/rtx.c @@ -22,6 +22,9 @@ #include #include #include +#ifdef PLATFORM_MDUV380 +#include "../../platform/drivers/baseband/HR_C6000.h" +#endif #include #include @@ -252,6 +255,28 @@ void rtx_taskFunc() _afCtrlSpeaker(false); sqlOpen = false; } + + /* + * Unfortunately on MD-UV3x0 radios the volume knob does not regulate + * the amplitude of the analog signal towards the audio amplifier but it + * rather serves to provide a digital value to be fed into the HR_C6000 + * lineout DAC gain. We thus have to place the #ifdef'd piece of code + * below to keep the real volume level consistent with the knob position. + * Knob position is given by an analog signal in the range 0 - 1500mV, + * which has to be mapped in a range between 1 and 31. + */ + #ifdef PLATFORM_MDUV380 + float level = (platform_getVolumeLevel() / 1560.0f) * 30.0f; + uint8_t volume = ((uint8_t) (level + 0.5f)); + + /* Update HR_C6000 gain only if volume changed */ + static uint8_t old_volume = 0; + if(volume != old_volume) + { + C6000_setDacGain(volume + 1); + old_volume = volume; + } + #endif } else if((rtxStatus.opMode == OFF) && enterRx) { diff --git a/platform/drivers/baseband/HR_C6000.c b/platform/drivers/baseband/HR_C6000.c index 2f34def4..38298db6 100644 --- a/platform/drivers/baseband/HR_C6000.c +++ b/platform/drivers/baseband/HR_C6000.c @@ -288,7 +288,7 @@ void C6000_setMod2Bias(uint8_t bias) _writeReg(0x04, 0x04, bias); } -void C6000_setDacRange(uint8_t value) +void C6000_setDacGain(uint8_t value) { uint8_t dacData = value + 1; if(dacData > 31) dacData = 31; diff --git a/platform/drivers/baseband/HR_C6000.h b/platform/drivers/baseband/HR_C6000.h index 549ccfed..d2ae69ec 100644 --- a/platform/drivers/baseband/HR_C6000.h +++ b/platform/drivers/baseband/HR_C6000.h @@ -62,9 +62,11 @@ void C6000_setMod2Bias(uint8_t bias); void C6000_setModFactor(uint8_t mf); /** - * + * Configure the gain of lineout DAC stage. Allowed range is 1 - 31 and each + * step corresponds to a variation of 1.5dB. + * @param value: gain for the DAC stage. */ -void C6000_setDacRange(uint8_t value); +void C6000_setDacGain(uint8_t value); /** * Configure chipset for DMR operation. diff --git a/platform/drivers/baseband/HR_C6000_UV3x0.c b/platform/drivers/baseband/HR_C6000_UV3x0.c index b971a322..7e0a941f 100644 --- a/platform/drivers/baseband/HR_C6000_UV3x0.c +++ b/platform/drivers/baseband/HR_C6000_UV3x0.c @@ -24,7 +24,6 @@ #include #include #include -#include #include #include @@ -194,11 +193,11 @@ void C6000_setMod2Bias(uint8_t bias) _writeReg(0x04, 0x04, bias); } -void C6000_setDacRange(uint8_t value) +void C6000_setDacGain(uint8_t value) { - uint8_t dacData = value + 1; - if(dacData > 31) dacData = 31; - _writeReg(0x04, 0x37, dacData); + if(value < 1) value = 1; + if(value > 31) value = 31; + _writeReg(0x04, 0x37, (0x80 | value)); } void C6000_dmrMode() @@ -256,7 +255,7 @@ void C6000_fmMode() _writeReg(0x04, 0x11, 0x80); _writeReg(0x04, 0xE0, 0xC9); - _writeReg(0x04, 0x37, 0x80); + _writeReg(0x04, 0x37, 0x81); } void C6000_startAnalogTx() @@ -290,7 +289,7 @@ void C6000_stopAnalogTx() _writeReg(0x04, 0x60, 0x00); _writeReg(0x04, 0xE0, 0xC9); - _writeReg(0x04, 0x37, 0x80); + _writeReg(0x04, 0x37, 0x81); } bool C6000_spiInUse() diff --git a/platform/drivers/baseband/radio_UV3x0.c b/platform/drivers/baseband/radio_UV3x0.c index b032aa0c..5f4a5486 100644 --- a/platform/drivers/baseband/radio_UV3x0.c +++ b/platform/drivers/baseband/radio_UV3x0.c @@ -226,6 +226,7 @@ void radio_disableRtx() gpio_clearPin(UHF_LNA_EN); gpio_clearPin(PA_EN_1); gpio_clearPin(PA_EN_2); + DAC->DHR12L1 = 0; AT1846S_disableCtcss(); AT1846S_setFuncMode(AT1846S_OFF); C6000_stopAnalogTx(); @@ -243,19 +244,24 @@ void radio_updateCalibrationParams(const rtxStatus_t *rtxCfg) if(currRxBand > 0) modBias = calData->uhfCal.freqAdjustMid; C6000_setModOffset(modBias); - freq_t *txCalPoints = calData->vhfCal.txFreq; - uint8_t *loPwrCal = calData->vhfCal.txLowPower; - uint8_t *hiPwrCal = calData->vhfCal.txLowPower; - uint8_t *qRangeCal = (rtxCfg->opMode == FM) ? - calData->vhfCal.analogSendQrange : calData->vhfCal.sendQrange; + /* + * Discarding "const" qualifier to suppress compiler warnings. + * This operation is safe anyway because calibration data is only read. + */ + mduv3x0Calib_t *cal = ((mduv3x0Calib_t *) calData); + freq_t *txCalPoints = cal->vhfCal.txFreq; + uint8_t *loPwrCal = cal->vhfCal.txLowPower; + uint8_t *hiPwrCal = cal->vhfCal.txLowPower; + uint8_t *qRangeCal = (rtxCfg->opMode == FM) ? cal->vhfCal.analogSendQrange + : cal->vhfCal.sendQrange; if(currTxBand > 0) { - txCalPoints = calData->uhfCal.txFreq; - loPwrCal = calData->uhfCal.txLowPower; - hiPwrCal = calData->uhfCal.txLowPower; - qRangeCal = (rtxCfg->opMode == FM) ? calData->uhfCal.analogSendQrange - : calData->uhfCal.sendQrange; + txCalPoints = cal->uhfCal.txFreq; + loPwrCal = cal->uhfCal.txLowPower; + hiPwrCal = cal->uhfCal.txLowPower; + qRangeCal = (rtxCfg->opMode == FM) ? cal->uhfCal.analogSendQrange + : cal->uhfCal.sendQrange; } /* APC voltage for TX output power control */