From b6d6d2899369290e4ed73cfbd97c0115f36036f2 Mon Sep 17 00:00:00 2001 From: Nunu Date: Sun, 7 Jan 2024 11:50:56 +0100 Subject: [PATCH 1/7] Removed SList, SList1, SList2 MENU items. --- app/menu.c | 33 ----------------------------- ui/menu.c | 61 ------------------------------------------------------ ui/menu.h | 3 --- 3 files changed, 97 deletions(-) diff --git a/app/menu.c b/app/menu.c index 8f2465b8..a1bbc67f 100644 --- a/app/menu.c +++ b/app/menu.c @@ -285,12 +285,6 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax) *pMax = MR_CHANNEL_LAST; break; - case MENU_SLIST1: - case MENU_SLIST2: - *pMin = -1; - *pMax = MR_CHANNEL_LAST; - break; - case MENU_SAVE: *pMin = 0; *pMax = ARRAY_SIZE(gSubMenu_SAVE) - 1; @@ -301,10 +295,6 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax) *pMax = 4; break; - case MENU_S_LIST: - *pMin = 0; - *pMax = 2; - break; #ifdef ENABLE_DTMF_CALLING case MENU_D_RSP: @@ -655,10 +645,6 @@ void MENU_AcceptSetting(void) gEeprom.CHAN_1_CALL = gSubMenuSelection; break; - case MENU_S_LIST: - gEeprom.SCAN_LIST_DEFAULT = gSubMenuSelection; - break; - #ifdef ENABLE_ALARM case MENU_AL_MOD: gEeprom.ALARM_MODE = gSubMenuSelection; @@ -1053,18 +1039,6 @@ void MENU_ShowCurrentSetting(void) gSubMenuSelection = gEeprom.CHAN_1_CALL; break; - case MENU_S_LIST: - gSubMenuSelection = gEeprom.SCAN_LIST_DEFAULT; - break; - - case MENU_SLIST1: - gSubMenuSelection = RADIO_FindNextChannel(0, 1, true, 0); - break; - - case MENU_SLIST2: - gSubMenuSelection = RADIO_FindNextChannel(0, 1, true, 1); - break; - #ifdef ENABLE_ALARM case MENU_AL_MOD: gSubMenuSelection = gEeprom.ALARM_MODE; @@ -1717,13 +1691,6 @@ static void MENU_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction) bCheckScanList = false; break; - case MENU_SLIST2: - VFO = 1; - [[fallthrough]]; - case MENU_SLIST1: - bCheckScanList = true; - break; - default: MENU_ClampSelection(Direction); gRequestDisplayScreen = DISPLAY_MENU; diff --git a/ui/menu.c b/ui/menu.c index 582c6d82..72062e58 100644 --- a/ui/menu.c +++ b/ui/menu.c @@ -58,21 +58,15 @@ const t_menu_item MenuList[] = {"ChSave", VOICE_ID_MEMORY_CHANNEL, MENU_MEM_CH }, // was "MEM-CH" {"ChDele", VOICE_ID_DELETE_CHANNEL, MENU_DEL_CH }, // was "DEL-CH" {"ChName", VOICE_ID_INVALID, MENU_MEM_NAME }, - - {"SList", VOICE_ID_INVALID, MENU_S_LIST }, - {"SList1", VOICE_ID_INVALID, MENU_SLIST1 }, - {"SList2", VOICE_ID_INVALID, MENU_SLIST2 }, {"ScnRev", VOICE_ID_INVALID, MENU_SC_REV }, #ifdef ENABLE_NOAA {"NOAA-S", VOICE_ID_INVALID, MENU_NOAA_S }, #endif - {"F1Shrt", VOICE_ID_INVALID, MENU_F1SHRT }, {"F1Long", VOICE_ID_INVALID, MENU_F1LONG }, {"F2Shrt", VOICE_ID_INVALID, MENU_F2SHRT }, {"F2Long", VOICE_ID_INVALID, MENU_F2LONG }, {"M Long", VOICE_ID_INVALID, MENU_MLONG }, - {"KeyLck", VOICE_ID_INVALID, MENU_AUTOLK }, // was "AUTOLk" {"TxTOut", VOICE_ID_TRANSMIT_OVER_TIME, MENU_TOT }, // was "TOT" {"BatSav", VOICE_ID_SAVE_MODE, MENU_SAVE }, // was "SAVE" @@ -121,7 +115,6 @@ const t_menu_item MenuList[] = {"BatVol", VOICE_ID_INVALID, MENU_VOL }, // was "VOL" {"RxMode", VOICE_ID_DUAL_STANDBY, MENU_TDR }, {"Sql", VOICE_ID_SQUELCH, MENU_SQL }, - // hidden menu items from here on // enabled if pressing both the PTT and upper side button at power-on {"F Lock", VOICE_ID_INVALID, MENU_F_LOCK }, @@ -740,13 +733,6 @@ void UI_DisplayMenu(void) sprintf(String, "%d*100ms", gSubMenuSelection); break; - case MENU_S_LIST: - if (gSubMenuSelection < 2) - sprintf(String, "LIST%u", 1 + gSubMenuSelection); - else - strcpy(String, "ALL"); - break; - #ifdef ENABLE_ALARM case MENU_AL_MOD: sprintf(String, gSubMenu_AL_MOD[gSubMenuSelection]); @@ -913,53 +899,6 @@ void UI_DisplayMenu(void) } } - if (UI_MENU_GetCurrentMenuId() == MENU_SLIST1 || UI_MENU_GetCurrentMenuId() == MENU_SLIST2) - { - i = (UI_MENU_GetCurrentMenuId() == MENU_SLIST1) ? 0 : 1; - -// if (gSubMenuSelection == 0xFF) - if (gSubMenuSelection < 0) - strcpy(String, "NULL"); - else - UI_GenerateChannelStringEx(String, true, gSubMenuSelection); - -// if (gSubMenuSelection == 0xFF || !gEeprom.SCAN_LIST_ENABLED[i]) - if (gSubMenuSelection < 0 || !gEeprom.SCAN_LIST_ENABLED[i]) - { - // channel number - UI_PrintString(String, menu_item_x1, menu_item_x2, 0, 8); - - // channel name - SETTINGS_FetchChannelName(String, gSubMenuSelection); - if (String[0] == 0) - strcpy(String, "--"); - UI_PrintString(String, menu_item_x1, menu_item_x2, 2, 8); - } - else - { - // channel number - UI_PrintString(String, menu_item_x1, menu_item_x2, 0, 8); - - // channel name - SETTINGS_FetchChannelName(String, gSubMenuSelection); - if (String[0] == 0) - strcpy(String, "--"); - UI_PrintStringSmall(String, menu_item_x1, menu_item_x2, 2); - - if (IS_MR_CHANNEL(gEeprom.SCANLIST_PRIORITY_CH1[i])) - { - sprintf(String, "PRI1:%u", gEeprom.SCANLIST_PRIORITY_CH1[i] + 1); - UI_PrintString(String, menu_item_x1, menu_item_x2, 3, 8); - } - - if (IS_MR_CHANNEL(gEeprom.SCANLIST_PRIORITY_CH2[i])) - { - sprintf(String, "PRI2:%u", gEeprom.SCANLIST_PRIORITY_CH2[i] + 1); - UI_PrintString(String, menu_item_x1, menu_item_x2, 5, 8); - } - } - } - if ((UI_MENU_GetCurrentMenuId() == MENU_R_CTCS || UI_MENU_GetCurrentMenuId() == MENU_R_DCS) && gCssBackgroundScan) UI_PrintString("SCAN", menu_item_x1, menu_item_x2, 4, 8); diff --git a/ui/menu.h b/ui/menu.h index be3dccd7..531e44ed 100644 --- a/ui/menu.h +++ b/ui/menu.h @@ -75,9 +75,6 @@ enum #endif MENU_COMPAND, MENU_1_CALL, - MENU_S_LIST, - MENU_SLIST1, - MENU_SLIST2, #ifdef ENABLE_ALARM MENU_AL_MOD, #endif From 7dd616d876085a9b60f2742cab916f78ff6e480d Mon Sep 17 00:00:00 2001 From: Nunu Date: Sun, 7 Jan 2024 12:07:01 +0100 Subject: [PATCH 2/7] MicBar MENU item removed, its on by default. --- app/app.c | 2 +- app/menu.c | 15 --------------- board.c | 3 --- misc.c | 3 --- misc.h | 3 --- settings.c | 3 --- ui/main.c | 56 ++++++++++++++++++++++++++---------------------------- ui/menu.c | 11 +---------- ui/menu.h | 3 --- 9 files changed, 29 insertions(+), 70 deletions(-) diff --git a/app/app.c b/app/app.c index a3465c91..991d1ed2 100644 --- a/app/app.c +++ b/app/app.c @@ -1205,7 +1205,7 @@ void APP_TimeSlice10ms(void) if (gCurrentFunction == FUNCTION_TRANSMIT) { // transmitting #ifdef ENABLE_AUDIO_BAR - if (gSetting_mic_bar && (gFlashLightBlinkCounter % (150 / 10)) == 0) // once every 150ms + if ((gFlashLightBlinkCounter % (150 / 10)) == 0) // once every 150ms UI_DisplayAudioBar(); #endif } diff --git a/app/menu.c b/app/menu.c index a1bbc67f..1bb53eb8 100644 --- a/app/menu.c +++ b/app/menu.c @@ -227,9 +227,6 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax) #ifdef ENABLE_AM_FIX case MENU_AM_FIX: #endif - #ifdef ENABLE_AUDIO_BAR - case MENU_MIC_BAR: - #endif case MENU_BCL: case MENU_BEEP: case MENU_AUTOLK: @@ -627,12 +624,6 @@ void MENU_AcceptSetting(void) gFlagReconfigureVfos = true; break; - #ifdef ENABLE_AUDIO_BAR - case MENU_MIC_BAR: - gSetting_mic_bar = gSubMenuSelection; - break; - #endif - case MENU_COMPAND: gTxVfo->Compander = gSubMenuSelection; SETTINGS_UpdateChannel(gTxVfo->CHANNEL_SAVE, gTxVfo, true); @@ -1025,12 +1016,6 @@ void MENU_ShowCurrentSetting(void) gSubMenuSelection = gEeprom.MIC_SENSITIVITY; break; -#ifdef ENABLE_AUDIO_BAR - case MENU_MIC_BAR: - gSubMenuSelection = gSetting_mic_bar; - break; -#endif - case MENU_COMPAND: gSubMenuSelection = gTxVfo->Compander; return; diff --git a/board.c b/board.c index 8626d261..cbaf84ed 100644 --- a/board.c +++ b/board.c @@ -720,9 +720,6 @@ void BOARD_EEPROM_Init(void) //gSetting_TX_EN = (Data[7] & (1u << 0)) ? true : false; gSetting_live_DTMF_decoder = (Data[7] & (1u << 1)) ? true : false; gSetting_battery_text = (((Data[7] >> 2) & 3u) <= 2) ? (Data[7] >> 2) & 3 : 2; - #ifdef ENABLE_AUDIO_BAR - gSetting_mic_bar = (Data[7] & (1u << 4)) ? true : false; - #endif #ifdef ENABLE_AM_FIX gSetting_AM_fix = (Data[7] & (1u << 5)) ? true : false; #endif diff --git a/misc.c b/misc.c index 22b18bf1..9df792b1 100644 --- a/misc.c +++ b/misc.c @@ -95,9 +95,6 @@ uint8_t gSetting_backlight_on_tx_rx; bool gSetting_AM_fix; #endif -#ifdef ENABLE_AUDIO_BAR - bool gSetting_mic_bar; -#endif bool gSetting_live_DTMF_decoder; uint8_t gSetting_battery_text; diff --git a/misc.h b/misc.h index 98ef1f38..5b6c6b0f 100644 --- a/misc.h +++ b/misc.h @@ -163,9 +163,6 @@ extern uint8_t gSetting_backlight_on_tx_rx; extern bool gSetting_AM_fix; #endif -#ifdef ENABLE_AUDIO_BAR - extern bool gSetting_mic_bar; -#endif extern bool gSetting_live_DTMF_decoder; extern uint8_t gSetting_battery_text; diff --git a/settings.c b/settings.c index dbf850d1..93438fc7 100644 --- a/settings.c +++ b/settings.c @@ -186,9 +186,6 @@ void SETTINGS_SaveSettings(void) //if (!gSetting_TX_EN) State[7] &= ~(1u << 0); if (!gSetting_live_DTMF_decoder) State[7] &= ~(1u << 1); State[7] = (State[7] & ~(3u << 2)) | ((gSetting_battery_text & 3u) << 2); - #ifdef ENABLE_AUDIO_BAR - if (!gSetting_mic_bar) State[7] &= ~(1u << 4); - #endif #ifdef ENABLE_AM_FIX if (!gSetting_AM_fix) State[7] &= ~(1u << 5); #endif diff --git a/ui/main.c b/ui/main.c index 1cd3f4b8..644f1d78 100644 --- a/ui/main.c +++ b/ui/main.c @@ -100,42 +100,40 @@ unsigned int sqrt16(unsigned int value) void UI_DisplayAudioBar(void) { - if (gSetting_mic_bar) - { - if(gLowBattery && !gLowBatteryConfirmed) - return; + if(gLowBattery && !gLowBatteryConfirmed) + return; - const unsigned int line = 3; + const unsigned int line = 3; - if (gCurrentFunction != FUNCTION_TRANSMIT || - gScreenToDisplay != DISPLAY_MAIN -#ifdef ENABLE_DTMF_CALLING - || gDTMF_CallState != DTMF_CALL_STATE_NONE -#endif - ) - { - return; // screen is in use - } - -#if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) + if (gCurrentFunction != FUNCTION_TRANSMIT || + gScreenToDisplay != DISPLAY_MAIN + #ifdef ENABLE_DTMF_CALLING + || gDTMF_CallState != DTMF_CALL_STATE_NONE + #endif + ) + { + return; // screen is in use + } + + #if defined(ENABLE_ALARM) || defined(ENABLE_TX1750) if (gAlarmState != ALARM_STATE_OFF) return; -#endif - const unsigned int voice_amp = BK4819_GetVoiceAmplitudeOut(); // 15:0 + #endif + const unsigned int voice_amp = BK4819_GetVoiceAmplitudeOut(); // 15:0 - // make non-linear to make more sensitive at low values - const unsigned int level = MIN(voice_amp * 8, 65535u); - const unsigned int sqrt_level = MIN(sqrt16(level), 124u); - uint8_t bars = 13 * sqrt_level / 124; + // make non-linear to make more sensitive at low values + const unsigned int level = MIN(voice_amp * 8, 65535u); + const unsigned int sqrt_level = MIN(sqrt16(level), 124u); + uint8_t bars = 13 * sqrt_level / 124; - uint8_t *p_line = gFrameBuffer[line]; - memset(p_line, 0, LCD_WIDTH); + uint8_t *p_line = gFrameBuffer[line]; + memset(p_line, 0, LCD_WIDTH); - DrawLevelBar(62, line, bars); + DrawLevelBar(62, line, bars); + + if (gCurrentFunction == FUNCTION_TRANSMIT) + ST7565_BlitFullScreen(); - if (gCurrentFunction == FUNCTION_TRANSMIT) - ST7565_BlitFullScreen(); - } } #endif @@ -661,7 +659,7 @@ void UI_DisplayMain(void) gCurrentFunction == FUNCTION_INCOMING); #ifdef ENABLE_AUDIO_BAR - if (gSetting_mic_bar && gCurrentFunction == FUNCTION_TRANSMIT) { + if (gCurrentFunction == FUNCTION_TRANSMIT) { center_line = CENTER_LINE_AUDIO_BAR; UI_DisplayAudioBar(); } diff --git a/ui/menu.c b/ui/menu.c index 72062e58..8fc27eb4 100644 --- a/ui/menu.c +++ b/ui/menu.c @@ -70,10 +70,7 @@ const t_menu_item MenuList[] = {"KeyLck", VOICE_ID_INVALID, MENU_AUTOLK }, // was "AUTOLk" {"TxTOut", VOICE_ID_TRANSMIT_OVER_TIME, MENU_TOT }, // was "TOT" {"BatSav", VOICE_ID_SAVE_MODE, MENU_SAVE }, // was "SAVE" - {"Mic", VOICE_ID_INVALID, MENU_MIC }, -#ifdef ENABLE_AUDIO_BAR - {"MicBar", VOICE_ID_INVALID, MENU_MIC_BAR }, -#endif + {"Mic", VOICE_ID_INVALID, MENU_MIC }, {"ChDisp", VOICE_ID_INVALID, MENU_MDF }, // was "MDF" {"POnMsg", VOICE_ID_INVALID, MENU_PONMSG }, {"BatTxt", VOICE_ID_INVALID, MENU_BAT_TXT }, @@ -506,12 +503,6 @@ void UI_DisplayMenu(void) } break; - #ifdef ENABLE_AUDIO_BAR - case MENU_MIC_BAR: - strcpy(String, gSubMenu_OFF_ON[gSubMenuSelection]); - break; - #endif - case MENU_STEP: { uint16_t step = gStepFrequencyTable[FREQUENCY_GetStepIdxFromSortedIdx(gSubMenuSelection)]; sprintf(String, "%d.%02ukHz", step / 100, step % 100); diff --git a/ui/menu.h b/ui/menu.h index 531e44ed..270d88e6 100644 --- a/ui/menu.h +++ b/ui/menu.h @@ -70,9 +70,6 @@ enum MENU_STE, MENU_RP_STE, MENU_MIC, -#ifdef ENABLE_AUDIO_BAR - MENU_MIC_BAR, -#endif MENU_COMPAND, MENU_1_CALL, #ifdef ENABLE_ALARM From f849cdf4c2de5ccbc9535007f660259a47ff43b4 Mon Sep 17 00:00:00 2001 From: Nunu Date: Sun, 7 Jan 2024 12:13:52 +0100 Subject: [PATCH 3/7] MENU BatSav setting values displayed as %. --- ui/menu.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ui/menu.c b/ui/menu.c index 8fc27eb4..9c5cdd8c 100644 --- a/ui/menu.c +++ b/ui/menu.c @@ -165,10 +165,10 @@ const char gSubMenu_OFF_ON[][4] = const char gSubMenu_SAVE[][4] = { "OFF", - "1:1", - "1:2", - "1:3", - "1:4" + "50%", + "67%", + "75%", + "80%" }; const char gSubMenu_TOT[][7] = From 31e53107565d4fb32c1ac60005c6912925415c99 Mon Sep 17 00:00:00 2001 From: Nunu Date: Sun, 7 Jan 2024 12:38:03 +0100 Subject: [PATCH 4/7] Removed "UNBLOCK ALL" option from the hidden menu. --- app/menu.c | 10 ---------- app/menu.h | 2 -- frequencies.c | 6 ------ settings.h | 3 +-- ui/menu.c | 8 ++------ 5 files changed, 3 insertions(+), 26 deletions(-) diff --git a/app/menu.c b/app/menu.c index 1bb53eb8..0c4db1f9 100644 --- a/app/menu.c +++ b/app/menu.c @@ -47,8 +47,6 @@ #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) #endif -uint8_t gUnlockAllTxConfCnt; - #ifdef ENABLE_F_CAL_MENU void writeXtalFreqCal(const int32_t value, const bool update_eeprom) { @@ -742,14 +740,6 @@ void MENU_AcceptSetting(void) break; case MENU_F_LOCK: { - if(gSubMenuSelection == F_LOCK_NONE) { // select 10 times to enable - gUnlockAllTxConfCnt++; - if(gUnlockAllTxConfCnt < 10) - return; - } - else - gUnlockAllTxConfCnt = 0; - gSetting_F_LOCK = gSubMenuSelection; break; } diff --git a/app/menu.h b/app/menu.h index 0b8a15c5..8c46f2fc 100644 --- a/app/menu.h +++ b/app/menu.h @@ -23,8 +23,6 @@ void writeXtalFreqCal(const int32_t value, const bool update_eeprom); #endif -extern uint8_t gUnlockAllTxConfCnt; - int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax); void MENU_AcceptSetting(void); void MENU_ShowCurrentSetting(void); diff --git a/frequencies.c b/frequencies.c index b582e64d..3981338c 100644 --- a/frequencies.c +++ b/frequencies.c @@ -207,12 +207,6 @@ int TX_freq_check(const uint32_t Frequency) case F_LOCK_ALL: break; - - case F_LOCK_NONE: - for (uint8_t i = 0; i < ARRAY_SIZE(frequencyBandTable); i++) - if (Frequency >= frequencyBandTable[i].lower && Frequency < frequencyBandTable[i].upper) - return 0; - break; } // dis-allowed TX frequency diff --git a/settings.h b/settings.h index 6d0e78f7..64a44a26 100644 --- a/settings.h +++ b/settings.h @@ -40,8 +40,7 @@ enum { F_LOCK_GB, F_LOCK_430, F_LOCK_438, - F_LOCK_ALL, // disable TX on all frequencies - F_LOCK_NONE, // enable TX on all frequencies + F_LOCK_ALL, // disable TX on all frequencies, scanner mode F_LOCK_LEN }; diff --git a/ui/menu.c b/ui/menu.c index 9c5cdd8c..8339f96a 100644 --- a/ui/menu.c +++ b/ui/menu.c @@ -274,8 +274,7 @@ const char * const gSubMenu_F_LOCK[] = "GB HAM\n144-148\n430-440", "137-174\n400-430", "137-174\n400-438", - "DISABLE\nALL", - "UNLOCK\nALL", + "DISABLE\nALL" }; const char gSubMenu_BACKLIGHT[][7] = @@ -793,10 +792,7 @@ void UI_DisplayMenu(void) break; case MENU_F_LOCK: - if(!gIsInSubMenu && gUnlockAllTxConfCnt>0 && gUnlockAllTxConfCnt<10) - strcpy(String, "READ\nMANUAL"); - else - strcpy(String, gSubMenu_F_LOCK[gSubMenuSelection]); + strcpy(String, gSubMenu_F_LOCK[gSubMenuSelection]); break; #ifdef ENABLE_F_CAL_MENU From d5828f36514017235df087740018629f413f5b45 Mon Sep 17 00:00:00 2001 From: Nunu Date: Sun, 7 Jan 2024 13:44:32 +0100 Subject: [PATCH 5/7] AM_FIX removed. --- Makefile | 11 -- README.md | 9 +- am_fix.c | 399 ---------------------------------------------- am_fix.h | 35 ---- app/action.c | 7 +- app/app.c | 49 +----- app/app.h | 2 +- app/chFrScanner.c | 4 +- app/menu.c | 16 -- board.c | 3 - main.c | 7 - misc.c | 4 - misc.h | 4 - settings.c | 3 - ui/main.c | 20 --- ui/main.h | 1 - ui/menu.c | 6 - ui/menu.h | 3 - utils/main.cpp | 19 --- 19 files changed, 8 insertions(+), 594 deletions(-) delete mode 100644 am_fix.c delete mode 100644 am_fix.h diff --git a/Makefile b/Makefile index cdd5b5b1..bbfb9833 100644 --- a/Makefile +++ b/Makefile @@ -22,7 +22,6 @@ ENABLE_PWRON_PASSWORD := 0 ENABLE_DTMF_CALLING := 0 #---- DEBUG ---- -ENABLE_AM_FIX_SHOW_DATA := 0 ENABLE_ULTRA_LOW_POWER_TX := 0 # ---- CUSTOM MODS ---- @@ -37,7 +36,6 @@ ENABLE_BOOT_BEEPS := 0 ENABLE_SHOW_CHARGE_LEVEL := 1 ENABLE_REVERSE_BAT_SYMBOL := 0 ENABLE_NO_CODE_SCAN_TIMEOUT := 1 -ENABLE_AM_FIX := 1 ENABLE_SQUELCH_MORE_SENSITIVE := 0 ENABLE_FASTER_CHANNEL_SCAN := 1 ENABLE_RSSI_BAR := 1 @@ -130,9 +128,6 @@ OBJS += app/scanner.o ifeq ($(ENABLE_UART),1) OBJS += app/uart.o endif -ifeq ($(ENABLE_AM_FIX), 1) - OBJS += am_fix.o -endif OBJS += audio.o OBJS += bitmaps.o OBJS += board.o @@ -320,12 +315,6 @@ endif ifeq ($(ENABLE_NO_CODE_SCAN_TIMEOUT),1) CFLAGS += -DENABLE_CODE_SCAN_TIMEOUT endif -ifeq ($(ENABLE_AM_FIX),1) - CFLAGS += -DENABLE_AM_FIX -endif -ifeq ($(ENABLE_AM_FIX_SHOW_DATA),1) - CFLAGS += -DENABLE_AM_FIX_SHOW_DATA -endif ifeq ($(ENABLE_SQUELCH_MORE_SENSITIVE),1) CFLAGS += -DENABLE_SQUELCH_MORE_SENSITIVE endif diff --git a/README.md b/README.md index 524110dc..28d3d58e 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,7 @@ Anyway, have fun. * `ENABLE_ADJUSTABLE_RX_GAIN_SETTINGS` keeps the rx gain settings set in spectrum mode after exit (otherwise these are always overwritten to default value), this makes much more sense considering that we have a radio with user adjustable gain so why not use it to adjust to current radio conditions, maximum gain allows to greatly increase reception in scan memory channels mode (in this configuration default gain settings are only set at boot and when exiting AM modulation mode to set it to sane value after am fix) * `ENABLE_SPECTRUM_CHANNEL_SCAN` this enables spectrum channel scan mode (enter by going into memory mode and press F+5, this allows SUPER fast channel scanning (4.5x faster than regular scanning), regular scan of 200 memory channels takes roughly 18 seconds, spectrum memory scan takes roughly 4 seconds, if you have less channels stored i.e 50 - the spectrum memory scan will take only **1 second** * `VOXSen` fixed and improved VOX sensitivity setting from menu. Added `VoxDel` - VOX delay setting allowing to set value to `0` for no VOX delay which might be useful for packet radio enthusiasts (APRS etc.). + * Fixed AM AGC so **AM demodulation is crystal clear**, no audible clicks, no need for `AM_FIX`. ## Keyboard shortcuts * In `VFO mode` long press `5` to enter `scan range mode` @@ -133,8 +134,6 @@ ENABLE_BOOT_BEEPS := 0 gives user audio feedback on volum ENABLE_SHOW_CHARGE_LEVEL := 1 show the charge level when the radio is on charge ENABLE_REVERSE_BAT_SYMBOL := 0 mirror the battery symbol on the status bar (+ pole on the right) ENABLE_NO_CODE_SCAN_TIMEOUT := 1 disable 32-sec CTCSS/DCS scan timeout (press exit butt instead of time-out to end scan) -ENABLE_AM_FIX := 1 dynamically adjust the front end gains when in AM mode to help prevent AM demodulator saturation, ignore the on-screen RSSI level (for now) -ENABLE_AM_FIX_SHOW_DATA := 0 show debug data for the AM fix ENABLE_SQUELCH_MORE_SENSITIVE := 0 make squelch levels a little bit more sensitive - this has been reported to cause radio freeze in presence of strong signals ENABLE_FASTER_CHANNEL_SCAN := 1 increases the channel scan speed, but the squelch is also made more twitchy ENABLE_RSSI_BAR := 1 enable a dBm/Sn RSSI bar graph level in place of the little antenna symbols @@ -236,9 +235,3 @@ You may obtain a copy of the License at

