From 3d739c642eb58905ccd9ec3a77dd50893eb18bcb Mon Sep 17 00:00:00 2001 From: Armel FAUVEAU Date: Tue, 31 Mar 2026 18:13:17 +0200 Subject: [PATCH] Add Rx audio profiles for AM --- App/app/action.c | 8 ++- App/app/menu.c | 22 ++++++-- App/misc.c | 3 +- App/misc.h | 3 +- App/radio.c | 139 +++++++++++++++++++++++++++++++++++------------ App/settings.c | 5 +- App/ui/main.c | 16 ++++-- App/ui/menu.c | 28 ++++++++-- App/ui/menu.h | 3 +- 9 files changed, 173 insertions(+), 54 deletions(-) diff --git a/App/app/action.c b/App/app/action.c index 54d185e6..b621cf6f 100644 --- a/App/app/action.c +++ b/App/app/action.c @@ -572,7 +572,11 @@ void ACTION_MainOnly(void) #ifdef ENABLE_FEAT_F4HWN_AUDIO void ACTION_RxA(void) { - gSetting_set_audio = (gSetting_set_audio + 1) % 5; + if(gRxVfo->Modulation == MODULATION_AM) + gSetting_set_audio_am = (gSetting_set_audio_am + 1) % 3; + else if (gRxVfo->Modulation == MODULATION_FM) + gSetting_set_audio_fm = (gSetting_set_audio_fm + 1) % 5; + RADIO_SetModulation(gRxVfo->Modulation); } #endif @@ -678,4 +682,4 @@ void ACTION_Remove_Offset(void) gVfoConfigureMode = VFO_CONFIGURE_RELOAD; } #endif -#endif \ No newline at end of file +#endif diff --git a/App/app/menu.c b/App/app/menu.c index 2c8eae87..7542ab70 100644 --- a/App/app/menu.c +++ b/App/app/menu.c @@ -429,7 +429,12 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax) #ifdef ENABLE_FEAT_F4HWN_AUDIO case MENU_SET_AUD: //*pMin = 0; - *pMax = ARRAY_SIZE(gSubMenu_SET_AUD) - 1; + if(gTxVfo->Modulation == MODULATION_AM) + *pMax = ARRAY_SIZE(gSubMenu_SET_AUD_AM) - 1; + else if (gTxVfo->Modulation == MODULATION_USB) + *pMax = 0; + else + *pMax = ARRAY_SIZE(gSubMenu_SET_AUD_FM) - 1; break; #endif #ifdef ENABLE_FEAT_F4HWN_NARROWER @@ -964,8 +969,12 @@ void MENU_AcceptSetting(void) break; #ifdef ENABLE_FEAT_F4HWN_AUDIO case MENU_SET_AUD: - gSetting_set_audio = gSubMenuSelection; - RADIO_SetModulation(gRxVfo->Modulation); + if(gTxVfo->Modulation == MODULATION_AM) + gSetting_set_audio_am = gSubMenuSelection; + else if (gTxVfo->Modulation == MODULATION_FM) + gSetting_set_audio_fm = gSubMenuSelection; + + RADIO_SetModulation(gTxVfo->Modulation); break; #endif #ifdef ENABLE_FEAT_F4HWN_NARROWER @@ -1419,7 +1428,12 @@ void MENU_ShowCurrentSetting(void) break; #ifdef ENABLE_FEAT_F4HWN_AUDIO case MENU_SET_AUD: - gSubMenuSelection = gSetting_set_audio; + if(gTxVfo->Modulation == MODULATION_AM) + gSubMenuSelection = gSetting_set_audio_am; + else if (gTxVfo->Modulation == MODULATION_USB) + gSubMenuSelection = 0; + else + gSubMenuSelection = gSetting_set_audio_fm; break; #endif #ifdef ENABLE_FEAT_F4HWN_NARROWER diff --git a/App/misc.c b/App/misc.c index 82414c1d..ee830a6a 100644 --- a/App/misc.c +++ b/App/misc.c @@ -127,7 +127,8 @@ enum BacklightOnRxTx_t gSetting_backlight_on_tx_rx; bool gSetting_set_met = 0; bool gSetting_set_gui = 0; #ifdef ENABLE_FEAT_F4HWN_AUDIO - uint8_t gSetting_set_audio = 0; + uint8_t gSetting_set_audio_fm = 0; + uint8_t gSetting_set_audio_am = 0; #endif #ifdef ENABLE_FEAT_F4HWN_NARROWER bool gSetting_set_nfm = 0; diff --git a/App/misc.h b/App/misc.h index 4aebbce3..c0932404 100644 --- a/App/misc.h +++ b/App/misc.h @@ -189,7 +189,8 @@ extern enum BacklightOnRxTx_t gSetting_backlight_on_tx_rx; extern bool gSetting_set_met; extern bool gSetting_set_gui; #ifdef ENABLE_FEAT_F4HWN_AUDIO - extern uint8_t gSetting_set_audio; + extern uint8_t gSetting_set_audio_fm; + extern uint8_t gSetting_set_audio_am; #endif #ifdef ENABLE_FEAT_F4HWN_NARROWER extern bool gSetting_set_nfm; diff --git a/App/radio.c b/App/radio.c index e728f69e..9a25df13 100644 --- a/App/radio.c +++ b/App/radio.c @@ -54,7 +54,22 @@ const char gModulationStr[MODULATION_UKNOWN][4] = { }; #ifdef ENABLE_FEAT_F4HWN_AUDIO - static void AUDIO_ApplyProfile(uint8_t profile) + + // About BK4819_WriteRegister(0x2b, val) experimentation... + // + // 0x000: 300 Hz high-pass filter enabled, 3 kHz low-pass filter enabled, de-emphasis enabled. + // Audio impression: the most "classic radio" tuning, more filtered and smoother. + // + // 0x300: 300 Hz high-pass filter enabled, 3 kHz low-pass filter disabled, de-emphasis disabled. + // Audio impression: clearer, brighter, and more open, while still cutting low frequencies. + // + // 0x400: 300 Hz high-pass filter disabled, 3 kHz low-pass filter enabled, de-emphasis enabled. + // Audio impression: fuller low end, but still softened by de-emphasis and upper-frequency limiting. + // + // 0x500: 300 Hz high-pass filter disabled, 3 kHz low-pass filter enabled, de-emphasis disabled. + // Audio impression: fuller bass, more direct sound, while still keeping the 3 kHz top-end limit. + + static void AUDIO_ApplyFMProfile(uint8_t profile) { switch (profile) { @@ -85,6 +100,41 @@ const char gModulationStr[MODULATION_UKNOWN][4] = { break; } } + + static void AUDIO_ApplyAMProfile(uint8_t profile) + { + switch (profile) + { + default: + case 0: // SHARP (ALPHA test profile) - Narrow IF filter (REG54 bits[14:8]=0, bits[7:0]=9), low IF gain (REG55 bits[11:8]=1, ref=169) + // Selective and crisp, best adjacent channel rejection, may sound harsh on strong signals + BK4819_WriteRegister(0x2b, 0x0300); + BK4819_WriteRegister(0x2f, 0x9990); + BK4819_WriteRegister(0x54, 0x9009); + BK4819_WriteRegister(0x55, 0x31A9); + break; + case 1: // STOCK - Narrow IF filter (REG54 bits[14:8]=0, bits[7:0]=9), moderate IF gain (REG55 bits[11:8]=4, ref=180) + // Selective filter with balanced gain, punchy and detailed, good compromise between rejection and sensitivity + BK4819_WriteRegister(0x2b, 0x0500); + BK4819_WriteRegister(0x2f, 0x9990); + BK4819_WriteRegister(0x54, 0x9009); + BK4819_WriteRegister(0x55, 0x31A9); + break; + case 2: // OPEN (BRAVO test profile) - Medium-wide IF filter (REG54 bits[14:8]=8, bits[7:0]=70), high IF gain (REG55 bits[11:8]=8, ref=192) + // Wide and pleasant, better sensitivity on weak signals, may struggle with adjacent channel interference + BK4819_WriteRegister(0x2b, 0x0300); + BK4819_WriteRegister(0x2f, 0x9990); + BK4819_WriteRegister(0x54, 0x8846); + BK4819_WriteRegister(0x55, 0x38C0); + break; + } + } + + static void AUDIO_ApplyUSBProfile(void) + { + BK4819_WriteRegister(0x54, 0x9009); + BK4819_WriteRegister(0x55, 0x31A9); + } #endif bool RADIO_CheckValidList(uint8_t scanList) @@ -1098,48 +1148,70 @@ void RADIO_SetModulation(ModulationMode_t modulation) BK4819_SetAF(mod); - // HACK, FIXME: + // // What follows is a direct copy of the AM enable/disable code from // the original UV-K1 firmware. It is not clear why these specific register // values are used for AM all of a sudden instead of the AF setting like on // the BK4819, nor what exactly they do. // So for now we just keep it as is to maintain compatibility. // - if (modulation != MODULATION_AM) + + switch (modulation) { - uint16_t uVar1 = BK4819_ReadRegister(0x31); - BK4819_WriteRegister(0x31,uVar1 & 0xfffffffe); - BK4819_WriteRegister(0x42,0x6b5a); - BK4819_WriteRegister(0x2a,0x7400); - BK4819_WriteRegister(0x2b,0); - BK4819_WriteRegister(0x2f,0x9890); - //BK4819_WriteRegister(0x54, 0x9009); - //BK4819_WriteRegister(0x55, 0x31a9); - #ifdef ENABLE_FEAT_F4HWN_AUDIO - AUDIO_ApplyProfile(gSetting_set_audio); - #else - BK4819_WriteRegister(0x54, 0x9009); - BK4819_WriteRegister(0x55, 0x31a9); - #endif - } - else - { - uint16_t uVar1 = BK4819_ReadRegister(0x31); - BK4819_WriteRegister(0x31,uVar1 | 1); - BK4819_WriteRegister(0x42,0x6f5c); - BK4819_WriteRegister(0x2a,0x7434); - BK4819_WriteRegister(0x2b,0x400); - BK4819_WriteRegister(0x2f,0x9990); - //BK4819_WriteRegister(0x54, 0x9775); - //BK4819_WriteRegister(0x55, 0x32c6); + case MODULATION_AM: + { + uint16_t uVar1 = BK4819_ReadRegister(0x31); + BK4819_WriteRegister(0x31, uVar1 | 1); // AM Demodulation Enable + BK4819_WriteRegister(0x42, 0x6f5c); + BK4819_WriteRegister(0x2a, 0x7434); - //BK4819_WriteRegister(0x54, 0x8846); - //BK4819_WriteRegister(0x55, 0x38C0); + #ifdef ENABLE_FEAT_F4HWN_AUDIO + AUDIO_ApplyAMProfile(gSetting_set_audio_am); + #else + BK4819_WriteRegister(0x54, 0x9009); + BK4819_WriteRegister(0x55, 0x31a9); + #endif - BK4819_WriteRegister(0x54, 0x9009); - BK4819_WriteRegister(0x55, 0x31a9); + BK4819_SetFilterBandwidth(BK4819_FILTER_BW_AM, true); + break; + } - BK4819_SetFilterBandwidth(BK4819_FILTER_BW_AM, true); + case MODULATION_USB: + { + uint16_t uVar1 = BK4819_ReadRegister(0x31); + BK4819_WriteRegister(0x31, uVar1 & 0xfffe); // AM Demodulation Disable + BK4819_WriteRegister(0x42, 0x6b5a); + BK4819_WriteRegister(0x2a, 0x7400); + BK4819_WriteRegister(0x2b, 0x0000); + BK4819_WriteRegister(0x2f, 0x9890); + + #ifdef ENABLE_FEAT_F4HWN_AUDIO + AUDIO_ApplyUSBProfile(); + #else + BK4819_WriteRegister(0x54, 0x9009); + BK4819_WriteRegister(0x55, 0x31a9); + #endif + break; + } + + case MODULATION_FM: + default: + { + uint16_t uVar1 = BK4819_ReadRegister(0x31); + BK4819_WriteRegister(0x31, uVar1 & 0xfffe); // AM Demodulation Disable + BK4819_WriteRegister(0x42, 0x6b5a); + BK4819_WriteRegister(0x2a, 0x7400); + BK4819_WriteRegister(0x2b, 0x0000); + BK4819_WriteRegister(0x2f, 0x9890); + + #ifdef ENABLE_FEAT_F4HWN_AUDIO + AUDIO_ApplyFMProfile(gSetting_set_audio_fm); + #else + BK4819_WriteRegister(0x54, 0x9009); + BK4819_WriteRegister(0x55, 0x31a9); + #endif + break; + } } BK4819_SetRegValue(afDacGainRegSpec, 0xF); @@ -1147,7 +1219,6 @@ void RADIO_SetModulation(ModulationMode_t modulation) BK4819_SetRegValue(afcDisableRegSpec, modulation != MODULATION_FM); RADIO_SetupAGC(modulation == MODULATION_AM, false); - //RADIO_SetupAGC(false, false); } void RADIO_SetupAGC(bool listeningAM, bool disable) diff --git a/App/settings.c b/App/settings.c index a0bf2c6a..cd2bec22 100644 --- a/App/settings.c +++ b/App/settings.c @@ -121,7 +121,8 @@ void SETTINGS_InitEEPROM(void) // 0E70..0E77 PY25Q16_ReadBuffer(0x00A000, Data, 8); #ifdef ENABLE_FEAT_F4HWN_AUDIO - gSetting_set_audio = (Data[0] < 5) ? Data[0] : 0; + gSetting_set_audio_fm = ((Data[0] & 0x0F) < 5) ? (Data[0] & 0x0F) : 0; + gSetting_set_audio_am = (((Data[0] >> 4) & 0x0F) < 3) ? ((Data[0] >> 4) & 0x0F) : 0; #endif gEeprom.SQUELCH_LEVEL = (Data[1] < 10) ? Data[1] : 1; gEeprom.TX_TIMEOUT_TIMER = (Data[2] > 4 && Data[2] < 180) ? Data[2] : 11; @@ -764,7 +765,7 @@ void SETTINGS_SaveSettings(void) // 0x0E70 State = SecBuf; #ifdef ENABLE_FEAT_F4HWN_AUDIO - State[0] = gSetting_set_audio; + State[0] = (gSetting_set_audio_fm & 0x0F) | ((gSetting_set_audio_am & 0x0F) << 4); #endif #ifdef ENABLE_FEAT_F4HWN if (gSquelchLevelOriginal < 10) diff --git a/App/ui/main.c b/App/ui/main.c index f30dbf62..ca00d40d 100644 --- a/App/ui/main.c +++ b/App/ui/main.c @@ -897,17 +897,25 @@ void UI_DisplayMain(void) // } // if (RxBlink == 0 || RxBlink == 1) { - if(gRxVfo->Modulation == MODULATION_AM) - GUI_DisplaySmallest("AIR", 10, RxLine == 0 ? 1 : 33, false, true); + if(gRxVfo->Modulation == MODULATION_AM) { + #ifdef ENABLE_FEAT_F4HWN_AUDIO + strcpy(String, gSubMenu_SET_AUD_AM[gSetting_set_audio_am]); + #else + strcpy(String, "AIR"); + #endif + } + else if (gRxVfo->Modulation == MODULATION_USB) { + strcpy(String, "USB"); + } else { #ifdef ENABLE_FEAT_F4HWN_AUDIO - strcpy(String, gSubMenu_SET_AUD[gSetting_set_audio]); + strcpy(String, gSubMenu_SET_AUD_FM[gSetting_set_audio_fm]); #else strcpy(String, "RX"); #endif - GUI_DisplaySmallest(String, 10, RxLine == 0 ? 1 : 33, false, true); } + GUI_DisplaySmallest(String, 10, RxLine == 0 ? 1 : 33, false, true); //UI_PrintStringSmallBold("RX", 8, 0, RxLine); // } #else diff --git a/App/ui/menu.c b/App/ui/menu.c index a9b486ed..d7a80b2e 100644 --- a/App/ui/menu.c +++ b/App/ui/menu.c @@ -413,7 +413,7 @@ const char gSubMenu_SCRAMBLER[][7] = }; #ifdef ENABLE_FEAT_F4HWN_AUDIO - const char gSubMenu_SET_AUD[][6] = + const char gSubMenu_SET_AUD_FM[][6] = { "FLAT", "CLEAN", @@ -421,6 +421,13 @@ const char gSubMenu_SCRAMBLER[][7] = "BOOST", "MAX" }; + + const char gSubMenu_SET_AUD_AM[][6] = + { + "SHARP", + "STOCK", + "OPEN" + }; #endif #ifdef ENABLE_FEAT_F4HWN_NARROWER @@ -1194,7 +1201,18 @@ void UI_DisplayMenu(void) #ifdef ENABLE_FEAT_F4HWN_AUDIO case MENU_SET_AUD: - strcpy(String, gSubMenu_SET_AUD[gSubMenuSelection]); + if(gTxVfo->Modulation == MODULATION_AM) { + strcpy(String, gSubMenu_SET_AUD_AM[gSubMenuSelection]); + UI_PrintStringSmallNormal("AM", 114, 0, 0); + } + else if (gTxVfo->Modulation == MODULATION_USB) { + strcpy(String, "USB"); + UI_PrintStringSmallNormal("USB", 108, 0, 0); + } + else { + strcpy(String, gSubMenu_SET_AUD_FM[gSubMenuSelection]); + UI_PrintStringSmallNormal("FM", 114, 0, 0); + } break; #endif @@ -1345,8 +1363,8 @@ void UI_DisplayMenu(void) || UI_MENU_GetCurrentMenuId() == MENU_D_LIST #endif ) { - sprintf(String, "%2d", gSubMenuSelection); - UI_PrintStringSmallNormal(String, 105, 0, 0); + sprintf(String, "%03d", gSubMenuSelection); + UI_PrintStringSmallNormal(String, 107, 0, 0); } if ((UI_MENU_GetCurrentMenuId() == MENU_RESET || @@ -1359,4 +1377,4 @@ void UI_DisplayMenu(void) } ST7565_BlitFullScreen(); -} \ No newline at end of file +} diff --git a/App/ui/menu.h b/App/ui/menu.h index 70ee5f12..8c06136d 100644 --- a/App/ui/menu.h +++ b/App/ui/menu.h @@ -198,7 +198,8 @@ extern const char gSubMenu_D_RSP[4][11]; extern const char gSubMenu_SET_KEY[][9]; #endif #ifdef ENABLE_FEAT_F4HWN_AUDIO - extern const char gSubMenu_SET_AUD[5][6]; + extern const char gSubMenu_SET_AUD_FM[5][6]; + extern const char gSubMenu_SET_AUD_AM[3][6]; #endif #endif