Implemented RX tone squelch on MD-UV3x0 and GDx (TG-43)

This commit is contained in:
Silvano Seva 2021-06-02 12:44:46 +02:00
parent fdba408831
commit b29b24fdc0
6 changed files with 159 additions and 26 deletions

View File

@ -83,7 +83,8 @@ public:
private: private:
bool sqlOpen; ///< Flag for current squelch status. bool rfSqlOpen; ///< Flag for RF squelch status (analog squelch).
bool sqlOpen; ///< Flag for squelch status.
bool enterRx; ///< Flag for RX management. bool enterRx; ///< Flag for RX management.
}; };

View File

@ -66,7 +66,7 @@ void _setVolume()
} }
#endif #endif
OpMode_FM::OpMode_FM() : sqlOpen(false), enterRx(true) OpMode_FM::OpMode_FM() : rfSqlOpen(false), sqlOpen(false), enterRx(true)
{ {
} }
@ -77,8 +77,9 @@ OpMode_FM::~OpMode_FM()
void OpMode_FM::enable() void OpMode_FM::enable()
{ {
// When starting, close squelch and prepare for entering in RX mode. // When starting, close squelch and prepare for entering in RX mode.
sqlOpen = false; rfSqlOpen = false;
enterRx = true; sqlOpen = false;
enterRx = true;
} }
void OpMode_FM::disable() void OpMode_FM::disable()
@ -87,8 +88,9 @@ void OpMode_FM::disable()
audio_disableAmp(); audio_disableAmp();
audio_disableMic(); audio_disableMic();
radio_disableRtx(); radio_disableRtx();
sqlOpen = false; rfSqlOpen = false;
enterRx = false; sqlOpen = false;
enterRx = false;
} }
void OpMode_FM::update(rtxStatus_t *const status, const bool newCfg) void OpMode_FM::update(rtxStatus_t *const status, const bool newCfg)
@ -98,28 +100,34 @@ void OpMode_FM::update(rtxStatus_t *const status, const bool newCfg)
// RX logic // RX logic
if(status->opStatus == RX) if(status->opStatus == RX)
{ {
// RF squelch mechanism
float squelch = -127.0f + status->sqlLevel * 66.0f / 15.0f; float squelch = -127.0f + status->sqlLevel * 66.0f / 15.0f;
float rssi = rtx_getRssi(); float rssi = rtx_getRssi();
if((rfSqlOpen == false) && (rssi > (squelch + 0.1f))) rfSqlOpen = true;
if((rfSqlOpen == true) && (rssi < (squelch - 0.1f))) rfSqlOpen = false;
if((sqlOpen == false) && (rssi > (squelch + 0.1f))) // Local flags for current RF and tone squelch status
bool rfSql = ((status->rxToneEn == 0) && (rfSqlOpen == true));
bool toneSql = ((status->rxToneEn == 1) && radio_checkRxDigitalSquelch());
// Audio control
if((sqlOpen == false) && (rfSql || toneSql))
{ {
audio_enableAmp(); audio_enableAmp();
sqlOpen = true; sqlOpen = true;
} }
if((sqlOpen == true) && (rssi < (squelch - 0.1f))) if((sqlOpen == true) && (rfSql == false) && (toneSql == false))
{ {
audio_disableAmp(); audio_disableAmp();
sqlOpen = false; sqlOpen = false;
} }
#ifdef PLATFORM_MDUV3x0 #ifdef PLATFORM_MDUV3x0
if(sqlOpen == true) // Set output volume by changing the HR_C6000 DAC gain
{ if(sqlOpen == true) _setVolume();
// Set output volume by changing the HR_C6000 DAC gain
_setVolume();
}
#endif #endif
} }
else if((status->opStatus == OFF) && enterRx) else if((status->opStatus == OFF) && enterRx)
{ {
@ -130,7 +138,7 @@ void OpMode_FM::update(rtxStatus_t *const status, const bool newCfg)
enterRx = false; enterRx = false;
} }
/* TX logic */ // TX logic
if(platform_getPttStatus() && (status->opStatus != TX) && if(platform_getPttStatus() && (status->opStatus != TX) &&
(status->txDisable == 0)) (status->txDisable == 0))
{ {
@ -156,13 +164,20 @@ void OpMode_FM::update(rtxStatus_t *const status, const bool newCfg)
switch(status->opStatus) switch(status->opStatus)
{ {
case RX: case RX:
if(sqlOpen) if(radio_checkRxDigitalSquelch())
{ {
platform_ledOn(GREEN); platform_ledOn(GREEN); // Red + green LEDs ("orange"): tone squelch open
platform_ledOn(RED);
}
else if(rfSqlOpen)
{
platform_ledOn(GREEN); // Green LED only: RF squelch open
platform_ledOff(RED);
} }
else else
{ {
platform_ledOff(GREEN); platform_ledOff(GREEN);
platform_ledOff(RED);
} }
break; break;

View File

@ -96,6 +96,7 @@ public:
/** /**
* Set the VCO frequency, either for transmission or reception. * Set the VCO frequency, either for transmission or reception.
*
* @param freq: VCO frequency. * @param freq: VCO frequency.
*/ */
void setFrequency(const freq_t freq) void setFrequency(const freq_t freq)
@ -113,18 +114,21 @@ public:
/** /**
* Set the transmission and reception bandwidth. * Set the transmission and reception bandwidth.
*
* @param band: bandwidth. * @param band: bandwidth.
*/ */
void setBandwidth(const AT1846S_BW band); void setBandwidth(const AT1846S_BW band);
/** /**
* Set the operating mode. * Set the operating mode.
*
* @param mode: operating mode. * @param mode: operating mode.
*/ */
void setOpMode(const AT1846S_OpMode mode); void setOpMode(const AT1846S_OpMode mode);
/** /**
* Set the functional mode. * Set the functional mode.
*
* @param mode: functional mode. * @param mode: functional mode.
*/ */
void setFuncMode(const AT1846S_FuncMode mode) void setFuncMode(const AT1846S_FuncMode mode)
@ -140,14 +144,42 @@ public:
/** /**
* Enable the CTCSS tone for transmission. * Enable the CTCSS tone for transmission.
*
* @param freq: CTCSS tone frequency. * @param freq: CTCSS tone frequency.
*/ */
void enableTxCtcss(const tone_t freq) void enableTxCtcss(const tone_t freq)
{ {
i2c_writeReg16(0x4A, freq*10); i2c_writeReg16(0x4A, freq*10); // Set CTCSS1 frequency reg.
i2c_writeReg16(0x4B, 0x0000); i2c_writeReg16(0x4B, 0x0000); // Clear CDCSS bits
i2c_writeReg16(0x4C, 0x0000); i2c_writeReg16(0x4C, 0x0000);
maskSetRegister(0x4E, 0x0600, 0x0600); maskSetRegister(0x4E, 0x0600, 0x0600); // Enable CTCSS TX
}
/**
* Enable the CTCSS tone detection during reception.
*
* @param freq: CTCSS tone frequency.
*/
void enableRxCtcss(const tone_t freq)
{
i2c_writeReg16(0x4D, freq*10); // Set CTCSS2 frequency reg.
i2c_writeReg16(0x5B, getCtcssThreshFromTone(freq));
maskSetRegister(0x3A, 0x001F, 0x0008); // Enable CTCSS2 freq. detection
}
/**
* Check if CTCSS tone is detected when in RX mode.
*
* @return true if the RX CTCSS tone is being detected.
*/
inline bool rxCtcssDetected()
{
// Check if CTCSS detection is enabled: if not, return false.
if((i2c_readReg16(0x3A) & 0x0008) == 0) return false;
// Check CTCSS2 compare flag
uint16_t reg = i2c_readReg16(0x1C);
return ((reg & 0x100) != 0);
} }
/** /**
@ -155,12 +187,15 @@ public:
*/ */
inline void disableCtcss() inline void disableCtcss()
{ {
i2c_writeReg16(0x4A, 0x0000); maskSetRegister(0x4E, 0x0600, 0x0000); // Disable TX CTCSS
maskSetRegister(0x4E, 0x0600, 0x0000); // Disable TX CTCSS maskSetRegister(0x3A, 0x001F, 0x0000); // Disable CTCSS freq. detection
i2c_writeReg16(0x4A, 0x0000); // Clear CTCSS1 frequency reg.
i2c_writeReg16(0x4D, 0x0000); // Clear CTCSS2 frequency reg.
} }
/** /**
* Get current RSSI value. * Get current RSSI value.
*
* @return current RSSI in dBm. * @return current RSSI in dBm.
*/ */
inline int16_t readRSSI() inline int16_t readRSSI()
@ -171,6 +206,7 @@ public:
/** /**
* Set the gain of internal programmable gain amplifier. * Set the gain of internal programmable gain amplifier.
*
* @param gain: PGA gain. * @param gain: PGA gain.
*/ */
inline void setPgaGain(const uint8_t gain) inline void setPgaGain(const uint8_t gain)
@ -181,6 +217,7 @@ public:
/** /**
* Set microphone gain for transmission. * Set microphone gain for transmission.
*
* @param gain: microphone gain. * @param gain: microphone gain.
*/ */
inline void setMicGain(const uint8_t gain) inline void setMicGain(const uint8_t gain)
@ -190,6 +227,7 @@ public:
/** /**
* Set maximum FM transmission deviation. * Set maximum FM transmission deviation.
*
* @param dev: maximum allowed deviation. * @param dev: maximum allowed deviation.
*/ */
inline void setTxDeviation(const uint16_t dev) inline void setTxDeviation(const uint16_t dev)
@ -200,6 +238,7 @@ public:
/** /**
* Set the gain for internal automatic gain control system. * Set the gain for internal automatic gain control system.
*
* @param gain: AGC gain. * @param gain: AGC gain.
*/ */
inline void setAgcGain(const uint8_t gain) inline void setAgcGain(const uint8_t gain)
@ -210,6 +249,7 @@ public:
/** /**
* Set audio gain for recepion. * Set audio gain for recepion.
*
* @param analogDacGain: "analog DAC gain" in AT1846S manual. * @param analogDacGain: "analog DAC gain" in AT1846S manual.
* @param digitalGain: "digital voice gain" in AT1846S manual. * @param digitalGain: "digital voice gain" in AT1846S manual.
*/ */
@ -223,6 +263,7 @@ public:
/** /**
* Set noise1 thresholds for squelch opening and closing. * Set noise1 thresholds for squelch opening and closing.
*
* @param highTsh: upper threshold. * @param highTsh: upper threshold.
* @param lowTsh: lower threshold. * @param lowTsh: lower threshold.
*/ */
@ -234,6 +275,7 @@ public:
/** /**
* Set noise2 thresholds for squelch opening and closing. * Set noise2 thresholds for squelch opening and closing.
*
* @param highTsh: upper threshold. * @param highTsh: upper threshold.
* @param lowTsh: lower threshold. * @param lowTsh: lower threshold.
*/ */
@ -245,6 +287,7 @@ public:
/** /**
* Set RSSI thresholds for squelch opening and closing. * Set RSSI thresholds for squelch opening and closing.
*
* @param highTsh: upper threshold. * @param highTsh: upper threshold.
* @param lowTsh: lower threshold. * @param lowTsh: lower threshold.
*/ */
@ -256,6 +299,7 @@ public:
/** /**
* Set PA drive control bits. * Set PA drive control bits.
*
* @param value: PA drive value. * @param value: PA drive value.
*/ */
inline void setPaDrive(const uint8_t value) inline void setPaDrive(const uint8_t value)
@ -266,6 +310,7 @@ public:
/** /**
* Set threshold for analog FM squelch opening. * Set threshold for analog FM squelch opening.
*
* @param thresh: squelch threshold. * @param thresh: squelch threshold.
*/ */
inline void setAnalogSqlThresh(const uint8_t thresh) inline void setAnalogSqlThresh(const uint8_t thresh)
@ -332,6 +377,67 @@ private:
* @param reg: address of the register to be read. * @param reg: address of the register to be read.
*/ */
uint16_t i2c_readReg16(const uint8_t reg); uint16_t i2c_readReg16(const uint8_t reg);
/**
* This function returns the value to be written into the AT1846S CTCSS
* threshold register when enabling the detection in RX mode.
* Values were obtained from the function contained in TYT firmware for
* MD-UV380 version S18.16 at address 0x0806ba2c.
*
* @param tone: tone_t variable specifying the CTCSS tone.
* @return an uint16_t value to be written directly into AT1846S
* CTCSS threshold register.
*/
uint16_t getCtcssThreshFromTone(const tone_t tone)
{
switch(tone)
{
case 670: return 0x0C0D; break; // 67.0 Hz
case 693: return 0x0C0C; break; // 69.3 Hz
case 719: return 0x0B0B; break; // 71.9 Hz
case 744: // 74.4 Hz
case 770: return 0x0A0A; break; // 77.0 Hz
case 797: // 79.7 Hz
case 825: return 0x0909; break; // 82.5 Hz
case 854: // 85.4 Hz
case 885: return 0x0808; break; // 88.5 Hz
case 915: // 91.5 Hz
case 948: return 0x0707; break; // 94.8 Hz
case 974: return 0x0706; break; // 97.4 Hz
case 1000: // 100.0Hz
case 1034: return 0x0606; break; // 103.4Hz
case 1072: // 107.2Hz
case 1109: return 0x0605; break; // 110.9Hz
case 1148: return 0x0505; break; // 114.8Hz
case 1188: // 118.8Hz
case 1230: return 0x0504; break; // 123.0Hz
case 1273: // 127.3Hz
case 1318: return 0x0404; break; // 131.8Hz
case 1365: // 136.5Hz
case 1413: // 141.3Hz
case 1462: return 0x0403; break; // 146.2Hz
case 1514: return 0x0504; break; // 151.4Hz
case 1567: // 156.7Hz
case 1622: // 162.2Hz
case 1679: // 167.9Hz
case 1713: // 171.3Hz
case 1799: return 0x0403; break; // 179.9Hz
case 1862: return 0x0400; break; // 186.2Hz
case 1928: return 0x0302; break; // 192.8Hz
case 2035: // 203.5Hz
case 2107: // 210.7Hz
case 2181: // 218.1Hz
case 2257: return 0x0302; break; // 225.7Hz
case 2336: // 233.6Hz
case 2418: // 241.8Hz
case 2503: return 0x0300; break; // 250.3Hz
// 159.8Hz, 165.5Hz, 173.8Hz,
// 177.3Hz, 183.5Hz, 189.9Hz,
// 196.6Hz, 199.5Hz, 206.5Hz,
default: return 0x0505; break; // 229.1Hz, 254.1Hz
}
}
}; };
#endif /* AT1846S_H */ #endif /* AT1846S_H */

View File

@ -119,7 +119,7 @@ void radio_setOpmode(const enum opmode mode)
bool radio_checkRxDigitalSquelch() bool radio_checkRxDigitalSquelch()
{ {
return true; return at1846s.rxCtcssDetected();
} }
void radio_enableRx() void radio_enableRx()
@ -152,6 +152,11 @@ void radio_enableRx()
} }
radioStatus = RX; radioStatus = RX;
if(config->rxToneEn)
{
at1846s.enableRxCtcss(config->rxTone);
}
} }
void radio_enableTx() void radio_enableTx()
@ -204,11 +209,12 @@ void radio_disableRtx()
if(radioStatus == TX) if(radioStatus == TX)
{ {
at1846s.disableCtcss(); // Set PA drive voltage to 0V
DAC0->DAT[0].DATH = 0; DAC0->DAT[0].DATH = 0;
DAC0->DAT[0].DATL = 0; DAC0->DAT[0].DATL = 0;
} }
at1846s.disableCtcss();
at1846s.setFuncMode(AT1846S_FuncMode::OFF); at1846s.setFuncMode(AT1846S_FuncMode::OFF);
radioStatus = OFF; radioStatus = OFF;
} }

