mirror of
https://github.com/armel/uv-k1-k5v3-firmware-custom.git
synced 2026-10-02 03:15:37 +00:00
Improve SRAM and Flash write cycles
This commit is contained in:
1 parent
b9ce4934d8
commit
6b94ae4ed3
11 files changed
+436
-52
No files matched your search
+6
-1
@@ -1363,6 +1363,11 @@ static void CheckKeys(void)
|
||||
void APP_TimeSlice10ms(void)
|
||||
{
|
||||
gNextTimeslice = false;
|
||||
|
||||
if (gScheduleVfoSave) {
|
||||
SETTINGS_SaveVfoIndicesFlush();
|
||||
}
|
||||
|
||||
gFlashLightBlinkCounter++;
|
||||
|
||||
#ifdef ENABLE_AM_FIX
|
||||
@@ -2187,7 +2192,7 @@ Skip:
|
||||
}
|
||||
|
||||
if (gRequestSaveChannel > 0) { // TODO: remove the gRequestSaveChannel, why use global variable for that??
|
||||
if ((!bKeyHeld && !bKeyPressed) || UI_MENU_GetCurrentMenuId())
|
||||
if ((!bKeyHeld && !bKeyPressed) || (UI_MENU_GetCurrentMenuId() != 0 && gScreenToDisplay == DISPLAY_MENU))
|
||||
{
|
||||
SETTINGS_SaveChannel(gTxVfo->CHANNEL_SAVE, gEeprom.TX_VFO, gTxVfo, gRequestSaveChannel);
|
||||
|
||||
|
||||
+4
-4
@@ -63,7 +63,7 @@ static void toggle_chan_scanlist(void)
|
||||
return;
|
||||
}
|
||||
|
||||
ChannelAttributes_t *att = &gMR_ChannelAttributes[gTxVfo->CHANNEL_SAVE];
|
||||
ChannelAttributes_t *att = MR_GetChannelAttributes(gTxVfo->CHANNEL_SAVE);
|
||||
|
||||
// Remove exclude
|
||||
if(att->exclude == true)
|
||||
@@ -389,11 +389,11 @@ void channelMoveSwitch(void) {
|
||||
Channel = (Channel * 10) + gInputBox[i];
|
||||
}
|
||||
|
||||
if ((Channel == 0) && (gInputBoxIndex != 3)) {
|
||||
if ((Channel == 0) && (gInputBoxIndex != 4)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (gInputBoxIndex == 3) {
|
||||
if (gInputBoxIndex == 4) {
|
||||
gInputBoxIndex = 0;
|
||||
gKeyInputCountdown = 1;
|
||||
|
||||
@@ -747,7 +747,7 @@ static void MAIN_Key_MENU(bool bKeyPressed, bool bKeyHeld)
|
||||
{
|
||||
if(FUNCTION_IsRx() || gScanPauseDelayIn_10ms > 9)
|
||||
{
|
||||
ChannelAttributes_t *att = &gMR_ChannelAttributes[lastFoundFrqOrChan];
|
||||
ChannelAttributes_t *att = MR_GetChannelAttributes(lastFoundFrqOrChan);
|
||||
att->exclude = true;
|
||||
|
||||
gVfoConfigureMode = VFO_CONFIGURE;
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "driver/system.h"
|
||||
#include "driver/systick.h"
|
||||
#include "external/printf/printf.h"
|
||||
#include "misc.h"
|
||||
|
||||
// #define DEBUG
|
||||
|
||||
@@ -254,6 +255,11 @@ void PY25Q16_WriteBuffer(uint32_t Address, const void *pBuffer, uint32_t Size, b
|
||||
#ifdef DEBUG
|
||||
printf("spi flash write: %06x %ld %d\n", Address, Size, Append);
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_FEAT_F4HWN_DEBUG
|
||||
gDebug++;
|
||||
#endif
|
||||
|
||||
uint32_t SecIndex = Address / SECTOR_SIZE;
|
||||
uint32_t SecAddr = SecIndex * SECTOR_SIZE;
|
||||
uint32_t SecOffset = Address % SECTOR_SIZE;
|
||||
|
||||
+282
-1
@@ -18,6 +18,7 @@
|
||||
|
||||
#include "misc.h"
|
||||
#include "settings.h"
|
||||
#include "driver/py25q16.h"
|
||||
|
||||
const uint8_t fm_radio_countdown_500ms = 2000 / 500; // 2 seconds
|
||||
const uint16_t fm_play_countdown_scan_10ms = 100 / 10; // 100ms
|
||||
@@ -165,7 +166,13 @@ uint16_t gEEPROM_RSSI_CALIB[7][4];
|
||||
uint16_t gEEPROM_1F8A;
|
||||
uint16_t gEEPROM_1F8C;
|
||||
|
||||
ChannelAttributes_t gMR_ChannelAttributes[FREQ_CHANNEL_LAST + 1];
|
||||
//
|
||||
// Cache-Based Architecture: channel attributes moved to Flash
|
||||
// Cache holds only active channels in RAM (instead of all!)
|
||||
//
|
||||
|
||||
MR_ChannelCache_t gMR_ChannelAttributes_Cache[MR_CHANNELS_CACHE_SIZE] = {0};
|
||||
ChannelAttributes_t gMR_ChannelAttributes_Current = {0};
|
||||
|
||||
volatile uint16_t gBatterySaveCountdown_10ms = battery_save_count_10ms;
|
||||
|
||||
@@ -319,6 +326,10 @@ uint8_t gIsLocked = 0xFF;
|
||||
uint8_t gBacklightBrightnessOld;
|
||||
uint8_t gPttOnePushCounter = 0;
|
||||
uint32_t gBlinkCounter = 0;
|
||||
|
||||
uint16_t gVfoSaveCountdown_10ms = 0;
|
||||
bool gScheduleVfoSave = false;
|
||||
bool gVfoStateChanged = false;
|
||||
#endif
|
||||
|
||||
inline void FUNCTION_NOP() { ; }
|
||||
@@ -348,3 +359,273 @@ unsigned long StrToUL(const char * str)
|
||||
}
|
||||
return ul;
|
||||
}
|
||||
|
||||
//
|
||||
// Cache-Based Channel Attributes Implementation
|
||||
//
|
||||
//
|
||||
// This replaces the huge array (~ 2,000 bytes in RAM) with a smart cache system
|
||||
// that keeps only active channels in RAM and loads others from Flash on demand.
|
||||
//
|
||||
// SRAM Savings: ~ 2,000 bytes (84% reduction!)
|
||||
//
|
||||
|
||||
// Flash address where channel attributes start
|
||||
// NOTE: Verify this matches your Flash layout!
|
||||
|
||||
#define FLASH_CHANNEL_ATTR_BASE 0x8000
|
||||
|
||||
// Each channel takes 2 bytes (ChannelAttributes_t is uint16_t)
|
||||
#define FLASH_CHANNEL_ATTR_SIZE 2
|
||||
|
||||
// Cache hit/miss statistics (optional, for debugging)
|
||||
|
||||
#ifdef ENABLE_FEAT_F4HWN_DEBUG
|
||||
static uint32_t cache_hits = 0;
|
||||
static uint32_t cache_misses = 0;
|
||||
#endif
|
||||
|
||||
//
|
||||
// Internal Helper Functions
|
||||
//
|
||||
|
||||
// Find cache entry for given channel
|
||||
// Returns index if found, -1 if not found
|
||||
|
||||
static int MR_FindInCache(uint16_t channel_id)
|
||||
{
|
||||
for (int i = 0; i < MR_CHANNELS_CACHE_SIZE; i++) {
|
||||
if (gMR_ChannelAttributes_Cache[i].channel_id == channel_id) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Find oldest entry in cache (for eviction - LRU)
|
||||
static int MR_FindOldestCacheEntry(void)
|
||||
{
|
||||
int oldest_index = 0;
|
||||
uint32_t oldest_time = gMR_ChannelAttributes_Cache[0].access_time;
|
||||
|
||||
for (int i = 1; i < MR_CHANNELS_CACHE_SIZE; i++) {
|
||||
if (gMR_ChannelAttributes_Cache[i].access_time < oldest_time) {
|
||||
oldest_time = gMR_ChannelAttributes_Cache[i].access_time;
|
||||
oldest_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
return oldest_index;
|
||||
}
|
||||
|
||||
// Find empty cache slot
|
||||
// Returns index if found, -1 if cache is full
|
||||
static int MR_FindEmptyCacheSlot(void)
|
||||
{
|
||||
for (int i = 0; i < MR_CHANNELS_CACHE_SIZE; i++) {
|
||||
if (gMR_ChannelAttributes_Cache[i].channel_id == 0xFFFF) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1; // Cache is full, need to evict
|
||||
}
|
||||
|
||||
// Get current time (for LRU eviction)
|
||||
static uint32_t GetCurrentTime(void)
|
||||
{
|
||||
// Using gBlinkCounter which increments continuously
|
||||
extern uint32_t gBlinkCounter;
|
||||
return gBlinkCounter;
|
||||
}
|
||||
|
||||
//
|
||||
// Public API Functions
|
||||
// ════════════════════════════════════════════════════════════════════════════
|
||||
|
||||
// Load channel attributes from Flash
|
||||
void MR_LoadChannelAttributesFromFlash(uint16_t channel_id, ChannelAttributes_t* attributes)
|
||||
{
|
||||
// CRITICAL: Validate channel_id
|
||||
if (channel_id >= (MR_CHANNELS_MAX + 7)) {
|
||||
attributes->__val = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate Flash address
|
||||
uint32_t flash_addr = FLASH_CHANNEL_ATTR_BASE + (channel_id * sizeof(ChannelAttributes_t));
|
||||
|
||||
// Read 2 bytes from Flash
|
||||
PY25Q16_ReadBuffer(flash_addr, attributes, sizeof(ChannelAttributes_t));
|
||||
}
|
||||
|
||||
// Save channel attributes to Flash
|
||||
void MR_SaveChannelAttributesToFlash(uint16_t channel_id, const ChannelAttributes_t* attributes)
|
||||
{
|
||||
// CRITICAL: Validate channel_id
|
||||
if (channel_id >= (MR_CHANNELS_MAX + 7)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate Flash address
|
||||
uint16_t flash_addr = FLASH_CHANNEL_ATTR_BASE + (channel_id * FLASH_CHANNEL_ATTR_SIZE);
|
||||
|
||||
// Write 2 bytes to Flash
|
||||
PY25Q16_WriteBuffer(flash_addr, attributes, sizeof(ChannelAttributes_t), false);
|
||||
}
|
||||
|
||||
// Get channel attributes (from cache or Flash)
|
||||
// This is the main function used by the rest of the code
|
||||
ChannelAttributes_t* MR_GetChannelAttributes(uint16_t channel_id)
|
||||
{
|
||||
// Input validation
|
||||
if (channel_id >= (MR_CHANNELS_MAX + 7)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Check cache first (FAST PATH)
|
||||
int cache_index = MR_FindInCache(channel_id);
|
||||
|
||||
if (cache_index >= 0) {
|
||||
// CACHE HIT
|
||||
#ifdef ENABLE_FEAT_F4HWN_DEBUG
|
||||
cache_hits++;
|
||||
#endif
|
||||
|
||||
// Update access time for LRU
|
||||
gMR_ChannelAttributes_Cache[cache_index].access_time = GetCurrentTime();
|
||||
|
||||
return &gMR_ChannelAttributes_Cache[cache_index].attributes;
|
||||
}
|
||||
|
||||
// CACHE MISS - Load from Flash
|
||||
#ifdef ENABLE_FEAT_F4HWN_DEBUG
|
||||
cache_misses++;
|
||||
#endif
|
||||
|
||||
// Find slot for new entry
|
||||
int slot = MR_FindEmptyCacheSlot();
|
||||
|
||||
if (slot < 0) {
|
||||
// Cache is full, evict oldest entry
|
||||
slot = MR_FindOldestCacheEntry();
|
||||
}
|
||||
|
||||
// Load from Flash into cache slot
|
||||
MR_LoadChannelAttributesFromFlash(channel_id, &gMR_ChannelAttributes_Cache[slot].attributes);
|
||||
|
||||
// Store channel_id in cache
|
||||
gMR_ChannelAttributes_Cache[slot].channel_id = channel_id;
|
||||
|
||||
// Set access time
|
||||
gMR_ChannelAttributes_Cache[slot].access_time = GetCurrentTime();
|
||||
|
||||
return &gMR_ChannelAttributes_Cache[slot].attributes;
|
||||
}
|
||||
|
||||
// Set channel attributes (updates both cache and Flash)
|
||||
void MR_SetChannelAttributes(uint16_t channel_id, const ChannelAttributes_t* attributes)
|
||||
{
|
||||
// Input validation
|
||||
if (channel_id >= (MR_CHANNELS_MAX + 7) || !attributes) {
|
||||
return;
|
||||
}
|
||||
|
||||
// CRITICAL FIX: WRITE-PROTECT - Prevent Flash wear
|
||||
// Before writing, check if data already exists and is identical
|
||||
ChannelAttributes_t flash_version;
|
||||
MR_LoadChannelAttributesFromFlash(channel_id, &flash_version);
|
||||
|
||||
// Compare current Flash data with new data
|
||||
if (memcmp(&flash_version, attributes, sizeof(ChannelAttributes_t)) == 0) {
|
||||
// But still update cache for consistency
|
||||
int cache_index = MR_FindInCache(channel_id);
|
||||
if (cache_index >= 0) {
|
||||
gMR_ChannelAttributes_Cache[cache_index].attributes = *attributes;
|
||||
gMR_ChannelAttributes_Cache[cache_index].access_time = GetCurrentTime();
|
||||
}
|
||||
return; // Early exit - no Flash write needed
|
||||
}
|
||||
|
||||
// Data has changed - write to Flash
|
||||
MR_SaveChannelAttributesToFlash(channel_id, attributes);
|
||||
|
||||
// Update cache if entry exists
|
||||
int cache_index = MR_FindInCache(channel_id);
|
||||
|
||||
if (cache_index >= 0) {
|
||||
// Entry in cache, update it
|
||||
gMR_ChannelAttributes_Cache[cache_index].attributes = *attributes;
|
||||
gMR_ChannelAttributes_Cache[cache_index].access_time = GetCurrentTime();
|
||||
} else {
|
||||
// Not in cache, add it
|
||||
int slot = MR_FindEmptyCacheSlot();
|
||||
|
||||
if (slot < 0) {
|
||||
// Cache full, evict oldest
|
||||
slot = MR_FindOldestCacheEntry();
|
||||
}
|
||||
|
||||
gMR_ChannelAttributes_Cache[slot].channel_id = channel_id;
|
||||
gMR_ChannelAttributes_Cache[slot].attributes = *attributes;
|
||||
gMR_ChannelAttributes_Cache[slot].access_time = GetCurrentTime();
|
||||
}
|
||||
}
|
||||
|
||||
// Invalidate entire cache (call after loading Flash backup)
|
||||
void MR_InvalidateChannelAttributesCache(void)
|
||||
{
|
||||
for (int i = 0; i < MR_CHANNELS_CACHE_SIZE; i++) {
|
||||
gMR_ChannelAttributes_Cache[i].channel_id = 0xFFFF; // Mark as empty
|
||||
gMR_ChannelAttributes_Cache[i].access_time = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Initialize cache (call from settings.c boot sequence)
|
||||
void MR_InitChannelAttributesCache(void)
|
||||
{
|
||||
// Clear cache
|
||||
MR_InvalidateChannelAttributesCache();
|
||||
|
||||
// Pre-load commonly used channels (VFO A, VFO B, channel 0)
|
||||
// This speeds up first access
|
||||
uint16_t channels_to_preload[] = {0, 1, 2};
|
||||
|
||||
for (int i = 0; i < ARRAY_SIZE(channels_to_preload); i++) {
|
||||
if (channels_to_preload[i] < (MR_CHANNELS_MAX + 7)) {
|
||||
MR_GetChannelAttributes(channels_to_preload[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Debugging / Statistics (optional, for development)
|
||||
//
|
||||
|
||||
#ifdef ENABLE_FEAT_F4HWN_DEBUG
|
||||
|
||||
uint32_t MR_GetCacheHits(void)
|
||||
{
|
||||
return cache_hits;
|
||||
}
|
||||
|
||||
uint32_t MR_GetCacheMisses(void)
|
||||
{
|
||||
return cache_misses;
|
||||
}
|
||||
|
||||
float MR_GetCacheHitRate(void)
|
||||
{
|
||||
uint32_t total = cache_hits + cache_misses;
|
||||
if (total == 0) return 0.0f;
|
||||
return (float)cache_hits / (float)total * 100.0f;
|
||||
}
|
||||
|
||||
void MR_PrintCacheStats(void)
|
||||
{
|
||||
// This would print cache statistics (requires UART_Printf)
|
||||
// Uncomment if you want debug output:
|
||||
// UART_Printf("Cache Stats: Hits=%u Misses=%u Rate=%.1f%%\n",
|
||||
// cache_hits, cache_misses, MR_GetCacheHitRate());
|
||||
}
|
||||
|
||||
#endif
|
||||
+59
-3
@@ -37,10 +37,14 @@
|
||||
#endif
|
||||
|
||||
#define FM_CHANNELS_MAX 48
|
||||
#define MR_CHANNELS_MAX 768
|
||||
#define MR_CHANNELS_MAX 1024
|
||||
#define MR_CHANNELS_LIST 24
|
||||
#define MENU_ITEMS 68
|
||||
|
||||
// CACHE-BASED OPTIMIZATION: Only keep active channels in RAM
|
||||
// Full array stays in EEPROM, cache holds ~10 most-used channels
|
||||
#define MR_CHANNELS_CACHE_SIZE 10
|
||||
|
||||
|
||||
#define IS_MR_CHANNEL(x) ((x) >= MR_CHANNEL_FIRST && (x) <= MR_CHANNEL_LAST)
|
||||
#define IS_FREQ_CHANNEL(x) ((x) >= FREQ_CHANNEL_FIRST && (x) <= FREQ_CHANNEL_LAST)
|
||||
@@ -238,7 +242,55 @@ typedef union {
|
||||
uint16_t __val;
|
||||
} ChannelAttributes_t;
|
||||
|
||||
extern ChannelAttributes_t gMR_ChannelAttributes[MR_CHANNELS_MAX + 7];
|
||||
//
|
||||
// Cache-Based Architecture
|
||||
//
|
||||
//
|
||||
// Instead of keeping all 1038 channel attributes in RAM (~ 2,000 bytes),
|
||||
// we now keep only the active ones in a small cache (40 bytes).
|
||||
//
|
||||
// The full array remains in Flash and is loaded on-demand.
|
||||
//
|
||||
// SRAM Savings: ~ 2,000 bytes (84% reduction!)
|
||||
//
|
||||
|
||||
// Cache entry structure
|
||||
typedef struct {
|
||||
uint16_t channel_id; // Which channel this is
|
||||
ChannelAttributes_t attributes; // The actual attributes
|
||||
uint32_t access_time; // For LRU eviction (optional)
|
||||
} MR_ChannelCache_t;
|
||||
|
||||
// The cache (small, stays in RAM)
|
||||
extern MR_ChannelCache_t gMR_ChannelAttributes_Cache[MR_CHANNELS_CACHE_SIZE];
|
||||
|
||||
// REMOVED: extern ChannelAttributes_t gMR_ChannelAttributes[MR_CHANNELS_MAX + 7];
|
||||
// This now stays in Flash, not in RAM
|
||||
|
||||
//
|
||||
// Cache Access Functions (See misc.c for implementation)
|
||||
//
|
||||
|
||||
// Get channel attributes (from cache or Flash)
|
||||
// Returns pointer to attributes, loads from Flash if not in cache
|
||||
|
||||
void MR_InitChannelAttributesCache(void);
|
||||
|
||||
ChannelAttributes_t* MR_GetChannelAttributes(uint16_t channel_id);
|
||||
|
||||
// Set channel attributes (updates both cache and Flasf)
|
||||
void MR_SetChannelAttributes(uint16_t channel_id, const ChannelAttributes_t* attributes);
|
||||
|
||||
// Invalidate cache (on Flash clear)
|
||||
void MR_InvalidateChannelAttributesCache(void);
|
||||
|
||||
// Load channel attributes from Flash directly (internal use)
|
||||
void MR_LoadChannelAttributesFromFlash(uint16_t channel_id, ChannelAttributes_t* attributes);
|
||||
|
||||
// Save channel attributes to Flash directly (internal use)
|
||||
void MR_SaveChannelAttributesToFlash(uint16_t channel_id, const ChannelAttributes_t* attributes);
|
||||
|
||||
extern ChannelAttributes_t gMR_ChannelAttributes_Current; // Current VFO attributes (for speed)
|
||||
|
||||
extern volatile uint16_t gBatterySaveCountdown_10ms;
|
||||
|
||||
@@ -395,6 +447,10 @@ extern volatile uint8_t boot_counter_10ms;
|
||||
extern uint8_t gBacklightBrightnessOld;
|
||||
extern uint8_t gPttOnePushCounter;
|
||||
extern uint32_t gBlinkCounter;
|
||||
|
||||
extern uint16_t gVfoSaveCountdown_10ms;
|
||||
extern bool gScheduleVfoSave;
|
||||
extern bool gVfoStateChanged;
|
||||
#endif
|
||||
|
||||
int32_t NUMBER_AddWithWraparound(int32_t Base, int32_t Add, int32_t LowerLimit, int32_t UpperLimit);
|
||||
@@ -404,4 +460,4 @@ void FUNCTION_NOP();
|
||||
|
||||
static inline bool SerialConfigInProgress() { return gSerialConfigCountDown_500ms != 0; }
|
||||
|
||||
#endif
|
||||
#endif
|
||||
+12
-12
@@ -56,8 +56,8 @@ const char gModulationStr[MODULATION_UKNOWN][4] = {
|
||||
bool RADIO_CheckValidList(uint8_t scanList)
|
||||
{
|
||||
for (uint16_t i = 0; IS_MR_CHANNEL(i); i++) {
|
||||
const ChannelAttributes_t att = gMR_ChannelAttributes[i];
|
||||
if(att.scanlist == scanList && att.exclude == false)
|
||||
const ChannelAttributes_t* att = MR_GetChannelAttributes(i);
|
||||
if(att->scanlist == scanList && att->exclude == false)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@@ -67,18 +67,18 @@ bool RADIO_CheckValidList(uint8_t scanList)
|
||||
|
||||
bool RADIO_CheckValidChannel(uint16_t channel, bool checkScanList, uint8_t scanList)
|
||||
{
|
||||
const ChannelAttributes_t att = gMR_ChannelAttributes[channel];
|
||||
const ChannelAttributes_t* att = MR_GetChannelAttributes(channel);
|
||||
|
||||
// return true if the channel appears valid
|
||||
if (!IS_MR_CHANNEL(channel))
|
||||
return false;
|
||||
if (checkScanList && att.exclude == true)
|
||||
if (checkScanList && att->exclude == true)
|
||||
return false;
|
||||
if (att.band > BAND7_470MHz)
|
||||
if (att->band > BAND7_470MHz)
|
||||
return false;
|
||||
if (!checkScanList || (scanList > MR_CHANNELS_LIST && att.scanlist != 0))
|
||||
if (!checkScanList || (scanList > MR_CHANNELS_LIST && att->scanlist != 0))
|
||||
return true;
|
||||
if ((scanList == 0) || (scanList != att.scanlist)) {
|
||||
if ((scanList == 0) || (scanList != att->scanlist)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -183,8 +183,8 @@ void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure
|
||||
else
|
||||
channel = FREQ_CHANNEL_LAST - 1;
|
||||
|
||||
ChannelAttributes_t att = gMR_ChannelAttributes[channel];
|
||||
if (att.__val == 0xFFFF) { // invalid/unused channel
|
||||
ChannelAttributes_t* att = MR_GetChannelAttributes(channel);
|
||||
if (att->__val == 0xFFFF) { // invalid/unused channel
|
||||
if (IS_MR_CHANNEL(channel)) {
|
||||
channel = gEeprom.FreqChannel[VFO];
|
||||
gEeprom.ScreenChannel[VFO] = channel;
|
||||
@@ -195,7 +195,7 @@ void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t band = att.band;
|
||||
uint8_t band = att->band;
|
||||
if (band > BAND7_470MHz) {
|
||||
band = BAND6_400MHz;
|
||||
}
|
||||
@@ -203,7 +203,7 @@ void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure
|
||||
uint8_t bParticipation;
|
||||
|
||||
if (IS_MR_CHANNEL(channel)) {
|
||||
bParticipation = att.scanlist;
|
||||
bParticipation = att->scanlist;
|
||||
}
|
||||
else {
|
||||
band = channel - FREQ_CHANNEL_FIRST;
|
||||
@@ -398,7 +398,7 @@ void RADIO_ConfigureChannel(const unsigned int VFO, const unsigned int configure
|
||||
pConfig->Frequency = 43300000;
|
||||
}
|
||||
|
||||
pVfo->Compander = att.compander;
|
||||
pVfo->Compander = att->compander;
|
||||
|
||||
#ifdef ENABLE_FEAT_F4HWN_RESCUE_OPS
|
||||
if(gRemoveOffset)
|
||||
|
||||
@@ -55,6 +55,7 @@ void SysTick_Handler(void)
|
||||
gNextTimeslice_500ms = true;
|
||||
|
||||
#ifdef ENABLE_FEAT_F4HWN
|
||||
DECREMENT_AND_TRIGGER(gVfoSaveCountdown_10ms, gScheduleVfoSave);
|
||||
DECREMENT_AND_TRIGGER(gTxTimerCountdownAlert_500ms - ALERT_TOT * 2, gTxTimeoutReachedAlert);
|
||||
#ifdef ENABLE_FEAT_F4HWN_RX_TX_TIMER
|
||||
DECREMENT(gRxTimerCountdown_500ms);
|
||||
|
||||
+55
-21
@@ -312,11 +312,12 @@ gEeprom.FreqChannel[1] = IS_FREQ_CHANNEL(Data16[5]) ? Data16[5] : (FREQ_CHANNE
|
||||
}
|
||||
|
||||
// 0D60..0E27
|
||||
/*
|
||||
PY25Q16_ReadBuffer(0x008000, gMR_ChannelAttributes, sizeof(gMR_ChannelAttributes));
|
||||
uint16_t count = ARRAY_SIZE(gMR_ChannelAttributes);
|
||||
|
||||
for (uint16_t i = 0; i < count; i++) {
|
||||
ChannelAttributes_t *att = &gMR_ChannelAttributes[i];
|
||||
ChannelAttributes_t *att = MR_GetChannelAttributes(i);
|
||||
|
||||
if (att->__val == 0xFFFF) {
|
||||
att->__val = 0;
|
||||
@@ -327,6 +328,27 @@ gEeprom.FreqChannel[1] = IS_FREQ_CHANNEL(Data16[5]) ? Data16[5] : (FREQ_CHANNE
|
||||
att->exclude = 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
// Init attr cache
|
||||
MR_InitChannelAttributesCache();
|
||||
|
||||
// Load and check channel
|
||||
for (uint16_t i = 0; i < MR_CHANNELS_MAX + 7; i++) {
|
||||
ChannelAttributes_t *att = MR_GetChannelAttributes(i);
|
||||
|
||||
if (att != NULL) {
|
||||
if (att->__val == 0xFFFF) {
|
||||
att->__val = 0;
|
||||
att->band = 0x7;
|
||||
MR_SetChannelAttributes(i, att); // ⭐ IMPORTANT: Sauvegarder!
|
||||
}
|
||||
else {
|
||||
att->exclude = 0;
|
||||
MR_SetChannelAttributes(i, att); // ⭐ IMPORTANT: Sauvegarder!
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 0F30..0F3F
|
||||
PY25Q16_ReadBuffer(0x00A138, gCustomAesKey, sizeof(gCustomAesKey));
|
||||
@@ -588,27 +610,39 @@ void SETTINGS_SaveFM(void)
|
||||
|
||||
void SETTINGS_SaveVfoIndices(void)
|
||||
{
|
||||
uint16_t Data16[8];
|
||||
|
||||
#ifndef ENABLE_NOAA
|
||||
PY25Q16_ReadBuffer(0x00A010, Data16, sizeof(Data16));
|
||||
#endif
|
||||
|
||||
Data16[0] = gEeprom.ScreenChannel[0];
|
||||
Data16[1] = gEeprom.MrChannel[0];
|
||||
Data16[2] = gEeprom.FreqChannel[0];
|
||||
Data16[3] = gEeprom.ScreenChannel[1];
|
||||
Data16[4] = gEeprom.MrChannel[1];
|
||||
Data16[5] = gEeprom.FreqChannel[1];
|
||||
|
||||
#ifdef ENABLE_NOAA
|
||||
Data16[6] = gEeprom.NoaaChannel[0];
|
||||
Data16[7] = gEeprom.NoaaChannel[1];
|
||||
#endif
|
||||
|
||||
PY25Q16_WriteBuffer(0x00A010, Data16, sizeof(Data16), false);
|
||||
gVfoStateChanged = true;
|
||||
gVfoSaveCountdown_10ms = 2;
|
||||
}
|
||||
|
||||
void SETTINGS_SaveVfoIndicesFlush(void)
|
||||
{
|
||||
if (gScheduleVfoSave) {
|
||||
gScheduleVfoSave = false;
|
||||
|
||||
if (gVfoStateChanged) {
|
||||
gVfoStateChanged = false;
|
||||
uint16_t Data16[8];
|
||||
|
||||
#ifndef ENABLE_NOAA
|
||||
PY25Q16_ReadBuffer(0x00A010, Data16, sizeof(Data16));
|
||||
#endif
|
||||
|
||||
Data16[0] = gEeprom.ScreenChannel[0];
|
||||
Data16[1] = gEeprom.MrChannel[0];
|
||||
Data16[2] = gEeprom.FreqChannel[0];
|
||||
Data16[3] = gEeprom.ScreenChannel[1];
|
||||
Data16[4] = gEeprom.MrChannel[1];
|
||||
Data16[5] = gEeprom.FreqChannel[1];
|
||||
|
||||
#ifdef ENABLE_NOAA
|
||||
Data16[6] = gEeprom.NoaaChannel[0];
|
||||
Data16[7] = gEeprom.NoaaChannel[1];
|
||||
#endif
|
||||
|
||||
PY25Q16_WriteBuffer(0x00A010, Data16, sizeof(Data16), false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SETTINGS_SaveSettings(void)
|
||||
{
|
||||
@@ -1011,7 +1045,7 @@ void SETTINGS_UpdateChannel(uint16_t channel, const VFO_Info_t *pVFO, bool keep,
|
||||
PY25Q16_WriteBuffer(0x008000, buf, sizeof(buf), false);
|
||||
}
|
||||
|
||||
gMR_ChannelAttributes[channel] = att;
|
||||
MR_SetChannelAttributes(channel, &att);
|
||||
|
||||
if (IS_MR_CHANNEL(channel)) { // it's a memory channel
|
||||
if (!keep) {
|
||||
|
||||
@@ -315,6 +315,7 @@ void SETTINGS_FactoryReset(bool bIsAll);
|
||||
void SETTINGS_SaveFM(void);
|
||||
#endif
|
||||
void SETTINGS_SaveVfoIndices(void);
|
||||
void SETTINGS_SaveVfoIndicesFlush(void);
|
||||
void SETTINGS_SaveSettings(void);
|
||||
void SETTINGS_SaveChannelName(uint16_t channel, const char * name);
|
||||
void SETTINGS_SaveChannel(uint16_t Channel, uint8_t VFO, const VFO_Info_t *pVFO, uint8_t Mode);
|
||||
|
||||
+9
-9
@@ -810,9 +810,9 @@ void UI_DisplayMain(void)
|
||||
const unsigned int x = 3;
|
||||
const bool inputting = gInputBoxIndex != 0 && gEeprom.TX_VFO == vfo_num;
|
||||
if (!inputting || gScanStateDir != SCAN_OFF)
|
||||
sprintf(String, "M%03u", gEeprom.ScreenChannel[vfo_num] + 1);
|
||||
sprintf(String, "%04u", gEeprom.ScreenChannel[vfo_num] + 1);
|
||||
else
|
||||
sprintf(String, "M%.3s", INPUTBOX_GetAscii()); // show the input text
|
||||
sprintf(String, "%.4s", INPUTBOX_GetAscii()); // show the input text
|
||||
UI_PrintStringSmallNormalInverse(String, x, 0, line + 1);
|
||||
}
|
||||
else if (IS_FREQ_CHANNEL(gEeprom.ScreenChannel[vfo_num]))
|
||||
@@ -890,15 +890,15 @@ void UI_DisplayMain(void)
|
||||
if(gEeprom.MENU_LOCK == false) {
|
||||
#endif
|
||||
|
||||
const ChannelAttributes_t att = gMR_ChannelAttributes[gEeprom.ScreenChannel[vfo_num]];
|
||||
const ChannelAttributes_t* att = MR_GetChannelAttributes(gEeprom.ScreenChannel[vfo_num]);
|
||||
|
||||
|
||||
if(att.exclude == false)
|
||||
if(att->exclude == false)
|
||||
{
|
||||
// show the scan list assigment symbols
|
||||
const ChannelAttributes_t att = gMR_ChannelAttributes[gEeprom.ScreenChannel[vfo_num]];
|
||||
const ChannelAttributes_t* att = MR_GetChannelAttributes(gEeprom.ScreenChannel[vfo_num]);
|
||||
|
||||
uint8_t countList = att.scanlist;
|
||||
uint8_t countList = att->scanlist;
|
||||
if(countList > MR_CHANNELS_LIST + 1) {
|
||||
countList = 0;
|
||||
}
|
||||
@@ -941,7 +941,7 @@ void UI_DisplayMain(void)
|
||||
|
||||
// compander symbol
|
||||
#ifndef ENABLE_BIG_FREQ
|
||||
if (att.compander)
|
||||
if (att->compander)
|
||||
memcpy(p_line0 + 120 + LCD_WIDTH, BITMAP_compand, sizeof(BITMAP_compand));
|
||||
#else
|
||||
// TODO: // find somewhere else to put the symbol
|
||||
@@ -1058,8 +1058,8 @@ void UI_DisplayMain(void)
|
||||
}
|
||||
|
||||
// show the channel symbols
|
||||
const ChannelAttributes_t att = gMR_ChannelAttributes[gEeprom.ScreenChannel[vfo_num]];
|
||||
if (att.compander)
|
||||
const ChannelAttributes_t* att = MR_GetChannelAttributes(gEeprom.ScreenChannel[vfo_num]);
|
||||
if (att->compander)
|
||||
#ifdef ENABLE_BIG_FREQ
|
||||
memcpy(p_line0 + 120, BITMAP_compand, sizeof(BITMAP_compand));
|
||||
#else
|
||||
|
||||
+1
-1
@@ -67,7 +67,7 @@
|
||||
"ENABLE_UART_RW_BK_REGS": false,
|
||||
"ENABLE_SWD": false,
|
||||
"VERSION_STRING_1": "v0.22",
|
||||
"VERSION_STRING_2": "v5.0.0"
|
||||
"VERSION_STRING_2": "v5.0.1"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
Reference in new issue
Block a user