diff --git a/Makefile b/Makefile index 65d0407..4cfcb29 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ ENABLE_LTO := 1 ENABLE_UART := 1 ENABLE_UART_DEBUG := 1 ENABLE_AIRCOPY := 1 +ENABLE_AIRCOPY_FREQ := 1 ENABLE_FMRADIO := 1 ENABLE_NOAA := 0 ENABLE_VOICE := 0 @@ -241,6 +242,9 @@ endif ifeq ($(ENABLE_AIRCOPY),1) CFLAGS += -DENABLE_AIRCOPY endif +ifeq ($(ENABLE_AIRCOPY_FREQ),1) + CFLAGS += -DENABLE_AIRCOPY_FREQ +endif ifeq ($(ENABLE_FMRADIO),1) CFLAGS += -DENABLE_FMRADIO endif diff --git a/README.md b/README.md index 437a116..0fe227b 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ ENABLE_LTO := 0 **experimental, reduces size of compiled ENABLE_UART := 1 without this you can't configure radio via PC ENABLE_UART_DEBUG := 0 just for code debugging, it sends debug info along the USB serial connection (programming lead) ENABLE_AIRCOPY := 1 clone radio-to-radio via RF +ENABLE_AIRCOPY_FREQ := 1 remember what you use for the aircopy frequency ENABLE_FMRADIO := 1 WBFM VHF broadcast band receiver ENABLE_NOAA := 1 everything NOAA (only of any use in the USA) ENABLE_VOICE := 0 want to hear voices ? diff --git a/app/aircopy.c b/app/aircopy.c index a1cd095..3d88b09 100644 --- a/app/aircopy.c +++ b/app/aircopy.c @@ -22,6 +22,7 @@ #include "frequencies.h" #include "misc.h" #include "radio.h" +#include "settings.h" #include "ui/helper.h" #include "ui/inputbox.h" #include "ui/ui.h" @@ -30,9 +31,7 @@ static const uint16_t Obfuscation[8] = {0x6C16, 0xE614, 0x912E, 0x400D, 0x3521, aircopy_state_t g_aircopy_state; uint16_t g_air_copy_block_number; -uint16_t g_errors_during_air_copyy; -uint8_t g_air_copy_is_send_mode; - +uint16_t g_errors_during_air_copy; uint16_t g_fsk_buffer[36]; void AIRCOPY_SendMessage(void) @@ -49,7 +48,10 @@ void AIRCOPY_SendMessage(void) g_fsk_buffer[i + 1] ^= Obfuscation[i % 8]; if (++g_air_copy_block_number >= 0x78) - g_aircopy_state = AIRCOPY_COMPLETE; + { + g_aircopy_state = AIRCOPY_COMPLETE; + g_update_display = true; + } RADIO_SetTxParameters(); @@ -101,7 +103,10 @@ void AIRCOPY_StorePacket(void) } if (Offset == 0x1E00) - g_aircopy_state = AIRCOPY_COMPLETE; + { + g_aircopy_state = AIRCOPY_COMPLETE; + g_update_display = true; + } g_air_copy_block_number++; @@ -109,8 +114,8 @@ void AIRCOPY_StorePacket(void) } } } - - g_errors_during_air_copyy++; + + g_errors_during_air_copy++; } static void AIRCOPY_Key_DIGITS(key_code_t Key, bool key_pressed, bool key_held) @@ -141,18 +146,29 @@ static void AIRCOPY_Key_DIGITS(key_code_t Key, bool key_pressed, bool key_held) if (Frequency >= FREQ_BAND_TABLE[i].lower && Frequency < FREQ_BAND_TABLE[i].upper) { #ifdef ENABLE_VOICE - g_another_voice_id = (voice_id_t)Key; + g_another_voice_id = (voice_id_t)Key; #endif - g_rx_vfo->band = i; - Frequency += 75; - Frequency = FREQUENCY_FloorToStep(Frequency, g_rx_vfo->step_freq, 0); + + g_rx_vfo->band = i; + + // round the frequency to nearest step size + Frequency = ((Frequency + (g_rx_vfo->step_freq / 2)) / g_rx_vfo->step_freq) * g_rx_vfo->step_freq; + + g_air_copy_freq = Frequency; + #ifdef ENABLE_AIRCOPY_FREQ + SETTINGS_SaveSettings(); // remeber the frequency for the next time + #endif + g_rx_vfo->freq_config_rx.frequency = Frequency; g_rx_vfo->freq_config_tx.frequency = Frequency; RADIO_ConfigureSquelchAndOutputPower(g_rx_vfo); - g_current_vfo = g_rx_vfo; + + g_current_vfo = g_rx_vfo; + RADIO_SetupRegisters(true); BK4819_SetupAircopy(); BK4819_ResetFSK(); + return; } } @@ -165,20 +181,24 @@ static void AIRCOPY_Key_EXIT(bool key_pressed, bool key_held) { if (!key_held && key_pressed) { - if (g_input_box_index == 0) - { - g_fsk_wite_index = 0; - g_air_copy_block_number = 0; - g_errors_during_air_copyy = 0; - g_input_box_index = 0; - g_air_copy_is_send_mode = 0; - - BK4819_PrepareFSKReceive(); - - g_aircopy_state = AIRCOPY_TRANSFER; + if (g_input_box_index > 0) + { // entering a new frequency to use + g_input_box[--g_input_box_index] = 10; } else - g_input_box[--g_input_box_index] = 10; + { // enter RX mode + + g_aircopy_state = AIRCOPY_RX; + g_update_display = true; + GUI_DisplayScreen(); + + g_fsk_wite_index = 0; + g_air_copy_block_number = 0; + g_errors_during_air_copy = 0; + g_input_box_index = 0; + + BK4819_PrepareFSKReceive(); + } g_request_display_screen = DISPLAY_AIRCOPY; } @@ -187,20 +207,20 @@ static void AIRCOPY_Key_EXIT(bool key_pressed, bool key_held) static void AIRCOPY_Key_MENU(bool key_pressed, bool key_held) { if (!key_held && key_pressed) - { + { // enter TX mode + + g_aircopy_state = AIRCOPY_TX; + g_update_display = true; + GUI_DisplayScreen(); + g_fsk_wite_index = 0; g_air_copy_block_number = 0; g_input_box_index = 0; - g_air_copy_is_send_mode = 1; g_fsk_buffer[0] = 0xABCD; g_fsk_buffer[1] = 0; g_fsk_buffer[35] = 0xDCBA; AIRCOPY_SendMessage(); - - GUI_DisplayScreen(); - - g_aircopy_state = AIRCOPY_TRANSFER; } } diff --git a/app/aircopy.h b/app/aircopy.h index c52fa14..c255382 100644 --- a/app/aircopy.h +++ b/app/aircopy.h @@ -24,16 +24,15 @@ enum aircopy_state_e { AIRCOPY_READY = 0, - AIRCOPY_TRANSFER, + AIRCOPY_RX, + AIRCOPY_TX, AIRCOPY_COMPLETE }; typedef enum aircopy_state_e aircopy_state_t; extern aircopy_state_t g_aircopy_state; extern uint16_t g_air_copy_block_number; -extern uint16_t g_errors_during_air_copyy; -extern uint8_t g_air_copy_is_send_mode; - +extern uint16_t g_errors_during_air_copy; extern uint16_t g_fsk_buffer[36]; void AIRCOPY_SendMessage(void); diff --git a/app/app.c b/app/app.c index 1da9b04..7713fdf 100644 --- a/app/app.c +++ b/app/app.c @@ -928,8 +928,7 @@ void APP_CheckRadioInterrupts(void) #ifdef ENABLE_AIRCOPY if (interrupt_status_bits & BK4819_REG_02_FSK_FIFO_ALMOST_FULL && g_screen_to_display == DISPLAY_AIRCOPY && - g_aircopy_state == AIRCOPY_TRANSFER && - g_air_copy_is_send_mode == 0) + g_aircopy_state == AIRCOPY_RX) { unsigned int i; for (i = 0; i < 4; i++) @@ -1833,7 +1832,7 @@ void APP_TimeSlice10ms(void) } #ifdef ENABLE_AIRCOPY - if (g_screen_to_display == DISPLAY_AIRCOPY && g_aircopy_state == AIRCOPY_TRANSFER && g_air_copy_is_send_mode == 1) + if (g_screen_to_display == DISPLAY_AIRCOPY && g_aircopy_state == AIRCOPY_TX) { if (g_air_copy_send_count_down > 0) { diff --git a/board.c b/board.c index fd16771..6855d95 100644 --- a/board.c +++ b/board.c @@ -610,15 +610,38 @@ void BOARD_EEPROM_load(void) g_eeprom.voice_prompt = (Data[0] < 3) ? Data[0] : VOICE_PROMPT_ENGLISH; #endif - // 0EA8..0EAF - EEPROM_ReadBuffer(0x0EA8, Data, 8); - #ifdef ENABLE_ALARM - g_eeprom.alarm_mode = (Data[0] < 2) ? Data[0] : true; - #endif - g_eeprom.roger_mode = (Data[1] < 3) ? Data[1] : ROGER_MODE_OFF; - g_eeprom.repeater_tail_tone_elimination = (Data[2] < 11) ? Data[2] : 0; - g_eeprom.tx_vfo = (Data[3] < 2) ? Data[3] : 0; + { // 0EA8..0EAF + struct { + uint8_t alarm_mode; + uint8_t roger_mode; + uint8_t repeater_tail_tone_elimination; + uint8_t tx_vfo; + uint32_t air_copy_freq; + } __attribute__((packed)) array; + EEPROM_ReadBuffer(0x0EA8, &array, sizeof(array)); + + #ifdef ENABLE_ALARM + g_eeprom.alarm_mode = (array.alarm_mode < 2) ? array.alarm_mode : true; + #endif + g_eeprom.roger_mode = (array.roger_mode < 3) ? array.roger_mode : ROGER_MODE_OFF; + g_eeprom.repeater_tail_tone_elimination = (array.repeater_tail_tone_elimination < 11) ? array.repeater_tail_tone_elimination : 0; + g_eeprom.tx_vfo = (array.tx_vfo < 2) ? array.tx_vfo : 0; + #ifdef ENABLE_AIRCOPY_FREQ + { + unsigned int i; + for (i = 0; i < ARRAY_SIZE(FREQ_BAND_TABLE); i++) + { + if (array.air_copy_freq >= FREQ_BAND_TABLE[i].lower && array.air_copy_freq < FREQ_BAND_TABLE[i].upper) + { + g_air_copy_freq = array.air_copy_freq; + break; + } + } + } + #endif + } + // 0ED0..0ED7 EEPROM_ReadBuffer(0x0ED0, Data, 8); g_eeprom.dtmf_side_tone = (Data[0] < 2) ? Data[0] : true; @@ -727,6 +750,8 @@ void BOARD_EEPROM_load(void) // 0D60..0E27 EEPROM_ReadBuffer(0x0D60, g_user_channel_attributes, sizeof(g_user_channel_attributes)); + // ***************************** + // 0F30..0F3F .. AES key EEPROM_ReadBuffer(0x0F30, g_custom_aes_key, sizeof(g_custom_aes_key)); g_has_custom_aes_key = false; @@ -740,6 +765,7 @@ void BOARD_EEPROM_load(void) } #if ENABLE_RESET_AES_KEY + // a fix to wipe the darned AES key if (g_has_custom_aes_key) { // ugh :( .. wipe it uint8_t *p_aes = (uint8_t*)&g_custom_aes_key; diff --git a/firmware.bin b/firmware.bin index d9a9560..fb33086 100644 Binary files a/firmware.bin and b/firmware.bin differ diff --git a/firmware.packed.bin b/firmware.packed.bin index ef36ba1..3d1e3bd 100644 Binary files a/firmware.packed.bin and b/firmware.packed.bin differ diff --git a/frequencies.c b/frequencies.c index ffc9a63..da523f5 100644 --- a/frequencies.c +++ b/frequencies.c @@ -19,7 +19,7 @@ #include "settings.h" // the initial AIRCOPY frequency to use -const uint32_t g_air_copy_freq = 41002500; +uint32_t g_air_copy_freq = 41002500; // the BK4819 has 2 bands it covers, 18MHz ~ 630MHz and 760MHz ~ 1300MHz const freq_band_table_t BX4819_band1 = { 1800000, 63000000}; diff --git a/frequencies.h b/frequencies.h index d2fbecf..abb8b2e 100644 --- a/frequencies.h +++ b/frequencies.h @@ -26,7 +26,7 @@ typedef struct { const uint32_t upper; } freq_band_table_t; -extern const uint32_t g_air_copy_freq; +extern uint32_t g_air_copy_freq; extern const freq_band_table_t BX4819_band1; extern const freq_band_table_t BX4819_band2; diff --git a/settings.c b/settings.c index 0ba3c5e..f33c8cc 100644 --- a/settings.c +++ b/settings.c @@ -73,7 +73,10 @@ void SETTINGS_SaveVfoIndices(void) EEPROM_WriteBuffer(0x0E80, State); } +// ************************************************* + #if 0 + const uint8_t calib1[] = { // my first radios calibration data 0x0A, 0x4B, 0x53, 0x56, 0x59, 0x5C, 0x5F, 0x62, 0x64, 0x66, 0xFF, 0xFF, @@ -180,8 +183,11 @@ void SETTINGS_restore_calibration(void) index += 8; } } + #endif +// ************************************************* + void SETTINGS_SaveSettings(void) { uint8_t State[8]; @@ -236,25 +242,44 @@ void SETTINGS_SaveSettings(void) #ifdef ENABLE_PWRON_PASSWORD array.password = g_eeprom.power_on_password; #endif - + EEPROM_WriteBuffer(0x0E98, &array); } - + #ifdef ENABLE_VOICE memset(State, 0xFF, sizeof(State)); State[0] = g_eeprom.voice_prompt; EEPROM_WriteBuffer(0x0EA0, State); #endif - #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) - State[0] = g_eeprom.alarm_mode; - #else - State[0] = false; - #endif - State[1] = g_eeprom.roger_mode; - State[2] = g_eeprom.repeater_tail_tone_elimination; - State[3] = g_eeprom.tx_vfo; - EEPROM_WriteBuffer(0x0EA8, State); + // ***************************** + + { + struct { + uint8_t alarm_mode; + uint8_t roger_mode; + uint8_t repeater_tail_tone_elimination; + uint8_t tx_vfo; + uint32_t air_copy_freq; + } __attribute__((packed)) array; + + memset(&array, 0xff, sizeof(array)); + + #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) + array.alarm_mode = g_eeprom.alarm_mode; + #else + array.alarm_mode = false; + #endif + array.roger_mode = g_eeprom.roger_mode; + array.repeater_tail_tone_elimination = g_eeprom.repeater_tail_tone_elimination; + array.tx_vfo = g_eeprom.tx_vfo; + #ifdef ENABLE_AIRCOPY_FREQ + // remember the AIRCOPY frequency + array.air_copy_freq = g_air_copy_freq; + #endif + + EEPROM_WriteBuffer(0x0EA8, &array); + } State[0] = g_eeprom.dtmf_side_tone; State[1] = g_eeprom.dtmf_separate_code; @@ -300,7 +325,7 @@ void SETTINGS_SaveSettings(void) if (!g_setting_am_fix) State[7] &= ~(1u << 5); #endif State[7] = (State[7] & ~(3u << 6)) | ((g_setting_backlight_on_tx_rx & 3u) << 6); - + EEPROM_WriteBuffer(0x0F40, State); } @@ -320,7 +345,7 @@ void SETTINGS_SaveChannel(uint8_t Channel, uint8_t VFO, const vfo_info_t *pVFO, OffsetVFO = (VFO == 0) ? 0x0C80 : 0x0C90; OffsetVFO += (Channel - FREQ_CHANNEL_FIRST) * 32; } - + if (Mode < 2 && Channel <= USER_CHANNEL_LAST) return; @@ -350,7 +375,7 @@ void SETTINGS_SaveChannel(uint8_t Channel, uint8_t VFO, const vfo_info_t *pVFO, if (Channel > USER_CHANNEL_LAST) return; // it's not a user channel - + #ifndef ENABLE_KEEP_MEM_NAME // clear/reset the channel name memset(&State, 0x00, sizeof(State)); @@ -378,28 +403,28 @@ void SETTINGS_UpdateChannel(uint8_t Channel, const vfo_info_t *pVFO, bool keep) if (IS_NOAA_CHANNEL(Channel)) return; #endif - + Attributes &= (uint8_t)(~USER_CH_COMPAND); // default to '0' = compander disabled - + EEPROM_ReadBuffer(Offset, State, sizeof(State)); - + if (keep) { Attributes = (pVFO->scanlist_1_participation << 7) | (pVFO->scanlist_2_participation << 6) | (pVFO->compander << 4) | (pVFO->band << 0); if (State[Channel & 7u] == Attributes) return; // no change in the attributes } - + State[Channel & 7u] = Attributes; - + EEPROM_WriteBuffer(Offset, State); - + g_user_channel_attributes[Channel] = Attributes; - + // #ifndef ENABLE_KEEP_MEM_NAME if (Channel <= USER_CHANNEL_LAST) { // it's a memory channel - + const uint16_t OffsetMR = Channel * 16; if (!keep) { // clear/reset the channel name diff --git a/ui/aircopy.c b/ui/aircopy.c index 33d5e7a..39f0986 100644 --- a/ui/aircopy.c +++ b/ui/aircopy.c @@ -31,13 +31,15 @@ void UI_DisplayAircopy(void) memset(g_frame_buffer, 0, sizeof(g_frame_buffer)); - if (g_aircopy_state == AIRCOPY_READY) - strcpy(String, "AIR COPY (RDY)"); - else - if (g_aircopy_state == AIRCOPY_TRANSFER) - strcpy(String, "AIR COPY"); - else - strcpy(String, "AIR COPY (CMP)"); + strcpy(String, "AIR COPY"); + switch (g_aircopy_state) + { + case AIRCOPY_READY: strcat(String, " READY"); break; + case AIRCOPY_RX: strcat(String, " RX"); break; + case AIRCOPY_TX: strcat(String, " TX"); break; + case AIRCOPY_COMPLETE: strcat(String, " DONE"); break; + default: strcat(String, " ???"); break; + } UI_PrintString(String, 2, 127, 0, 8); if (g_input_box_index == 0) @@ -50,14 +52,22 @@ void UI_DisplayAircopy(void) UI_DisplayFrequency(g_input_box, 16, 2, 1, 0); memset(String, 0, sizeof(String)); - if (g_air_copy_is_send_mode == 0) - sprintf(String, "RCV %u E %u", g_air_copy_block_number, g_errors_during_air_copyy); + if (g_aircopy_state == AIRCOPY_RX) + sprintf(String, "RCV %u E %u", g_air_copy_block_number, g_errors_during_air_copy); else - if (g_air_copy_is_send_mode == 1) + if (g_aircopy_state == AIRCOPY_TX) sprintf(String, "SND %u", g_air_copy_block_number); UI_PrintString(String, 2, 127, 4, 8); - UI_PrintStringSmall("EXIT rx M tx", 0, 127, 6); + switch (g_aircopy_state) + { + case AIRCOPY_READY: strcpy(String, "EXIT rx M tx"); break; + case AIRCOPY_RX: strcpy(String, "receive mode"); break; + case AIRCOPY_TX: strcpy(String, "transmit mode"); break; + case AIRCOPY_COMPLETE: strcpy(String, "finished"); break; + default: strcpy(String, "???"); break; + } + UI_PrintStringSmall(String, 0, 127, 6); ST7565_BlitFullScreen(); }