diff --git a/app/uart.c b/app/uart.c new file mode 100644 index 0000000..e46e0a6 --- /dev/null +++ b/app/uart.c @@ -0,0 +1,569 @@ +/* Copyright 2023 Dual Tachyon + * https://github.com/DualTachyon + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include + +#if !defined(ENABLE_OVERLAY) + #include "ARMCM0.h" +#endif +#ifdef ENABLE_FMRADIO + #include "app/fm.h" +#endif +#include "app/uart.h" +#include "board.h" +#include "bsp/dp32g030/dma.h" +#include "bsp/dp32g030/gpio.h" +#include "driver/aes.h" +#include "driver/bk4819.h" +#include "driver/crc.h" +#include "driver/eeprom.h" +#include "driver/gpio.h" +#include "driver/uart.h" +#include "functions.h" +#include "misc.h" +#include "settings.h" +#if defined(ENABLE_OVERLAY) + #include "sram-overlay.h" +#endif +#include "version.h" +#include "ui/ui.h" + +#define DMA_INDEX(x, y) (((x) + (y)) % sizeof(UART_DMA_Buffer)) + +typedef struct { + uint16_t ID; + uint16_t Size; +} Header_t; + +typedef struct { + uint8_t Padding[2]; + uint16_t ID; +} Footer_t; + +typedef struct { + Header_t Header; + uint32_t Timestamp; +} CMD_0514_t; + +typedef struct { + Header_t Header; + struct { + char Version[16]; + bool g_has_custom_aes_key; + bool g_is_in_lock_screen; + uint8_t Padding[2]; + uint32_t Challenge[4]; + } Data; +} REPLY_0514_t; + +typedef struct { + Header_t Header; + uint16_t Offset; + uint8_t Size; + uint8_t Padding; + uint32_t Timestamp; +} CMD_051B_t; + +typedef struct { + Header_t Header; + struct { + uint16_t Offset; + uint8_t Size; + uint8_t Padding; + uint8_t Data[128]; + } Data; +} REPLY_051B_t; + +typedef struct { + Header_t Header; + uint16_t Offset; + uint8_t Size; + bool bAllowPassword; + uint32_t Timestamp; + uint8_t Data[0]; +} CMD_051D_t; + +typedef struct { + Header_t Header; + struct { + uint16_t Offset; + } Data; +} REPLY_051D_t; + +typedef struct { + Header_t Header; + struct { + uint16_t RSSI; + uint8_t ExNoiseIndicator; + uint8_t GlitchIndicator; + } Data; +} REPLY_0527_t; + +typedef struct { + Header_t Header; + struct { + uint16_t Voltage; + uint16_t Current; + } Data; +} REPLY_0529_t; + +typedef struct { + Header_t Header; + uint32_t Response[4]; +} CMD_052D_t; + +typedef struct { + Header_t Header; + struct { + bool bIsLocked; + uint8_t Padding[3]; + } Data; +} REPLY_052D_t; + +typedef struct { + Header_t Header; + uint32_t Timestamp; +} CMD_052F_t; + +static const uint8_t Obfuscation[16] = +{ + 0x16, 0x6C, 0x14, 0xE6, 0x2E, 0x91, 0x0D, 0x40, 0x21, 0x35, 0xD5, 0x40, 0x13, 0x03, 0xE9, 0x80 +}; + +static union +{ + uint8_t Buffer[256]; + struct + { + Header_t Header; + uint8_t Data[252]; + }; +} UART_Command; + +static uint32_t Timestamp; +static uint16_t g_uart_write_index; +static bool bIsEncrypted = true; + +static void SendReply(void *pReply, uint16_t Size) +{ + Header_t Header; + Footer_t Footer; + + if (bIsEncrypted) + { + uint8_t *pBytes = (uint8_t *)pReply; + unsigned int i; + for (i = 0; i < Size; i++) + pBytes[i] ^= Obfuscation[i % 16]; + } + + Header.ID = 0xCDAB; + Header.Size = Size; + UART_Send(&Header, sizeof(Header)); + UART_Send(pReply, Size); + + if (bIsEncrypted) + { + Footer.Padding[0] = Obfuscation[(Size + 0) % 16] ^ 0xFF; + Footer.Padding[1] = Obfuscation[(Size + 1) % 16] ^ 0xFF; + } + else + { + Footer.Padding[0] = 0xFF; + Footer.Padding[1] = 0xFF; + } + Footer.ID = 0xBADC; + + UART_Send(&Footer, sizeof(Footer)); +} + +static void SendVersion(void) +{ + REPLY_0514_t Reply; + + Reply.Header.ID = 0x0515; + Reply.Header.Size = sizeof(Reply.Data); + strcpy(Reply.Data.Version, Version); + Reply.Data.g_has_custom_aes_key = g_has_custom_aes_key; + Reply.Data.g_is_in_lock_screen = g_is_in_lock_screen; + Reply.Data.Challenge[0] = g_challenge[0]; + Reply.Data.Challenge[1] = g_challenge[1]; + Reply.Data.Challenge[2] = g_challenge[2]; + Reply.Data.Challenge[3] = g_challenge[3]; + + SendReply(&Reply, sizeof(Reply)); +} + +static bool IsBadChallenge(const uint32_t *pKey, const uint32_t *pIn, const uint32_t *pResponse) +{ + unsigned int i; + uint32_t IV[4]; + + IV[0] = 0; + IV[1] = 0; + IV[2] = 0; + IV[3] = 0; + + AES_Encrypt(pKey, IV, pIn, IV, true); + + for (i = 0; i < 4; i++) + if (IV[i] != pResponse[i]) + return true; + + return false; +} + +static void CMD_0514(const uint8_t *pBuffer) +{ + const CMD_0514_t *pCmd = (const CMD_0514_t *)pBuffer; + + Timestamp = pCmd->Timestamp; + + #ifdef ENABLE_FMRADIO + g_fm_radio_count_down_500ms = fm_radio_countdown_500ms; + #endif + + g_serial_config_count_down_500ms = serial_config_count_down_500ms; + + // turn the LCD backlight off +// GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_BACKLIGHT); + + // show message + g_request_display_screen = DISPLAY_MAIN; + g_update_display = true; + + SendVersion(); +} + +static void CMD_051B(const uint8_t *pBuffer) +{ + const CMD_051B_t *pCmd = (const CMD_051B_t *)pBuffer; + REPLY_051B_t Reply; + bool bLocked = false; + + if (pCmd->Timestamp != Timestamp) + return; + + g_serial_config_count_down_500ms = serial_config_count_down_500ms; + + #ifdef ENABLE_FMRADIO + g_fm_radio_count_down_500ms = fm_radio_countdown_500ms; + #endif + + memset(&Reply, 0, sizeof(Reply)); + Reply.Header.ID = 0x051C; + Reply.Header.Size = pCmd->Size + 4; + Reply.Data.Offset = pCmd->Offset; + Reply.Data.Size = pCmd->Size; + + if (g_has_custom_aes_key) + bLocked = g_is_locked; + + if (!bLocked) + EEPROM_ReadBuffer(pCmd->Offset, Reply.Data.Data, pCmd->Size); + + SendReply(&Reply, pCmd->Size + 8); +} + +static void CMD_051D(const uint8_t *pBuffer) +{ + const CMD_051D_t *pCmd = (const CMD_051D_t *)pBuffer; + REPLY_051D_t Reply; + bool bReloadEeprom; + bool bIsLocked; + + if (pCmd->Timestamp != Timestamp) + return; + + g_serial_config_count_down_500ms = serial_config_count_down_500ms; + + bReloadEeprom = false; + + #ifdef ENABLE_FMRADIO + g_fm_radio_count_down_500ms = fm_radio_countdown_500ms; + #endif + + Reply.Header.ID = 0x051E; + Reply.Header.Size = sizeof(Reply.Data); + Reply.Data.Offset = pCmd->Offset; + + bIsLocked = g_has_custom_aes_key ? g_is_locked : g_has_custom_aes_key; + + if (!bIsLocked) + { + unsigned int i; + for (i = 0; i < (pCmd->Size / 8); i++) + { + const uint16_t Offset = pCmd->Offset + (i * 8U); + + if (Offset >= 0x0F30 && Offset < 0x0F40) + if (!g_is_locked) + bReloadEeprom = true; + + if ((Offset < 0x0E98 || Offset >= 0x0EA0) || !g_is_in_lock_screen || pCmd->bAllowPassword) + EEPROM_WriteBuffer(Offset, &pCmd->Data[i * 8U]); + } + + if (bReloadEeprom) + BOARD_EEPROM_Init(); + } + + SendReply(&Reply, sizeof(Reply)); +} + +static void CMD_0527(void) +{ + REPLY_0527_t Reply; + + Reply.Header.ID = 0x0528; + Reply.Header.Size = sizeof(Reply.Data); + Reply.Data.RSSI = BK4819_ReadRegister(BK4819_REG_67) & 0x01FF; + Reply.Data.ExNoiseIndicator = BK4819_ReadRegister(BK4819_REG_65) & 0x007F; + Reply.Data.GlitchIndicator = BK4819_ReadRegister(BK4819_REG_63); + + SendReply(&Reply, sizeof(Reply)); +} + +static void CMD_0529(void) +{ + REPLY_0529_t Reply; + + Reply.Header.ID = 0x52A; + Reply.Header.Size = sizeof(Reply.Data); + + // Original doesn't actually send current! + BOARD_ADC_GetBatteryInfo(&Reply.Data.Voltage, &Reply.Data.Current); + + SendReply(&Reply, sizeof(Reply)); +} + +static void CMD_052D(const uint8_t *pBuffer) +{ + const CMD_052D_t *pCmd = (const CMD_052D_t *)pBuffer; + REPLY_052D_t Reply; + bool bIsLocked; + + #ifdef ENABLE_FMRADIO + g_fm_radio_count_down_500ms = fm_radio_countdown_500ms; + #endif + Reply.Header.ID = 0x052E; + Reply.Header.Size = sizeof(Reply.Data); + + bIsLocked = g_has_custom_aes_key; + + if (!bIsLocked) + bIsLocked = IsBadChallenge(g_custom_aes_key, g_challenge, pCmd->Response); + + if (!bIsLocked) + { + bIsLocked = IsBadChallenge(g_default_aes_key, g_challenge, pCmd->Response); + if (bIsLocked) + g_try_count++; + } + + if (g_try_count < 3) + { + if (!bIsLocked) + g_try_count = 0; + } + else + { + g_try_count = 3; + bIsLocked = true; + } + + g_is_locked = bIsLocked; + Reply.Data.bIsLocked = bIsLocked; + + SendReply(&Reply, sizeof(Reply)); +} + +static void CMD_052F(const uint8_t *pBuffer) +{ + const CMD_052F_t *pCmd = (const CMD_052F_t *)pBuffer; + + g_eeprom.dual_watch = DUAL_WATCH_OFF; + g_eeprom.cross_vfo_rx_tx = CROSS_BAND_OFF; + g_eeprom.rx_vfo = 0; + g_eeprom.dtmf_side_tone = false; + g_eeprom.vfo_info[0].frequency_reverse = false; + g_eeprom.vfo_info[0].pRX = &g_eeprom.vfo_info[0].freq_config_rx; + g_eeprom.vfo_info[0].pTX = &g_eeprom.vfo_info[0].freq_config_tx; + g_eeprom.vfo_info[0].tx_offset_freq_dir = TX_OFFSET_FREQ_DIR_OFF; + g_eeprom.vfo_info[0].dtmf_ptt_id_tx_mode = PTT_ID_OFF; + g_eeprom.vfo_info[0].dtmf_decoding_enable = false; + + #ifdef ENABLE_NOAA + g_is_noaa_mode = false; + #endif + + if (g_current_function == FUNCTION_POWER_SAVE) + FUNCTION_Select(FUNCTION_FOREGROUND); + + g_serial_config_count_down_500ms = serial_config_count_down_500ms; + + Timestamp = pCmd->Timestamp; + + // turn the LCD backlight off +// GPIO_ClearBit(&GPIOB->DATA, GPIOB_PIN_BACKLIGHT); + + // show message + g_request_display_screen = DISPLAY_MAIN; + g_update_display = true; + + SendVersion(); +} + +bool UART_IsCommandAvailable(void) +{ + uint16_t Index; + uint16_t TailIndex; + uint16_t Size; + uint16_t CRC; + uint16_t CommandLength; + uint16_t DmaLength = DMA_CH0->ST & 0xFFFU; + + while (1) + { + if (g_uart_write_index == DmaLength) + return false; + + while (g_uart_write_index != DmaLength && UART_DMA_Buffer[g_uart_write_index] != 0xABU) + g_uart_write_index = DMA_INDEX(g_uart_write_index, 1); + + if (g_uart_write_index == DmaLength) + return false; + + if (g_uart_write_index < DmaLength) + CommandLength = DmaLength - g_uart_write_index; + else + CommandLength = (DmaLength + sizeof(UART_DMA_Buffer)) - g_uart_write_index; + + if (CommandLength < 8) + return 0; + + if (UART_DMA_Buffer[DMA_INDEX(g_uart_write_index, 1)] == 0xCD) + break; + + g_uart_write_index = DMA_INDEX(g_uart_write_index, 1); + } + + Index = DMA_INDEX(g_uart_write_index, 2); + Size = (UART_DMA_Buffer[DMA_INDEX(Index, 1)] << 8) | UART_DMA_Buffer[Index]; + + if ((Size + 8u) > sizeof(UART_DMA_Buffer)) + { + g_uart_write_index = DmaLength; + return false; + } + + if (CommandLength < (Size + 8)) + return false; + + Index = DMA_INDEX(Index, 2); + TailIndex = DMA_INDEX(Index, Size + 2); + + if (UART_DMA_Buffer[TailIndex] != 0xDC || UART_DMA_Buffer[DMA_INDEX(TailIndex, 1)] != 0xBA) + { + g_uart_write_index = DmaLength; + return false; + } + + if (TailIndex < Index) + { + const uint16_t ChunkSize = sizeof(UART_DMA_Buffer) - Index; + memmove(UART_Command.Buffer, UART_DMA_Buffer + Index, ChunkSize); + memmove(UART_Command.Buffer + ChunkSize, UART_DMA_Buffer, TailIndex); + } + else + memmove(UART_Command.Buffer, UART_DMA_Buffer + Index, TailIndex - Index); + + TailIndex = DMA_INDEX(TailIndex, 2); + if (TailIndex < g_uart_write_index) + { + memset(UART_DMA_Buffer + g_uart_write_index, 0, sizeof(UART_DMA_Buffer) - g_uart_write_index); + memset(UART_DMA_Buffer, 0, TailIndex); + } + else + memset(UART_DMA_Buffer + g_uart_write_index, 0, TailIndex - g_uart_write_index); + + g_uart_write_index = TailIndex; + + if (UART_Command.Header.ID == 0x0514) + bIsEncrypted = false; + + if (UART_Command.Header.ID == 0x6902) + bIsEncrypted = true; + + if (bIsEncrypted) + { + unsigned int i; + for (i = 0; i < (Size + 2u); i++) + UART_Command.Buffer[i] ^= Obfuscation[i % 16]; + } + + CRC = UART_Command.Buffer[Size] | (UART_Command.Buffer[Size + 1] << 8); + + return (CRC_Calculate(UART_Command.Buffer, Size) != CRC) ? false : true; +} + +void UART_HandleCommand(void) +{ + switch (UART_Command.Header.ID) + { + case 0x0514: + CMD_0514(UART_Command.Buffer); + break; + + case 0x051B: + CMD_051B(UART_Command.Buffer); + break; + + case 0x051D: + CMD_051D(UART_Command.Buffer); + break; + + case 0x051F: // Not implementing non-authentic command + break; + + case 0x0521: // Not implementing non-authentic command + break; + + case 0x0527: + CMD_0527(); + break; + + case 0x0529: + CMD_0529(); + break; + + case 0x052D: + CMD_052D(UART_Command.Buffer); + break; + + case 0x052F: + CMD_052F(UART_Command.Buffer); + break; + + case 0x05DD: + #if defined(ENABLE_OVERLAY) + overlay_FLASH_RebootToBootloader(); + #else + NVIC_SystemReset(); + #endif + break; + } +} diff --git a/main.c b/main.c index 2402b52..77c31dc 100644 --- a/main.c +++ b/main.c @@ -81,6 +81,10 @@ void Main(void) memset(g_dtmf_string, '-', sizeof(g_dtmf_string)); g_dtmf_string[sizeof(g_dtmf_string) - 1] = 0; +#if 0 + SETTINGS_restore_calibration(); +#endif + BK4819_Init(); BOARD_ADC_GetBatteryInfo(&g_usb_current_voltage, &g_usb_current); @@ -116,7 +120,7 @@ void Main(void) // sort the menu list UI_SortMenu(!g_f_lock); - + ST7565_SetContrast(g_setting_contrast); // wait for user to release all butts before moving on diff --git a/settings.c b/settings.c index 079334c..bbfcb8a 100644 --- a/settings.c +++ b/settings.c @@ -73,6 +73,113 @@ void SETTINGS_SaveVfoIndices(void) EEPROM_WriteBuffer(0x0E80, State); } +const uint8_t calib1[] = +{ // my first radios calibration data + 0x0A, 0x4B, 0x53, 0x56, 0x59, 0x5C, 0x5F, 0x62, 0x64, 0x66, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0x46, 0x50, 0x53, 0x56, 0x59, 0x5C, 0x5F, + 0x62, 0x64, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0x2D, 0x29, 0x26, + 0x23, 0x20, 0x1D, 0x1A, 0x17, 0x14, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x64, 0x30, 0x2D, 0x29, 0x26, 0x23, 0x20, 0x1D, 0x1A, 0x17, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0x14, 0x11, 0x0E, 0x0B, 0x08, 0x03, 0x02, + 0x02, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x64, 0x11, 0x0E, 0x0B, + 0x08, 0x05, 0x05, 0x04, 0x04, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x32, 0x68, 0x6B, 0x6E, 0x6F, 0x72, 0x75, 0x77, 0x79, 0x7B, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x64, 0x67, 0x6A, 0x6C, 0x6E, 0x71, 0x73, + 0x76, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x32, 0x2D, 0x28, + 0x24, 0x21, 0x1E, 0x1A, 0x17, 0x16, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x46, 0x37, 0x32, 0x2D, 0x28, 0x25, 0x22, 0x1E, 0x1B, 0x19, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0x19, 0x0F, 0x0A, 0x09, 0x08, 0x07, 0x06, + 0x05, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x64, 0x1E, 0x14, 0x0F, + 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x6E, 0x00, 0x78, 0x00, 0x82, 0x00, 0x8C, 0x00, 0x86, 0x00, 0xAA, 0x00, + 0xCE, 0x00, 0xF2, 0x00, 0x32, 0x32, 0x32, 0x64, 0x64, 0x64, 0x8C, 0x8C, + 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x32, 0x32, 0x32, 0x64, + 0x64, 0x64, 0x8C, 0x8C, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x5F, 0x5F, 0x5F, 0x69, 0x69, 0x69, 0x91, 0x91, 0x8F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x32, 0x32, 0x32, 0x64, 0x64, 0x64, 0x8C, 0x8C, + 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0x5A, 0x5A, 0x64, + 0x64, 0x64, 0x82, 0x82, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x5A, 0x5A, 0x5A, 0x64, 0x64, 0x64, 0x8F, 0x91, 0x8A, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x32, 0x32, 0x32, 0x64, 0x64, 0x64, 0x8C, 0x8C, + 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xDE, 0x04, 0xFA, 0x06, + 0x45, 0x07, 0x5E, 0x07, 0xC5, 0x07, 0xFC, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, + 0x1E, 0x00, 0x32, 0x00, 0x46, 0x00, 0x5A, 0x00, 0x6E, 0x00, 0x82, 0x00, + 0x96, 0x00, 0xAA, 0x00, 0xC8, 0x00, 0xE6, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x14, 0x00, 0x28, 0x00, 0x3C, 0x00, 0x50, 0x00, 0x64, 0x00, 0x78, 0x00, + 0x8C, 0x00, 0xA0, 0x00, 0xBE, 0x00, 0xDC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x03, 0x08, 0x10, 0x18, 0x1F, 0xFF, 0xFF, 0xFF, 0x04, 0x00, 0x46, 0x00, + 0x50, 0x00, 0x2C, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +const uint8_t calib2[] = +{ // my 2nd radios calibration data + 0x0A, 0x4B, 0x53, 0x56, 0x59, 0x5C, 0x5F, 0x62, 0x64, 0x66, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x05, 0x46, 0x50, 0x53, 0x56, 0x59, 0x5C, 0x5F, + 0x62, 0x64, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0x2D, 0x29, 0x26, + 0x23, 0x20, 0x1D, 0x1A, 0x17, 0x14, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x64, 0x30, 0x2D, 0x29, 0x26, 0x23, 0x20, 0x1D, 0x1A, 0x17, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0x14, 0x11, 0x0E, 0x0B, 0x08, 0x03, 0x02, + 0x02, 0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x64, 0x11, 0x0E, 0x0B, + 0x08, 0x05, 0x05, 0x04, 0x04, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x32, 0x68, 0x6B, 0x6E, 0x6F, 0x72, 0x75, 0x77, 0x79, 0x7B, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x28, 0x64, 0x67, 0x6A, 0x6C, 0x6E, 0x71, 0x73, + 0x76, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x41, 0x32, 0x2D, 0x28, + 0x24, 0x21, 0x1E, 0x1A, 0x17, 0x16, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x46, 0x37, 0x32, 0x2D, 0x28, 0x25, 0x22, 0x1E, 0x1B, 0x19, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0x19, 0x0F, 0x0A, 0x09, 0x08, 0x07, 0x06, + 0x05, 0x04, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x64, 0x1E, 0x14, 0x0F, + 0x0D, 0x0C, 0x0B, 0x0A, 0x09, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x6E, 0x00, 0x78, 0x00, 0x82, 0x00, 0x8C, 0x00, 0x86, 0x00, 0xAA, 0x00, + 0xCE, 0x00, 0xF2, 0x00, 0x32, 0x32, 0x32, 0x64, 0x64, 0x64, 0x8C, 0x8C, + 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x32, 0x32, 0x32, 0x64, + 0x64, 0x64, 0x8C, 0x8C, 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x5F, 0x5F, 0x5F, 0x69, 0x69, 0x69, 0x7B, 0x7D, 0x7F, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x32, 0x32, 0x32, 0x64, 0x64, 0x64, 0x8C, 0x8C, + 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x5A, 0x5A, 0x5A, 0x64, + 0x64, 0x64, 0x82, 0x82, 0x82, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0x5A, 0x5A, 0x5A, 0x64, 0x64, 0x64, 0x8B, 0x8D, 0x8A, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0x32, 0x32, 0x32, 0x64, 0x64, 0x64, 0x8C, 0x8C, + 0x8C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xEE, 0x04, 0x10, 0x07, + 0x5A, 0x07, 0x73, 0x07, 0xD9, 0x07, 0xFC, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, + 0x1E, 0x00, 0x32, 0x00, 0x46, 0x00, 0x5A, 0x00, 0x6E, 0x00, 0x82, 0x00, + 0x96, 0x00, 0xAA, 0x00, 0xC8, 0x00, 0xE6, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x14, 0x00, 0x28, 0x00, 0x3C, 0x00, 0x50, 0x00, 0x64, 0x00, 0x78, 0x00, + 0x8C, 0x00, 0xA0, 0x00, 0xBE, 0x00, 0xDC, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, + 0x03, 0x08, 0x0E, 0x13, 0x18, 0xFF, 0xFF, 0xFF, 0x05, 0x00, 0x46, 0x00, + 0x50, 0x00, 0x2C, 0x0E, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF +}; + +void SETTINGS_restore_calibration(void) +{ +// const uint8_t buf[8] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + unsigned int index = 0; + while (index < sizeof(calib2)) + { + const unsigned int addr = 0x1E00 + index; + EEPROM_WriteBuffer(addr, &calib2[index]); +// EEPROM_WriteBuffer(addr, buf); + index += 8; + } +} + void SETTINGS_SaveSettings(void) { uint8_t State[8]; diff --git a/settings.h b/settings.h index 03e1efb..009a9ac 100644 --- a/settings.h +++ b/settings.h @@ -226,6 +226,7 @@ extern eeprom_config_t g_eeprom; void SETTINGS_SaveFM(void); #endif void SETTINGS_SaveVfoIndices(void); +//void SETTINGS_restore_calibration(void); void SETTINGS_SaveSettings(void); void SETTINGS_SaveChannel(uint8_t Channel, uint8_t VFO, const vfo_info_t *pVFO, uint8_t Mode); void SETTINGS_UpdateChannel(uint8_t Channel, const vfo_info_t *pVFO, bool keep);