- -Video showing the AM fix working .. - - - - diff --git a/am_fix.c b/am_fix.c deleted file mode 100644 index bfde70d7..00000000 --- a/am_fix.c +++ /dev/null @@ -1,399 +0,0 @@ - -/* Copyright 2023 OneOfEleven - * 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. - */ - -// code to 'try' and reduce the AM demodulator saturation problem -// -// that is until someone works out how to properly configure the BK chip ! - -#include - -#include "am_fix.h" -#include "app/main.h" -#include "board.h" -#include "driver/bk4819.h" -#include "external/printf/printf.h" -#include "frequencies.h" -#include "functions.h" -#include "misc.h" - -#ifdef ENABLE_AM_FIX - -typedef struct -{ - uint16_t reg_val; - int8_t gain_dB; -} __attribute__((packed)) t_gain_table; - -// REG_10 AGC gain table -// -// <15:10> ??? -// -// <9:8> = LNA Gain Short -// 3 = 0dB < original value -// 2 = -24dB // was -11 -// 1 = -30dB // was -16 -// 0 = -33dB // was -19 -// -// <7:5> = LNA Gain -// 7 = 0dB -// 6 = -2dB -// 5 = -4dB < original value -// 4 = -6dB -// 3 = -9dB -// 2 = -14dB -// 1 = -19dB -// 0 = -24dB -// -// <4:3> = MIXER Gain -// 3 = 0dB < original value -// 2 = -3dB -// 1 = -6dB -// 0 = -8dB -// -// <2:0> = PGA Gain -// 7 = 0dB -// 6 = -3dB < original value -// 5 = -6dB -// 4 = -9dB -// 3 = -15dB -// 2 = -21dB -// 1 = -27dB -// 0 = -33dB - -// front end register dB values -// -// these values need to be accurate for the code to properly/reliably switch -// between table entries when adjusting the front end registers. -// -// these 4 tables need a measuring/calibration update -// -// -// QUESTION: why do I have to surround the negative numbers in brackets ??? -// if I don't add the brackets, reading the table returns unexpected/different values !!! -// -// -//// static const int16_t lna_short_dB[] = { -19, -16, -11, 0}; // was (but wrong) -// static const int16_t lna_short_dB[] = { (-33), (-30), (-24), 0}; // corrected'ish -// static const int16_t lna_dB[] = { (-24), (-19), (-14), ( -9), (-6), (-4), (-2), 0}; -// static const int16_t mixer_dB[] = { ( -8), ( -6), ( -3), 0}; -// static const int16_t pga_dB[] = { (-33), (-27), (-21), (-15), (-9), (-6), (-3), 0}; - -// lookup table is hugely easier than writing code to do the same -// -static const t_gain_table gain_table[] = -{ - {0x035E, -17}, // 0 .. 3 2 3 6 .. 0dB -14dB 0dB -3dB .. -17dB original - - {0x0000, -98}, // 1 .. 0 0 0 0 .. -33dB -24dB -8dB -33dB .. -98dB - {0x0008, -96}, // 2 .. 0 0 1 0 .. -33dB -24dB -6dB -33dB .. -96dB - {0x0100, -95}, // 3 .. 1 0 0 0 .. -30dB -24dB -8dB -33dB .. -95dB - {0x0020, -93}, // 4 .. 0 1 0 0 .. -33dB -19dB -8dB -33dB .. -93dB - {0x0001, -92}, // 5 .. 0 0 0 1 .. -33dB -24dB -8dB -27dB .. -92dB - {0x0028, -91}, // 6 .. 0 1 1 0 .. -33dB -19dB -6dB -33dB .. -91dB - {0x0009, -90}, // 7 .. 0 0 1 1 .. -33dB -24dB -6dB -27dB .. -90dB - {0x0101, -89}, // 8 .. 1 0 0 1 .. -30dB -24dB -8dB -27dB .. -89dB - {0x0030, -88}, // 9 .. 0 1 2 0 .. -33dB -19dB -3dB -33dB .. -88dB - {0x0118, -87}, // 10 .. 1 0 3 0 .. -30dB -24dB 0dB -33dB .. -87dB - {0x0002, -86}, // 11 .. 0 0 0 2 .. -33dB -24dB -8dB -21dB .. -86dB - {0x0130, -85}, // 12 .. 1 1 2 0 .. -30dB -19dB -3dB -33dB .. -85dB - {0x0019, -84}, // 13 .. 0 0 3 1 .. -33dB -24dB 0dB -27dB .. -84dB - {0x0060, -83}, // 14 .. 0 3 0 0 .. -33dB -9dB -8dB -33dB .. -83dB - {0x0138, -82}, // 15 .. 1 1 3 0 .. -30dB -19dB 0dB -33dB .. -82dB - {0x0119, -81}, // 16 .. 1 0 3 1 .. -30dB -24dB 0dB -27dB .. -81dB - {0x0058, -80}, // 17 .. 0 2 3 0 .. -33dB -14dB 0dB -33dB .. -80dB - {0x0141, -79}, // 18 .. 1 2 0 1 .. -30dB -14dB -8dB -27dB .. -79dB - {0x0070, -78}, // 19 .. 0 3 2 0 .. -33dB -9dB -3dB -33dB .. -78dB - {0x0180, -77}, // 20 .. 1 4 0 0 .. -30dB -6dB -8dB -33dB .. -77dB - {0x0139, -76}, // 21 .. 1 1 3 1 .. -30dB -19dB 0dB -27dB .. -76dB - {0x0013, -75}, // 22 .. 0 0 2 3 .. -33dB -24dB -3dB -15dB .. -75dB - {0x0161, -74}, // 23 .. 1 3 0 1 .. -30dB -9dB -8dB -27dB .. -74dB - {0x01C0, -73}, // 24 .. 1 6 0 0 .. -30dB -2dB -8dB -33dB .. -73dB - {0x00E8, -72}, // 25 .. 0 7 1 0 .. -33dB 0dB -6dB -33dB .. -72dB - {0x00D0, -71}, // 26 .. 0 6 2 0 .. -33dB -2dB -3dB -33dB .. -71dB - {0x0239, -70}, // 27 .. 2 1 3 1 .. -24dB -19dB 0dB -27dB .. -70dB - {0x006A, -69}, // 28 .. 0 3 1 2 .. -33dB -9dB -6dB -21dB .. -69dB - {0x0006, -68}, // 29 .. 0 0 0 6 .. -33dB -24dB -8dB -3dB .. -68dB - {0x00B1, -67}, // 30 .. 0 5 2 1 .. -33dB -4dB -3dB -27dB .. -67dB - {0x000E, -66}, // 31 .. 0 0 1 6 .. -33dB -24dB -6dB -3dB .. -66dB - {0x015A, -65}, // 32 .. 1 2 3 2 .. -30dB -14dB 0dB -21dB .. -65dB - {0x022B, -64}, // 33 .. 2 1 1 3 .. -24dB -19dB -6dB -15dB .. -64dB - {0x01F8, -63}, // 34 .. 1 7 3 0 .. -30dB 0dB 0dB -33dB .. -63dB - {0x0163, -62}, // 35 .. 1 3 0 3 .. -30dB -9dB -8dB -15dB .. -62dB - {0x0035, -61}, // 36 .. 0 1 2 5 .. -33dB -19dB -3dB -6dB .. -61dB - {0x0214, -60}, // 37 .. 2 0 2 4 .. -24dB -24dB -3dB -9dB .. -60dB - {0x01D9, -59}, // 38 .. 1 6 3 1 .. -30dB -2dB 0dB -27dB .. -59dB - {0x0145, -58}, // 39 .. 1 2 0 5 .. -30dB -14dB -8dB -6dB .. -58dB - {0x02A2, -57}, // 40 .. 2 5 0 2 .. -24dB -4dB -8dB -21dB .. -57dB - {0x02D1, -56}, // 41 .. 2 6 2 1 .. -24dB -2dB -3dB -27dB .. -56dB - {0x00B3, -55}, // 42 .. 0 5 2 3 .. -33dB -4dB -3dB -15dB .. -55dB - {0x0216, -54}, // 43 .. 2 0 2 6 .. -24dB -24dB -3dB -3dB .. -54dB - {0x0066, -53}, // 44 .. 0 3 0 6 .. -33dB -9dB -8dB -3dB .. -53dB - {0x00C4, -52}, // 45 .. 0 6 0 4 .. -33dB -2dB -8dB -9dB .. -52dB - {0x006E, -51}, // 46 .. 0 3 1 6 .. -33dB -9dB -6dB -3dB .. -51dB - {0x015D, -50}, // 47 .. 1 2 3 5 .. -30dB -14dB 0dB -6dB .. -50dB - {0x00AD, -49}, // 48 .. 0 5 1 5 .. -33dB -4dB -6dB -6dB .. -49dB - {0x007D, -48}, // 49 .. 0 3 3 5 .. -33dB -9dB 0dB -6dB .. -48dB - {0x00D4, -47}, // 50 .. 0 6 2 4 .. -33dB -2dB -3dB -9dB .. -47dB - {0x01B4, -46}, // 51 .. 1 5 2 4 .. -30dB -4dB -3dB -9dB .. -46dB - {0x030B, -45}, // 52 .. 3 0 1 3 .. 0dB -24dB -6dB -15dB .. -45dB - {0x00CE, -44}, // 53 .. 0 6 1 6 .. -33dB -2dB -6dB -3dB .. -44dB - {0x01B5, -43}, // 54 .. 1 5 2 5 .. -30dB -4dB -3dB -6dB .. -43dB - {0x0097, -42}, // 55 .. 0 4 2 7 .. -33dB -6dB -3dB 0dB .. -42dB - {0x0257, -41}, // 56 .. 2 2 2 7 .. -24dB -14dB -3dB 0dB .. -41dB - {0x02B4, -40}, // 57 .. 2 5 2 4 .. -24dB -4dB -3dB -9dB .. -40dB - {0x027D, -39}, // 58 .. 2 3 3 5 .. -24dB -9dB 0dB -6dB .. -39dB - {0x01DD, -38}, // 59 .. 1 6 3 5 .. -30dB -2dB 0dB -6dB .. -38dB - {0x02AE, -37}, // 60 .. 2 5 1 6 .. -24dB -4dB -6dB -3dB .. -37dB - {0x0379, -36}, // 61 .. 3 3 3 1 .. 0dB -9dB 0dB -27dB .. -36dB - {0x035A, -35}, // 62 .. 3 2 3 2 .. 0dB -14dB 0dB -21dB .. -35dB - {0x02B6, -34}, // 63 .. 2 5 2 6 .. -24dB -4dB -3dB -3dB .. -34dB - {0x030E, -33}, // 64 .. 3 0 1 6 .. 0dB -24dB -6dB -3dB .. -33dB - {0x0307, -32}, // 65 .. 3 0 0 7 .. 0dB -24dB -8dB 0dB .. -32dB - {0x02BE, -31}, // 66 .. 2 5 3 6 .. -24dB -4dB 0dB -3dB .. -31dB - {0x037A, -30}, // 67 .. 3 3 3 2 .. 0dB -9dB 0dB -21dB .. -30dB - {0x02DE, -29}, // 68 .. 2 6 3 6 .. -24dB -2dB 0dB -3dB .. -29dB - {0x0345, -28}, // 69 .. 3 2 0 5 .. 0dB -14dB -8dB -6dB .. -28dB - {0x03A3, -27}, // 70 .. 3 5 0 3 .. 0dB -4dB -8dB -15dB .. -27dB - {0x0364, -26}, // 71 .. 3 3 0 4 .. 0dB -9dB -8dB -9dB .. -26dB - {0x032F, -25}, // 72 .. 3 1 1 7 .. 0dB -19dB -6dB 0dB .. -25dB - {0x0393, -24}, // 73 .. 3 4 2 3 .. 0dB -6dB -3dB -15dB .. -24dB - {0x0384, -23}, // 74 .. 3 4 0 4 .. 0dB -6dB -8dB -9dB .. -23dB - {0x0347, -22}, // 75 .. 3 2 0 7 .. 0dB -14dB -8dB 0dB .. -22dB - {0x03EB, -21}, // 76 .. 3 7 1 3 .. 0dB 0dB -6dB -15dB .. -21dB - {0x03D3, -20}, // 77 .. 3 6 2 3 .. 0dB -2dB -3dB -15dB .. -20dB - {0x03BB, -19}, // 78 .. 3 5 3 3 .. 0dB -4dB 0dB -15dB .. -19dB - {0x037C, -18}, // 79 .. 3 3 3 4 .. 0dB -9dB 0dB -9dB .. -18dB - {0x03CC, -17}, // 80 .. 3 6 1 4 .. 0dB -2dB -6dB -9dB .. -17dB - {0x03C5, -16}, // 81 .. 3 6 0 5 .. 0dB -2dB -8dB -6dB .. -16dB - {0x03EC, -15}, // 82 .. 3 7 1 4 .. 0dB 0dB -6dB -9dB .. -15dB - {0x035F, -14}, // 83 .. 3 2 3 7 .. 0dB -14dB 0dB 0dB .. -14dB - {0x03BC, -13}, // 84 .. 3 5 3 4 .. 0dB -4dB 0dB -9dB .. -13dB - {0x038F, -12}, // 85 .. 3 4 1 7 .. 0dB -6dB -6dB 0dB .. -12dB - {0x03E6, -11}, // 86 .. 3 7 0 6 .. 0dB 0dB -8dB -3dB .. -11dB - {0x03AF, -10}, // 87 .. 3 5 1 7 .. 0dB -4dB -6dB 0dB .. -10dB - {0x03F5, -9 }, // 88 .. 3 7 2 5 .. 0dB 0dB -3dB -6dB .. -9dB - {0x03D6, -8 }, // 89 .. 3 6 2 6 .. 0dB -2dB -3dB -3dB .. -8dB - {0x03BE, -7 }, // 90 .. 3 5 3 6 .. 0dB -4dB 0dB -3dB .. -7dB original - {0x03F6, -6 }, // 91 .. 3 7 2 6 .. 0dB 0dB -3dB -3dB .. -6dB - {0x03DE, -5 }, // 92 .. 3 6 3 6 .. 0dB -2dB 0dB -3dB .. -5dB - {0x03BF, -4 }, // 93 .. 3 5 3 7 .. 0dB -4dB 0dB 0dB .. -4dB - {0x03F7, -3 }, // 94 .. 3 7 2 7 .. 0dB 0dB -3dB 0dB .. -3dB - {0x03DF, -2 }, // 95 .. 3 6 3 7 .. 0dB -2dB 0dB 0dB .. -2dB - {0x03FF, 0 }, // 96 .. 3 7 3 7 .. 0dB 0dB 0dB 0dB .. 0dB -}; - -static const unsigned int original_index = 90; - -#ifdef ENABLE_AM_FIX_SHOW_DATA - // display update rate - static const unsigned int display_update_rate = 250 / 10; // max 250ms display update rate - unsigned int counter = 0; -#endif - -unsigned int gain_table_index[2] = {original_index, original_index}; - - -// used simply to detect a changed gain setting -unsigned int gain_table_index_prev[2] = {0, 0}; - -// holds the previous RSSI level .. we do an average of old + new RSSI reading -int16_t prev_rssi[2] = {0, 0}; - -// to help reduce gain hunting, peak hold count down tick -unsigned int hold_counter[2] = {0, 0}; - -// used to correct the RSSI readings after our RF gain adjustments -int16_t rssi_gain_diff[2] = {0, 0}; - -// used to limit the max RF gain -unsigned int max_index = ARRAY_SIZE(gain_table) - 1; - -// -110dBm, any higher and the AM demodulator starts to saturate/clip/distort -const int16_t desired_rssi = (-110 + 180) * 2; - -void AM_fix_init(void) -{ // called at boot-up - for (int i = 0; i < 2; i++) { - gain_table_index[i] = original_index; // re-start with original QS setting - } - - // use the full range of available gains - max_index = ARRAY_SIZE(gain_table) - 1; -} - -void AM_fix_reset(const int vfo) -{ // reset the AM fixer upper - #ifdef ENABLE_AM_FIX_SHOW_DATA - counter = 0; - #endif - - prev_rssi[vfo] = 0; - hold_counter[vfo] = 0; - rssi_gain_diff[vfo] = 0; - gain_table_index_prev[vfo] = 0; -} - -// adjust the RX gain to try and prevent the AM demodulator from -// saturating/overloading/clipping (distorted AM audio) -// -// we're actually doing the BK4819's job for it here, but as the chip -// won't/don't do it for itself, we're left to bodging it ourself by -// playing with the RF front end gain setting -// -void AM_fix_10ms(const int vfo) -{ - int16_t diff_dB; - int16_t rssi; - - switch (gCurrentFunction) - { - case FUNCTION_TRANSMIT: - case FUNCTION_BAND_SCOPE: - case FUNCTION_POWER_SAVE: - #ifdef ENABLE_AM_FIX_SHOW_DATA - counter = display_update_rate; // queue up a display update as soon as we switch to RX mode - #endif - return; - - // only adjust stuff if we're in one of these modes - case FUNCTION_FOREGROUND: - case FUNCTION_RECEIVE: - case FUNCTION_MONITOR: - case FUNCTION_INCOMING: - break; - } - -#ifdef ENABLE_AM_FIX_SHOW_DATA - if (counter > 0) { - if (++counter >= display_update_rate) { // trigger a display update - counter = 0; - gUpdateDisplay = true; - } - } -#endif - - { // sample the current RSSI level - // average it with the previous rssi (a bit of noise/spike immunity) - const int16_t new_rssi = BK4819_GetRSSI(); - rssi = (prev_rssi[vfo] > 0) ? (prev_rssi[vfo] + new_rssi) / 2 : new_rssi; - prev_rssi[vfo] = new_rssi; - } - - // save the corrected RSSI level -#ifdef ENABLE_AM_FIX_SHOW_DATA - { - const int16_t new_rssi = rssi - rssi_gain_diff[vfo]; - if (gCurrentRSSI[vfo] != new_rssi) { - gCurrentRSSI[vfo] = new_rssi; - - if (counter == 0) { - counter = 1; - gUpdateDisplay = true; // trigger a display update - } - } - } -#else - gCurrentRSSI[vfo] = rssi; -#endif - - - // automatically adjust the RF RX gain - - // update the gain hold counter - if (hold_counter[vfo] > 0) - hold_counter[vfo]--; - - // dB difference between actual and desired RSSI level - diff_dB = (rssi - desired_rssi) / 2; - - if (diff_dB > 0) { // decrease gain - unsigned int index = gain_table_index[vfo]; // current position we're at - - if (diff_dB >= 10) { // jump immediately to a new gain setting - // this greatly speeds up initial gain reduction (but reduces noise/spike immunity) - - const int16_t desired_gain_dB = (int16_t)gain_table[index].gain_dB - diff_dB + 8; // get no closer than 8dB (bit of noise/spike immunity) - - // scan the table to see what index to jump straight too - while (index > 1) - if (gain_table[--index].gain_dB <= desired_gain_dB) - break; - } - else - { // incrementally reduce the gain .. taking it slow improves noise/spike immunity - if (index > 1) - index--; // slow step-by-step gain reduction - } - - index = (index < 1) ? 1 : (index > max_index) ? max_index : index; - - if (gain_table_index[vfo] != index) - { - gain_table_index[vfo] = index; - hold_counter[vfo] = 30; // 300ms hold - } - } - - if (diff_dB >= -6) // 6dB hysterisis (help reduce gain hunting) - hold_counter[vfo] = 30; // 300ms hold - - if (hold_counter[vfo] == 0) - { // hold has been released, we're free to increase gain - const unsigned int index = gain_table_index[vfo] + 1; // move up to next gain index - gain_table_index[vfo] = (index <= max_index) ? index : max_index; // limit the gain index - } - - - { // apply the new settings to the front end registers - - const unsigned int index = gain_table_index[vfo]; - - // remember the new table index - gain_table_index_prev[vfo] = index; - - BK4819_WriteRegister(BK4819_REG_13, gain_table[index].reg_val); - - // offset the RSSI reading to the rest of the firmware to cancel out the gain adjustments we make - - // RF gain difference from original QS setting - rssi_gain_diff[vfo] = ((int16_t)gain_table[index].gain_dB - gain_table[original_index].gain_dB) * 2; - } - - // save the corrected RSSI level - gCurrentRSSI[vfo] = rssi; - -#ifdef ENABLE_AM_FIX_SHOW_DATA - if (counter == 0) { - counter = 1; - gUpdateDisplay = true; - } -#endif -} - -#ifdef ENABLE_AM_FIX_SHOW_DATA - -void AM_fix_print_data(const int vfo, char *s) { - if (s != NULL && vfo >= 0 && vfo < (int)ARRAY_SIZE(gain_table_index)) { - const unsigned int index = gain_table_index[vfo]; - sprintf(s, "%2u %4ddB %3u", index, gain_table[index].gain_dB, prev_rssi[vfo]); - counter = 0; - } -} - -#endif - -#endif diff --git a/am_fix.h b/am_fix.h deleted file mode 100644 index 3c94d17e..00000000 --- a/am_fix.h +++ /dev/null @@ -1,35 +0,0 @@ - -/* Copyright 2023 OneOfEleven - * 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. - */ - -#ifndef AM_FIXH - -#include -#include - -#ifdef ENABLE_AM_FIX - extern int16_t rssi_gain_diff[2]; - - void AM_fix_init(void); - void AM_fix_reset(const int vfo); - void AM_fix_10ms(const int vfo); - #ifdef ENABLE_AM_FIX_SHOW_DATA - void AM_fix_print_data(const int vfo, char *s); - #endif - -#endif - -#endif diff --git a/app/action.c b/app/action.c index df9285c9..3b72c3e2 100644 --- a/app/action.c +++ b/app/action.c @@ -81,7 +81,7 @@ void ACTION_Monitor(void) gNoaaChannel = gRxVfo->CHANNEL_SAVE - NOAA_CHANNEL_FIRST; #endif RADIO_SetupRegisters(true); - APP_StartListening(FUNCTION_MONITOR, false); + APP_StartListening(FUNCTION_MONITOR); return; } @@ -301,11 +301,6 @@ void ACTION_Scan(bool bRestart) void ACTION_SwitchDemodul(void) { - #if defined(ENABLE_ADJUSTABLE_RX_GAIN_SETTINGS) && defined(ENABLE_AM_FIX) - //if we switch back from AM modulation fix set gain to default values - if(gTxVfo->Modulation==MODULATION_AM) - BK4819_SetDefaultAmplifierSettings(); - #endif gTxVfo->Modulation++; if(gTxVfo->Modulation == MODULATION_UKNOWN) gTxVfo->Modulation = MODULATION_FM; diff --git a/app/app.c b/app/app.c index 991d1ed2..b2da9469 100644 --- a/app/app.c +++ b/app/app.c @@ -44,7 +44,6 @@ #include "driver/keyboard.h" #include "driver/st7565.h" #include "driver/system.h" -#include "am_fix.h" #include "dtmf.h" #include "external/printf/printf.h" #include "frequencies.h" @@ -71,12 +70,6 @@ static void UpdateRSSI(const int vfo) { int16_t rssi = BK4819_GetRSSI(); - // #ifdef ENABLE_AM_FIX - // // add RF gain adjust compensation - // if (gEeprom.VfoInfo[vfo].Modulation == MODULATION_AM && gSetting_AM_fix) - // rssi -= rssi_gain_diff[vfo]; - // #endif - if (gCurrentRSSI[vfo] == rssi) return; // no change @@ -231,7 +224,7 @@ static void HandleIncoming(void) } #endif - APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE, false); + APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE); } static void HandleReceive(void) @@ -426,7 +419,7 @@ static void HandleFunction(void) } } -void APP_StartListening(FUNCTION_Type_t Function, const bool reset_am_fix) +void APP_StartListening(FUNCTION_Type_t Function) { const unsigned int chan = gEeprom.RX_VFO; // const unsigned int chan = gRxVfo->CHANNEL_SAVE; @@ -481,37 +474,7 @@ void APP_StartListening(FUNCTION_Type_t Function, const bool reset_am_fix) gUpdateStatus = true; } - { - -#ifdef ENABLE_AM_FIX - - BK4819_SetAGC(!gSetting_AM_fix); - - if (gRxVfo->Modulation == MODULATION_AM) { // AM RX mode - if(gSetting_AM_fix) - { - if (reset_am_fix) - AM_fix_reset(chan); // TODO: only reset it when moving channel/frequency - AM_fix_10ms(chan); - } - else - { - // if not getting AM fix restore gain settings to sane values after AM fix has been turned off - BK4819_SetDefaultAmplifierSettings(); - } - } - else { // FM RX mode - #ifndef ENABLE_ADJUSTABLE_RX_GAIN_SETTINGS - BK4819.BK4819_SetDefaultAmplifierSettings(); - #endif - } -#else - (void)reset_am_fix; - #ifndef ENABLE_ADJUSTABLE_RX_GAIN_SETTINGS - BK4819.BK4819_SetDefaultAmplifierSettings(); - #endif -#endif - } + BK4819_SetAGC(true); // AF gain - original QS values // if (gRxVfo->Modulation != MODULATION_FM){ @@ -1183,12 +1146,6 @@ void APP_TimeSlice10ms(void) AUDIO_PlayBeep(BEEP_880HZ_40MS_OPTIONAL); #endif - #ifdef ENABLE_AM_FIX -// if (gEeprom.VfoInfo[gEeprom.RX_VFO].Modulation != MODULATION_FM && gSetting_AM_fix) - if (gRxVfo->Modulation == MODULATION_AM && gSetting_AM_fix) - AM_fix_10ms(gEeprom.RX_VFO); - #endif - if (UART_IsCommandAvailable()) { __disable_irq(); diff --git a/app/app.h b/app/app.h index ef3b7067..1a7da7c4 100644 --- a/app/app.h +++ b/app/app.h @@ -24,7 +24,7 @@ #include "radio.h" void APP_EndTransmission(void); -void APP_StartListening(FUNCTION_Type_t Function, const bool reset_am_fix); +void APP_StartListening(FUNCTION_Type_t Function); uint32_t APP_SetFreqByStepAndLimits(VFO_Info_t *pInfo, int8_t direction, uint32_t lower, uint32_t upper); uint32_t APP_SetFrequencyByStep(VFO_Info_t *pInfo, int8_t direction); void APP_Update(void); diff --git a/app/chFrScanner.c b/app/chFrScanner.c index 01b03b34..33b50dd9 100644 --- a/app/chFrScanner.c +++ b/app/chFrScanner.c @@ -72,14 +72,14 @@ void CHFRSCANNER_ContinueScanning(void) if (IS_FREQ_CHANNEL(gNextMrChannel)) { if (gCurrentFunction == FUNCTION_INCOMING) - APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE, true); + APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE); else NextFreqChannel(); // switch to next frequency } else { if (gCurrentCodeType == CODE_TYPE_OFF && gCurrentFunction == FUNCTION_INCOMING) - APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE, true); + APP_StartListening(gMonitor ? FUNCTION_MONITOR : FUNCTION_RECEIVE); else NextMemChannel(); // switch to next channel } diff --git a/app/menu.c b/app/menu.c index 0c4db1f9..7d68daf6 100644 --- a/app/menu.c +++ b/app/menu.c @@ -222,9 +222,6 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax) *pMax = ARRAY_SIZE(gSubMenu_RX_TX) - 1; break; - #ifdef ENABLE_AM_FIX - case MENU_AM_FIX: - #endif case MENU_BCL: case MENU_BEEP: case MENU_AUTOLK: @@ -710,14 +707,6 @@ void MENU_AcceptSetting(void) gRequestSaveChannel = 1; return; - #ifdef ENABLE_AM_FIX - case MENU_AM_FIX: - gSetting_AM_fix = gSubMenuSelection; - gVfoConfigureMode = VFO_CONFIGURE_RELOAD; - gFlagResetVfos = true; - break; - #endif - #ifdef ENABLE_NOAA case MENU_NOAA_S: gEeprom.NOAA_AUTO_SCAN = gSubMenuSelection; @@ -1070,11 +1059,6 @@ void MENU_ShowCurrentSetting(void) gSubMenuSelection = gTxVfo->Modulation; break; -#ifdef ENABLE_AM_FIX - case MENU_AM_FIX: - gSubMenuSelection = gSetting_AM_fix; - break; -#endif #ifdef ENABLE_NOAA case MENU_NOAA_S: gSubMenuSelection = gEeprom.NOAA_AUTO_SCAN; diff --git a/board.c b/board.c index cbaf84ed..c775c839 100644 --- a/board.c +++ b/board.c @@ -720,9 +720,6 @@ void BOARD_EEPROM_Init(void) //gSetting_TX_EN = (Data[7] & (1u << 0)) ? true : false; gSetting_live_DTMF_decoder = (Data[7] & (1u << 1)) ? true : false; gSetting_battery_text = (((Data[7] >> 2) & 3u) <= 2) ? (Data[7] >> 2) & 3 : 2; - #ifdef ENABLE_AM_FIX - gSetting_AM_fix = (Data[7] & (1u << 5)) ? true : false; - #endif gSetting_backlight_on_tx_rx = (Data[7] >> 6) & 3u; // Read RxOffset setting EEPROM_ReadBuffer(RX_OFFSET_ADDR, Data, 4); diff --git a/main.c b/main.c index c539c3a5..114757e3 100644 --- a/main.c +++ b/main.c @@ -17,9 +17,6 @@ #include #include // NULL -#ifdef ENABLE_AM_FIX - #include "am_fix.h" -#endif #include "app/app.h" #include "app/dtmf.h" #include "audio.h" @@ -99,10 +96,6 @@ void Main(void) BATTERY_GetReadings(false); - #ifdef ENABLE_AM_FIX - AM_fix_init(); - #endif - BootMode = BOOT_GetMode(); if (BootMode == BOOT_MODE_F_LOCK) diff --git a/misc.c b/misc.c index 9df792b1..37c3d94b 100644 --- a/misc.c +++ b/misc.c @@ -91,10 +91,6 @@ bool gSetting_ScrambleEnable; uint8_t gSetting_backlight_on_tx_rx; -#ifdef ENABLE_AM_FIX - bool gSetting_AM_fix; -#endif - bool gSetting_live_DTMF_decoder; uint8_t gSetting_battery_text; diff --git a/misc.h b/misc.h index 5b6c6b0f..08a901e2 100644 --- a/misc.h +++ b/misc.h @@ -159,10 +159,6 @@ extern bool gSetting_ScrambleEnable; extern uint8_t gSetting_backlight_on_tx_rx; -#ifdef ENABLE_AM_FIX - extern bool gSetting_AM_fix; -#endif - extern bool gSetting_live_DTMF_decoder; extern uint8_t gSetting_battery_text; diff --git a/settings.c b/settings.c index 93438fc7..ca4eef55 100644 --- a/settings.c +++ b/settings.c @@ -186,9 +186,6 @@ void SETTINGS_SaveSettings(void) //if (!gSetting_TX_EN) State[7] &= ~(1u << 0); if (!gSetting_live_DTMF_decoder) State[7] &= ~(1u << 1); State[7] = (State[7] & ~(3u << 2)) | ((gSetting_battery_text & 3u) << 2); - #ifdef ENABLE_AM_FIX - if (!gSetting_AM_fix) State[7] &= ~(1u << 5); - #endif State[7] = (State[7] & ~(3u << 6)) | ((gSetting_backlight_on_tx_rx & 3u) << 6); EEPROM_WriteBuffer(0x0F40, State, true); diff --git a/ui/main.c b/ui/main.c index 644f1d78..84f13f51 100644 --- a/ui/main.c +++ b/ui/main.c @@ -19,9 +19,6 @@ #include "app/chFrScanner.h" #include "app/dtmf.h" -#ifdef ENABLE_AM_FIX_SHOW_DATA - #include "am_fix.h" -#endif #include "bitmaps.h" #include "board.h" #include "driver/bk4819.h" @@ -666,23 +663,6 @@ void UI_DisplayMain(void) else #endif -#if defined(ENABLE_AM_FIX) && defined(ENABLE_AM_FIX_SHOW_DATA) - if (rx && gEeprom.VfoInfo[gEeprom.RX_VFO].Modulation == MODULATION_AM && gSetting_AM_fix) - { - if (gScreenToDisplay != DISPLAY_MAIN -#ifdef ENABLE_DTMF_CALLING - || gDTMF_CallState != DTMF_CALL_STATE_NONE -#endif - ) - return; - - center_line = CENTER_LINE_AM_FIX_DATA; - AM_fix_print_data(gEeprom.RX_VFO, String); - UI_PrintStringSmall(String, 2, 0, 3); - } - else -#endif - #ifdef ENABLE_RSSI_BAR if (rx) { center_line = CENTER_LINE_RSSI; diff --git a/ui/main.h b/ui/main.h index 80024f92..1ee4063c 100644 --- a/ui/main.h +++ b/ui/main.h @@ -22,7 +22,6 @@ enum center_line_t { CENTER_LINE_IN_USE, CENTER_LINE_AUDIO_BAR, CENTER_LINE_RSSI, - CENTER_LINE_AM_FIX_DATA, CENTER_LINE_DTMF_DEC, CENTER_LINE_CHARGE_DATA }; diff --git a/ui/menu.c b/ui/menu.c index 8339f96a..f171c7e9 100644 --- a/ui/menu.c +++ b/ui/menu.c @@ -102,9 +102,6 @@ const t_menu_item MenuList[] = {"D List", VOICE_ID_INVALID, MENU_D_LIST }, #endif {"D Live", VOICE_ID_INVALID, MENU_D_LIVE_DEC }, // live DTMF decoder -#ifdef ENABLE_AM_FIX - {"AM Fix", VOICE_ID_INVALID, MENU_AM_FIX }, -#endif #ifdef ENABLE_VOX {"VOXSen", VOICE_ID_VOX, MENU_VOX }, // VOX Sensibility or OFF {"VOXDel", VOICE_ID_VOX, MENU_VOX_DELAY }, // VOX delay @@ -608,9 +605,6 @@ void UI_DisplayMenu(void) strcpy(String, gSubMenu_RX_TX[gSubMenuSelection]); break; - #ifdef ENABLE_AM_FIX - case MENU_AM_FIX: - #endif case MENU_BCL: case MENU_BEEP: case MENU_S_ADD1: diff --git a/ui/menu.h b/ui/menu.h index 270d88e6..b312deaf 100644 --- a/ui/menu.h +++ b/ui/menu.h @@ -97,9 +97,6 @@ enum MENU_VOL, MENU_BAT_TXT, MENU_AM, -#ifdef ENABLE_AM_FIX - MENU_AM_FIX, -#endif #ifdef ENABLE_NOAA MENU_NOAA_S, #endif diff --git a/utils/main.cpp b/utils/main.cpp index ec5d917a..960d8bc0 100644 --- a/utils/main.cpp +++ b/utils/main.cpp @@ -234,25 +234,6 @@ void create_gain_table(const char *filename) // *************************** // save the table to a file -/* - typedef struct - { - #if 1 - // bitfields take up less flash bytes - uint8_t lna_short:2; // 0 ~ 3 - uint8_t lna:3; // 0 ~ 7 - uint8_t mixer:2; // 0 ~ 3 - uint8_t pga:3; // 0 ~ 7 - #else - uint8_t lna_short; // 0 ~ 3 - uint8_t lna; // 0 ~ 7 - uint8_t mixer; // 0 ~ 3 - uint8_t pga; // 0 ~ 7 - #endif - } t_am_fix_gain_table; - //} __attribute__((packed)) t_am_fix_gain_table; -*/ - FILE *file = fopen(filename, "w"); if (file == NULL) return; From 2c268a50b50c9f1855c391cfce50c64ae20ee912 Mon Sep 17 00:00:00 2001 From: Nunu Date: Sun, 7 Jan 2024 15:29:59 +0100 Subject: [PATCH 6/7] Added RxAGC MENU item. --- app/menu.c | 15 +++++++++++++++ board.c | 5 +++-- docs/UV K5 EEPROM.xlsx | Bin 68563 -> 68605 bytes settings.c | 10 ++++++---- settings.h | 8 ++++++++ ui/menu.c | 12 ++++++++++++ ui/menu.h | 4 +++- 7 files changed, 47 insertions(+), 7 deletions(-) diff --git a/app/menu.c b/app/menu.c index 7d68daf6..89c54b6c 100644 --- a/app/menu.c +++ b/app/menu.c @@ -250,6 +250,11 @@ int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax) *pMax = ARRAY_SIZE(gModulationStr) - 1; break; + case MENU_RX_AGC: + *pMin = 0; + *pMax = ARRAY_SIZE(gSubMenu_RX_AGC) - 1; + break; + case MENU_SCR: *pMin = 0; *pMax = ARRAY_SIZE(gSubMenu_SCRAMBLER) - 1; @@ -707,6 +712,12 @@ void MENU_AcceptSetting(void) gRequestSaveChannel = 1; return; + case MENU_RX_AGC: + gEeprom.RX_AGC = gSubMenuSelection; + gVfoConfigureMode = VFO_CONFIGURE_RELOAD; + gFlagResetVfos = true; + break; + #ifdef ENABLE_NOAA case MENU_NOAA_S: gEeprom.NOAA_AUTO_SCAN = gSubMenuSelection; @@ -1059,6 +1070,10 @@ void MENU_ShowCurrentSetting(void) gSubMenuSelection = gTxVfo->Modulation; break; + case MENU_RX_AGC: + gSubMenuSelection = gEeprom.RX_AGC; + break; + #ifdef ENABLE_NOAA case MENU_NOAA_S: gSubMenuSelection = gEeprom.NOAA_AUTO_SCAN; diff --git a/board.c b/board.c index c775c839..f1c24253 100644 --- a/board.c +++ b/board.c @@ -605,10 +605,11 @@ void BOARD_EEPROM_Init(void) memmove(&gEeprom.POWER_ON_PASSWORD, Data, 4); // 0EA0..0EA7 + EEPROM_ReadBuffer(0x0EA0, Data, 8); #ifdef ENABLE_VOX - EEPROM_ReadBuffer(0x0EA0, Data, 8); gEeprom.VOX_DELAY = (Data[0] < 11) ? Data[0] : 4; #endif + gEeprom.RX_AGC = (Data[1] < RX_AGC_LEN) ? Data[1] : RX_AGC_SLOW; // 0EA8..0EAF EEPROM_ReadBuffer(0x0EA8, Data, 8); @@ -619,7 +620,7 @@ void BOARD_EEPROM_Init(void) gEeprom.REPEATER_TAIL_TONE_ELIMINATION = (Data[2] < 11) ? Data[2] : 0; gEeprom.TX_VFO = (Data[3] < 2) ? Data[3] : 0; gEeprom.BATTERY_TYPE = (Data[4] < BATTERY_TYPE_UNKNOWN) ? Data[4] : BATTERY_TYPE_1600_MAH; - + // 0ED0..0ED7 EEPROM_ReadBuffer(0x0ED0, Data, 8); gEeprom.DTMF_SIDE_TONE = (Data[0] < 2) ? Data[0] : true; diff --git a/docs/UV K5 EEPROM.xlsx b/docs/UV K5 EEPROM.xlsx index 5c2ffb4c47c440eafc06e7cdc248de1f8cb109a7..c037c5f19cb6caa722623ff8158e3807044d0456 100644 GIT binary patch literal 68605 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 delta 26816 zcmbrm2_RJK{|B7Pl0Dnlmv&jknzB~btXWDoG)37;Qe<~pxsmlGBqp*%MN(0gNkT!7GxI)Y>fUD5@Av-R|9kK4%y~Y~cVC|KoM)y>PFmZXw3d6n*_yQitJv7s zR&70zW?#g;k!dY*Q>@OUv6^-VpIIXXHO8dw6bPNPm+mf!i_17>c<+VXU*l#6p4#R$ zc}j_&`TKy&#{MV!aFvzGyl>izRa0Va-Q$hE5F9e0Bd*9Dzcs8vE{`A>b?eNtGh5N2 zZB_F9yN=boBKwvtyG&?4HIO&Hp;~^1Sb83_75(+_ge;}B>X7F4HTO{yM(;+g@b`-$ zE=6l{f_<{=@%M(;vNQ#++S{+bTh3y$uOe?U;>b0&b8xa({R!EVTl*chBwkniHr%E6 zoIPB%t#QOAT}~Eq31`kMNP2xFRr*@nZ3)7a0`5&d@&7id#Prnm9Y6 zA$CP%dy(Y45pP;RwCP@==Dj?zO`d*@nhubygS}E~pvfzVEf3JMbPx_kNrp-d9@+@!9FPz8Zal7OX_}y~-LcOlIw!*#Iw3Z9gSaGWqH?DRva$2O)n^Y(>mJ-`TD(iyKehV{aM?mXWIV$ z)DDgB^hOqvh9I==w%_Hay`{;==LX;Hu3Zj;ki_=-Xrz zaq&Yq$Ba{U_@I189*66ZeJX4tV}26X{AboAnLuvVw<_1!b>$y*+i)z<_Rz68Bi{Le zo9KP4a;f>2;rfB|%tNg4VhM7d-dQCM*qsAXp|@_2+1@9#+zTt6Y{}p%FmCV_a9MwD zzF0j{q~^M_k@DT-bFUjNnJwkqwoo*E|2?zC9KFwCHmW9o+~!YK=?RX-ntuq5?Rhw9 zI>`|PWzL@r&Xa225q#TAZ!!k+^rQxU;MTxUKRM^b_6s%H!Sl10!7b>C#>YLC?{oUE z%-3sq`Ho+g9rsrrAJV@b3 zTc_us!`{uumKw^;OalMPtX_Eg{sQlzbsumPNCJ`-kK4P^LvF3>=gR(a(KD_@AC{+s zYr5t5Cv}9TSX!(znGDgh67NqXDYij<7;X+FB=bh)|Siib{D?RR+?=ooMsfzIsVBRC#A#P!N_fpHCgYZ(N zLaK$B64c-qbHA2{*b!DTE^!u;YM&Shm2fVz3Ep}sH?{xN(h;!cR=ROQ`$G%A_q?Tihv7KFEPrH@_zJ~p6m3jVLS%rgF7-{-jSIA7} z&TI1#1B0iZcc1Q%vZ{PSg4+ry^Jj5-23^^y6LxAci6r$5+hIY( zgmq0!Bt=Z%yS#HrR%Pb{OQ`M7B1m(2vHfR)aE@Md2)Sne-zImcJk3R7LsaA&8@Q1Yqw(S-{&|PJJ0zQNyI4JJca7) zZ+A}fFX9(>*kp{-swpxw@+(pmcgQ-1(&}yB;9u6hD@K8@GRmp9J=4^;$n1lJbzfPp zAWwm6@nDso=ML@C5AWCW6u{>iE{}b`J=LqC1EuY$JrSl^&~LfrUjN>SUDfq(XhYn>6dy=KgR~-wv~4K0lA&~GR8R&G~pM1R)?sm|2#c7EyEFSXi2Pkp1u_s zZ&lIPX(Jf8-Wv)^f5SN!jvizL9P#`q8R=tz8&q4)K{_bCH@Z992zE5`Q6M<|KVIH( zT9l^es_63<3}uSW0d;P)`;>-{ua!LGMQ)wZ!5 z9=V{*?(lq=(;fzTB$4qt9>ikSlnhxI!yyS}#>`i7Ri6XHHiDz8`@1>qB#~Qy74h{y zUQkgb9O*tf=;Pt8j(Cog43Rd%URU?px$-!XTff1srDEGv)%t^uyy1LbnjU383*1OT zY(Os1uiKw@D*9{M2sWip*$xr|V)m)i|Bb~^b6 zTPq!M@`bFG0>G^GX{9n~nEURR-t&zLM$fAzGJ~(5y<9oA8&7ucH0poJAYk?~#^OQk09Xx@}q?@AEs?5GUHXBDt&d^!G z1J)H^zKq~^dm6kQc4&%mF+6wHk9#&DWnlqzq zMaXb()P@Yh_>Y+;9@be;w%M3c1&E=yMsB!jW~W$s{t4hXt4wA}wN@&7mK`DwJIcB#;5?o(or6~3#uln*vTh7D!Mu6{YH{*Z+f&LNe>vhJ;=~6WT z7Xe3%g}>g0XwM~5kZVpc=HTHRAR`(l33|-^q5s*mVrm14{J#THpA*VBrk^z+AsZ~w!>%Nu9 zoeAu%%B+SBBaEZC@j?=kikjL^z5(UKQz4CgOn0mKjf{=1OC;953~Xnv8@M{1VuT|01bYczMPs6@KDruHe{fR5p*(#F2PyVYxqBeurGTo(`C&Xnqf5>H}H zx6;(U<9mGX;y63dJ~ce`t+B81ZgsJ7L_{pNm6U{}o~AbB8?b6*YHd^e`s2Vs*~v?Y zf2I+vH)G7@fB3gSBHbWJ<=S`KT)pRR^3aPNTTxQCR9Cfr{}Q{uP+z@yW}_Wpo!(yc zlM@^5&QocElq*~$}E^X|h~(ePS| zsL+i|3p-yH9*R3gwhnb^d_0nwbIWq`@OP=n+U7y?S04%o`6g!a^D{@gmbc$hZ_W07 z+X>B^sdaTz99E+Xx{ZtV4n}mws)Tfeoo>5jht+6&(DmIuqIIaXFUr@#N!>el$os=! zW6cb{IjYsj!6U0;WI31kb;}@O`aQn!!C`mwVQlQ_c52$e{pY;q+A8X)qd_5yhYP|Q z{dSdgJsrzr;)Ey^j$unvVFhMhl48CUdKB;^}Z(+4%~m?h%yv!7_564{=G| zt)6TgaE&Rna+fcp@O0t~*dN+Q43B$0>?3X9o0PIo8j><1M7@nT7d_#P&u!+3-hPQ} z^t#MD?Kl=)8#G*Jfh#i#PWih8E$I?l5ccADV@>hM_nO&|9g{5!Z3ESZ`IkPo81_T& zXOf=2nd2_t-cjkS?sLmRr!$XKKC_2EyC6L7T)%Ouojts+SH`j|*`FnL=eTpX zsP;FtNiNB=w=`IJcD*mV9C3Sayh`7aKYuPQh}5>97cT!?Byc~5 zv^$Yp)ow`2w07h=F(Sc7v!9%C{Pu?cXd8n68LqzH;cPV8Fje_X_;JTn(=*|wj;Xt2J4N!sOU%AEne}lOK0Q7n+kuFnBQ>|dt=%ki5CoPxk!G#E>R z-D&VG1b#?^3;%);@>4WC6~V`8IPR}w06udNvE;VkO^m71c@&t`ak~msG}9*ikjW=$ zf&dPs!TmHikOrqCa0Lw}(BM!Sj74CwTQ(4~=CB9QaPc4{3Z&dgyovp!d_L)B4{`-G zPVNYe7>y?4ARtl8OayQm4VI(9Q8f520(a41EgBqqPy|qC9RRR|MQ` z12?5yRL|RkNiW(Y<}ifJCL^=HISA838tzSFx=n*~5qO*iLx;Tp^__!AaPPGOSi$ot zP!UUmvuJQ00(*Hr9hjE5-i1uwrA_7`lTY%I$qLV>eIk+{?;ngJXGTOqFM9M1$rE?D z0ya3eoYIIG7~d1-n19k>T^OHJD9fFb26Lf&PQkvAl#@XB*2bq1WMZS?djN&%TsUd) z9GNrQE#+j_v9+<)-@MdF;4>i7SU=ln7>W@2Up#5x5&CXR+Jnpox?F|D2X3_F_W8Yt zJiDY;{=web6dMk;t&@8<**vA`V)!;p^hnNklN*bY`EC6sVQlxs-cBz1Y_t{)zIX4O zj-9|m$?eQG;Y-wRK**p0f-o)Erz>OV~`7`kk`a7A#{rC=5-VeJ!B*Q?fC9^yQr z6p;6dw3-*E%gr43c=hfx_}+Dwb2-zM1CCDJuHs-p9|*v#`kHZc+lA{0tHGamV}m%( zvmbh7`|?uSYN77}kB;VEVAf)mZr29#B*Gf`H7pj-Za}jw# z0t+!H+^(>?D2!TVAG$Y8k@nw*-Z139Hz?)l`J>~|QBMi;hnMsGl%8_ue5z{EOg_wN zI~L$s)A{^qMBbdzQ^}l9)h$8Ehk0zrj(O^sKdj3;&;vVeReHM4+-tRM>dTfbbhp}1 zze>z#Ud^*O=4qSUA&|3!?sgzga5A(_#N3O;Hnpn7Rp}}17W#Q_^)SG`j9cj`Q_hZ; zEiB0$t8B%Ndag0|x{${Ogpx;t0(U+sLw8xnR;fc1{-uK@WbU@*;-0=+QuA7l^CkI{ z*D;P2{*B8nL}K0ek|kLli^&en!WTB_ejc*-keVXge}Z3JJkU``Uf%xxGj)0U=OR7p z$w6JnVYlkIUYY6g*%l|k)OXuFr_=NIt49f=ANSpzR(WVcJ)3ecA9`+nzZK`0BY3iy^jJ^6t?_sp zh4S(A=`xNI$o+Fifz(9j@cXk*)sHeVJ5I@)jU7binBo2LSiHI*0NfOw}K!TKY6W~ZLM{J>4l(7KAWiBU#{y|a22_H zZq6YG-_GKCIPBH^RU^G9>hlrxD((mHL&bf3HJetwcaZUON+@a7F5h}lKZp6`VXn=) zE^I6w&FS4T^zf>Er|6??Rm{33Ww%okPVrh;=Jkv1Z!ql6s3<-C(0MrHVcs!lIihuU z^Ulh<>~ZVDug_o1Na1^{Y%?X>bjnM0Et_Qq6SJsUg zsnTOFx|hgycdAPUj;7oTBXFH7o$`jB+?1B&(d}pV|6))O-E2X9YsbPf*l#Wu1$84Fx%^j5*^)VI*PYL5aF3YkNF3hXb{ zePipqC&eQ*BzXLyTfoKow?-+)PT`UcIOw?fuki}%Lm6x;cAn9^cVuw$X5u6Mz~G`= z7DJ^bK9UP<+nzsvN1@eZKC0*MB@l>PAVmAkIO)I7f`z18ete%bA)WE_q#E8J4{d4- z+%imFW)~$Y9CURowy^0GP+1m|46|MGi`bGO^l;CmHM^T;mzQJ(`tHpVZhMX;PG;p+ zzA-nb$W5-p@aRz&dMG`(5Na89VWJL8S+2%VM~GI`sXii(G*JjG_gO)dG3r8Y57GNA z^qfNR*CQ{FW2m#^M7`y?G6-5CQ|))RwuSK;p(q3fU@*6l7&w*^Qwr*GWMOBM}gJQHruq zjR_++E*FL@R@V>W2xw?oZ?TFpGagGN^ibz9x}klz(4|SCFcl-}}4b5A`kj6}BT30*42g_86tNlBAo6V&-dJQPOCSX?_MMeV~< zr+ILd3*ZBUcUFip(?%(i!jamLaFS;+Nx3{y>0u&E+N#ToWz^-7E-JYUOBs)#n(LDP zrc%fyz`JSH96ib+WHo@LE_H1sFV;a+!7?cdAyujpuUmn_zM7-(+?>>{@Q_qIM7$;)8^Q`X;^o7rUSkA~_coLW%G0%$=MfQfu{2g22N+Wgg_J4usbqOEF5^?k z+zP|R+ zir4h%usm*gyM+Haf6}-?-)lcDAOEi>AT4X7?xJ3cPy?e&{!b&Xuk}7DA+oN!ZHo$D zd6C!gO#yCYN;{~0uN>Gy+4R|5*lgL(vDIrWROfDcSh0hurQ+w=pj?7zA{;^UQ%;U6U!)B$a0 zmre66gL6lZ=U>8D>86_>m>PSlk*jn-=F47_y(ao^_P){Iwzo85fA|zz273l~#<~oy z46Unq?0pJXbg#%1)-`m#e{o#)`?-krDv6p|Z z*j|5bTS3M^F3RP-_@0&@mB$V_;F9yFO6JV|yEjg+?5;w;qKCM%XqsOD-0{qR)$^$^ zXZx}jSu|(+6$iF`Y#wZXu?4ajvJrXT@k+|r$+XC*$vlzqZ3DiRU;P-NbVVs#>8eu1 zBS&09eo}?)+}?cdKJPJf)+jIK8HMjZ3V~=+(7@LKjtrh-Y{xi{u^;0;76=SU*Zm&W zN4)%;9l}ukT=^eNq2_yB!_0)v>hoBfHq8@QVBVma|l#za*e$esV zM#uNM9uGu!z8vpSGbmV$z`dht7O!($C|mYc#jHlXK_znNV863-VX4MW=% zIQGSJzKvh~eB{6Rs4T{b~xmyNW4mVqQZ zt)N8jgq$Ly(e8?&3^AHgRA30{Hncp0lNhuDqjW*|K3aH%2x)i%&9wp(fu)p07<|`P zLNkaCRZ^k1^tqBUgC%oHq4b(Vlo`37fiZn8Oo1_d^0%v~GDOy0MV-N#dn(HG+WS=) z<0P%B#K7*Ls>r~8LzOWT4Pc(WSeVt&^x}2Z7;7Z}jOk19v6?cyv*T)t49;v(S7snz zze7rlJ4V;IgVi!dH^ROb1AcfSO;-ftYSM7II`;}0GVr`Q?+Q7LR-5i%u=?^2Myo5p znBMC3I|N`34GDV7`!u9Q_B17#kY4UF)}l{eNsaP*4oKv za;}CH?6;GLA=t4y8O(mOlhN$eyBN*Z-o+4X|6Pn)AMIi^@}ibNf~GjVo&LL|VIxh( z@IKll17FZ&w3Wum0l&~>G`B^Q!CWpaMstn9m_EuEwHO#<+x#*a>MMZZ<6VV4BTfZ4y*4GT!~3o#Vdwazii9%678yKui3338&B_%vYj}b zzh^y%&Gr*Eih@l}+p{C!cu#To>mI%p8Wq{|ZtQz*XX2lCLlX8e6^Cv23Nb<`IC8HT zgYA#@qUnQ;w~>HZ^aU8X#Nplgf(%hbYzp}UR;vHIom2WN?G%S)4fuXn!7O|-G_512 z(doJqr!UM$AN4Q;#w>&xpx{OWQHDrzS&GAahWzy2pbbGWtO#4Up#Vcd!wkgXD#MjY zSrJMJc!$w?25o(Y(!$d-V=X(PC!D`K-$}h;!Vr52IQMr3xF2Bj#YHtzUXcuO*xs1$ zH~Zp@1y(2*hwF`3+AI#Unh5;n?^BbN#R``16*2i=XtwR+XG|FicHAe1@A?7rVk z#qQ(glRYJUB>VR$p-g}G!q#*}{rzrmttlUaW~8&I09)CWJIz+qnY0M2zjD0dV6S4W zBFl??*BILq1!tM9Y!7kR(VT1j=RZ)3!_wx03@UeKGO0!}t(4F7I(Y1r6;>$emH zTQFMxztc&eM?oh|`oRC&SQ0KhAjII%=L3oi&hQ;nq>qW|LB=Ax491KqCE<>P>**sqcTkl< z;-kIdu$8?4y;LMTk@kZ0T*$Mt#$Jd)IP%C_eQ0GNiNo55RzBXOn9up52t+vakT|5K zDVQE~yC(M%L?tZPJqn6KE|b%Fy%p$w+p1vd-&V|%p@LZUZjz?1U^&quWP8A5=dfMC zL5C7cubcUXf-Pp3)l6YEv-oJC z4$;f-N*X0l$dkq7$+!5gWX-3c)z8oJrD=wnscZVNCwcmgiYvAbw`_LIZ_GPcYIoNb z-3Pq9O1y)b&dWWMXOx>>oh_QCc?BWoM92jY@?8kI8A9H6CQsKPM&H{8ZOPTN&7w(O zL5%(8C}m)wcwj-ce9w5l=F`CH>dvUjYri||V!IUyYXeZ|bO?l14mdaW$|l7YjUUZ$Lst&N#W;)cKeRL0|F`@*=@A# zJJ7ia@F~iBeYLeh0;Foz+PVGCiimb@Pp^3RRp7`|GA*R={Pip(4&`@0T)Q&Z4`;u3nYv-2x$in#!G~bl*VEa<0{(J_xup)W znl)XfMR`;CUP4&d+DRDJc4AjV2-@ue_B;lWFl#MKyu;89lLv$5PiLPCXq^XT0SXaT zbQ0$IM`lgVtNYK03-C542?$a9F_ob+sa>Y{?uWkIg&kpzxzD_J`peN63a4c!4n|t~ zl-T%2mL+D|et9VHk3h1fUy#3pHhAI5OYqE#Kb+^_QM{>Kj*TvJ3GLK^J8qNgnh{A~ z^a^Y--Cf>U_9I&$`sb3}zNalF4_h8Sxt8w#eD}Y_=q^@KP4Ry&US2;SKEG3{Ew9=& z5{iaWmlA5*IjTK}207pb4v&t2V?vM&F>(6U2Fl*~&E=1-%F# zJQL07aIXdBI*oc9JapA?`Ks>$nryA&fMbF{=x4&KEtI_lE(9R^eZo`$*FCyL#hF^R zgS-2w4|jc4>{!eEwVW~kSo1D?#Bu^YkevQ$8qpo-)*$^WvAo|-xO$iTZV<#&F8f0l!ua7-jF@c!A4o!&o}kbj;&2-~$43?2 zngf}`0`}K3Z7JUSPDS1~Xq1KeBQ1OqhkGTsR%Tp+ixmhy_h}j_mae3oe(N|sw!yL( zF=#sF*{}fCBgzuoU~+d*i%~WT>NawIa$cVjO2mI9Y1<()QqS2lQ#UVjxZQqen~Jmg zurtca$A3R4mdl`6BtWrD+yNEM3MyJ_8>r|#tk{&Z>qxDnq&$C|_|hr9dxuA6DD@FF zr^qKpyI!r!OMH>I1LCL?TSZ^mx5?hCb_T3@x%oi_5`oeyPl+01EhMw2AOCsr{;HSX zR_bi)JJ~4vf;cSDrKRWj)8Yg#4EJ1{Ii)`dV?7Q6gz+>Qy!ZbhI$TRzNw#Dv;M>2k`Kx=)eqjTG)ESFl6y{VsY ziz;)9cXU0aejblx>Ujp>2fOHP=vdogBlv5{Kx{Yw#oo+MnwsbU-9w%CCa0opCs&U) z6Eh5Gub$4?@4b`yqF)jh1h5}tEPcEW`9@l~8|N-uIsebie4*_mG^TU-$XfDnB-~VEyNm=7o!lq;)Jv!;WZe zr~Z;We~;NGZVdjyi!Rd8@|AkoCd$IPB-{3y@)g_ae*!}ExI({o0|7ZWD&Uc=-8dkS z7X+@y<(U7Ni^LrsPcB{hm5R7pvfMq}tV=T^3ArYP{mq-LjzRS^f6gPq>&?hZ%CXJz zX4gw6f-cF4cWRJ51+93ir|aB%Z8?$?y_> z;)INy!2);yTih)Z?v!GD3H$e9x9{#a58d-uZK8*Ad&9WZf((Hc?Fr`(Im%fpPaCAA z`&`(;&N)>rJXUsrR(~BeyBV~DH(SYE6BNJh@YkOv{NX)NT=Mn?C-a4SH-75+!|@Ml zYe&v>IfObF8Zp@EA$@J-*2Fuar^XDmw|{ESC~d&DKpvZB_-9#}*?8vf&XmH5Ua zP^^;oXFxkx zP<>?LPpWDCI!?uRrX8<~KDDk)qKW_HW4T?Uq8r{V@_eg_q;Al6?QAjJK~%BA9o80F zZ!C3N5#AjlwB9YV<~3&j0zp&Ia-&0oo1-*5l`jO7{RDYvGll=mpNPlRzk z)2fZm%e6Iln8{Cp6K@c84YzZ8$Zz{?BUm~>Q8>k2dAej1rQDLaSs3d7T1d4dD@Q*Q z-Ujo=3BoT=^Kt3&D{P@`Xu!7Roe}MV;{p^oX{xf95F_rwM?j}B6r?OxrB=CIT2Zr1x@qoGUgHQ1zFv|H zJnsQV3e$mtva@w+raes?9yV8%r`0+9nLz?k>#YBrFzF*)Ek&sxw&~*2zFP-o>qP$3^zuh;0YfA?vm@d z)Ab5l8l5Y@IJ+yu)A@oMQOwOIQSm|^;K7!}J;J%|R&A$41J3)c+KZY^hZ~X{I2DZG zJ%Pgi&5*M{4cWkG$Qe=WgtxNQH6cQc5aEWqGUk-B6|8hxWaI3R+Fr&8Ls5aCfY8s9 zbAeyZQGt))-g9UUDZub7xe)mPd^V0SFn!Wn84na~eU|J7NckNa&i!b( zEhzG?=#M2&OzuC~SLSQtw!2ZSyT>`*OBrKz>K6wmER&3aX~bbf`w&q(6ZX>G`UF0)3v3`tNiXhKEU^t>m0 z$Df&fSEKWhFGwrYAWjLt@(6j3t0@O$91aa;nKk8)YRX?Tf0co&yalBjvCV9uW>HT} zQ=gbc__7FC^ph0^Hv<9f&PRZRtMDU#6>hm7e2@R-+XTYNvK~nM^9&cm47}S*o;}GR zD$oyULVM7J%It-wl|ej4gZWfHWYjAG?^kqNT>DZBp?UPD*3Zi-+Kx15`T206|Ft}9exxx z?`eL%(@}v-)0fo;yMzgN<@sb{=^psyS>ertjiPH5nznm2DM~bn>{p8=wk7+YY|y)0 zyMb^zW^qV3wISG1hW6z8n6P$3>_xhjr;ZfdP^L48-Q$uNsPSg`+;ykHt_|=@Z{dxx zLL% zc0}9;@Rw;A#l0(cIFTNv{T!csg0gE+*Ch!wo``fACta6oclVs=9#^4q-XdK;Hi&hZ zP`wHFMT$x{?Eck4@B7Io2D?-U_&Y$7D@{@=B589couoePurEEXx~EjBoT8+L2p=Hp zyQ-8A901mGp-rTqT@XL#9*L@D%((0Dp<@O!E z7$?VM3=2dn!)I_2cC#iV3z`XUv=S8RWyvbEGzJ#e~279sM_jwq}@%| zHgxbR7{FCv53nOjfEx>FU+EH30P%NKEPU)Tn&Zf48d>5GG6imglM&)!fSPrY%)#$t z_&7pxmKyGp%=7W(FJSy-Wfni|zPS{8SSD7HDFxmitIXF3az&H=9`U97%MV}J-2lgP zeAZG!Dl8E#$L9xO7ft6u@|Iv~^=B{Z>TM8|bObM%1+xxl8tk z4&q#(20#O6_z1$9e+zK+GzI!1ZdwsVfCTW+l+kW-quU(~PS5Lt-H~Q2&HE8ueQZ4J za}EWs{+pjW)NF9N9!YWK7q?;HNWP#HikV=7rQgleb&|ktW<>i1lK3RJFaph~kYH%3)4aM(3*ux0tJEwO>1B+&CIxj>XN7HnBS zs^NlbylZO?(4Md;q*(d2H!n3b^8hLXY~WIrE&&{*(slv(D?+?ChE=Wf+TGImLI+1! zNe%GNVq@VjolVIF>At2*n1%O*gB{Fu7H*mxVu}HF(JkYcBzz%Gp2s#5zpU!f-~v7f zP{ZAS*x{7O7py?E)pu3k-(`9DWt0j0KI$Hm8&XPe*7fnV9HfS*f614lP2dmFTChQk z*V@*fHF@`a3=>mr@rPJRrqzM|py5w3U4tFsPx5R|uPCu|SqzA#icNvvRKnBu1Yxx( zf%V?<-g&h%)3w?;qV;uJ1a}u?-Gh%M2y*sc4m4N48EZAzSi2f*JWv~AcL*`AzD4EP zfC)uN_LRr!B^!%zAa$@oyW`NEU%TYNX-e(PO+fJdJ)&r_0ZhX$uZgS%LZ{>T*+CJh z-vmYUgIW4NFoPnhof*+}`PVv*=Fly3BFTVJZw<1*$i$vUF&bA^p8cXemt;Pws)U(P z4P$|&qeW!Alt2D@K>$m1RG`_@WHd3Q#qB7l#bwTa)>tkS`w)1%>JrjHA$?b!{83es zKWpGHr~%@S>an7glK-#8nfH$zpla446Y#Se;~ar6{q-hS>tub;#KQ%Ns!V$D*F+8G zbGegY-LT|Mb!kdf4}N*F9b3$b(CE4GY|pa!c}xqw@myX5-%b`bvee}p|F(DyuR)zW zq!g@-P#&FkUO|Z*bfcJy-L}#{Tq{UgZ;dlyZM|vY1^C9zO_Bz5>2jT>U7+nOT9XCYjq^`xH>&G?7ySq~MhlD2 zgPUI|EB1%l7EJu2x4x*2a9RT&jTaSjT0{2=H9s*aDwS6-ZP2#x=;Ur%kzpyf4k)8TgTh-HtMX~3(hX2`27qilDrr&q}BpUgb2nFMl_`zS%!3|TEaMVyebkNfD z(4AwkS5B;}=RdgVf%zf7zZS&D&fRbt1?#x-rDfIrVi=Xb!7Wq%?pJ`|H-xl~C*1DlRUn5~E z5rxB-E!P)qMP^iynXAamJBi2XKaZ~ohE>Sm*G{Y}gEaQpEkC^m;{%Q!5YY;(BQ8>3 z)@OVxvO>h5{I~hZQ_jBm3QMF4L&uq~{5TFCjJl)+2ER6?FZ7A_FY$KFvz;F({_;yQ z1TVJ{7cB6x2tBcX^w6?}K8Uc64~RiJ5(6|cV~;2hL+nh`I{uzs@_RE< zG0=Ro`hz8@S+Su$5jJ&SdnD4y1MU2@ASm7zg=Fr_|2)~n2z&tpy55j@fqNI0lYeUY zzBzQHE>lXS=WMdJ5Ou@5y8mhyh+h@R59u5CUr9f|Z$a_{2LGmqeez=)*>6$qKoUfL zXao|p9EVwcXf)ztH7#K(6&y3Uf2rLpB%-PANWaz%-Fcy&jM*aM0(W+7=xhINq2E<2 z^+#MV(-KRM6ZC(4$v`lKx@CqPe)ZWfcNgX@jxTY!#)?XwJhY%6qjzs^4EFaC&_LhQ7 z6(X6^Kr*F;NWY9!)LSGXU%9hmYGj`+(&}y5=dI;vHbnc~0GfRw4lhf$-3LX6wOugP z&Yj{z&0yP#h9erzv5&ZD=f>&Q{^{nei%;Z3>e=f<0!?)RmVNa@0(70RczZQNR;jzL z7QQ~mj`oqE20{{1VQ>DsSjs9;z$W0*~FS2 z?ptBm)Uaud@Eptt6uanPz}Z~r3r%Z8ZNZ2nb;Iw{c0jAHYb_Px#0fpjB;S`OQ1%SJKyW%ydgTaey+!Ude|SEMHJ~ zj=45P{#x=ahfdTt)dWa4H&`42BzF)=@Mggq7;{rM{(&;^wXoJ@4N2z^c!xm5UC zbuBuKqtkxFS=@pGbZUg=_772k4L^()4~{nTo=f^M6NNR3(ERzkAh4vOb4JqQ3N#W|CZ{LqXv!R4xx33c*m$%2%SnD&CVcTeOn`{0Db9 z@uTdgxqduu;oTBYqK6(tgwLd<#9}@Jf<`Whkb#9Hdm|0snM4qct~(WU z=VV>cot^q5@J`Y7H+BdYb5-x^LS768yiN6=-h>f>C^hzjC^9j&Z147L(|qa-?iDpA zBM(SLH)vas(S;!=20cchzyUE>Cqo1ZHFMPs6aR*+O|q}C#+1o+DOGI9iRH!6AEr*0 zO(mXKN}Mj1N-TUpoq4yg%MkOKGLVS>61|W}HmriyG}eHhG@;pD(-jqe)t4Hf#2@^{ z+=P^&T?u1{N++kq-(q5(Z`~UE>kpx`GTT%?A03&qD{NvEyq0}g)A0=H(;VuJX@WvC z*f%7duZ&^#zsy1>*jMAUcQ2>}|BYd6!$W@GaZ;b)s(UDDWMemboGufe%PO{lOngYE zIu2@FHAA*gn?bXFzWd(v*HijKcQe^*UbfY>KcYA6NFC+2&X4WXrbe)7U9p`?BgnSy z>fb5{9&(pH_tQiM3W+wPzvun+JaM0&@D8`ia~0MrAi+oPN{iy?wgg~HMjn@K?OD({ z(pGd7J`yi3DZ$CWJ9*S9k6Q?O)C$z0dz)>)tPL}Tr*dT3 zIzQMh6Q}gD;g|W_SqEe(TI1Lz5D;0m9n%6-@|@KO9REO;H6kFATCkK0$LDY1e6=gM z61Pjc4nmV{;bR5cSyAczxXTn-cp_hx&3hewx<`Y01D*sT{4WnJOx}ckC=#nWw@iFP zQzXaq8II3UV8X+=97Q-V`zjmz(Dwm~d^CSO6YK3_A}RP~860;{0TzB34&!rK zij^PmG9eoJfreu=4I>5Ca8EvGaq~l7rVSsd_|(vi*P_?%=3Q=zcPx06aZ$vbOpS0{ zTd`;9OtVLB1&r@kD1P+KnF;pp;DU7r?AWsPNP#%k<#t%9T%PIwa^1q2fDNS(gLoD+ zQYhx|`s%Il^O|9JdrcYJ4a)a6l1^_Dto%;CIPmEXCivwW7TEl$-P-+2#XZGbC9X{H zou@1?Z^;3+5j>^5XAOmBLGkM6fEHhR7_lw@#~Om5a;yJ;eQaTC!jeOQr{FxgL%#T0 zIijJK1$HdAV>5;37sGfKo**+!|Cj3)R$yolFcfBbCJ(z6ZUds3|F56LZiSE5Fky;? zi=VD%A{KvmeS^oC+EZ3B-tObLPBct#508@5`uMW^XGg`7-x3x>%KMWyUvp0p*!Dtf zI2Y^a;PN(wn%_B_ILrLz>k&>EclLzDurI!#hqe4HoH2!lod)IC#t^@U!Av9qY&A5; zEiv(#JTepdvfoT{QsgbXXKE|Fel)e1XJiM{n(6eE;`L)!nP8r=W2`a6h9fwhNAN|0 zQnBK=H4}Vch#4k-cVaDfn^+3H&=234Ll>ha!Ni#{7ILhd>H9vtc9tn z_h-gI7LI#PaR`8a1)~I_1kD7@1nULr1?2?f1n&#n7d$C&QgBRQOi)ZfOfXd-RnS4e zL9jDso+P*&3-yGB1(SqA7UuiBp~bq+Hf;BD2_|gO3#UO{F2~4uQ^yv2mdgsg^(Kg~ zDIX6nihP&|b59%W=6RUAI36*dvq<0>FCIkeJwe~XQ9f3BhEX#rPM%H=Ylo;U{KZ(| zx#QH2M&uS(YP%8niz~I)i2Ti!I&4J#?n<39BF{pu)CD8*va8eu>#axU*9-fxoX1`~ z;C7TKa>$S6U|4^vNP8&D!L*BAZb$$7ZKqpri%4lGi)GqHa68+HZo|;-=)gbRmWbkC z+Pd|Qt4_6u1duqj{aCtn*H}?icT;%x!|`O{wa66QNEU#5$Sly8d66%(dg}&a_xiDv zgtBP->53tDvnq`?l$fWY2EOo6Ra|f?qemN6f4e%&daYI{TD# zMrvj^y`9a{Xod}%;UgASP=bZklB4AG!Vw+a8Eb6)M(G~eH^zG_o8w~t4*7p7yY`@_ z&MeMV9t)vv%P7dz5lgVPgUYrNEAq&6N7E=GS}hoaWZHdXB4xASP~bvx+p23V&BTzE zD+*jSl{ZGknuQReQWvubnGj;2DG9p~17t#Y`Y=Y%hr=zgHWuQ#IISlhsiaUDC~no0n7HU z&n=)E-T4W-c=Rij67{rpG}P;$>`Fm03gW17!?eaEFTUv^Q;2(ex?7wlZD(kG^q}f!acvhk99w|yf5uYGd6x#Yo zQU9PMZXYEiFJjxVNz5NC8>beT4;Mpijq>q1*hP&HI=4{G2_>l{Cf|= zkakv9c%!USFU|QC>eIAM>t;_0^glw@yqSV_=go_+)QQwV$w_8NN%SmJQ2)qHi)XfS zYZbJc=(>`eS?0xhjhjYfc5?5*8ALRD&6U#4%xm0e1+4?!Qc{Z)hXK(ArmjWTT~E|w zS_`_bB-+e8Uw^|r?sxrVG4`(Xn1a@hTI7dZ*d_hLoV>Bw?O&vKXP&hFx#a0A)58}U zh(Dg)nNn!)@(n1Mxv43_t{k!st{28Rhr6oks`UzFcopz=KoG(lj^nx0XaS;J1#Au= z(P0kP?ZpZ3(*y0H*51PT^6|+A$s3!* z8+w=e9vIK!gLjwrmRu!!N=KxJtOZ-M%(kY|kT&Z_i9Yv-74)EYdJfRiC|y@VhIKa%i@i#GP6xzs^lYI29kIo z7*F&q+!-QEqcca4`@uj;sJmR1iB=<51AzhGOYyr9AaspyA>x-*>-}{4H)_K-!rD+E zC3vYk{VN43)8J?NBm{^%X6^lhr(EG^kbDs* z9`9Rfv>5m4%Jg?R_&*+c={-JDWXF>x;g~qO0fNNZTbx)lJ5w~f{|W?Mfkv7d^-Ya; zTbm`VTbJR9P2xy1`VpcG1!56ZC=dgyb)&*v_R(EgGFj0F+3XE$OgiQql~=D$A=ta9 z!=L-M3A&Dv2cK=zDkD-7?Og|kPx?9pc!_$*5});RtjS-n@&C%6_71a~oAa2~8mRef zZo|*kqLuH5msjrQj zl9K24aepx?yRa9=d5PRNr4^$Ya69aC%nX_geIA#ke;^x$-4;GO$~$9j=09pyvcJPw zs{C%BM2!92n&w@!tFbDV*V3Ql*O}OC2Ih@^X!V;dW=S?|dI0+eU)cMz*;D7lWX{j> z`6T>eLe{AD?b>EsjP1XgXxsPHHqMkL8#6Jc251U?_^o73W?P#g={r_?dz2s=to9@7~sKX9V( zq+0UtLGO%Ff=*RF=VDrzGce`1E*>3a#4&tE1oNkPy^d}@bIDicnRckEF1Rqehas=> zIqdz-Y)|uxseS{t1jGK_IGdDC7pL~(`{BdfFq6S)_y`*$`)^|}d`{C6qC98#Zc>{K z`{<2Nu!YL`X0LBh45NC#eTXB^-U3BVO8F?)Ta0ns-tBIiT|$a~l|aev?refjO{czO((egi7dnP!Jj(f!n~U zwLz~M_?*3*e0dJ%LL0`Z;*itfz Date: Sun, 7 Jan 2024 17:51:20 +0100 Subject: [PATCH 7/7] RxAGC setting working. --- app/app.c | 3 ++- driver/bk4819.c | 25 +++++++++++++++++++------ driver/bk4819.h | 2 +- main.c | 4 ++-- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/app/app.c b/app/app.c index b2da9469..143f11fd 100644 --- a/app/app.c +++ b/app/app.c @@ -474,7 +474,8 @@ void APP_StartListening(FUNCTION_Type_t Function) gUpdateStatus = true; } - BK4819_SetAGC(true); + BK4819_InitAGC(gEeprom.RX_AGC); + BK4819_SetAGC(gEeprom.RX_AGC!=RX_AGC_OFF); // AF gain - original QS values // if (gRxVfo->Modulation != MODULATION_FM){ diff --git a/driver/bk4819.c b/driver/bk4819.c index e80be7db..fd0186b0 100644 --- a/driver/bk4819.c +++ b/driver/bk4819.c @@ -23,6 +23,7 @@ #include "driver/gpio.h" #include "driver/system.h" #include "driver/systick.h" +#include "settings.h" #ifndef ARRAY_SIZE #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) @@ -55,8 +56,10 @@ void BK4819_Init(void) BK4819_WriteRegister(BK4819_REG_37, 0x1D0F); BK4819_WriteRegister(BK4819_REG_36, 0x0022); - BK4819_InitAGC(); - BK4819_SetAGC(true); + BK4819_SetDefaultAmplifierSettings(); + + BK4819_InitAGC(gEeprom.RX_AGC); + BK4819_SetAGC(gEeprom.RX_AGC!=RX_AGC_OFF); BK4819_WriteRegister(BK4819_REG_19, 0b0001000001000001); // <15> MIC AGC 1 = disable 0 = enable @@ -263,7 +266,7 @@ void BK4819_SetAGC(bool enable) // } } -void BK4819_InitAGC() +void BK4819_InitAGC(const uint8_t agcType) { // REG_10, REG_11, REG_12 REG_13, REG_14 // @@ -304,7 +307,17 @@ void BK4819_InitAGC() // 0 = -33dB // - BK4819_SetDefaultAmplifierSettings(); // 0x03BE / 000000 11 101 11 110 / -7dB + switch(agcType) + { + case RX_AGC_SLOW: + BK4819_WriteRegister(BK4819_REG_49, (0b00 << 14) | (50 << 7) | (15 << 0)); + break; + case RX_AGC_FAST: + BK4819_WriteRegister(BK4819_REG_49, (0b00 << 14) | (45 << 7) | (25 << 0)); + break; + default: + return; + } BK4819_WriteRegister(BK4819_REG_12, 0x037B); // 0x037B / 000000 11 011 11 011 / -24dB BK4819_WriteRegister(BK4819_REG_11, 0x027B); // 0x027B / 000000 10 011 11 011 / -43dB @@ -315,8 +328,8 @@ void BK4819_InitAGC() //50, 15, - SOFT - signal doesn't fall too low - works best for now //45, 25 - AGRESSIVE - lower histeresis, but volume jumps heavily, not good for music, might be good for aviation //1 << 14 - way better, seems to open squelch and match squelch as opposed to 0 - BK4819_WriteRegister(BK4819_REG_49, (0b00 << 14) | (50 << 7) | (15 << 0)); //0x2A38 / 00 1010100 0111000 / 84, 56 - BK4819_WriteRegister(BK4819_REG_7B, 0x8420); + + BK4819_WriteRegister(BK4819_REG_7B, 0x8420); // ? } diff --git a/driver/bk4819.h b/driver/bk4819.h index 511c5b72..f1f01b61 100644 --- a/driver/bk4819.h +++ b/driver/bk4819.h @@ -75,7 +75,7 @@ void BK4819_WriteU8(uint8_t Data); void BK4819_WriteU16(uint16_t Data); void BK4819_SetAGC(bool enable); -void BK4819_InitAGC(); +void BK4819_InitAGC(const uint8_t agcType); void BK4819_ToggleGpioOut(BK4819_GPIO_PIN_t Pin, bool bSet); diff --git a/main.c b/main.c index 114757e3..d1fcaaf1 100644 --- a/main.c +++ b/main.c @@ -76,12 +76,12 @@ void Main(void) memset(gDTMF_String, '-', sizeof(gDTMF_String)); gDTMF_String[sizeof(gDTMF_String) - 1] = 0; - BK4819_Init(); - BOARD_ADC_GetBatteryInfo(&gBatteryCurrentVoltage, &gBatteryCurrent); BOARD_EEPROM_Init(); + BK4819_Init(); + BOARD_EEPROM_LoadCalibration(); RADIO_ConfigureChannel(0, VFO_CONFIGURE_RELOAD);