diff --git a/meson.build b/meson.build index 6f92f874..f17d7271 100644 --- a/meson.build +++ b/meson.build @@ -168,9 +168,9 @@ mdx_src = ['platform/drivers/ADC/ADC1_MDx.c', ## gdx_src = ['platform/targets/GDx/platform.c', + 'platform/targets/GDx/hwconfig.c', 'platform/drivers/NVM/W25Qx.c', 'platform/drivers/NVM/AT24Cx_GDx.c', - 'platform/drivers/NVM/spiFlash_GDx.c', 'platform/drivers/NVM/nvmem_GDx.c', 'platform/drivers/CPS/cps_io_native_GDx.c', 'platform/drivers/ADC/ADC0_GDx.c', @@ -181,7 +181,9 @@ gdx_src = ['platform/targets/GDx/platform.c', 'platform/drivers/baseband/HR_C6000_GDx.cpp', 'platform/drivers/display/UC1701_GDx.c', 'platform/drivers/keyboard/keyboard_GDx.c', - 'platform/drivers/audio/audio_GDx.c'] + 'platform/drivers/audio/audio_GDx.c', + 'platform/drivers/SPI/spi_custom.c', + 'platform/drivers/SPI/spi_bitbang.c'] gdx_inc = ['platform/targets/GDx'] diff --git a/platform/drivers/CPS/cps_io_native_GDx.c b/platform/drivers/CPS/cps_io_native_GDx.c index 71eb7984..dee5d919 100644 --- a/platform/drivers/CPS/cps_io_native_GDx.c +++ b/platform/drivers/CPS/cps_io_native_GDx.c @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2020 - 2023 by Federico Amedeo Izzo IU2NUO, * + * Copyright (C) 2020 - 2024 by Federico Amedeo Izzo IU2NUO, * * Niccolò Izzo IU2KIN * * Frederik Saraci IU2NRO * * Silvano Seva IU2KWO * @@ -22,6 +22,7 @@ #include #include #include +#include #include #include "AT24Cx.h" #include "W25Qx.h" @@ -37,6 +38,8 @@ static const uint32_t maxNumChannels = 1024; /**< Maximum number of c static const uint32_t maxNumZones = 68; /**< Maximum number of zones in memory */ static const uint32_t maxNumContacts = 1024; /**< Maximum number of contacts in memory */ +extern const struct nvmDevice eflash; + // Strings in GD-77 codeplug are terminated with 0xFF, // replace 0xFF terminator with 0x00 to be compatible with C strings static void _addStringTerminator(char *buf, uint8_t max_len) @@ -100,11 +103,8 @@ int cps_readChannel(channel_t *channel, uint16_t pos) // Remaining 7 channel banks (896 channels) are saved in SPI Flash else { - W25Qx_wakeup(); - delayUs(5); uint32_t readAddr = channelBaseAddrFlash + (bank_num - 1) * sizeof(gdxChannelBank_t); - W25Qx_readData(readAddr, ((uint8_t *) &bitmap), sizeof(bitmap)); - W25Qx_sleep(); + nvm_devRead(&eflash, readAddr, ((uint8_t *) &bitmap), sizeof(bitmap)); } uint8_t bitmap_byte = bank_channel / 8; uint8_t bitmap_bit = bank_channel % 8; @@ -126,11 +126,8 @@ int cps_readChannel(channel_t *channel, uint16_t pos) // Remaining 7 channel banks (896 channels) are saved in SPI Flash else { - W25Qx_wakeup(); - delayUs(5); uint32_t bankAddr = channelBaseAddrFlash + bank_num * sizeof(gdxChannelBank_t); - W25Qx_readData(bankAddr + channelOffset, ((uint8_t *) &chData), sizeof(gdxChannel_t)); - W25Qx_sleep(); + nvm_devRead(&eflash, bankAddr + channelOffset, ((uint8_t *) &chData), sizeof(gdxChannel_t)); } } // Copy data to OpenRTX channel_t @@ -245,13 +242,9 @@ int cps_readContact(contact_t *contact, uint16_t pos) { if(pos >= maxNumContacts) return -1; - W25Qx_wakeup(); - delayUs(5); - gdxContact_t contactData; uint32_t contactAddr = contactBaseAddr + pos * sizeof(gdxContact_t); - W25Qx_readData(contactAddr, ((uint8_t *) &contactData), sizeof(gdxContact_t)); - W25Qx_sleep(); + nvm_devRead(&eflash, contactAddr, ((uint8_t *) &contactData), sizeof(gdxContact_t)); // Check if contact is empty if(wcslen((wchar_t *) contactData.name) == 0) return -1; diff --git a/platform/drivers/NVM/nvmem_GDx.c b/platform/drivers/NVM/nvmem_GDx.c index 44b5201d..40dd3cb8 100644 --- a/platform/drivers/NVM/nvmem_GDx.c +++ b/platform/drivers/NVM/nvmem_GDx.c @@ -22,13 +22,22 @@ #include #include #include +#include #include +#include +#include #include #include "AT24Cx.h" #include "W25Qx.h" -W25Qx_DEVICE_DEFINE(eflash, 0x100000) // 1 MB, 8 Mbit -AT24Cx_DEVICE_DEFINE(eeprom, 0x10000) // 64 kB, 512 kbit +static const struct W25QxCfg eflashCfg = +{ + .spi = (const struct spiDevice *) &nvm_spi, + .cs = { FLASH_CS } +}; + +W25Qx_DEVICE_DEFINE(eflash, eflashCfg, 0x100000) // 1 MB, 8 Mbit +AT24Cx_DEVICE_DEFINE(eeprom, 0x10000) // 64 kB, 512 kbit static const struct nvmDescriptor nvmDevices[] = { @@ -65,42 +74,42 @@ static const uint32_t VHF_CAL_BASE = 0x6F070; */ static void _loadBandCalData(uint32_t baseAddr, bandCalData_t *cal) { - W25Qx_readData(baseAddr + 0x08, &(cal->modBias), 2); - W25Qx_readData(baseAddr + 0x0A, &(cal->mod2Offset), 1); - W25Qx_readData(baseAddr + 0x3F, cal->analogSqlThresh, 8); - W25Qx_readData(baseAddr + 0x47, &(cal->noise1_HighTsh_Wb), 1); - W25Qx_readData(baseAddr + 0x48, &(cal->noise1_LowTsh_Wb), 1); - W25Qx_readData(baseAddr + 0x49, &(cal->noise2_HighTsh_Wb), 1); - W25Qx_readData(baseAddr + 0x4A, &(cal->noise2_LowTsh_Wb), 1); - W25Qx_readData(baseAddr + 0x4B, &(cal->rssi_HighTsh_Wb), 1); - W25Qx_readData(baseAddr + 0x4C, &(cal->rssi_LowTsh_Wb), 1); - W25Qx_readData(baseAddr + 0x4D, &(cal->noise1_HighTsh_Nb), 1); - W25Qx_readData(baseAddr + 0x4E, &(cal->noise1_LowTsh_Nb), 1); - W25Qx_readData(baseAddr + 0x4F, &(cal->noise2_HighTsh_Nb), 1); - W25Qx_readData(baseAddr + 0x50, &(cal->noise2_LowTsh_Nb), 1); - W25Qx_readData(baseAddr + 0x51, &(cal->rssi_HighTsh_Nb), 1); - W25Qx_readData(baseAddr + 0x52, &(cal->rssi_LowTsh_Nb), 1); - W25Qx_readData(baseAddr + 0x53, &(cal->RSSILowerThreshold), 1); - W25Qx_readData(baseAddr + 0x54, &(cal->RSSIUpperThreshold), 1); - W25Qx_readData(baseAddr + 0x55, cal->mod1Amplitude, 8); - W25Qx_readData(baseAddr + 0x5D, &(cal->digAudioGain), 1); - W25Qx_readData(baseAddr + 0x5E, &(cal->txDev_DTMF), 1); - W25Qx_readData(baseAddr + 0x5F, &(cal->txDev_tone), 1); - W25Qx_readData(baseAddr + 0x60, &(cal->txDev_CTCSS_wb), 1); - W25Qx_readData(baseAddr + 0x61, &(cal->txDev_CTCSS_nb), 1); - W25Qx_readData(baseAddr + 0x62, &(cal->txDev_DCS_wb), 1); - W25Qx_readData(baseAddr + 0x63, &(cal->txDev_DCS_nb), 1); - W25Qx_readData(baseAddr + 0x64, &(cal->PA_drv), 1); - W25Qx_readData(baseAddr + 0x65, &(cal->PGA_gain), 1); - W25Qx_readData(baseAddr + 0x66, &(cal->analogMicGain), 1); - W25Qx_readData(baseAddr + 0x67, &(cal->rxAGCgain), 1); - W25Qx_readData(baseAddr + 0x68, &(cal->mixGainWideband), 2); - W25Qx_readData(baseAddr + 0x6A, &(cal->mixGainNarrowband), 2); - W25Qx_readData(baseAddr + 0x6C, &(cal->rxDacGain), 1); - W25Qx_readData(baseAddr + 0x6D, &(cal->rxVoiceGain), 1); + nvm_devRead(&eflash, baseAddr + 0x08, &(cal->modBias), 2); + nvm_devRead(&eflash, baseAddr + 0x0A, &(cal->mod2Offset), 1); + nvm_devRead(&eflash, baseAddr + 0x3F, cal->analogSqlThresh, 8); + nvm_devRead(&eflash, baseAddr + 0x47, &(cal->noise1_HighTsh_Wb), 1); + nvm_devRead(&eflash, baseAddr + 0x48, &(cal->noise1_LowTsh_Wb), 1); + nvm_devRead(&eflash, baseAddr + 0x49, &(cal->noise2_HighTsh_Wb), 1); + nvm_devRead(&eflash, baseAddr + 0x4A, &(cal->noise2_LowTsh_Wb), 1); + nvm_devRead(&eflash, baseAddr + 0x4B, &(cal->rssi_HighTsh_Wb), 1); + nvm_devRead(&eflash, baseAddr + 0x4C, &(cal->rssi_LowTsh_Wb), 1); + nvm_devRead(&eflash, baseAddr + 0x4D, &(cal->noise1_HighTsh_Nb), 1); + nvm_devRead(&eflash, baseAddr + 0x4E, &(cal->noise1_LowTsh_Nb), 1); + nvm_devRead(&eflash, baseAddr + 0x4F, &(cal->noise2_HighTsh_Nb), 1); + nvm_devRead(&eflash, baseAddr + 0x50, &(cal->noise2_LowTsh_Nb), 1); + nvm_devRead(&eflash, baseAddr + 0x51, &(cal->rssi_HighTsh_Nb), 1); + nvm_devRead(&eflash, baseAddr + 0x52, &(cal->rssi_LowTsh_Nb), 1); + nvm_devRead(&eflash, baseAddr + 0x53, &(cal->RSSILowerThreshold), 1); + nvm_devRead(&eflash, baseAddr + 0x54, &(cal->RSSIUpperThreshold), 1); + nvm_devRead(&eflash, baseAddr + 0x55, cal->mod1Amplitude, 8); + nvm_devRead(&eflash, baseAddr + 0x5D, &(cal->digAudioGain), 1); + nvm_devRead(&eflash, baseAddr + 0x5E, &(cal->txDev_DTMF), 1); + nvm_devRead(&eflash, baseAddr + 0x5F, &(cal->txDev_tone), 1); + nvm_devRead(&eflash, baseAddr + 0x60, &(cal->txDev_CTCSS_wb), 1); + nvm_devRead(&eflash, baseAddr + 0x61, &(cal->txDev_CTCSS_nb), 1); + nvm_devRead(&eflash, baseAddr + 0x62, &(cal->txDev_DCS_wb), 1); + nvm_devRead(&eflash, baseAddr + 0x63, &(cal->txDev_DCS_nb), 1); + nvm_devRead(&eflash, baseAddr + 0x64, &(cal->PA_drv), 1); + nvm_devRead(&eflash, baseAddr + 0x65, &(cal->PGA_gain), 1); + nvm_devRead(&eflash, baseAddr + 0x66, &(cal->analogMicGain), 1); + nvm_devRead(&eflash, baseAddr + 0x67, &(cal->rxAGCgain), 1); + nvm_devRead(&eflash, baseAddr + 0x68, &(cal->mixGainWideband), 2); + nvm_devRead(&eflash, baseAddr + 0x6A, &(cal->mixGainNarrowband), 2); + nvm_devRead(&eflash, baseAddr + 0x6C, &(cal->rxDacGain), 1); + nvm_devRead(&eflash, baseAddr + 0x6D, &(cal->rxVoiceGain), 1); uint8_t txPwr[32] = {0}; - W25Qx_readData(baseAddr + 0x0B, txPwr, 32); + nvm_devRead(&eflash, baseAddr + 0x0B, txPwr, 32); for(uint8_t i = 0; i < 16; i++) { @@ -112,13 +121,14 @@ static void _loadBandCalData(uint32_t baseAddr, bandCalData_t *cal) void nvm_init() { - W25Qx_init(); + spiBitbang_init(&nvm_spi); + W25Qx_init(&eflash); AT24Cx_init(); } void nvm_terminate() { - W25Qx_terminate(); + W25Qx_terminate(&eflash); AT24Cx_terminate(); } @@ -132,16 +142,11 @@ const struct nvmDescriptor *nvm_getDesc(const size_t index) void nvm_readCalibData(void *buf) { - W25Qx_wakeup(); - delayUs(5); - gdxCalibration_t *calib = ((gdxCalibration_t *) buf); _loadBandCalData(VHF_CAL_BASE, &(calib->data[0])); /* Load VHF band calibration data */ _loadBandCalData(UHF_CAL_BASE, &(calib->data[1])); /* Load UHF band calibration data */ - W25Qx_sleep(); - /* * Finally, load calibration points. These are common among all the GDx * devices. diff --git a/platform/drivers/NVM/spiFlash_GDx.c b/platform/drivers/NVM/spiFlash_GDx.c deleted file mode 100644 index fbf9accc..00000000 --- a/platform/drivers/NVM/spiFlash_GDx.c +++ /dev/null @@ -1,74 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2020 - 2023 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 - -/* - * Implementation of external flash SPI interface for GDx devices. - * In these radios the SPI communication has to be managed through software bit - * banging, since there is no SPI peripheral available. - */ - -uint8_t spiFlash_SendRecv(uint8_t val) -{ - uint8_t data = 0; - for(uint8_t i = 0; i < 8; i++) - { - gpio_clearPin(FLASH_CLK); - delayUs(1); - - if((val << i) & 0x80) - { - gpio_setPin(FLASH_SDO); - } - else - { - gpio_clearPin(FLASH_SDO); - } - - gpio_setPin(FLASH_CLK); - delayUs(1); - - data <<= 1; - data |= (gpio_readPin(FLASH_SDI)) ? 0x01 : 0x00; - } - - return data; -} - -void spiFlash_init() -{ - gpio_setMode(FLASH_CLK, OUTPUT); - gpio_setMode(FLASH_SDO, OUTPUT); - gpio_setMode(FLASH_SDI, INPUT); - - gpio_clearPin(FLASH_CLK); - gpio_clearPin(FLASH_SDO); -} - -void spiFlash_terminate() -{ - gpio_setMode(FLASH_CLK, INPUT); - gpio_setMode(FLASH_SDO, INPUT); - gpio_setMode(FLASH_SDI, INPUT); -} diff --git a/platform/targets/GDx/hwconfig.c b/platform/targets/GDx/hwconfig.c new file mode 100644 index 00000000..495f9395 --- /dev/null +++ b/platform/targets/GDx/hwconfig.c @@ -0,0 +1,34 @@ +/*************************************************************************** + * Copyright (C) 2024 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 + +static const struct spiConfig spiFlashCfg = +{ + .clk = { FLASH_CLK }, + .mosi = { FLASH_SDO }, + .miso = { FLASH_SDI }, + .clkPeriod = SCK_PERIOD_FROM_FREQ(1000000), + .flags = 0 +}; + +SPI_BITBANG_DEVICE_DEFINE(nvm_spi, spiFlashCfg, NULL) diff --git a/platform/targets/GDx/hwconfig.h b/platform/targets/GDx/hwconfig.h index 9dee6354..d1fdf61a 100644 --- a/platform/targets/GDx/hwconfig.h +++ b/platform/targets/GDx/hwconfig.h @@ -33,6 +33,8 @@ extern "C" { #endif +extern const struct spiCustomDevice nvm_spi; + /* Screen dimensions */ #define CONFIG_SCREEN_WIDTH 128 #define CONFIG_SCREEN_HEIGHT 64 diff --git a/platform/targets/GDx/pinmap_DM1801.h b/platform/targets/GDx/pinmap_DM1801.h index 0def7797..2ed3bda5 100644 --- a/platform/targets/GDx/pinmap_DM1801.h +++ b/platform/targets/GDx/pinmap_DM1801.h @@ -56,7 +56,7 @@ #define MONI_SW GPIOB,9 /* External flash */ -#define FLASH_CS GPIOE,6 +#define FLASH_CS &GpioE,6 #define FLASH_CLK GPIOE,5 #define FLASH_SDO GPIOE,4 #define FLASH_SDI GPIOA,19 diff --git a/platform/targets/GDx/pinmap_GD77.h b/platform/targets/GDx/pinmap_GD77.h index a0f04f8b..cb1cabe2 100644 --- a/platform/targets/GDx/pinmap_GD77.h +++ b/platform/targets/GDx/pinmap_GD77.h @@ -56,7 +56,7 @@ #define MONI_SW GPIOB,9 /* External flash */ -#define FLASH_CS GPIOA,19 +#define FLASH_CS &GpioA,19 #define FLASH_CLK GPIOE,5 #define FLASH_SDO GPIOE,4 #define FLASH_SDI GPIOE,6