diff --git a/App/app/aircopy.c b/App/app/aircopy.c index 6d6aa7bd..7c2fadc6 100644 --- a/App/app/aircopy.c +++ b/App/app/aircopy.c @@ -42,6 +42,7 @@ AIRCOPY_State_t gAircopyState; uint16_t gAirCopyBlockNumber; uint16_t gErrorsDuringAirCopy; bool gAirCopyIsSendMode; +bool gAircopyAll; uint16_t g_FSK_Buffer[36]; @@ -60,24 +61,51 @@ uint16_t g_FSK_Buffer[36]; static uint16_t AircopyCountdown; static uint8_t AircopyRetries; -#define AIRCOPY_NUM_MAPS (AIRCOPY_NUM_BANKS + 1u) #define AIRCOPY_BANK_BLOCKS 68u #define AIRCOPY_SETTINGS_BLOCKS 12u +#define AIRCOPY_ALL_BLOCKS (AIRCOPY_NUM_BANKS * AIRCOPY_BANK_BLOCKS + AIRCOPY_SETTINGS_BLOCKS) // ============================================================================ // 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 ? AIRCOPY_SETTINGS_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) { - 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. 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. - const uint16_t channelOffset = gAircopyCurrentMapIndex * 0x0800u; + const uint16_t channelOffset = map * 0x0800u; if (block < 32u) return channelOffset + block * AIRCOPY_BLOCK_SIZE; if (block < 64u) return 0x4000u + channelOffset + (block - 32u) * AIRCOPY_BLOCK_SIZE; - return 0x8000u + gAircopyCurrentMapIndex * 0x0100u + return 0x8000u + map * 0x0100u + (block - 64u) * AIRCOPY_BLOCK_SIZE; } @@ -314,8 +342,9 @@ void AIRCOPY_StorePacket(void) static void AIRCOPY_InitTransfer(bool isSendMode) { - if (gAircopyCurrentMapIndex >= AIRCOPY_NUM_MAPS) + if (gAircopyCurrentMapIndex > AIRCOPY_ALL_INDEX) gAircopyCurrentMapIndex = 0; + gAircopyAll = (gAircopyCurrentMapIndex == AIRCOPY_ALL_INDEX); gFSKWriteIndex = 0; gAirCopyBlockNumber = 0; @@ -400,10 +429,10 @@ static void AIRCOPY_Key_UP_DOWN(int8_t Direction) switch(Direction) { case 1: - gAircopyCurrentMapIndex = (gAircopyCurrentMapIndex + 1) % AIRCOPY_NUM_MAPS; + gAircopyCurrentMapIndex = (gAircopyCurrentMapIndex + 1) % (AIRCOPY_NUM_MAPS + 1u); break; case -1: - gAircopyCurrentMapIndex = (gAircopyCurrentMapIndex + AIRCOPY_NUM_MAPS - 1) % AIRCOPY_NUM_MAPS; + gAircopyCurrentMapIndex = (gAircopyCurrentMapIndex + AIRCOPY_NUM_MAPS) % (AIRCOPY_NUM_MAPS + 1u); break; } } diff --git a/App/app/aircopy.h b/App/app/aircopy.h index 2dd594d6..1092bbc0 100644 --- a/App/app/aircopy.h +++ b/App/app/aircopy.h @@ -28,6 +28,8 @@ #define AIRCOPY_BLOCK_SIZE 0x0040u // 64 bytes per AirCopy block #define AIRCOPY_CHANNELS_PER_BANK 128 #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 // ============================================================================ @@ -49,6 +51,7 @@ extern AIRCOPY_State_t gAircopyState; extern uint16_t gAirCopyBlockNumber; extern uint16_t gErrorsDuringAirCopy; extern bool gAirCopyIsSendMode; +extern bool gAircopyAll; // All mode: banks + settings in one pass extern uint16_t g_FSK_Buffer[36]; @@ -59,7 +62,8 @@ extern uint16_t g_FSK_Buffer[36]; bool AIRCOPY_SendMessage(void); void AIRCOPY_StorePacket(void); 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. // Self-inverse: applying twice restores the original buffer. diff --git a/App/ui/aircopy.c b/App/ui/aircopy.c index 333820b5..daba1a45 100644 --- a/App/ui/aircopy.c +++ b/App/ui/aircopy.c @@ -37,7 +37,17 @@ void UI_DisplayAircopy(void) if (gAircopyState == AIRCOPY_READY) { pPrintStr = "AIR COPY(RDY)"; } 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) { pPrintStr = "AIR COPY OK"; } else { @@ -60,7 +70,7 @@ void UI_DisplayAircopy(void) // show the main large frequency digits UI_DisplayFrequency(String, 16, 2, false); - const uint8_t totalBlocks = AIRCOPY_GetTotalBlocks(); + const uint16_t totalBlocks = AIRCOPY_GetTotalBlocks(); uint16_t doneBlocks = gAirCopyBlockNumber; if (doneBlocks > totalBlocks) @@ -69,10 +79,12 @@ void UI_DisplayAircopy(void) // Draw memory selection 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); + } else if(gAircopyCurrentMapIndex == AIRCOPY_NUM_BANKS) { + strcpy(String, "Settings"); } else { - strcpy(String, "Settings"); + strcpy(String, "All (Mem+Set)"); } UI_PrintString(String, 2, 127, 5, 8); }