diff --git a/openrtx/include/interfaces/nvmem.h b/openrtx/include/interfaces/nvmem.h
index cf046d4c..e70f1637 100644
--- a/openrtx/include/interfaces/nvmem.h
+++ b/openrtx/include/interfaces/nvmem.h
@@ -57,7 +57,7 @@ void nvm_readCalibData(void *buf);
*
* @param info: destination data structure for hardware information data.
*/
-void nvm_loadHwInfo(hwInfo_t *info);
+void nvm_readHwInfo(hwInfo_t *info);
/**
* Read from storage the channel data corresponding to the VFO channel A.
@@ -65,7 +65,7 @@ void nvm_loadHwInfo(hwInfo_t *info);
* @param channel: pointer to the channel_t data structure to be populated.
* @return 0 on success, -1 on failure
*/
-int nvm_readVFOChannelData(channel_t *channel);
+int nvm_readVfoChannelData(channel_t *channel);
/**
* Read OpenRTX settings from storage.
diff --git a/openrtx/src/core/cps.c b/openrtx/src/core/cps.c
index 497814aa..f1af29d0 100644
--- a/openrtx/src/core/cps.c
+++ b/openrtx/src/core/cps.c
@@ -26,7 +26,7 @@ channel_t cps_getDefaultChannel()
channel_t channel;
channel.mode = OPMODE_FM;
channel.bandwidth = BW_25;
- channel.power = 1.0;
+ channel.power = 100; // 1W, P = 10dBm + n*0.2dBm, we store n
// Set initial frequency based on supported bands
const hwInfo_t* hwinfo = platform_getHwInfo();
diff --git a/openrtx/src/core/state.c b/openrtx/src/core/state.c
index 6998db47..16866bc0 100644
--- a/openrtx/src/core/state.c
+++ b/openrtx/src/core/state.c
@@ -48,7 +48,7 @@ void state_init()
* Try loading VFO configuration from nonvolatile memory and default to sane
* values in case of failure.
*/
- if(nvm_readVFOChannelData(&state.channel) < 0)
+ if(nvm_readVfoChannelData(&state.channel) < 0)
{
state.channel = cps_getDefaultChannel();
}
diff --git a/platform/drivers/NVM/nvmem_GDx.c b/platform/drivers/NVM/nvmem_GDx.c
index ca873066..d48067ab 100644
--- a/platform/drivers/NVM/nvmem_GDx.c
+++ b/platform/drivers/NVM/nvmem_GDx.c
@@ -40,8 +40,11 @@ static const uint32_t VHF_CAL_BASE = 0x6F070;
/**
* \internal Utility function for loading band-specific calibration data into
* the corresponding data structure.
+ *
+ * @param baseAddr: start address of the data block;
+ * @param cal: pointer to calibration data structure to be filled.
*/
-void _loadBandCalData(uint32_t baseAddr, bandCalData_t *cal)
+static void _loadBandCalData(uint32_t baseAddr, bandCalData_t *cal)
{
W25Qx_readData(baseAddr + 0x08, &(cal->modBias), 2);
W25Qx_readData(baseAddr + 0x0A, &(cal->mod2Offset), 1);
@@ -87,6 +90,7 @@ void _loadBandCalData(uint32_t baseAddr, bandCalData_t *cal)
}
}
+
void nvm_init()
{
W25Qx_init();
@@ -133,13 +137,13 @@ void nvm_readCalibData(void *buf)
calib->vhfCalPoints[7] = 172000000;
}
-void nvm_loadHwInfo(hwInfo_t *info)
+void nvm_readHwInfo(hwInfo_t *info)
{
/* GDx devices does not have any hardware info in the external flash. */
(void) info;
}
-int nvm_readVFOChannelData(channel_t *channel)
+int nvm_readVfoChannelData(channel_t *channel)
{
(void) channel;
return -1;
diff --git a/platform/drivers/NVM/nvmem_MD3x0.c b/platform/drivers/NVM/nvmem_MD3x0.c
index d074bba5..3cbb71ae 100644
--- a/platform/drivers/NVM/nvmem_MD3x0.c
+++ b/platform/drivers/NVM/nvmem_MD3x0.c
@@ -96,7 +96,7 @@ void nvm_readCalibData(void *buf)
}
}
-void nvm_loadHwInfo(hwInfo_t *info)
+void nvm_readHwInfo(hwInfo_t *info)
{
uint16_t freqMin = 0;
uint16_t freqMax = 0;
@@ -142,32 +142,10 @@ void nvm_loadHwInfo(hwInfo_t *info)
}
/**
- * The MD380 stock CPS does not have a VFO channel slot
- * because the stock firmware does not have a VFO
- * To enable this functionality reserve a Flash portion for saving the VFO
- *
- * TODO: temporarily implemented in "nvmem_settings_MDx.c"
+ * TODO: functions temporarily implemented in "nvmem_settings_MDx.c"
int nvm_readVFOChannelData(channel_t *channel)
-{
- (void) channel;
- return -1;
-}
-*/
-
-/*
-
-TODO: temporarily implemented in "nvmem_settings_MDx.c"
-
int nvm_readSettings(settings_t *settings)
-{
- (void) settings;
- return -1;
-}
-*/
-
int nvm_writeSettings(const settings_t *settings)
-{
- (void) settings;
- return -1;
-}
+
+*/
diff --git a/platform/drivers/NVM/nvmem_MD9600.c b/platform/drivers/NVM/nvmem_MD9600.c
index 5262644a..0d5535a1 100644
--- a/platform/drivers/NVM/nvmem_MD9600.c
+++ b/platform/drivers/NVM/nvmem_MD9600.c
@@ -42,36 +42,16 @@ void nvm_readCalibData(void *buf)
return;
}
-/*
-TODO: temporarily implemented in "nvmem_settings_MDx.c"
+void nvm_readHwInfo(hwInfo_t *info)
+{
+ (void) info;
+}
+
+/**
+ * TODO: functions temporarily implemented in "nvmem_settings_MDx.c"
int nvm_readVFOChannelData(channel_t *channel)
-{
- return _cps_readChannelAtAddress(channel, vfoChannelBaseAddr);
-}
-*/
-
-/*
-
-TODO: temporarily implemented in "nvmem_settings_MDx.c"
-
int nvm_readSettings(settings_t *settings)
-{
- settings_t newSettings;
- W25Qx_wakeup();
- delayUs(5);
- W25Qx_readData(settingsAddr, ((uint8_t *) &newSettings), sizeof(settings_t));
- W25Qx_sleep();
- if(memcmp(newSettings.valid, default_settings.valid, 6) != 0)
- return -1;
- memcpy(settings, &newSettings, sizeof(settings_t));
- return 0;
-}
-*/
-
int nvm_writeSettings(const settings_t *settings)
-{
- // Disable settings write until DFU is implemented for flash backups
- (void) settings;
- return -1;
-}
+
+*/
diff --git a/platform/drivers/NVM/nvmem_MDUV3x0.c b/platform/drivers/NVM/nvmem_MDUV3x0.c
index b321508c..c5fb2594 100644
--- a/platform/drivers/NVM/nvmem_MDUV3x0.c
+++ b/platform/drivers/NVM/nvmem_MDUV3x0.c
@@ -104,7 +104,7 @@ void nvm_readCalibData(void *buf)
}
}
-void nvm_loadHwInfo(hwInfo_t *info)
+void nvm_readHwInfo(hwInfo_t *info)
{
uint16_t vhf_freqMin = 0;
uint16_t vhf_freqMax = 0;
@@ -142,35 +142,11 @@ void nvm_loadHwInfo(hwInfo_t *info)
info->lcd_type = lcdInfo & 0x03;
}
-/*
-TODO: temporarily implemented in "nvmem_settings_MDx.c"
+/**
+ * TODO: functions temporarily implemented in "nvmem_settings_MDx.c"
int nvm_readVFOChannelData(channel_t *channel)
-{
- return _cps_readChannelAtAddress(channel, vfoChannelBaseAddr);
-}
-*/
-
-/*
-TODO: temporarily implemented in "nvmem_settings_MDx.c"
-
int nvm_readSettings(settings_t *settings)
-{
- settings_t newSettings;
- W25Qx_wakeup();
- delayUs(5);
- W25Qx_readData(settingsAddr, ((uint8_t *) &newSettings), sizeof(settings_t));
- W25Qx_sleep();
- if(memcmp(newSettings.valid, default_settings.valid, 6) != 0)
- return -1;
- memcpy(settings, &newSettings, sizeof(settings_t));
- return 0;
-}
-*/
-
int nvm_writeSettings(const settings_t *settings)
-{
- (void) settings;
- // Disable settings write until DFU is implemented for flash backups
- return -1;
-}
+
+*/
diff --git a/platform/drivers/NVM/nvmem_Mod17.c b/platform/drivers/NVM/nvmem_Mod17.c
index a4bed1bd..e3acce5a 100644
--- a/platform/drivers/NVM/nvmem_Mod17.c
+++ b/platform/drivers/NVM/nvmem_Mod17.c
@@ -35,12 +35,12 @@ void nvm_readCalibData(void *buf)
(void) buf;
}
-void nvm_loadHwInfo(hwInfo_t *info)
+void nvm_readHwInfo(hwInfo_t *info)
{
(void) info;
}
-int nvm_readVFOChannelData(channel_t *channel)
+int nvm_readVfoChannelData(channel_t *channel)
{
// Module 17 has no channels: just load default values for it
channel->mode = OPMODE_M17;
diff --git a/platform/drivers/NVM/nvmem_linux.c b/platform/drivers/NVM/nvmem_linux.c
index c9bad75c..e32ce7f1 100644
--- a/platform/drivers/NVM/nvmem_linux.c
+++ b/platform/drivers/NVM/nvmem_linux.c
@@ -223,13 +223,13 @@ void nvm_terminate()
}
}
-void nvm_loadHwInfo(hwInfo_t *info)
+void nvm_readHwInfo(hwInfo_t *info)
{
/* Linux devices does not have any hardware info in the external flash. */
(void) info;
}
-int nvm_readVFOChannelData(channel_t *channel)
+int nvm_readVfoChannelData(channel_t *channel)
{
return _cps_read(memory_paths[P_VFO], channel, sizeof(channel_t));
}
diff --git a/platform/drivers/NVM/nvmem_settings_MDx.c b/platform/drivers/NVM/nvmem_settings_MDx.c
index 0715297d..7c35955f 100644
--- a/platform/drivers/NVM/nvmem_settings_MDx.c
+++ b/platform/drivers/NVM/nvmem_settings_MDx.c
@@ -18,29 +18,33 @@
* along with this program; if not, see *
***************************************************************************/
-#include
#include
+#include
#include
+#include
#include "flash.h"
/*
- * Data structure defining the memory layout used for saving and restore
+ * Data structures defining the memory layout used for saving and restore
* of user settings and VFO configuration.
*/
typedef struct
{
- uint32_t magic;
- uint32_t flags[64];
- struct dataBlock
- {
- settings_t settings;
- channel_t vfoData;
- }
- data[2048];
+ uint16_t crc;
+ settings_t settings;
+ channel_t vfoData;
+}
+__attribute__((packed)) dataBlock_t;
+
+typedef struct
+{
+ uint32_t magic;
+ uint32_t flags[32];
+ dataBlock_t data[1024];
}
__attribute__((packed)) memory_t;
-static const uint32_t validMagic = 0x584E504F; // "OPNX"
+static const uint32_t MEM_MAGIC = 0x584E504F; // "OPNX"
static const uint32_t baseAddress = 0x080E0000;
memory_t *memory = ((memory_t *) baseAddress);
@@ -53,15 +57,17 @@ memory_t *memory = ((memory_t *) baseAddress);
*
* @return number currently active data block or -1 if memory data is invalid.
*/
-int findActiveBlock()
+static int findActiveBlock()
{
- if(memory->magic != validMagic)
- {
- return -1; // Invalid memory data
- }
+ // Check for invalid memory data
+ if(memory->magic != MEM_MAGIC)
+ return -1;
uint16_t block = 0;
- for(; block < 64; block++)
+ uint16_t bit = 0;
+
+ // Find the first 32-bit block not full of zeroes
+ for(; block < 32; block++)
{
if(memory->flags[block] != 0x00000000)
{
@@ -69,7 +75,7 @@ int findActiveBlock()
}
}
- uint16_t bit = 0;
+ // Find the last zero within a block
for(; bit < 32; bit++)
{
if((memory->flags[block] & (1 << bit)) != 0)
@@ -79,12 +85,19 @@ int findActiveBlock()
}
block = (block * 32) + bit;
- return block - 1;
+ block -= 1;
+
+ // Check data validity
+ uint16_t crc = crc_ccitt(&(memory->data[block].settings),
+ sizeof(settings_t) + sizeof(channel_t));
+ if(crc != memory->data[block].crc)
+ return -2;
+
+ return block;
}
-
-int nvm_readVFOChannelData(channel_t *channel)
+int nvm_readVfoChannelData(channel_t *channel)
{
int block = findActiveBlock();
@@ -110,8 +123,9 @@ int nvm_readSettings(settings_t *settings)
int nvm_writeSettingsAndVfo(const settings_t *settings, const channel_t *vfo)
{
- uint32_t addr = 0;
- int block = findActiveBlock();
+ uint32_t addr = 0;
+ int block = findActiveBlock();
+ uint16_t prevCrc = 0;
/*
* Memory never initialised or save space finished: erase all the sector.
@@ -122,21 +136,28 @@ int nvm_writeSettingsAndVfo(const settings_t *settings, const channel_t *vfo)
{
flash_eraseSector(11);
addr = ((uint32_t) &(memory->magic));
- flash_write(addr, &validMagic, sizeof(validMagic));
+ flash_write(addr, &MEM_MAGIC, sizeof(MEM_MAGIC));
block = 0;
}
else
{
+ prevCrc = memory->data[block].crc;
block += 1;
}
- // Save settings
- addr = ((uint32_t) &(memory->data[block].settings));
- flash_write(addr, settings, sizeof(settings_t));
+ dataBlock_t tmpBlock;
+ memcpy((&tmpBlock.settings), settings, sizeof(settings_t));
+ memcpy((&tmpBlock.vfoData), vfo, sizeof(channel_t));
+ tmpBlock.crc = crc_ccitt(&(tmpBlock.settings),
+ sizeof(settings_t) + sizeof(channel_t));
- // Save VFO configuration
- addr = ((uint32_t) &(memory->data[block].vfoData));
- flash_write(addr, vfo, sizeof(channel_t));
+ // New data is equal to the old one, avoid saving
+ if((block != 0) && (tmpBlock.crc == prevCrc))
+ return 0;
+
+ // Save data
+ addr = ((uint32_t) &(memory->data[block]));
+ flash_write(addr, &tmpBlock, sizeof(dataBlock_t));
// Update the flags marking used data blocks
uint32_t flag = ~(1 << (block % 32));
diff --git a/platform/targets/MD-3x0/platform.c b/platform/targets/MD-3x0/platform.c
index 40aded4d..a62f72d3 100644
--- a/platform/targets/MD-3x0/platform.c
+++ b/platform/targets/MD-3x0/platform.c
@@ -62,7 +62,7 @@ void platform_init()
nvm_init(); /* Initialise non volatile memory manager */
nvm_readCalibData(&calibration); /* Load calibration data */
- nvm_loadHwInfo(&hwInfo); /* Load hardware information data */
+ nvm_readHwInfo(&hwInfo); /* Load hardware information data */
toneGen_init(); /* Initialise tone generator */
rtc_init(); /* Initialise RTC */
backlight_init(); /* Initialise backlight driver */
diff --git a/platform/targets/MD-UV3x0/platform.c b/platform/targets/MD-UV3x0/platform.c
index 25676ff3..0783dde5 100644
--- a/platform/targets/MD-UV3x0/platform.c
+++ b/platform/targets/MD-UV3x0/platform.c
@@ -61,7 +61,7 @@ void platform_init()
nvm_init(); /* Initialise non volatile memory manager */
nvm_readCalibData(&calibration); /* Load calibration data */
- nvm_loadHwInfo(&hwInfo); /* Load hardware information data */
+ nvm_readHwInfo(&hwInfo); /* Load hardware information data */
toneGen_init(); /* Initialise tone generator */
rtc_init(); /* Initialise RTC */
chSelector_init(); /* Initialise channel selector handler */