View File

@ -191,7 +191,7 @@ void radio_setOpmode(const enum opmode mode)
bool radio_checkRxDigitalSquelch() bool radio_checkRxDigitalSquelch()
{ {
return true; return false;
} }
void radio_enableRx() void radio_enableRx()

View File

@ -125,7 +125,7 @@ void radio_setOpmode(const enum opmode mode)
bool radio_checkRxDigitalSquelch() bool radio_checkRxDigitalSquelch()
{ {
return true; return at1846s.rxCtcssDetected();
} }
void radio_enableRx() void radio_enableRx()
@ -151,6 +151,11 @@ void radio_enableRx()
gpio_setPin(UHF_LNA_EN); gpio_setPin(UHF_LNA_EN);
} }
if(config->rxToneEn)
{
at1846s.enableRxCtcss(config->rxTone);
}
radioStatus = RX; radioStatus = RX;
} }
@ -225,10 +230,10 @@ void radio_disableRtx()
// If we are currently transmitting, stop tone and C6000 TX // If we are currently transmitting, stop tone and C6000 TX
if(radioStatus == TX) if(radioStatus == TX)
{ {
at1846s.disableCtcss();
C6000.stopAnalogTx(); C6000.stopAnalogTx();
} }
at1846s.disableCtcss();
at1846s.setFuncMode(AT1846S_FuncMode::OFF); at1846s.setFuncMode(AT1846S_FuncMode::OFF);
radioStatus = OFF; radioStatus = OFF;
} }