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

replace/711ae1a683dc784fe516cb2dc3d4ddfa4a28acc9
Silvano Seva 2021-06-02 12:44:46 +02:00
rodzic fdba408831
commit b29b24fdc0
6 zmienionych plików z 159 dodań i 26 usunięć

Wyświetl plik

@ -83,7 +83,8 @@ public:
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.
};

Wyświetl plik

@ -66,7 +66,7 @@ void _setVolume()
}
#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()
{
// When starting, close squelch and prepare for entering in RX mode.
sqlOpen = false;
enterRx = true;
rfSqlOpen = false;
sqlOpen = false;
enterRx = true;
}
void OpMode_FM::disable()
@ -87,8 +88,9 @@ void OpMode_FM::disable()
audio_disableAmp();
audio_disableMic();
radio_disableRtx();
sqlOpen = false;
enterRx = false;
rfSqlOpen = false;
sqlOpen = false;
enterRx = false;
}
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
if(status->opStatus == RX)
{
// RF squelch mechanism
float squelch = -127.0f + status->sqlLevel * 66.0f / 15.0f;
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();
sqlOpen = true;
}
if((sqlOpen == true) && (rssi < (squelch - 0.1f)))
if((sqlOpen == true) && (rfSql == false) && (toneSql == false))
{
audio_disableAmp();
sqlOpen = false;
}
#ifdef PLATFORM_MDUV3x0
if(sqlOpen == true)
{
// Set output volume by changing the HR_C6000 DAC gain
_setVolume();
}
// Set output volume by changing the HR_C6000 DAC gain
if(sqlOpen == true) _setVolume();
#endif
}
else if((status->opStatus == OFF) && enterRx)
{
@ -130,7 +138,7 @@ void OpMode_FM::update(rtxStatus_t *const status, const bool newCfg)
enterRx = false;
}
/* TX logic */
// TX logic
if(platform_getPttStatus() && (status->opStatus != TX) &&
(status->txDisable == 0))
{
@ -156,13 +164,20 @@ void OpMode_FM::update(rtxStatus_t *const status, const bool newCfg)
switch(status->opStatus)
{
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
{
platform_ledOff(GREEN);
platform_ledOff(RED);
}
break;

Wyświetl plik

@ -96,6 +96,7 @@ public:
/**
* Set the VCO frequency, either for transmission or reception.
*
* @param freq: VCO frequency.
*/
void setFrequency(const freq_t freq)
@ -113,18 +114,21 @@ public:
/**
* Set the transmission and reception bandwidth.
*
* @param band: bandwidth.
*/
void setBandwidth(const AT1846S_BW band);
/**
* Set the operating mode.
*
* @param mode: operating mode.
*/
void setOpMode(const AT1846S_OpMode mode);
/**
* Set the functional mode.
*
* @param mode: functional mode.
*/
void setFuncMode(const AT1846S_FuncMode mode)
@ -140,14 +144,42 @@ public:
/**
* Enable the CTCSS tone for transmission.
*
* @param freq: CTCSS tone frequency.
*/
void enableTxCtcss(const tone_t freq)
{
i2c_writeReg16(0x4A, freq*10);
i2c_writeReg16(0x4B, 0x0000);
i2c_writeReg16(0x4A, freq*10); // Set CTCSS1 frequency reg.
i2c_writeReg16(0x4B, 0x0000); // Clear CDCSS bits
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()
{
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.
*
* @return current RSSI in dBm.
*/
inline int16_t readRSSI()
@ -171,6 +206,7 @@ public:
/**
* Set the gain of internal programmable gain amplifier.
*
* @param gain: PGA gain.
*/
inline void setPgaGain(const uint8_t gain)
@ -181,6 +217,7 @@ public:
/**
* Set microphone gain for transmission.
*
* @param gain: microphone gain.
*/
inline void setMicGain(const uint8_t gain)
@ -190,6 +227,7 @@ public:
/**
* Set maximum FM transmission deviation.
*
* @param dev: maximum allowed deviation.
*/
inline void setTxDeviation(const uint16_t dev)
@ -200,6 +238,7 @@ public:
/**
* Set the gain for internal automatic gain control system.
*
* @param gain: AGC gain.
*/
inline void setAgcGain(const uint8_t gain)
@ -210,6 +249,7 @@ public:
/**
* Set audio gain for recepion.
*
* @param analogDacGain: "analog DAC 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.
*
* @param highTsh: upper threshold.
* @param lowTsh: lower threshold.
*/
@ -234,6 +275,7 @@ public:
/**
* Set noise2 thresholds for squelch opening and closing.
*
* @param highTsh: upper threshold.
* @param lowTsh: lower threshold.
*/
@ -245,6 +287,7 @@ public:
/**
* Set RSSI thresholds for squelch opening and closing.
*
* @param highTsh: upper threshold.
* @param lowTsh: lower threshold.
*/
@ -256,6 +299,7 @@ public:
/**
* Set PA drive control bits.
*
* @param value: PA drive value.
*/
inline void setPaDrive(const uint8_t value)
@ -266,6 +310,7 @@ public:
/**
* Set threshold for analog FM squelch opening.
*
* @param thresh: squelch threshold.
*/
inline void setAnalogSqlThresh(const uint8_t thresh)
@ -332,6 +377,67 @@ private:
* @param reg: address of the register to be read.
*/
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 */

Wyświetl plik

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

Wyświetl plik

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

Wyświetl plik

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