Modified HR_Cx000::setInputGain() function to accept a value expressed in dB instead of a raw binary value to be written directly inside the chip's register

replace/4a02fe4dae0c118200c966a4b2d963227a8ac32e
Silvano Seva 2021-09-21 12:01:31 +02:00
rodzic d018dbb4a0
commit 431ba17b26
3 zmienionych plików z 63 dodań i 11 usunięć

Wyświetl plik

@ -47,18 +47,67 @@ void HR_Cx000< C6000_SpiOpModes >::setDacGain(uint8_t value)
}
template <>
void HR_Cx000< C5000_SpiOpModes >::setInputGain(uint8_t value)
void HR_Cx000< C5000_SpiOpModes >::setInputGain(int8_t value)
{
// Mic gain is controlled by bytes 7:3 of register 0x0F (ADLinVol).
if(value > 31) value = 31;
writeReg(C5000_SpiOpModes::CONFIG, 0x0F, value << 3);
/*
* On HR_C5000 the input gain value is controlled by bits 7:3 of of register
* 0x0F (ADLinVol): these bits allow to set the gain in a range from +12dB
* to -34.5dB in steps of 1.5dB each.
* The equation relating the gain in dB with register value is: Gain = reg*1.5 - 34.5
* Its inverse is: reg = (gain + 34.5)/1.5 or, equivalently, reg = (gain/1.5) + 23
*/
// Keep gain value in range +12dB ... -34.5dB
if(value > 12) value = 12;
if(value < -34.5) value = -34.5;
// Apply the inverse equation to obtain gain register. Gain is multiplied
// by ten and divided by 15 to keep using integer operations.
int16_t result = (((int16_t) value) * 10)/15 + 23;
uint8_t regVal = ((uint8_t) result);
if(regVal > 31) regVal = 31;
writeReg(C5000_SpiOpModes::CONFIG, 0x0F, regVal << 3);
}
template <>
void HR_Cx000< C6000_SpiOpModes >::setInputGain(uint8_t value)
void HR_Cx000< C6000_SpiOpModes >::setInputGain(int8_t value)
{
// TODO: Experiments needed for identification of HR_C6000 mic gain register.
(void) value;
/*
* On HR_C6000 the input gain in two stages: the first one is a "coarse"
* stage capable of doing only 0dB, -6dB and -12dB. The second stage is a
* "fine" stage ranging from 0 to +36dB in steps of 3dB.
* Both of them are controlled by register 0xE4: bits 5:4 control the first
* stage, while bits 4:0 control the fine stage.
*
* Allowable gain ranges are:
* - 0 ... +36dB when coarse stage bits are 00
* - -6 ... +30dB when coarse stage bits are 01
* - -12 ... +24dB when coarse stage bits are 10 or 11
*
* General equation for gain is reg*3 + offset, where "offset" is the gain
* of the coarse stage.
* Inverse equation, given the coarse gain, is: reg = (gain - offset)/3
*
* In this code we use -12dB and 0dB coarse gain values, leaving the fine
* tuning to the second stage.
*/
uint8_t regValue = 0;
if(value < 24)
{
int8_t fineGain = (value + 12)/3; // Compute fine gain, -12dB offset
regValue = (2 << 4) // Select -12dB coarse gain
| ((uint8_t) fineGain); // Set fine gain bits
}
else
{
// For values starting from +24dB set coarse gain to 0dB and use
// only fine gain
regValue = ((uint8_t) value/3);
}
writeReg(C6000_SpiOpModes::CONFIG, 0xE4, regValue);
}
ScopedChipSelect::ScopedChipSelect()

Wyświetl plik

@ -158,9 +158,12 @@ public:
* sources. This value affects the modulation level in analog FM mode and
* it must be correctly tuned to avoid distorsions.
*
* @param value: gain value. Allowed range is 0-31.
* HR_C5000 gain ranges from -34.5dB to +12dB
* HR_C6000 gain ranges from -12dB to +36dB
*
* @param value: gain value in dB.
*/
void setInputGain(uint8_t value);
void setInputGain(int8_t value);
/**
* Configure chipset for DMR operation.

Wyświetl plik

@ -201,7 +201,7 @@ void radio_setOpmode(const enum opmode mode)
gpio_clearPin(DMR_SW); // Disconnect analog paths for DMR
gpio_setPin(FM_SW); // Enable analog RX stage after superhet
C5000.fmMode(); // HR_C5000 in FM mode
C5000.setInputGain(0x19); // Input gain, as per TYT firmware
C5000.setInputGain(+3); // Input gain in dB, as per TYT firmware
break;
case DMR:
@ -214,7 +214,7 @@ void radio_setOpmode(const enum opmode mode)
gpio_clearPin(DMR_SW); // Disconnect analog paths for DMR
gpio_setPin(FM_SW); // Enable analog RX stage after superhet
C5000.fmMode(); // HR_C5000 in FM mode
C5000.setInputGain(0x14); // Input gain, found experimentally
C5000.setInputGain(-5); // Input gain in dB, found experimentally
break;
default: