diff --git a/meson.build b/meson.build
index 76da2a56..0b0ab1dd 100644
--- a/meson.build
+++ b/meson.build
@@ -265,7 +265,7 @@ dm1801_src = src + mk22fn512_src + ['platform/targets/DM-1801/platform.c',
'platform/drivers/ADC/ADC0_GDx.c',
'platform/drivers/baseband/rtx_GDx.c',
'platform/drivers/baseband/AT1846S.c',
- 'platform/drivers/baseband/HR-C6000.c',
+ 'platform/drivers/baseband/HR_C6000.c',
'platform/drivers/baseband/interfaces_GDx.c']
dm1801_inc = inc + mk22fn512_inc + ['platform/targets/DM-1801']
@@ -428,7 +428,7 @@ targets = [
'flashable': true,
'wrap': 'UV3X0',
'load_addr': '0x0800C000'},
-
+
{'name': 'mduv380g',
'opts': mduv380g_opts,
'flashable': true,
@@ -446,7 +446,7 @@ targets = [
'flashable': true,
'wrap': 'UV3X0',
'load_addr': '0x0800C000'},
-
+
{'name': 'md9600',
'opts': md9600_opts,
'flashable': true,
diff --git a/platform/drivers/baseband/rtx_GDx.c b/platform/drivers/baseband/rtx_GDx.c
index 1587485d..e47e9688 100644
--- a/platform/drivers/baseband/rtx_GDx.c
+++ b/platform/drivers/baseband/rtx_GDx.c
@@ -18,20 +18,212 @@
* along with this program; if not, see *
***************************************************************************/
+#include
+#include
+#include
+#include
+#include
#include
#include
-#include
#include
#include
#include
-#include
-#include
+#include "HR_C6000.h"
+#include "AT1846S.h"
OS_MUTEX *cfgMutex; /* Mutex for incoming config messages */
OS_Q cfgMailbox; /* Queue for incoming config messages */
+const gdxCalibration_t *calData; /* Pointer to calibration data */
+
rtxStatus_t rtxStatus; /* RTX driver status */
+/*
+ * Helper functions to reduce code mess. They all access 'rtxStatus'
+ * internally.
+ */
+
+int8_t _getBandFromFrequency(freq_t freq)
+{
+ if((freq >= FREQ_LIMIT_VHF_LO) && (freq <= FREQ_LIMIT_VHF_HI)) return 0;
+ if((freq >= FREQ_LIMIT_UHF_LO) && (freq <= FREQ_LIMIT_UHF_HI)) return 1;
+ return -1;
+}
+
+void _setBandwidth()
+{
+ /* Override bandwidth configuration for digital modes */
+ uint8_t bandwidth = BW_12_5;
+ if(rtxStatus.opMode == FM) bandwidth = rtxStatus.bandwidth;
+
+ switch(bandwidth)
+ {
+ case BW_12_5:
+ AT1846S_setBandwidth(AT1846S_BW_12P5);
+ break;
+
+ case BW_20:
+ case BW_25:
+ AT1846S_setBandwidth(AT1846S_BW_25);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void _setOpMode()
+{
+ switch(rtxStatus.opMode)
+ {
+ case FM:
+ gpio_setPin(RX_AUDIO_MUX); /* Audio out to amplifier */
+ gpio_clearPin(TX_AUDIO_MUX); /* Audio in to microphone */
+ AT1846S_setOpMode(AT1846S_OP_FM);
+ break;
+
+ case DMR:
+ gpio_clearPin(RX_AUDIO_MUX); /* Audio out to HR_C6000 */
+ gpio_setPin(TX_AUDIO_MUX); /* Audio in from HR_C6000 */
+ AT1846S_setOpMode(AT1846S_OP_FM);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void _setVcoFrequency()
+{
+ freq_t freq = rtxStatus.rxFrequency;
+ if(rtxStatus.opStatus == TX) freq = rtxStatus.txFrequency;
+ AT1846S_setFrequency(freq);
+}
+
+void _enableTxStage()
+{
+ if(rtxStatus.txDisable == 1) return;
+
+ gpio_clearPin(VHF_LNA_EN);
+ gpio_clearPin(UHF_LNA_EN);
+ gpio_clearPin(VHF_PA_EN);
+ gpio_clearPin(UHF_PA_EN);
+
+ int8_t band = _getBandFromFrequency(rtxStatus.txFrequency);
+ if(band < 0) return;
+
+ /*
+ * Set transmit power. Initial setting is 1W, overridden to 5W if tx power
+ * is greater than 1W.
+ * TODO: increase granularity
+ */
+// const uint8_t *paramPtr = calData->txLowPower;
+// if(rtxStatus.txPower > 1.0f) paramPtr = calData->txHighPower;
+// uint8_t apc = interpCalParameter(rtxStatus.txFrequency, calData->txFreq,
+// paramPtr, 9);
+// DAC->DHR12L1 = apc * 0xFF;
+
+ if(band == 0)
+ {
+ gpio_setPin(VHF_PA_EN);
+ }
+ else
+ {
+ gpio_setPin(UHF_PA_EN);
+ }
+
+ rtxStatus.opStatus = TX;
+ _setVcoFrequency();
+ AT1846S_setFuncMode(AT1846S_TX);
+}
+
+void _enableRxStage()
+{
+ gpio_clearPin(VHF_LNA_EN);
+ gpio_clearPin(UHF_LNA_EN);
+ gpio_clearPin(VHF_PA_EN);
+ gpio_clearPin(UHF_PA_EN);
+
+ int8_t band = _getBandFromFrequency(rtxStatus.rxFrequency);
+ if(band < 0) return;
+
+ if(band == 0)
+ {
+ gpio_setPin(VHF_LNA_EN);
+ }
+ else
+ {
+ gpio_setPin(UHF_LNA_EN);
+ }
+
+ rtxStatus.opStatus = RX;
+ _setVcoFrequency();
+ AT1846S_setFuncMode(AT1846S_RX);
+}
+
+void _disableRtxStages()
+{
+ gpio_clearPin(VHF_LNA_EN);
+ gpio_clearPin(UHF_LNA_EN);
+ gpio_clearPin(VHF_PA_EN);
+ gpio_clearPin(UHF_PA_EN);
+ AT1846S_setFuncMode(AT1846S_OFF);
+ rtxStatus.opStatus = OFF;
+}
+
+void _updateTuningParams()
+{
+ int8_t band = _getBandFromFrequency(rtxStatus.rxFrequency);
+ if(band < 0) return;
+
+ const bandCalData_t *cal = &(calData->data[band]);
+
+ AT1846S_setPgaGain(cal->PGA_gain);
+ AT1846S_setMicGain(cal->analogMicGain);
+ AT1846S_setTxDeviation(cal->txDev_tone);
+ AT1846S_setAgcGain(cal->rxAGCgain);
+ AT1846S_setRxAudioGain(cal->rxAudioGainWideband, cal->rxAudioGainNarrowband);
+ AT1846S_setPaDrive(cal->PA_drv);
+
+ C6000_setDacRange(cal->dacDataRange);
+ C6000_setMod2Bias(cal->mod2Offset);
+ C6000_setModOffset(cal->mod1Bias);
+
+ uint8_t mod1Amp = 0;
+ uint8_t sqlTresh = 0;
+ if(band == 0)
+ {
+ /* VHF band */
+ mod1Amp = interpCalParameter(rtxStatus.txFrequency, calData->vhfCalPoints,
+ cal->mod1Amplitude, 8);
+
+ sqlTresh = interpCalParameter(rtxStatus.rxFrequency, calData->vhfCalPoints,
+ cal->analogSqlThresh, 8);
+ }
+ else
+ {
+ /* UHF band */
+ mod1Amp = interpCalParameter(rtxStatus.txFrequency, calData->uhfMod1CalPoints,
+ cal->mod1Amplitude, 8);
+
+ sqlTresh = interpCalParameter(rtxStatus.rxFrequency, calData->uhfMod1CalPoints,
+ cal->analogSqlThresh, 8);
+ }
+
+ C6000_setMod1Amplitude(mod1Amp);
+ AT1846S_setAnalogSqlThresh(sqlTresh);
+}
+
+void _setCTCSS()
+{
+ /* TODO */
+}
+
+void _updateSqlThresholds()
+{
+ /* TODO */
+}
+
void rtx_init(OS_MUTEX *m)
{
/* Initialise mutex for configuration access */
@@ -44,6 +236,41 @@ void rtx_init(OS_MUTEX *m)
(OS_MSG_QTY) 1,
(OS_ERR *) &err);
+ /*
+ * Configure RTX GPIOs
+ */
+ gpio_setMode(VHF_LNA_EN, OUTPUT);
+ gpio_setMode(UHF_LNA_EN, OUTPUT);
+ gpio_setMode(VHF_PA_EN, OUTPUT);
+ gpio_setMode(UHF_PA_EN, OUTPUT);
+
+ gpio_clearPin(VHF_LNA_EN); /* Turn VHF LNA off */
+ gpio_clearPin(UHF_LNA_EN); /* Turn UHF LNA off */
+ gpio_clearPin(VHF_PA_EN); /* Turn VHF PA off */
+ gpio_clearPin(UHF_PA_EN); /* Turn UHF PA off */
+
+ /*
+ * Configure audio control GPIOs
+ */
+ gpio_setMode(AUDIO_AMP_EN, OUTPUT);
+ gpio_setMode(RX_AUDIO_MUX, OUTPUT);
+ gpio_setMode(TX_AUDIO_MUX, OUTPUT);
+
+ gpio_clearPin(AUDIO_AMP_EN);
+ gpio_clearPin(RX_AUDIO_MUX);
+ gpio_clearPin(TX_AUDIO_MUX);
+
+ /*
+ * Load calibration data
+ */
+ calData = ((const gdxCalibration_t *) platform_getCalibrationData());
+
+ /*
+ * Enable and configure both AT1846S and HR_C6000
+ */
+ AT1846S_init();
+ C6000_init();
+
/*
* Default initialisation for rtx status
*/
@@ -55,12 +282,17 @@ void rtx_init(OS_MUTEX *m)
rtxStatus.txFrequency = 430000000;
rtxStatus.txPower = 0.0f;
rtxStatus.sqlLevel = 1;
+ rtxStatus.rxToneEn = 0;
rtxStatus.rxTone = 0;
+ rtxStatus.txToneEn = 0;
rtxStatus.txTone = 0;
}
void rtx_terminate()
{
+ _disableRtxStages();
+ gpio_clearPin(AUDIO_AMP_EN);
+ C6000_terminate();
}
void rtx_configure(const rtxStatus_t *cfg)
@@ -119,13 +351,58 @@ void rtx_taskFunc()
/* Done, release mutex */
OSMutexPost(cfgMutex, OS_OPT_POST_NONE, &err);
+
+ /* Update HW configuration */
+ _setOpMode();
+ _setBandwidth();
+ _updateTuningParams();
+ _setCTCSS();
+ _updateSqlThresholds();
+ _setVcoFrequency();
+
+ /* TODO: temporarily force to RX mode if rtx is off. */
+ if(rtxStatus.opStatus == OFF) _enableRxStage();
+ }
+ }
+
+ if(rtxStatus.opStatus == RX)
+ {
+ float sqlLevel = (rtx_getRssi() + 127.0f)/6.0f;
+
+ float sqlThresh = 7.0f;
+ if(rtxStatus.sqlLevel > 0) sqlThresh = 3.0f;
+
+ if((gpio_readPin(AUDIO_AMP_EN) == 0) && (sqlLevel > (sqlThresh + 0.1f)))
+ {
+ gpio_setPin(AUDIO_AMP_EN);
+ platform_ledOn(GREEN);
}
- // Do nothing since this is a stub
+ if((gpio_readPin(AUDIO_AMP_EN) == 1) && (sqlLevel < sqlThresh))
+ {
+ gpio_clearPin(AUDIO_AMP_EN);
+ platform_ledOff(GREEN);
+ }
}
+
+// if(platform_getPttStatus() && (rtxStatus.opStatus != TX))
+// {
+// _disableRtxStages();
+// _enableTxStage();
+// platform_ledOn(RED);
+// }
+//
+// if(!platform_getPttStatus() && (rtxStatus.opStatus == TX))
+// {
+// _disableRtxStages();
+// _enableRxStage();
+// platform_ledOff(RED);
+// }
}
float rtx_getRssi()
{
- return 0.0;
+ uint16_t val = AT1846S_readRSSI();
+ int8_t rssi = -151 + (val >> 8);
+ return ((float) rssi);
}
diff --git a/platform/targets/DM-1801/platform.c b/platform/targets/DM-1801/platform.c
index 0cf0d3b7..7db38030 100644
--- a/platform/targets/DM-1801/platform.c
+++ b/platform/targets/DM-1801/platform.c
@@ -19,8 +19,10 @@
***************************************************************************/
#include
-#include
+#include
#include
+#include
+#include
#include
#include
#include "hwconfig.h"
@@ -29,6 +31,8 @@
OS_MUTEX adc_mutex;
OS_ERR e;
+gdxCalibration_t calibration;
+
void platform_init()
{
/* Configure GPIOs */
@@ -70,6 +74,12 @@ void platform_init()
gpio_setAlternateFunction(I2C_SDA, 3);
gpio_setAlternateFunction(I2C_SCL, 3);
i2c0_init();
+
+ /*
+ * Initialise non volatile memory manager and load calibration data.
+ */
+ nvm_init();
+ nvm_readCalibData(&calibration);
}
void platform_terminate()
@@ -169,3 +179,8 @@ void platform_setBacklightLevel(uint8_t level)
{
FTM0->CONTROLS[3].CnV = level;
}
+
+const void *platform_getCalibrationData()
+{
+ return ((const void *) &calibration);
+}