Add full memory and settings transfer

This commit is contained in:
Armel FAUVEAU committed 2026-08-28 17:13:13 +02:00
1 parent f35408317e
commit 678cb9b73a
3 files changed
+58 -13

No files matched your search

+37 -8
View File
@@ -42,6 +42,7 @@ AIRCOPY_State_t gAircopyState;
uint16_t gAirCopyBlockNumber; uint16_t gAirCopyBlockNumber;
uint16_t gErrorsDuringAirCopy; uint16_t gErrorsDuringAirCopy;
bool gAirCopyIsSendMode; bool gAirCopyIsSendMode;
bool gAircopyAll;
uint16_t g_FSK_Buffer[36]; uint16_t g_FSK_Buffer[36];
@@ -60,24 +61,51 @@ uint16_t g_FSK_Buffer[36];
static uint16_t AircopyCountdown; static uint16_t AircopyCountdown;
static uint8_t AircopyRetries; static uint8_t AircopyRetries;
#define AIRCOPY_NUM_MAPS (AIRCOPY_NUM_BANKS + 1u)
#define AIRCOPY_BANK_BLOCKS 68u #define AIRCOPY_BANK_BLOCKS 68u
#define AIRCOPY_SETTINGS_BLOCKS 12u #define AIRCOPY_SETTINGS_BLOCKS 12u
#define AIRCOPY_ALL_BLOCKS (AIRCOPY_NUM_BANKS * AIRCOPY_BANK_BLOCKS + AIRCOPY_SETTINGS_BLOCKS)
// ============================================================================ // ============================================================================
// Helper Functions // Helper Functions
// ============================================================================ // ============================================================================
uint8_t AIRCOPY_GetTotalBlocks(void) uint16_t AIRCOPY_GetTotalBlocks(void)
{ {
if (gAircopyAll)
return AIRCOPY_ALL_BLOCKS; // banks + settings, one continuous run
return gAircopyCurrentMapIndex == AIRCOPY_NUM_BANKS return gAircopyCurrentMapIndex == AIRCOPY_NUM_BANKS
? AIRCOPY_SETTINGS_BLOCKS ? AIRCOPY_SETTINGS_BLOCKS
: AIRCOPY_BANK_BLOCKS; : AIRCOPY_BANK_BLOCKS;
} }
// Resolve the map that a (possibly global, in All mode) block index lands in.
// On return, *block is rewritten to the block index within that map.
static uint8_t AIRCOPY_ResolveMap(uint16_t *block)
{
if (!gAircopyAll)
return gAircopyCurrentMapIndex;
uint8_t map = 0;
while (map < AIRCOPY_NUM_BANKS && *block >= AIRCOPY_BANK_BLOCKS)
{
*block -= AIRCOPY_BANK_BLOCKS;
map++;
}
return map; // AIRCOPY_NUM_BANKS once the banks are exhausted (settings map)
}
// Map index of the block currently in progress, for the All-mode slice label.
uint8_t AIRCOPY_CurrentSliceMap(void)
{
uint16_t block = gAirCopyBlockNumber;
return AIRCOPY_ResolveMap(&block);
}
static uint16_t AIRCOPY_GetBlockOffset(uint16_t block) static uint16_t AIRCOPY_GetBlockOffset(uint16_t block)
{ {
if (gAircopyCurrentMapIndex == AIRCOPY_NUM_BANKS) const uint8_t map = AIRCOPY_ResolveMap(&block);
if (map == AIRCOPY_NUM_BANKS)
{ {
// Settings: 6 blocks at 0xA000, 2 at 0x880E and 4 at 0x9000. // Settings: 6 blocks at 0xA000, 2 at 0x880E and 4 at 0x9000.
if (block < 6u) if (block < 6u)
@@ -88,12 +116,12 @@ static uint16_t AIRCOPY_GetBlockOffset(uint16_t block)
} }
// A bank contains 32 frequency, 32 name and 4 attribute blocks. // A bank contains 32 frequency, 32 name and 4 attribute blocks.
const uint16_t channelOffset = gAircopyCurrentMapIndex * 0x0800u; const uint16_t channelOffset = map * 0x0800u;
if (block < 32u) if (block < 32u)
return channelOffset + block * AIRCOPY_BLOCK_SIZE; return channelOffset + block * AIRCOPY_BLOCK_SIZE;
if (block < 64u) if (block < 64u)
return 0x4000u + channelOffset + (block - 32u) * AIRCOPY_BLOCK_SIZE; return 0x4000u + channelOffset + (block - 32u) * AIRCOPY_BLOCK_SIZE;
return 0x8000u + gAircopyCurrentMapIndex * 0x0100u return 0x8000u + map * 0x0100u
+ (block - 64u) * AIRCOPY_BLOCK_SIZE; + (block - 64u) * AIRCOPY_BLOCK_SIZE;
} }
@@ -314,8 +342,9 @@ void AIRCOPY_StorePacket(void)
static void AIRCOPY_InitTransfer(bool isSendMode) static void AIRCOPY_InitTransfer(bool isSendMode)
{ {
if (gAircopyCurrentMapIndex >= AIRCOPY_NUM_MAPS) if (gAircopyCurrentMapIndex > AIRCOPY_ALL_INDEX)
gAircopyCurrentMapIndex = 0; gAircopyCurrentMapIndex = 0;
gAircopyAll = (gAircopyCurrentMapIndex == AIRCOPY_ALL_INDEX);
gFSKWriteIndex = 0; gFSKWriteIndex = 0;
gAirCopyBlockNumber = 0; gAirCopyBlockNumber = 0;
@@ -400,10 +429,10 @@ static void AIRCOPY_Key_UP_DOWN(int8_t Direction)
switch(Direction) switch(Direction)
{ {
case 1: case 1:
gAircopyCurrentMapIndex = (gAircopyCurrentMapIndex + 1) % AIRCOPY_NUM_MAPS; gAircopyCurrentMapIndex = (gAircopyCurrentMapIndex + 1) % (AIRCOPY_NUM_MAPS + 1u);
break; break;
case -1: case -1:
gAircopyCurrentMapIndex = (gAircopyCurrentMapIndex + AIRCOPY_NUM_MAPS - 1) % AIRCOPY_NUM_MAPS; gAircopyCurrentMapIndex = (gAircopyCurrentMapIndex + AIRCOPY_NUM_MAPS) % (AIRCOPY_NUM_MAPS + 1u);
break; break;
} }
} }
+5 -1
View File
@@ -28,6 +28,8 @@
#define AIRCOPY_BLOCK_SIZE 0x0040u // 64 bytes per AirCopy block #define AIRCOPY_BLOCK_SIZE 0x0040u // 64 bytes per AirCopy block
#define AIRCOPY_CHANNELS_PER_BANK 128 #define AIRCOPY_CHANNELS_PER_BANK 128
#define AIRCOPY_NUM_BANKS MR_CHANNELS_MAX / AIRCOPY_CHANNELS_PER_BANK #define AIRCOPY_NUM_BANKS MR_CHANNELS_MAX / AIRCOPY_CHANNELS_PER_BANK
#define AIRCOPY_NUM_MAPS (AIRCOPY_NUM_BANKS + 1u) // banks + one settings map
#define AIRCOPY_ALL_INDEX AIRCOPY_NUM_MAPS // selection sentinel: send/receive everything
#define AIRCOPY_BAR_WIDTH 120 // Visible width of the progress gauge #define AIRCOPY_BAR_WIDTH 120 // Visible width of the progress gauge
// ============================================================================ // ============================================================================
@@ -49,6 +51,7 @@ extern AIRCOPY_State_t gAircopyState;
extern uint16_t gAirCopyBlockNumber; extern uint16_t gAirCopyBlockNumber;
extern uint16_t gErrorsDuringAirCopy; extern uint16_t gErrorsDuringAirCopy;
extern bool gAirCopyIsSendMode; extern bool gAirCopyIsSendMode;
extern bool gAircopyAll; // All mode: banks + settings in one pass
extern uint16_t g_FSK_Buffer[36]; extern uint16_t g_FSK_Buffer[36];
@@ -59,7 +62,8 @@ extern uint16_t g_FSK_Buffer[36];
bool AIRCOPY_SendMessage(void); bool AIRCOPY_SendMessage(void);
void AIRCOPY_StorePacket(void); void AIRCOPY_StorePacket(void);
void AIRCOPY_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld); void AIRCOPY_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld);
uint8_t AIRCOPY_GetTotalBlocks(void); uint16_t AIRCOPY_GetTotalBlocks(void);
uint8_t AIRCOPY_CurrentSliceMap(void); // map index of the block in progress (All slice label)
// XOR-obfuscate `count` words of g_FSK_Buffer starting at index 1. // XOR-obfuscate `count` words of g_FSK_Buffer starting at index 1.
// Self-inverse: applying twice restores the original buffer. // Self-inverse: applying twice restores the original buffer.
+16 -4
View File
@@ -37,7 +37,17 @@ void UI_DisplayAircopy(void)
if (gAircopyState == AIRCOPY_READY) { if (gAircopyState == AIRCOPY_READY) {
pPrintStr = "AIR COPY(RDY)"; pPrintStr = "AIR COPY(RDY)";
} else if (gAircopyState == AIRCOPY_TRANSFER) { } else if (gAircopyState == AIRCOPY_TRANSFER) {
pPrintStr = "AIR COPY"; if (gAircopyAll) {
// All mode: show the slice being replicated in place of the title.
const uint8_t m = AIRCOPY_CurrentSliceMap();
if (m < AIRCOPY_NUM_BANKS)
sprintf(String, "MEM %03u-%03u", (m * 128) + 1, (m + 1) * 128);
else
strcpy(String, "SETTINGS");
pPrintStr = String;
} else {
pPrintStr = "AIR COPY";
}
} else if (gAircopyState == AIRCOPY_COMPLETE) { } else if (gAircopyState == AIRCOPY_COMPLETE) {
pPrintStr = "AIR COPY OK"; pPrintStr = "AIR COPY OK";
} else { } else {
@@ -60,7 +70,7 @@ void UI_DisplayAircopy(void)
// show the main large frequency digits // show the main large frequency digits
UI_DisplayFrequency(String, 16, 2, false); UI_DisplayFrequency(String, 16, 2, false);
const uint8_t totalBlocks = AIRCOPY_GetTotalBlocks(); const uint16_t totalBlocks = AIRCOPY_GetTotalBlocks();
uint16_t doneBlocks = gAirCopyBlockNumber; uint16_t doneBlocks = gAirCopyBlockNumber;
if (doneBlocks > totalBlocks) if (doneBlocks > totalBlocks)
@@ -69,10 +79,12 @@ void UI_DisplayAircopy(void)
// Draw memory selection // Draw memory selection
if (gAircopyState == AIRCOPY_READY) if (gAircopyState == AIRCOPY_READY)
{ {
if(gAircopyCurrentMapIndex < AIRCOPY_NUM_BANKS) { if(gAircopyCurrentMapIndex < AIRCOPY_NUM_BANKS) {
sprintf(String, "MEM %03u - %03u", (gAircopyCurrentMapIndex * 128) + 1, (gAircopyCurrentMapIndex + 1) * 128); sprintf(String, "MEM %03u - %03u", (gAircopyCurrentMapIndex * 128) + 1, (gAircopyCurrentMapIndex + 1) * 128);
} else if(gAircopyCurrentMapIndex == AIRCOPY_NUM_BANKS) {
strcpy(String, "Settings");
} else { } else {
strcpy(String, "Settings"); strcpy(String, "All (Mem+Set)");
} }
UI_PrintString(String, 2, 127, 5, 8); UI_PrintString(String, 2, 127, 5, 8);
} }