diff --git a/openrtx/src/core/cps_io_libc.c b/openrtx/src/core/cps_io_libc.c index 7db6080c..1b9aa33f 100644 --- a/openrtx/src/core/cps_io_libc.c +++ b/openrtx/src/core/cps_io_libc.c @@ -52,31 +52,13 @@ int _writeHeader(cps_header_t header) int _pushDown(uint32_t offset, uint32_t amount) { - // Start from the end of the codeplug - cps_header_t header = { 0 }; - if (_readHeader(&header)) - return -1; - fseek(cps_file, - header.ct_count * sizeof(contact_t) + - header.ch_count * sizeof(channel_t), - SEEK_CUR); - // If banks are present skip those - if (header.b_count != 0) { - fseek(cps_file, - (header.b_count - 1) * sizeof(uint32_t), - SEEK_CUR); - uint32_t b_offset = 0; - bankHdr_t b_header = { 0 }; - fread(&b_offset, sizeof(uint32_t), 1, cps_file); - fseek(cps_file, b_offset, SEEK_CUR); - fread(&b_header, sizeof(bankHdr_t), 1, cps_file); - fseek(cps_file, b_header.ch_count * sizeof(uint32_t), SEEK_CUR); - } - // Move data downwards in chunks of fixed size + // Get end of file + fseek(cps_file, 0, SEEK_END); long end = ftell(cps_file); // If offset equals end, just return if (offset == end) return 0; + // Move data downwards in chunks of fixed size char buffer[CPS_CHUNK_SIZE] = { 0 }; for(int i = 1; i <= ((end - offset) / CPS_CHUNK_SIZE); i++) { @@ -162,6 +144,51 @@ int _updateChNumbering(uint16_t pos, bool add) return 0; } +/** + * Internal: get bank data offset + * + * @param pos: position of the bank to be read + * @return the offset in the file where the bank data is stored, -1 if error + */ +long _getBankDataOffset(uint16_t pos) +{ + cps_header_t header = { 0 }; + if (_readHeader(&header)) + return -1; + if (pos >= header.b_count + 1) + return -1; + if (pos == header.b_count) + { + // No bank is present, no offset to read + if (header.b_count == 0) + return ftell(cps_file) + + header.ct_count * sizeof(contact_t) + + header.ch_count * sizeof(channel_t) + + sizeof(uint32_t); + // Read last bank offset + fseek(cps_file, + header.ct_count * sizeof(contact_t) + + header.ch_count * sizeof(channel_t) + + (header.b_count - 1) * sizeof(uint32_t), + SEEK_CUR); + uint32_t offset = 0; + fread(&offset, sizeof(uint32_t), 1, cps_file); + long bdata_pos = ftell(cps_file); + bankHdr_t last_bank = { 0 }; + cps_readBankHeader(&last_bank, header.b_count - 1); + return bdata_pos + offset + sizeof(bankHdr_t) + last_bank.ch_count * sizeof(uint32_t); + } + fseek(cps_file, + header.ct_count * sizeof(contact_t) + + header.ch_count * sizeof(channel_t) + + pos * sizeof(uint32_t), + SEEK_CUR); + uint32_t offset = 0; + fread(&offset, sizeof(uint32_t), 1, cps_file); + return ftell(cps_file) + + (header.b_count - pos - 1) * sizeof(uint32_t) + + offset; +} int cps_open(char *cps_name) { @@ -244,7 +271,7 @@ int cps_readBankHeader(bankHdr_t *b_header, uint16_t pos) SEEK_CUR); uint32_t offset = 0; fread(&offset, sizeof(uint32_t), 1, cps_file); - fseek(cps_file, (header.b_count - pos) * sizeof(uint32_t) + offset, SEEK_CUR); + fseek(cps_file, (header.b_count - pos - 1) * sizeof(uint32_t) + offset, SEEK_CUR); fread(b_header, sizeof(bankHdr_t), 1, cps_file); return 0; } @@ -263,7 +290,7 @@ int32_t cps_readBankData(uint16_t bank_pos, uint16_t pos) SEEK_CUR); uint32_t offset = 0; fread(&offset, sizeof(uint32_t), 1, cps_file); - fseek(cps_file, header.b_count - bank_pos * sizeof(uint32_t) + offset, SEEK_CUR); + fseek(cps_file, (header.b_count - bank_pos - 1) * sizeof(uint32_t) + offset, SEEK_CUR); bankHdr_t b_header = { 0 }; fread(&b_header, sizeof(bankHdr_t), 1, cps_file); if (pos >= b_header.ch_count) @@ -334,7 +361,7 @@ int cps_writeBankData(uint32_t ch, uint16_t bank_pos, uint16_t pos) SEEK_CUR); uint32_t offset = 0; fread(&offset, sizeof(uint32_t), 1, cps_file); - fseek(cps_file, header.b_count - bank_pos * sizeof(uint32_t) + offset, SEEK_CUR); + fseek(cps_file, (header.b_count - bank_pos - 1) * sizeof(uint32_t) + offset, SEEK_CUR); bankHdr_t b_header = { 0 }; fread(&b_header, sizeof(bankHdr_t), 1, cps_file); if (pos >= b_header.ch_count) @@ -386,16 +413,14 @@ int cps_insertBankHeader(bankHdr_t b_header, uint16_t pos) return -1; if (pos >= header.b_count + 1) return -1; - // Read old offset - uint32_t b_offset = 0; fseek(cps_file, header.ct_count * sizeof(contact_t) + header.ch_count * sizeof(channel_t) + pos * sizeof(uint32_t), SEEK_CUR); long b_offset_pos = ftell(cps_file); - fread(&b_offset, sizeof(uint32_t), 1, cps_file); - // Write new offset + uint32_t b_offset = _getBankDataOffset(pos) - _getBankDataOffset(0); + // Read position of the new offset _pushDown(b_offset_pos, sizeof(uint32_t)); fwrite(&b_offset, sizeof(uint32_t), 1, cps_file); // Update all the offsets following the moved bank @@ -408,13 +433,10 @@ int cps_insertBankHeader(bankHdr_t b_header, uint16_t pos) o += sizeof(bankHdr_t); fwrite(&o, sizeof(uint32_t), 1, cps_file); } - // Write new bank - fseek(cps_file, b_offset, SEEK_CUR); - long h_pos = ftell(cps_file); - _pushDown(h_pos, sizeof(bankHdr_t)); - fwrite(&b_header, sizeof(bankHdr_t), 1, cps_file); header.b_count++; _writeHeader(header); + _pushDown(_getBankDataOffset(pos), sizeof(bankHdr_t)); + fwrite(&b_header, sizeof(bankHdr_t), 1, cps_file); return 0; } @@ -423,7 +445,7 @@ int cps_insertBankData(uint32_t ch, uint16_t bank_pos, uint16_t pos) cps_header_t header = { 0 }; if (_readHeader(&header)) return -1; - if (bank_pos >= header.b_count + 1) + if (bank_pos >= header.b_count) return -1; fseek(cps_file, header.ct_count * sizeof(contact_t) + diff --git a/openrtx/src/ui/ui.c b/openrtx/src/ui/ui.c index fe00b69b..141f6f14 100644 --- a/openrtx/src/ui/ui.c +++ b/openrtx/src/ui/ui.c @@ -538,25 +538,24 @@ bool _ui_drawDarkOverlay() { return true; } -int _ui_fsm_loadChannel(uint16_t channel_index, bool *sync_rtx) { +int _ui_fsm_loadChannel(int16_t channel_index, bool *sync_rtx) { channel_t channel; + int32_t selected_channel = channel_index; // If a bank is active, get index from current bank if(state.bank_enabled) { bankHdr_t bank = { 0 }; cps_readBankHeader(&bank, state.bank); - if((channel_index <= 0) || (channel_index > bank.ch_count)) + if((channel_index < 0) || (channel_index >= bank.ch_count)) return -1; - else - // Channel index is 1-based while bank array access is 0-based - channel_index = cps_readBankData(state.bank, channel_index); + channel_index = cps_readBankData(state.bank, channel_index); } int result = cps_readChannel(&channel, channel_index); // Read successful and channel is valid if(result != -1 && _ui_channel_valid(&channel)) { // Set new channel index - state.channel_index = channel_index; + state.channel_index = selected_channel; // Copy channel read to state state.channel = channel; *sync_rtx = true; @@ -1349,7 +1348,7 @@ void ui_updateFSM(event_t event, bool *sync_rtx) if(ui_state.last_main_state == MAIN_VFO) state.vfo_channel = state.channel; // Load bank first channel - _ui_fsm_loadChannel(1, sync_rtx); + _ui_fsm_loadChannel(0, sync_rtx); // Switch to MEM screen state.ui_screen = MAIN_MEM; } diff --git a/tests/unit/cps.c b/tests/unit/cps.c index 29098905..3ff8232f 100644 --- a/tests/unit/cps.c +++ b/tests/unit/cps.c @@ -117,7 +117,6 @@ int test_createComplexCPS() { cps_insertBankData(2, 1, 0); cps_insertBankData(3, 1, 1); cps_insertBankData(4, 1, 2); - cps_insertBankData(5, 1, 3); cps_close(); return 0; } @@ -135,20 +134,20 @@ int test_createOOOCPS() { channel_t ch5 = { M17, 0, 0, 0, 0, 0, 0, 0, 0, "Test channel 5", "", {0}, {{0}} }; bankHdr_t b1 = { "Test Bank 1", 0 }; bankHdr_t b2 = { "Test Bank 2", 0 }; - cps_insertContact(ct2, 0); cps_insertContact(ct1, 0); - cps_insertBankHeader(b2, 0); + cps_insertContact(ct2, 1); cps_insertBankHeader(b1, 0); + cps_insertBankHeader(b2, 1); cps_insertChannel(ch5, 0); - cps_insertBankData(0, 0, 0); + cps_insertBankData(0, 1, 0); cps_insertChannel(ch4, 0); - cps_insertBankData(0, 0, 1); + cps_insertBankData(0, 1, 0); cps_insertChannel(ch3, 0); cps_insertBankData(0, 1, 0); cps_insertChannel(ch2, 0); - cps_insertBankData(0, 1, 1); + cps_insertBankData(0, 0, 0); cps_insertChannel(ch1, 0); - cps_insertBankData(0, 1, 2); + cps_insertBankData(0, 0, 0); cps_close(); return 0; }