diff --git a/meson.build b/meson.build index 5487ebc3..d11062b3 100644 --- a/meson.build +++ b/meson.build @@ -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'] diff --git a/openrtx/include/datatypes.h b/openrtx/include/datatypes.h index a6106cf8..fe4ec7ab 100644 --- a/openrtx/include/datatypes.h +++ b/openrtx/include/datatypes.h @@ -22,23 +22,23 @@ #include -/** - * \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 */ diff --git a/openrtx/include/interfaces/rtx.h b/openrtx/include/interfaces/rtx.h new file mode 100644 index 00000000..596c7b43 --- /dev/null +++ b/openrtx/include/interfaces/rtx.h @@ -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 * + ***************************************************************************/ + +#ifndef RTX_H +#define RTX_H + +#include +#include + +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 */ diff --git a/platform/drivers/baseband/pll_MD3x0.c b/platform/drivers/baseband/pll_MD3x0.c new file mode 100644 index 00000000..69b7f088 --- /dev/null +++ b/platform/drivers/baseband/pll_MD3x0.c @@ -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 * + ***************************************************************************/ + +#include "pll_MD3x0.h" +#include +#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; +} + diff --git a/platform/drivers/baseband/pll_MD3x0.h b/platform/drivers/baseband/pll_MD3x0.h new file mode 100644 index 00000000..695931ef --- /dev/null +++ b/platform/drivers/baseband/pll_MD3x0.h @@ -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 * + ***************************************************************************/ + +#ifndef PLL_MD3x0_H +#define PLL_MD3x0_H + +#include +#include + +/** + * 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 */ diff --git a/platform/drivers/baseband/rtx_MD3x0.c b/platform/drivers/baseband/rtx_MD3x0.c new file mode 100644 index 00000000..c4ea981a --- /dev/null +++ b/platform/drivers/baseband/rtx_MD3x0.c @@ -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 * + ***************************************************************************/ + +#include +#include +#include +#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; + } +} diff --git a/platform/targets/MD-380/hwconfig.h b/platform/targets/MD-380/hwconfig.h index 293e5f70..a4cd2a16 100644 --- a/platform/targets/MD-380/hwconfig.h +++ b/platform/targets/MD-380/hwconfig.h @@ -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