Initial implementation of rtx driver for TYT MD-380 radio, by now supporting only analog FM reception

replace/28c74ad279e6f8f10b7d57f40f37dbfd59d11dd8
Silvano Seva 2020-11-14 14:44:59 +01:00
rodzic 17376b819a
commit 55b182406d
7 zmienionych plików z 494 dodań i 17 usunięć

Wyświetl plik

@ -11,7 +11,6 @@ project('OpenRTX', 'c',
## OpenRTX
openrtx_src = ['openrtx/src/bootstrap.c',
'openrtx/src/state.c',
'openrtx/src/ui.c',
@ -32,6 +31,8 @@ openrtx_inc = ['openrtx/include/interfaces',
'platform/drivers/NVM',
'platform/drivers/tones',
'openrtx/include/fonts/adafruit']
'platform/drivers/tones',
'platform/drivers/baseband']
## RTOS
rtos_src = ['rtos/uC-OS3/Source/__dbg_uCOS-III.c',
@ -174,6 +175,8 @@ md380_src = src + stm32f405_src + ['platform/drivers/display/HX83XX_MDx.c',
'platform/drivers/NVM/extFlash_MDx.c',
'platform/drivers/NVM/nvmem_MD3x0.c',
'platform/drivers/tones/toneGenerator_MDx.c',
'platform/drivers/baseband/pll_MD3x0.c',
'platform/drivers/baseband/rtx_MD3x0.c',
'platform/targets/MD-380/platform.c',
'openrtx/src/graphics/graphics_rgb565.c']

Wyświetl plik

@ -22,23 +22,23 @@
#include <stdint.h>
/**
* \brief CTCSS and DCS type definition.
*
* Continuous Tone Controlled Squelch System (CTCSS)
* sub-audible tone frequency are expressed in \em tenth of Hz.
* For example, the subaudible tone of 88.5 Hz is represented within
* Hamlib by 885.
*
* Digitally-Coded Squelch codes are simple direct integers.
*/
/**
* \brief CTCSS and DCS type definition.
*
* Continuous Tone Controlled Squelch System (CTCSS)
* sub-audible tone frequency are expressed in \em tenth of Hz.
* For example, the subaudible tone of 88.5 Hz is represented within Hamlib by
* 885.
*
* Digitally-Coded Squelch codes are simple direct integers.
*/
typedef unsigned int tone_t;
/**
* \brief Frequency type,
*
* Frequency type unit in Hz, able to hold SHF frequencies.
*/
/**
* \brief Frequency type.
*
* Frequency type unit in Hz, able to hold SHF frequencies.
*/
typedef uint32_t freq_t;
#endif /* DATATYPES_H */

Wyświetl plik

@ -0,0 +1,74 @@
/***************************************************************************
* Copyright (C) 2020 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN *
* Frederik Saraci IU2NRO *
* Silvano Seva IU2KWO *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, see <http://www.gnu.org/licenses/> *
***************************************************************************/
#ifndef RTX_H
#define RTX_H
#include <stdint.h>
#include <datatypes.h>
enum funcmode
{
OFF,
RX,
TX
};
enum tone
{
NONE,
CTCSS_67_0,
CTCSS_71_9,
CTCSS_81_5
};
enum bw
{
BW_12_5,
BW_25
};
enum opmode
{
FM,
DMR
};
void rtx_init();
void rtx_terminate();
void rtx_setTxFreq(freq_t freq);
void rtx_setRxFreq(freq_t freq);
void rtx_setFuncmode(enum funcmode mode);
void rtx_setToneRx(enum tone t);
void rtx_setToneTx(enum tone t);
void rtx_setBandwidth(enum bw b);
float rtx_getRssi();
void rtx_setOpmode(enum opmode mode);
#endif /* RTX_H */

Wyświetl plik

@ -0,0 +1,111 @@
/***************************************************************************
* Copyright (C) 2020 by Silvano Seva IU2KWO and Niccolò Izzo IU2KIN *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, see <http://www.gnu.org/licenses/> *
***************************************************************************/
#include "pll_MD3x0.h"
#include <math.h>
#include "gpio.h"
#include "delays.h"
#include "hwconfig.h"
#define REF_CLK 16800000.0F /* Reference clock: 16.8MHz */
#define PHD_GAIN 0x1F /* Phase detector gain: hex value, max 0x1F */
void _spiSend(uint16_t value)
{
uint16_t temp = value;
gpio_clearPin(PLL_CS);
delayUs(10);
for(uint8_t i = 0; i < 16; i++)
{
gpio_setPin(PLL_CLK);
delayUs(1);
if(temp & 0x8000)
{
gpio_setPin(PLL_DAT);
}
else
{
gpio_clearPin(PLL_DAT);
}
temp <<= 1;
delayUs(1);
gpio_clearPin(PLL_CLK);
delayUs(1);
}
gpio_setPin(PLL_CLK);
delayUs(10);
gpio_setPin(PLL_CS);
}
void pll_init()
{
gpio_setMode(PLL_CLK, OUTPUT);
gpio_setMode(PLL_DAT, OUTPUT);
gpio_setMode(PLL_CS, OUTPUT);
gpio_setPin(PLL_CS);
gpio_setMode(PLL_LD, INPUT);
_spiSend(0x6000 | ((uint16_t) PHD_GAIN)); /* Phase detector gain */
_spiSend(0x73D0); /* Power down/multiplexer control register */
_spiSend(0x8000); /* Modulation control register */
_spiSend(0x9000); /* Modulation data register */
}
void pll_terminate()
{
gpio_setMode(PLL_CLK, INPUT);
gpio_setMode(PLL_DAT, INPUT);
gpio_setMode(PLL_CS, INPUT);
}
void pll_setFrequency(float freq, uint8_t clkDiv)
{
/* Maximum allowable value for reference clock divider is 32 */
if (clkDiv > 32) clkDiv = 32;
float K = freq/(REF_CLK/((float) clkDiv));
float Ndiv = floor(K) - 32.0;
float Ndnd = round(262144*(K - Ndiv - 32.0));
uint32_t dnd = ((uint32_t) Ndnd);
uint16_t dndMsb = dnd >> 8;
uint16_t dndLsb = dnd & 0x00FF;
_spiSend((uint16_t) Ndiv); /* Divider register */
_spiSend(0x2000 | dndLsb); /* Dividend LSB register */
_spiSend(0x1000 | dndMsb); /* Dividend MSB register */
_spiSend(0x5000 | ((uint16_t)clkDiv - 1)); /* Reference clock divider */
}
bool pll_locked()
{
return (gpio_readPin(PLL_LD) == 1) ? true : false;
}
bool pll_spiInUse()
{
/* If PLL chip select is low, SPI is being used by this driver. */
return (gpio_readPin(PLL_CS) == 1) ? false : true;
}

Wyświetl plik

@ -0,0 +1,64 @@
/***************************************************************************
* Copyright (C) 2020 by Silvano Seva IU2KWO and Niccolò Izzo IU2KIN *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, see <http://www.gnu.org/licenses/> *
***************************************************************************/
#ifndef PLL_MD3x0_H
#define PLL_MD3x0_H
#include <stdint.h>
#include <stdbool.h>
/**
* Driver for PLL in MD3x0 radios (MD380 and MD380), which is SKY73210.
*
* WARNING: the PLL and DMR chips share the SPI MOSI line, thus particular care
* has to be put to avoid them stomping reciprocally. This driver does not make
* any check if a SPI transfer is already in progress, deferring the correct bus
* management to higher level modules. However, a function returning true if the
* bus is currently in use by this driver is provided.
*/
/**
* Initialise the PLL.
*/
void pll_init();
/**
* Terminate PLL driver, bringing GPIOs back to reset state.
*/
void pll_terminate();
/**
* Change VCO frequency.
* @param freq: new VCO frequency, in Hz.
* @param clkDiv: reference clock division factor.
*/
void pll_setFrequency(float freq, uint8_t clkDiv);
/**
* Check if PLL is locked.
* @return true if PLL is locked.
*/
bool pll_locked();
/**
* Check if the SPI bus in common between PLL and DMR chips is in use by this
* driver.
* @return true if this driver is using the SPI bus.
*/
bool pll_spiInUse();
#endif /* PLL_H */

Wyświetl plik

@ -0,0 +1,194 @@
/***************************************************************************
* Copyright (C) 2020 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN *
* Frederik Saraci IU2NRO *
* Silvano Seva IU2KWO *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, see <http://www.gnu.org/licenses/> *
***************************************************************************/
#include <hwconfig.h>
#include <datatypes.h>
#include <gpio.h>
#include "rtx.h"
#include "pll_MD3x0.h"
#include "ADC1_MDxx380.h"
const freq_t IF_FREQ = 49950000.0f; /* Intermediate frequency: 49.95MHz */
freq_t rxFreq = 430000000.0f;
freq_t txFreq = 430000000.0f;
void _setMod2Bias(uint16_t value)
{
DAC->DHR12R2 = value;
}
void _setApcTv(uint16_t value)
{
DAC->DHR12R1 = value;
}
void rtx_init()
{
/*
* Configure GPIOs
*/
gpio_setMode(PLL_PWR, OUTPUT);
gpio_setMode(VCOVCC_SW, OUTPUT);
gpio_setMode(DMR_SW, OUTPUT);
gpio_setMode(WN_SW, OUTPUT);
gpio_setMode(FM_SW, OUTPUT);
// gpio_setMode(V_CS, OUTPUT);
gpio_setMode(RF_APC_SW, OUTPUT);
gpio_setMode(TX_STG_EN, OUTPUT);
gpio_setMode(RX_STG_EN, OUTPUT);
gpio_clearPin(PLL_PWR); /* PLL off */
gpio_setPin(VCOVCC_SW); /* VCOVCC high enables RX VCO, TX VCO if low */
gpio_clearPin(WN_SW); /* 25kHz band (?) */
gpio_clearPin(DMR_SW); /* Disconnect HR_C5000 input IF signal and audio out */
gpio_clearPin(FM_SW); /* Disconnect analog FM audio path */
// gpio_setPin(V_CS);
gpio_clearPin(RF_APC_SW); /* Disable RF power control */
gpio_clearPin(TX_STG_EN); /* Disable TX power stage */
gpio_clearPin(RX_STG_EN); /* Disable RX input stage */
/*
* Configure and enble DAC
*/
gpio_setMode(APC_TV, INPUT_ANALOG);
gpio_setMode(MOD2_BIAS, INPUT_ANALOG);
RCC->APB1ENR |= RCC_APB1ENR_DACEN;
DAC->CR = DAC_CR_EN2 | DAC_CR_EN1;
DAC->DHR12R2 = 0;
DAC->DHR12R1 = 0;
/*
* Enable and configure PLL
*/
gpio_setPin(PLL_PWR);
pll_init();
}
void rtx_terminate()
{
pll_terminate();
gpio_clearPin(PLL_PWR); /* PLL off */
gpio_clearPin(DMR_SW); /* Disconnect HR_C5000 input IF signal and audio out */
gpio_clearPin(FM_SW); /* Disconnect analog FM audio path */
gpio_clearPin(RF_APC_SW); /* Disable RF power control */
gpio_clearPin(TX_STG_EN); /* Disable TX power stage */
gpio_clearPin(RX_STG_EN); /* Disable RX input stage */
DAC->DHR12R2 = 0;
DAC->DHR12R1 = 0;
RCC->APB1ENR &= ~RCC_APB1ENR_DACEN;
}
void rtx_setTxFreq(freq_t freq)
{
txFreq = freq;
}
void rtx_setRxFreq(freq_t freq)
{
rxFreq = freq;
}
void rtx_setFuncmode(enum funcmode mode)
{
switch(mode)
{
case OFF:
gpio_clearPin(TX_STG_EN);
gpio_clearPin(RX_STG_EN);
break;
case RX:
gpio_clearPin(TX_STG_EN);
gpio_clearPin(RF_APC_SW);
gpio_setPin(VCOVCC_SW);
pll_setFrequency(rxFreq - IF_FREQ, 5);
_setMod2Bias(0x3c0); /* TODO use calibration */
_setApcTv(0x956); /* TODO use calibration */
gpio_setPin(RX_STG_EN);
break;
case TX:
/* TODO */
break;
default:
/* TODO */
break;
}
}
void rtx_setToneRx(enum tone t)
{
/* TODO */
}
void rtx_setToneTx(enum tone t)
{
/* TODO */
}
void rtx_setBandwidth(enum bw b)
{
switch(b)
{
case BW_25:
gpio_clearPin(WN_SW);
break;
case BW_12_5:
gpio_setPin(WN_SW);
break;
default:
/* TODO */
break;
}
}
float rtx_getRssi()
{
return adc1_getMeasurement(1);
}
void rtx_setOpmode(enum opmode mode)
{
switch(mode)
{
case FM:
gpio_clearPin(DMR_SW);
gpio_setPin(FM_SW);
break;
case DMR:
gpio_clearPin(FM_SW);
gpio_setPin(DMR_SW);
break;
default:
/* TODO */
break;
}
}

Wyświetl plik

@ -87,4 +87,35 @@
#define FLASH_SDO GPIOB,4
#define FLASH_SDI GPIOB,5
/* PLL */
#define PLL_CS GPIOD,11
#define PLL_CLK GPIOE,4
#define PLL_DAT GPIOE,5 /* WARNING: this line is also HR_C5000 MOSI */
#define PLL_LD GPIOD,10
/* HR_C5000 */
#define DMR_CS GPIOE,2
#define DMR_CLK GPIOC,13
#define DMR_MOSI PLL_DAT
#define DMR_MISO GPIOE,3
#define DMR_SLEEP GPIOE,6
#define V_CS GPIOB,12
/* RTX control */
#define PLL_PWR GPIOA,8
#define VCOVCC_SW GPIOA,9
#define DMR_SW GPIOA,10
#define FM_SW GPIOB,2
#define WN_SW GPIOA,13
#define RF_APC_SW GPIOC,4
#define TX_STG_EN GPIOC,5
#define RX_STG_EN GPIOC,9
#define APC_TV GPIOA,4
#define MOD2_BIAS GPIOA,5
/* Audio control */
#define AMP_EN GPIOB,9
#define SPK_MUTE GPIOB,8
#define FM_MUTE GPIOE,13
#endif