/* Copyright 2023 Dual Tachyon
 * https://github.com/DualTachyon
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *     Unless required by applicable law or agreed to in writing, software
 *     distributed under the License is distributed on an "AS IS" BASIS,
 *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *     See the License for the specific language governing permissions and
 *     limitations under the License.
 */
#include <stdio.h>
#include "app/mdc1200.h"
#include <string.h>
#include "driver/uart.h"
#if !defined(ENABLE_OVERLAY)
	#include "ARMCM0.h"
#endif
#include "app/dtmf.h"
#include "app/generic.h"
#include "app/menu.h"
#include "app/scanner.h"
#include "audio.h"
#include "board.h"
#include "bsp/dp32g030/gpio.h"
#include "driver/backlight.h"
#include "driver/bk4819.h"
#include "driver/eeprom.h"
#include "driver/gpio.h"
#include "driver/keyboard.h"
#include "frequencies.h"
#include "helper/battery.h"
#include "misc.h"
#include "settings.h"
#if defined(ENABLE_OVERLAY)
	#include "sram-overlay.h"
#endif
#include "ui/inputbox.h"
#include "ui/menu.h"
#include "ui/menu.h"
#include "ui/ui.h"

#ifndef ARRAY_SIZE
	#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)
	{
		BK4819_WriteRegister(BK4819_REG_3B, 22656 + value);

		if (update_eeprom)
		{
			struct
			{
				int16_t  BK4819_XtalFreqLow;
				uint16_t EEPROM_1F8A;
				uint16_t EEPROM_1F8C;
				uint8_t  VOLUME_GAIN;
				uint8_t  DAC_GAIN;
			} __attribute__((packed)) misc;

			gEeprom.BK4819_XTAL_FREQ_LOW = value;

			// radio 1 .. 04 00 46 00 50 00 2C 0E
			// radio 2 .. 05 00 46 00 50 00 2C 0E
			//
			EEPROM_ReadBuffer(0x1F88, &misc, 8);
			misc.BK4819_XtalFreqLow = value;
			EEPROM_WriteBuffer(0x1F88, &misc);
		}
	}
#endif

void MENU_StartCssScan(void)
{
	SCANNER_Start(true);
	gUpdateStatus = true;
	gCssBackgroundScan = true;

	gRequestDisplayScreen = DISPLAY_MENU;
}

void MENU_CssScanFound(void)
{
	if(gScanCssResultType == CODE_TYPE_DIGITAL || gScanCssResultType == CODE_TYPE_REVERSE_DIGITAL) {
		gMenuCursor = UI_MENU_GetMenuIdx(MENU_R_DCS);
	}
	else if(gScanCssResultType == CODE_TYPE_CONTINUOUS_TONE) {
		gMenuCursor = UI_MENU_GetMenuIdx(MENU_R_CTCS);
	}

	MENU_ShowCurrentSetting();

	gUpdateStatus = true;
	gUpdateDisplay = true;
}

void MENU_StopCssScan(void)
{
	gCssBackgroundScan = false;
	
#ifdef ENABLE_VOICE
	gAnotherVoiceID       = VOICE_ID_SCANNING_STOP;
#endif
	gUpdateDisplay = true;
	gUpdateStatus = true;
}

int MENU_GetLimits(uint8_t menu_id, int32_t *pMin, int32_t *pMax)
{
	switch (menu_id)
	{
		case MENU_SQL:
			*pMin = 0;
			*pMax = 9;
			break;

		case MENU_STEP:
			*pMin = 0;
			*pMax = ARRAY_SIZE(gStepFrequencyTable) - 1;
			break;

		case MENU_ABR:
			*pMin = 0;
			*pMax = ARRAY_SIZE(gSubMenu_BACKLIGHT) - 1;
			break;

//		case MENU_ABR_MIN:
//			*pMin = 0;
//			*pMax = 9;
//			break;

		case MENU_ABR_MAX:
			*pMin = 1;
			*pMax = 10;
			break;	

		case MENU_F_LOCK:
			*pMin = 0;
			*pMax = ARRAY_SIZE(gSubMenu_F_LOCK) - 1;
			break;

		case MENU_MDF:
			*pMin = 0;
			*pMax = ARRAY_SIZE(gSubMenu_MDF) - 1;
			break;

//		case MENU_TXP:
//			*pMin = 0;
//			*pMax = ARRAY_SIZE(gSubMenu_TXP) - 1;
//			break;

		case MENU_SFT_D:
			*pMin = 0;
			*pMax = ARRAY_SIZE(gSubMenu_SFT_D) - 1;
			break;

		case MENU_TDR:
			*pMin = 0;
			*pMax = ARRAY_SIZE(gSubMenu_RXMode) - 1;
			break;

		#ifdef ENABLE_VOICE
			case MENU_VOICE:
				*pMin = 0;
				*pMax = ARRAY_SIZE(gSubMenu_VOICE) - 1;
				break;
		#endif

		case MENU_SC_REV:
			*pMin = 0;
			*pMax = ARRAY_SIZE(gSubMenu_SC_REV) - 1;
			break;

		case MENU_ROGER:
			*pMin = 0;
			*pMax = ARRAY_SIZE(gSubMenu_ROGER) - 1;
			break;

//		case MENU_PONMSG:
//			*pMin = 0;
//			*pMax = ARRAY_SIZE(gSubMenu_OFF_ON) - 1;
//			break;

		case MENU_R_DCS:
		case MENU_T_DCS:
			*pMin = 0;
			*pMax = 208;
			//*pMax = (ARRAY_SIZE(DCS_Options) * 2);
			break;

		case MENU_R_CTCS:
		case MENU_T_CTCS:
			*pMin = 0;
			*pMax = ARRAY_SIZE(CTCSS_Options) - 1;
			break;

//		case MENU_W_N:
//			*pMin = 0;
//			*pMax = ARRAY_SIZE(gSubMenu_W_N) - 1;
//			break;

		#ifdef ENABLE_ALARM
			case MENU_AL_MOD:
				*pMin = 0;
				*pMax = ARRAY_SIZE(gSubMenu_AL_MOD) - 1;
				break;
		#endif

		case MENU_RESET:
			*pMin = 0;
			*pMax = ARRAY_SIZE(gSubMenu_RESET) - 1;
			break;

		case MENU_COMPAND:
//		case MENU_ABR_ON_TX_RX:
			*pMin = 0;
			*pMax = ARRAY_SIZE(gSubMenu_RX_TX) - 1;
			break;

		#ifdef ENABLE_AM_FIX_TEST1
			case MENU_AM_FIX_TEST1:
				*pMin = 0;
				*pMax = ARRAY_SIZE(gSubMenu_AM_fix_test1) - 1;
				break;
		#endif

		#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:
		//case MENU_S_ADD1:
		//case MENU_S_ADD2:
		case MENU_STE:
		case MENU_D_ST:
#ifdef ENABLE_DTMF_CALLING
	//	case MENU_D_DCD:
#endif
		case MENU_D_LIVE_DEC:
		#ifdef ENABLE_NOAA
			case MENU_NOAA_S:
		#endif
//		case MENU_350TX:
//		case MENU_200TX:
//		case MENU_500TX:
//		case MENU_350EN:
//		case MENU_SCREN:
//			*pMin = 0;
//			*pMax = ARRAY_SIZE(gSubMenu_OFF_ON) - 1;
//			break;
            *pMin = 0;
            *pMax = ARRAY_SIZE(gSubMenu_OFF_ON) - 1;
            break;
//		case MENU_AM:
//			*pMin = 0;
//			*pMax = ARRAY_SIZE(gModulationStr) - 1;
//			break;

		case MENU_SCR:
			*pMin = 0;
			*pMax = ARRAY_SIZE(gSubMenu_SCRAMBLER) - 1;
			break;

		case MENU_TOT:
			*pMin = 0;
			*pMax = ARRAY_SIZE(gSubMenu_TOT) - 1;
			break;

		#ifdef ENABLE_VOX
			//case MENU_VOX:
		#endif
		case MENU_RP_STE:
			*pMin = 0;
			*pMax = 10;
			break;

		case MENU_MEM_CH:
		case MENU_1_CALL:
		case MENU_DEL_CH:
		case MENU_MEM_NAME:
			*pMin = 0;
			*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;
			break;

		case MENU_MIC:
			*pMin = 0;
			*pMax = 4;
			break;

		case MENU_S_LIST:
			*pMin = 0;
			*pMax = 2;
			break;
#ifdef ENABLE_DTMF_CALLING
		case MENU_D_RSP:
			*pMin = 0;
			*pMax = ARRAY_SIZE(gSubMenu_D_RSP) - 1;
			break;
#endif
		case MENU_PTT_ID:
			*pMin = 0;
			*pMax = ARRAY_SIZE(gSubMenu_PTT_ID) - 1;
			break;

//		case MENU_BAT_TXT:
//			*pMin = 0;
//			*pMax = ARRAY_SIZE(gSubMenu_BAT_TXT) - 1;
//			break;
#ifdef ENABLE_DTMF_CALLING
		case MENU_D_HOLD:
			*pMin = 5;
			*pMax = 60;
			break;
#endif
		case MENU_D_PRE:
			*pMin = 3;
			*pMax = 99;
			break;
#ifdef ENABLE_DTMF_CALLING
		case MENU_D_LIST:
			*pMin = 1;
			*pMax = 16;
			break;
#endif
		#ifdef ENABLE_F_CAL_MENU
			case MENU_F_CALI:
				*pMin = -50;
				*pMax = +50;
				break;
		#endif

		case MENU_BATCAL:
			*pMin = 1600;
			*pMax = 2200;
			break;

		case MENU_BATTYP:
			*pMin = 0;
			*pMax = 1;
			break;

//		case MENU_F1SHRT:
//		case MENU_F1LONG:
//		case MENU_F2SHRT:
//		case MENU_F2LONG:
//		case MENU_MLONG:
//			*pMin = 0;
//			*pMax = gSubMenu_SIDEFUNCTIONS_size-1;
//			break;

		default:
			return -1;
	}

	return 0;
}

void MENU_AcceptSetting(void)
{
	int32_t        Min;
	int32_t        Max;
	FREQ_Config_t *pConfig = &gTxVfo->freq_config_RX;

	if (!MENU_GetLimits(UI_MENU_GetCurrentMenuId(), &Min, &Max))
	{
		if (gSubMenuSelection < Min) gSubMenuSelection = Min;
		else
		if (gSubMenuSelection > Max) gSubMenuSelection = Max;
	}
    char a=gSubMenuSelection;//UART_Send(a,1);
    UART_Send((uint8_t *)&a, 1);

    switch (UI_MENU_GetCurrentMenuId()) {
        default:
            return;

        case MENU_SQL:
            gEeprom.SQUELCH_LEVEL = gSubMenuSelection;
            gVfoConfigureMode = VFO_CONFIGURE;
            break;

        case MENU_STEP:
            gTxVfo->STEP_SETTING = FREQUENCY_GetStepIdxFromSortedIdx(gSubMenuSelection);
            if (IS_FREQ_CHANNEL(gTxVfo->CHANNEL_SAVE)) {
                gRequestSaveChannel = 1;
                return;
            }
            return;

//		case MENU_TXP:
//			gTxVfo->OUTPUT_POWER = gSubMenuSelection;
//			gRequestSaveChannel = 1;
//			return;

        case MENU_T_DCS:
            pConfig = &gTxVfo->freq_config_TX;

            // Fallthrough

        case MENU_R_DCS:{
            if (gSubMenuSelection == 0) {
                if (pConfig->CodeType == CODE_TYPE_CONTINUOUS_TONE) {
                    return;
                }
                pConfig->Code = 0;
                pConfig->CodeType = CODE_TYPE_OFF;
            } else if (gSubMenuSelection < 105) {
                pConfig->CodeType = CODE_TYPE_DIGITAL;
                pConfig->Code = gSubMenuSelection - 1;
            } else {
                pConfig->CodeType = CODE_TYPE_REVERSE_DIGITAL;
                pConfig->Code = gSubMenuSelection - 105;
            }

            gRequestSaveChannel = 1;
            return;
    }
		case MENU_T_CTCS:
			pConfig = &gTxVfo->freq_config_TX;
			[[fallthrough]];
		case MENU_R_CTCS:{
			if (gSubMenuSelection == 0)
			{
				if (pConfig->CodeType != CODE_TYPE_CONTINUOUS_TONE)
				{
					return;
				}
                pConfig->Code = 0;
				pConfig->CodeType = CODE_TYPE_OFF;

			}
            else {
                pConfig->Code     = gSubMenuSelection - 1;
                pConfig->CodeType = CODE_TYPE_CONTINUOUS_TONE;

            }

            gRequestSaveChannel = 1;
            return;
    }

		case MENU_SFT_D:
			gTxVfo->TX_OFFSET_FREQUENCY_DIRECTION = gSubMenuSelection;
			gRequestSaveChannel                   = 1;
			return;

		case MENU_OFFSET:
			gTxVfo->TX_OFFSET_FREQUENCY = gSubMenuSelection;
			gRequestSaveChannel         = 1;
			return;

//		case MENU_W_N:
//			gTxVfo->CHANNEL_BANDWIDTH = gSubMenuSelection;
//			gRequestSaveChannel       = 1;
//			return;

		case MENU_SCR:
			gTxVfo->SCRAMBLING_TYPE = gSubMenuSelection;
			#if 0
				if (gSubMenuSelection > 0 && gSetting_ScrambleEnable)
					BK4819_EnableScramble(gSubMenuSelection - 1);
				else
					BK4819_DisableScramble();
			#endif
			gRequestSaveChannel     = 1;
			return;

		case MENU_BCL:
			gTxVfo->BUSY_CHANNEL_LOCK = gSubMenuSelection;
			gRequestSaveChannel       = 1;
			return;

		case MENU_MEM_CH:
			gTxVfo->CHANNEL_SAVE = gSubMenuSelection;
			#if 0
				gEeprom.MrChannel[0] = gSubMenuSelection;
			#else
				gEeprom.MrChannel[gEeprom.TX_VFO] = gSubMenuSelection;
			#endif
			gRequestSaveChannel = 2;
			gVfoConfigureMode   = VFO_CONFIGURE_RELOAD;
			gFlagResetVfos      = true;
			return;
#ifdef ENABLE_MDC1200
            case MENU_MDC_ID:
//                for (int i = 3; i >= 0; i--) {
//                    if (edit[i] != ' ' && edit[i] != '_' && edit[i] != 0x00 && edit[i] != 0xff)
//                        break;
//                    edit[i] = ' ';
//			}
        gEeprom.MDC1200_ID=extractHex(edit);
			return;
#endif
		case MENU_MEM_NAME:
				// trailing trim
                for (int i = 9; i >= 0; i--) {
                    if (edit[i] != ' ' && edit[i] != '_' && edit[i] != 0x00 && edit[i] != 0xff)
                        break;
                    edit[i] = ' ';
			}

            SETTINGS_SaveChannelName(gSubMenuSelection, edit);
			return;

		case MENU_SAVE:
			gEeprom.BATTERY_SAVE = gSubMenuSelection;
			break;

		#ifdef ENABLE_VOX
//			case MENU_VOX:
//				gEeprom.VOX_SWITCH = gSubMenuSelection != 0;
//				if (gEeprom.VOX_SWITCH)
//					gEeprom.VOX_LEVEL = gSubMenuSelection - 1;
//				SETTINGS_LoadCalibration();
//				gFlagReconfigureVfos = true;
//				gUpdateStatus        = true;
//				break;
		#endif

		case MENU_ABR:
			gEeprom.BACKLIGHT_TIME = gSubMenuSelection;
			break;

//		case MENU_ABR_MIN:
//			gEeprom.BACKLIGHT_MIN = gSubMenuSelection;
//			gEeprom.BACKLIGHT_MAX = MAX(gSubMenuSelection + 1 , gEeprom.BACKLIGHT_MAX);
//			break;

		case MENU_ABR_MAX:
			gEeprom.BACKLIGHT_MAX = gSubMenuSelection;
			break;

//		case MENU_ABR_ON_TX_RX:
//			gSetting_backlight_on_tx_rx = gSubMenuSelection;
//			break;

		case MENU_TDR:
			gEeprom.DUAL_WATCH = (gEeprom.TX_VFO + 1) * (gSubMenuSelection & 1);
			gEeprom.CROSS_BAND_RX_TX = (gEeprom.TX_VFO + 1) * ((gSubMenuSelection & 2) > 0);

			gFlagReconfigureVfos = true;
			gUpdateStatus        = true;
			break;

//		case MENU_BEEP:
//			gEeprom.BEEP_CONTROL = gSubMenuSelection;
//			break;

		case MENU_TOT:
			gEeprom.TX_TIMEOUT_TIMER = gSubMenuSelection;
			break;

		#ifdef ENABLE_VOICE
			case MENU_VOICE:
				gEeprom.VOICE_PROMPT = gSubMenuSelection;
				gUpdateStatus        = true;
				break;
		#endif

		case MENU_SC_REV:
			gEeprom.SCAN_RESUME_MODE = gSubMenuSelection;
			break;

		case MENU_MDF:
			gEeprom.CHANNEL_DISPLAY_MODE = gSubMenuSelection;
			break;

//		case MENU_AUTOLK:
//			gEeprom.AUTO_KEYPAD_LOCK = gSubMenuSelection;
//			gKeyLockCountdown        = 30;
//			break;

//		case MENU_S_ADD1:
//			gTxVfo->SCANLIST1_PARTICIPATION = gSubMenuSelection;
//			SETTINGS_UpdateChannel(gTxVfo->CHANNEL_SAVE, gTxVfo, true);
//			gVfoConfigureMode = VFO_CONFIGURE;
//			gFlagResetVfos    = true;
//			return;

//		case MENU_S_ADD2:
//			gTxVfo->SCANLIST2_PARTICIPATION = gSubMenuSelection;
//			SETTINGS_UpdateChannel(gTxVfo->CHANNEL_SAVE, gTxVfo, true);
//			gVfoConfigureMode = VFO_CONFIGURE;
//			gFlagResetVfos    = true;
//			return;

		case MENU_STE:
			gEeprom.TAIL_TONE_ELIMINATION = gSubMenuSelection;
			break;

		case MENU_RP_STE:
			gEeprom.REPEATER_TAIL_TONE_ELIMINATION = gSubMenuSelection;
			break;

		case MENU_MIC:
			gEeprom.MIC_SENSITIVITY = gSubMenuSelection;
            SETTINGS_LoadCalibration();
			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);
			gVfoConfigureMode = VFO_CONFIGURE;
			gFlagResetVfos    = true;
//			gRequestSaveChannel = 1;
			return;

		case MENU_1_CALL:
			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;
				break;
		#endif

		case MENU_D_ST:
			gEeprom.DTMF_SIDE_TONE = gSubMenuSelection;
			break;
#ifdef ENABLE_DTMF_CALLING
		case MENU_D_RSP:
			gEeprom.DTMF_DECODE_RESPONSE = gSubMenuSelection;
			break;

		case MENU_D_HOLD:
			gEeprom.DTMF_auto_reset_time = gSubMenuSelection;
			break;
#endif
		case MENU_D_PRE:
			gEeprom.DTMF_PRELOAD_TIME = gSubMenuSelection * 10;
			break;

		case MENU_PTT_ID:
			gTxVfo->DTMF_PTT_ID_TX_MODE = gSubMenuSelection;
			gRequestSaveChannel         = 1;
			return;

//		case MENU_BAT_TXT:
//			gSetting_battery_text = gSubMenuSelection;
//			break;
#ifdef ENABLE_DTMF_CALLING
//		case MENU_D_DCD:
//			gTxVfo->DTMF_DECODING_ENABLE = gSubMenuSelection;
//			DTMF_clear_RX();
//			gRequestSaveChannel = 1;
//			return;
#endif
		case MENU_D_LIVE_DEC:
			gSetting_live_DTMF_decoder = gSubMenuSelection;
			gDTMF_RX_live_timeout = 0;
			memset(gDTMF_RX_live, 0, sizeof(gDTMF_RX_live));
			if (!gSetting_live_DTMF_decoder)
				BK4819_DisableDTMF();
			gFlagReconfigureVfos     = true;
			gUpdateStatus            = true;
			break;
#ifdef ENABLE_DTMF_CALLING
		case MENU_D_LIST:
			gDTMF_chosen_contact = gSubMenuSelection - 1;
			if (gIsDtmfContactValid)
			{
				GUI_SelectNextDisplay(DISPLAY_MAIN);
				gDTMF_InputMode       = true;
				gDTMF_InputBox_Index  = 3;
				memmove(gDTMF_InputBox, gDTMF_ID, 4);
				gRequestDisplayScreen = DISPLAY_INVALID;
			}
			return;
#endif
//		case MENU_PONMSG:
//			gEeprom.POWER_ON_DISPLAY_MODE = gSubMenuSelection;
//			break;

		case MENU_ROGER:
			gEeprom.ROGER = gSubMenuSelection;
			break;

//		case MENU_AM:
//			gTxVfo->Modulation     = gSubMenuSelection;
//			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_AM_FIX_TEST1
			case MENU_AM_FIX_TEST1:
				gSetting_AM_fix_test1 = gSubMenuSelection;
				gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
				gFlagResetVfos    = true;
				break;
		#endif

		#ifdef ENABLE_NOAA
			case MENU_NOAA_S:
				gEeprom.NOAA_AUTO_SCAN = gSubMenuSelection;
				gFlagReconfigureVfos   = true;
				break;
		#endif

		case MENU_DEL_CH:
			SETTINGS_UpdateChannel(gSubMenuSelection, NULL, false);
			gVfoConfigureMode = VFO_CONFIGURE_RELOAD;
			gFlagResetVfos    = true;
			return;

		case MENU_RESET:
            SETTINGS_FactoryReset(gSubMenuSelection);
            return;

//		case MENU_350TX:
//			gSetting_350TX = gSubMenuSelection;
//			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;
		}
//		case MENU_200TX:
//			gSetting_200TX = gSubMenuSelection;
//			break;
//
//		case MENU_500TX:
//			gSetting_500TX = gSubMenuSelection;
//			break;

//		case MENU_350EN:
//			gSetting_350EN       = gSubMenuSelection;
//			gVfoConfigureMode    = VFO_CONFIGURE_RELOAD;
//			gFlagResetVfos       = true;
//			break;

//		case MENU_SCREN:
//			gSetting_ScrambleEnable = gSubMenuSelection;
//			gFlagReconfigureVfos    = true;
//			break;

		#ifdef ENABLE_F_CAL_MENU
			case MENU_F_CALI:
				writeXtalFreqCal(gSubMenuSelection, true);
				return;
		#endif

		case MENU_BATCAL:
		{																 // voltages are averages between discharge curves of 1600 and 2200 mAh
			// gBatteryCalibration[0] = (520ul * gSubMenuSelection) / 760;  // 5.20V empty, blinking above this value, reduced functionality below
			// gBatteryCalibration[1] = (689ul * gSubMenuSelection) / 760;  // 6.89V,  ~5%, 1 bars above this value
			// gBatteryCalibration[2] = (724ul * gSubMenuSelection) / 760;  // 7.24V, ~17%, 2 bars above this value
			gBatteryCalibration[3] =          gSubMenuSelection;         // 7.6V,  ~29%, 3 bars above this value
			// gBatteryCalibration[4] = (771ul * gSubMenuSelection) / 760;  // 7.71V, ~65%, 4 bars above this value
			// gBatteryCalibration[5] = 2300;
			SETTINGS_SaveBatteryCalibration(gBatteryCalibration);
			return;
		}

		case MENU_BATTYP:
			gEeprom.BATTERY_TYPE = gSubMenuSelection;
			break;

//		case MENU_F1SHRT:
//		case MENU_F1LONG:
//		case MENU_F2SHRT:
//		case MENU_F2LONG:
//		case MENU_MLONG:
//			{
//				uint8_t * fun[]= {
//					&gEeprom.KEY_1_SHORT_PRESS_ACTION,
//					&gEeprom.KEY_1_LONG_PRESS_ACTION,
//					&gEeprom.KEY_2_SHORT_PRESS_ACTION,
//					&gEeprom.KEY_2_LONG_PRESS_ACTION,
//					&gEeprom.KEY_M_LONG_PRESS_ACTION};
//				*fun[UI_MENU_GetCurrentMenuId()-MENU_F1SHRT] = gSubMenu_SIDEFUNCTIONS[gSubMenuSelection].id;
//			}
//			break;

	}

	gRequestSaveSettings = true;
}

static void MENU_ClampSelection(int8_t Direction)
{
	int32_t Min;
	int32_t Max;

	if (!MENU_GetLimits(UI_MENU_GetCurrentMenuId(), &Min, &Max))
	{
		int32_t Selection = gSubMenuSelection;
		if (Selection < Min) Selection = Min;
		else
		if (Selection > Max) Selection = Max;
		gSubMenuSelection = NUMBER_AddWithWraparound(Selection, Direction, Min, Max);
	}
}

void MENU_ShowCurrentSetting(void)
{
	switch (UI_MENU_GetCurrentMenuId())
	{
		case MENU_SQL:
			gSubMenuSelection = gEeprom.SQUELCH_LEVEL;
			break;

		case MENU_STEP:
			gSubMenuSelection = FREQUENCY_GetSortedIdxFromStepIdx(gTxVfo->STEP_SETTING);
			break;

//		case MENU_TXP:
//			gSubMenuSelection = gTxVfo->OUTPUT_POWER;
//			break;

		case MENU_RESET:
			gSubMenuSelection = 0;
			break;			

		case MENU_R_DCS: 
		case MENU_R_CTCS:
		{
			DCS_CodeType_t type = gTxVfo->freq_config_RX.CodeType;
			uint8_t code = gTxVfo->freq_config_RX.Code;
			int menuid = UI_MENU_GetCurrentMenuId();

			if(gScanUseCssResult) {
				gScanUseCssResult = false;
				type = gScanCssResultType;
				code = gScanCssResultCode;
			}
			if((menuid==MENU_R_CTCS) ^ (type==CODE_TYPE_CONTINUOUS_TONE)) { //not the same type
				gSubMenuSelection = 0;
				break;
			}

			switch (type) {
				case CODE_TYPE_CONTINUOUS_TONE:
				case CODE_TYPE_DIGITAL:
					gSubMenuSelection = code + 1;
					break;
				case CODE_TYPE_REVERSE_DIGITAL:
					gSubMenuSelection = code + 105;
					break;
				default:
					gSubMenuSelection = 0;
					break;
			}
		break;
		}

		case MENU_T_DCS:
			switch (gTxVfo->freq_config_TX.CodeType)
			{
				case CODE_TYPE_DIGITAL:
					gSubMenuSelection = gTxVfo->freq_config_TX.Code + 1;
					break;
				case CODE_TYPE_REVERSE_DIGITAL:
					gSubMenuSelection = gTxVfo->freq_config_TX.Code + 105;
					break;
				default:
					gSubMenuSelection = 0;
					break;
			}
			break;

		case MENU_T_CTCS:
			gSubMenuSelection = (gTxVfo->freq_config_TX.CodeType == CODE_TYPE_CONTINUOUS_TONE) ? gTxVfo->freq_config_TX.Code + 1 : 0;
			break;

		case MENU_SFT_D:
			gSubMenuSelection = gTxVfo->TX_OFFSET_FREQUENCY_DIRECTION;
			break;

		case MENU_OFFSET:
			gSubMenuSelection = gTxVfo->TX_OFFSET_FREQUENCY;
			break;

//		case MENU_W_N:
//			gSubMenuSelection = gTxVfo->CHANNEL_BANDWIDTH;
//			break;

		case MENU_SCR:
			gSubMenuSelection = gTxVfo->SCRAMBLING_TYPE;
			break;

		case MENU_BCL:
			gSubMenuSelection = gTxVfo->BUSY_CHANNEL_LOCK;
			break;

		case MENU_MEM_CH:
			#if 0
				gSubMenuSelection = gEeprom.MrChannel[0];
			#else
				gSubMenuSelection = gEeprom.MrChannel[gEeprom.TX_VFO];
			#endif
			break;

		case MENU_MEM_NAME:
			gSubMenuSelection = gEeprom.MrChannel[gEeprom.TX_VFO];
			break;

		case MENU_SAVE:
			gSubMenuSelection = gEeprom.BATTERY_SAVE;
			break;

#ifdef ENABLE_VOX
//		case MENU_VOX:
//			gSubMenuSelection = gEeprom.VOX_SWITCH ? gEeprom.VOX_LEVEL + 1 : 0;
//			break;
#endif

		case MENU_ABR:
			gSubMenuSelection = gEeprom.BACKLIGHT_TIME;
			break;

//		case MENU_ABR_MIN:
//			gSubMenuSelection = gEeprom.BACKLIGHT_MIN;
//			break;

		case MENU_ABR_MAX:
			gSubMenuSelection = gEeprom.BACKLIGHT_MAX;
			break;		

//		case MENU_ABR_ON_TX_RX:
//			gSubMenuSelection = gSetting_backlight_on_tx_rx;
//			break;

		case MENU_TDR:
			gSubMenuSelection = (gEeprom.DUAL_WATCH != DUAL_WATCH_OFF) + (gEeprom.CROSS_BAND_RX_TX != CROSS_BAND_OFF) * 2;
			break;

//		case MENU_BEEP:
//			gSubMenuSelection = gEeprom.BEEP_CONTROL;
//			break;

		case MENU_TOT:
			gSubMenuSelection = gEeprom.TX_TIMEOUT_TIMER;
			break;

#ifdef ENABLE_VOICE
		case MENU_VOICE:
			gSubMenuSelection = gEeprom.VOICE_PROMPT;
			break;
#endif

		case MENU_SC_REV:
			gSubMenuSelection = gEeprom.SCAN_RESUME_MODE;
			break;

		case MENU_MDF:
			gSubMenuSelection = gEeprom.CHANNEL_DISPLAY_MODE;
			break;

//		case MENU_AUTOLK:
//			gSubMenuSelection = gEeprom.AUTO_KEYPAD_LOCK;
//			break;

//		case MENU_S_ADD1:
//			gSubMenuSelection = gTxVfo->SCANLIST1_PARTICIPATION;
//			break;
//
//		case MENU_S_ADD2:
//			gSubMenuSelection = gTxVfo->SCANLIST2_PARTICIPATION;
//			break;

		case MENU_STE:
			gSubMenuSelection = gEeprom.TAIL_TONE_ELIMINATION;
			break;

		case MENU_RP_STE:
			gSubMenuSelection = gEeprom.REPEATER_TAIL_TONE_ELIMINATION;
			break;

		case MENU_MIC:
			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;

		case MENU_1_CALL:
			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;
				break;
		#endif

		case MENU_D_ST:
			gSubMenuSelection = gEeprom.DTMF_SIDE_TONE;
			break;
#ifdef ENABLE_DTMF_CALLING
		case MENU_D_RSP:
			gSubMenuSelection = gEeprom.DTMF_DECODE_RESPONSE;
			break;

		case MENU_D_HOLD:
			gSubMenuSelection = gEeprom.DTMF_auto_reset_time;
			break;
#endif
		case MENU_D_PRE:
			gSubMenuSelection = gEeprom.DTMF_PRELOAD_TIME / 10;
			break;

		case MENU_PTT_ID:
			gSubMenuSelection = gTxVfo->DTMF_PTT_ID_TX_MODE;
			break;

//		case MENU_BAT_TXT:
//			gSubMenuSelection = gSetting_battery_text;
//			return;
#ifdef ENABLE_DTMF_CALLING
//		case MENU_D_DCD:
//			gSubMenuSelection = gTxVfo->DTMF_DECODING_ENABLE;
//			break;

		case MENU_D_LIST:
			gSubMenuSelection = gDTMF_chosen_contact + 1;
			break;
#endif
		case MENU_D_LIVE_DEC:
			gSubMenuSelection = gSetting_live_DTMF_decoder;
			break;

//		case MENU_PONMSG:
//			gSubMenuSelection = gEeprom.POWER_ON_DISPLAY_MODE;
//			break;

		case MENU_ROGER:
			gSubMenuSelection = gEeprom.ROGER;
			break;

//		case MENU_AM:
//			gSubMenuSelection = gTxVfo->Modulation;
//			break;

#ifdef ENABLE_AM_FIX
		case MENU_AM_FIX:
			gSubMenuSelection = gSetting_AM_fix;
			break;
#endif

		#ifdef ENABLE_AM_FIX_TEST1
			case MENU_AM_FIX_TEST1:
				gSubMenuSelection = gSetting_AM_fix_test1;
				break;
		#endif

		#ifdef ENABLE_NOAA
			case MENU_NOAA_S:
				gSubMenuSelection = gEeprom.NOAA_AUTO_SCAN;
				break;
		#endif

		case MENU_DEL_CH:
			#if 0
				gSubMenuSelection = RADIO_FindNextChannel(gEeprom.MrChannel[0], 1, false, 1);
			#else
				gSubMenuSelection = RADIO_FindNextChannel(gEeprom.MrChannel[gEeprom.TX_VFO], 1, false, 1);
			#endif
			break;

//		case MENU_350TX:
//			gSubMenuSelection = gSetting_350TX;
//			break;

		case MENU_F_LOCK:
			gSubMenuSelection = gSetting_F_LOCK;
			break;

//		case MENU_200TX:
//			gSubMenuSelection = gSetting_200TX;
//			break;
//
//		case MENU_500TX:
//			gSubMenuSelection = gSetting_500TX;
//			break;
//
//		case MENU_350EN:
//			gSubMenuSelection = gSetting_350EN;
//			break;

//		case MENU_SCREN:
//			gSubMenuSelection = gSetting_ScrambleEnable;
//			break;

		#ifdef ENABLE_F_CAL_MENU
			case MENU_F_CALI:
				gSubMenuSelection = gEeprom.BK4819_XTAL_FREQ_LOW;
				break;
		#endif

		case MENU_BATCAL:
			gSubMenuSelection = gBatteryCalibration[3];
			break;

		case MENU_BATTYP:
			gSubMenuSelection = gEeprom.BATTERY_TYPE;
			break;

//		case MENU_F1SHRT:
//		case MENU_F1LONG:
//		case MENU_F2SHRT:
//		case MENU_F2LONG:
//		case MENU_MLONG:
//		{
//			uint8_t * fun[]= {
//				&gEeprom.KEY_1_SHORT_PRESS_ACTION,
//				&gEeprom.KEY_1_LONG_PRESS_ACTION,
//				&gEeprom.KEY_2_SHORT_PRESS_ACTION,
//				&gEeprom.KEY_2_LONG_PRESS_ACTION,
//				&gEeprom.KEY_M_LONG_PRESS_ACTION};
//			uint8_t id = *fun[UI_MENU_GetCurrentMenuId()-MENU_F1SHRT];
//
//			for(int i = 0; i < gSubMenu_SIDEFUNCTIONS_size; i++) {
//				if(gSubMenu_SIDEFUNCTIONS[i].id==id) {
//					gSubMenuSelection = i;
//					break;
//				}
//
//			}
//			break;
//		}

		default:
			return;
	}
}

static void MENU_Key_0_to_9(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{
	uint8_t  Offset;
	int32_t  Min;
	int32_t  Max;
	uint16_t Value = 0;

	if (bKeyHeld || !bKeyPressed)
		return;

	gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
uint8_t now_menu=UI_MENU_GetCurrentMenuId();
        uint8_t end_index=now_menu==MENU_MEM_NAME?10:4;
	if (( now_menu== MENU_MEM_NAME||now_menu==MENU_MDC_ID) && edit_index >= 0)
	{	// currently editing the channel name

		if (edit_index < end_index)
		{
			if (Key <= KEY_9)
			{
				edit[edit_index] = '0' + Key - KEY_0;

				if (++edit_index >= end_index)
				{	// exit edit
					gFlagAcceptSetting  = false;
					gAskForConfirmation = 1;
				}

				gRequestDisplayScreen = DISPLAY_MENU;
			}
		}

		return;
	}

	INPUTBOX_Append(Key);

	gRequestDisplayScreen = DISPLAY_MENU;

	if (!gIsInSubMenu)
	{
		switch (gInputBoxIndex)
		{
			case 2:
				gInputBoxIndex = 0;

				Value = (gInputBox[0] * 10) + gInputBox[1];

				if (Value > 0 && Value <= gMenuListCount)
				{
					gMenuCursor         = Value - 1;
					gFlagRefreshSetting = true;
					return;
				}

				if (Value <= gMenuListCount)
					break;

				gInputBox[0]   = gInputBox[1];
				gInputBoxIndex = 1;
				[[fallthrough]];
			case 1:
				Value = gInputBox[0];
				if (Value > 0 && Value <= gMenuListCount)
				{
					gMenuCursor         = Value - 1;
					gFlagRefreshSetting = true;
					return;
				}
				break;
		}

		gInputBoxIndex = 0;

		gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
		return;
	}

	if (UI_MENU_GetCurrentMenuId() == MENU_OFFSET)
	{
		uint32_t Frequency;

		if (gInputBoxIndex < 6)
		{	// invalid frequency
			#ifdef ENABLE_VOICE
				gAnotherVoiceID = (VOICE_ID_t)Key;
			#endif
			return;
		}

		#ifdef ENABLE_VOICE
			gAnotherVoiceID = (VOICE_ID_t)Key;
		#endif
		
		Frequency = StrToUL(INPUTBOX_GetAscii())*100;
		gSubMenuSelection = FREQUENCY_RoundToStep(Frequency, gTxVfo->StepFrequency);

		gInputBoxIndex = 0;
		return;
	}
	
	if (UI_MENU_GetCurrentMenuId() == MENU_MEM_CH || 
		UI_MENU_GetCurrentMenuId() == MENU_DEL_CH || 
		UI_MENU_GetCurrentMenuId() == MENU_1_CALL || 
		UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME)
	{	// enter 3-digit channel number

		if (gInputBoxIndex < 3)
		{
			#ifdef ENABLE_VOICE
				gAnotherVoiceID   = (VOICE_ID_t)Key;
			#endif
			gRequestDisplayScreen = DISPLAY_MENU;
			return;
		}

		gInputBoxIndex = 0;

		Value = ((gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2]) - 1;

		if (IS_MR_CHANNEL(Value))
		{
			#ifdef ENABLE_VOICE
				gAnotherVoiceID = (VOICE_ID_t)Key;
			#endif
			gSubMenuSelection = Value;
			return;
		}

		gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
		return;
	}

	if (MENU_GetLimits(UI_MENU_GetCurrentMenuId(), &Min, &Max))
	{
		gInputBoxIndex = 0;
		gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
		return;
	}

	Offset = (Max >= 100) ? 3 : (Max >= 10) ? 2 : 1;

	switch (gInputBoxIndex)
	{
		case 1:
			Value = gInputBox[0];
			break;
		case 2:
			Value = (gInputBox[0] *  10) + gInputBox[1];
			break;
		case 3:
			Value = (gInputBox[0] * 100) + (gInputBox[1] * 10) + gInputBox[2];
			break;
	}

	if (Offset == gInputBoxIndex)
		gInputBoxIndex = 0;

	if (Value <= Max)
	{
		gSubMenuSelection = Value;
		return;
	}

	gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
}

static void MENU_Key_EXIT(bool bKeyPressed, bool bKeyHeld)
{
	if (bKeyHeld || !bKeyPressed)
		return;

	gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;

	if (!gCssBackgroundScan)
	{
		if (gIsInSubMenu)
		{
			if (gInputBoxIndex == 0 || UI_MENU_GetCurrentMenuId() != MENU_OFFSET)
			{
				gAskForConfirmation = 0;
				gIsInSubMenu        = false;
				gInputBoxIndex      = 0;
				gFlagRefreshSetting = true;

				#ifdef ENABLE_VOICE
					gAnotherVoiceID = VOICE_ID_CANCEL;
				#endif
			}
			else
				gInputBox[--gInputBoxIndex] = 10;

			// ***********************

			gRequestDisplayScreen = DISPLAY_MENU;
			return;
		}

		#ifdef ENABLE_VOICE
			gAnotherVoiceID = VOICE_ID_CANCEL;
		#endif

		gRequestDisplayScreen = DISPLAY_MAIN;

		if (gEeprom.BACKLIGHT_TIME == 0) // backlight set to always off
		{
			BACKLIGHT_TurnOff();	// turn the backlight OFF
		}
	}
	else
	{
		MENU_StopCssScan();

		#ifdef ENABLE_VOICE
			gAnotherVoiceID   = VOICE_ID_SCANNING_STOP;
		#endif

		gRequestDisplayScreen = DISPLAY_MENU;
	}

	gPttWasReleased = true;
}

static void MENU_Key_MENU(const bool bKeyPressed, const bool bKeyHeld)
{
	if (bKeyHeld || !bKeyPressed)
		return;

	gBeepToPlay           = BEEP_1KHZ_60MS_OPTIONAL;
	gRequestDisplayScreen = DISPLAY_MENU;

	if (!gIsInSubMenu)
	{
		#ifdef ENABLE_VOICE
			if (UI_MENU_GetCurrentMenuId() != MENU_SCR)
				gAnotherVoiceID = MenuList[gMenuCursor].voice_id;
		#endif

		#if 1
			if (UI_MENU_GetCurrentMenuId() == MENU_DEL_CH || UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME)
				if (!RADIO_CheckValidChannel(gSubMenuSelection, false, 0))
					return;  // invalid channel
		#endif

		gAskForConfirmation = 0;
		gIsInSubMenu        = true;

//		if (UI_MENU_GetCurrentMenuId() != MENU_D_LIST)
		{
			gInputBoxIndex      = 0;
			edit_index          = -1;
		}

		return;
	}
#ifdef ENABLE_MDC1200
    if (UI_MENU_GetCurrentMenuId() == MENU_MDC_ID)
    {
//        	if (edit_index < 0)
//		{
////                edit_index = 0;
//
//
////			while (edit_index < 4)
////				edit[edit_index++] = '_';
//			edit_index = 0;  // 'edit_index' is going to be used as the cursor position
//			// make a copy so we can test for change when exiting the menu item
//			memmove(edit_original, edit, sizeof(edit_original));
//			return;
//		}
//		else
		if (edit_index >= 0 && edit_index < 4)
		{	// editing the channel name characters

			if (++edit_index < 4)
				return;	// next char

			// exit
			if (memcmp(edit_original, edit, sizeof(edit_original)) == 0)
			{	// no change - drop it
				gFlagAcceptSetting  = false;
				gIsInSubMenu        = false;
				gAskForConfirmation = 0;
			}
			else
			{
				gFlagAcceptSetting  = false;
				gAskForConfirmation = 0;
			}
		}
    }


else
#endif
    if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME)
	{
		if (edit_index < 0)
		{	// enter channel name edit mode
			if (!RADIO_CheckValidChannel(gSubMenuSelection, false, 0))
				return;

            SETTINGS_FetchChannelName(edit, gSubMenuSelection);
			// pad the channel name out with '_'
			edit_index = strlen(edit);
			while (edit_index < 10)
				edit[edit_index++] = '_';
			edit[edit_index] = 0;
			edit_index = 0;  // 'edit_index' is going to be used as the cursor position

			// make a copy so we can test for change when exiting the menu item
			memmove(edit_original, edit, sizeof(edit_original));

			return;
		}
		else
		if (edit_index >= 0 && edit_index < 10)
		{	// editing the channel name characters

			if (++edit_index < 10)
				return;	// next char

			// exit
			if (memcmp(edit_original, edit, sizeof(edit_original)) == 0)
			{	// no change - drop it
				gFlagAcceptSetting  = false;
				gIsInSubMenu        = false;
				gAskForConfirmation = 0;
			}
			else
			{
				gFlagAcceptSetting  = false;
				gAskForConfirmation = 0;
			}
		}
	}

	// exiting the sub menu

	if (gIsInSubMenu)
	{
		if (UI_MENU_GetCurrentMenuId() == MENU_RESET  ||
			UI_MENU_GetCurrentMenuId() == MENU_MEM_CH ||
			UI_MENU_GetCurrentMenuId() == MENU_DEL_CH ||
			UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME||
                UI_MENU_GetCurrentMenuId() == MENU_MDC_ID)
		{
			switch (gAskForConfirmation)
			{
				case 0:
					gAskForConfirmation = 1;
					break;

				case 1:
					gAskForConfirmation = 2;

					UI_DisplayMenu();

					if (UI_MENU_GetCurrentMenuId() == MENU_RESET)
					{
						#ifdef ENABLE_VOICE
							AUDIO_SetVoiceID(0, VOICE_ID_CONFIRM);
							AUDIO_PlaySingleVoice(true);
						#endif

						MENU_AcceptSetting();

						#if defined(ENABLE_OVERLAY)
							overlay_FLASH_RebootToBootloader();
						#else
							NVIC_SystemReset();
						#endif
					}

					gFlagAcceptSetting  = true;
					gIsInSubMenu        = false;
					gAskForConfirmation = 0;
			}
		}
		else
		{
			gFlagAcceptSetting = true;
			gIsInSubMenu       = false;
		}
	}

	SCANNER_Stop();

	#ifdef ENABLE_VOICE
		if (UI_MENU_GetCurrentMenuId() == MENU_SCR)
			gAnotherVoiceID = (gSubMenuSelection == 0) ? VOICE_ID_SCRAMBLER_OFF : VOICE_ID_SCRAMBLER_ON;
		else
			gAnotherVoiceID = VOICE_ID_CONFIRM;
	#endif

	gInputBoxIndex = 0;
}

static void MENU_Key_STAR(const bool bKeyPressed, const bool bKeyHeld)
{
	if (bKeyHeld || !bKeyPressed)
		return;

	gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;

	if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0)
	{	// currently editing the channel name

		if (edit_index < 10)
		{
			edit[edit_index] = '-';

			if (++edit_index >= 10)
			{	// exit edit
				gFlagAcceptSetting  = false;
				gAskForConfirmation = 1;
			}

			gRequestDisplayScreen = DISPLAY_MENU;
		}

		return;
	}

	RADIO_SelectVfos();

	#ifdef ENABLE_NOAA
		if (!IS_NOAA_CHANNEL(gRxVfo->CHANNEL_SAVE) && gRxVfo->Modulation == MODULATION_FM)
	#else
		if (gRxVfo->Modulation ==  MODULATION_FM)
	#endif
	{
		if ((UI_MENU_GetCurrentMenuId() == MENU_R_CTCS || UI_MENU_GetCurrentMenuId() == MENU_R_DCS) && gIsInSubMenu)
		{	// scan CTCSS or DCS to find the tone/code of the incoming signal
			if (!SCANNER_IsScanning())
				MENU_StartCssScan();
			else
				MENU_StopCssScan();
		}

		gPttWasReleased = true;
		return;
	}

	gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
}

static void MENU_Key_UP_DOWN(bool bKeyPressed, bool bKeyHeld, int8_t Direction)
{
	uint8_t VFO;
	uint8_t Channel;
	bool    bCheckScanList;
if( gIsInSubMenu && edit_index >= 0){
        if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME) {    // change the character
            if (bKeyPressed && edit_index < 10 ) {
                const char unwanted[] = "$%&!\"':;?^`|{}";
                char c = edit[edit_index] + Direction;
                unsigned int i = 0;
                while (i < sizeof(unwanted) && c >= 32 && c <= 126) {
                    if (c == unwanted[i++]) {    // choose next character
                        c += Direction;
                        i = 0;
                    }
                }
                edit[edit_index] = (c < 32) ? 126 : (c > 126) ? 32 : c;

                gRequestDisplayScreen = DISPLAY_MENU;
            }
            return;
        } else if (UI_MENU_GetCurrentMenuId() == MENU_MDC_ID)
        {
            if (bKeyPressed && edit_index < 4 ) {
                char c = edit[edit_index] + Direction;
                    if(c<'0')c='F';
                    else if(c>'F')c='0';
                    else if(c>'9'&&c<'A'){
                        if(Direction==1)c='A';
                        else c='9';
                    }

                edit[edit_index]=c;
                gRequestDisplayScreen = DISPLAY_MENU;
            }
            return;
        }
    }
	if (!bKeyHeld)
	{
		if (!bKeyPressed)
			return;

		gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;

		gInputBoxIndex = 0;
	}
	else
	if (!bKeyPressed)
		return;

	if (SCANNER_IsScanning()) {
		return;
	}

	if (!gIsInSubMenu)
	{
		gMenuCursor = NUMBER_AddWithWraparound(gMenuCursor, -Direction, 0, gMenuListCount - 1);

		gFlagRefreshSetting = true;

		gRequestDisplayScreen = DISPLAY_MENU;

		if (UI_MENU_GetCurrentMenuId() != MENU_ABR && gEeprom.BACKLIGHT_TIME == 0) // backlight always off and not in the backlight menu
		{
			BACKLIGHT_TurnOff();
		}

		return;
	}

	if (UI_MENU_GetCurrentMenuId() == MENU_OFFSET)
	{
		int32_t Offset = (Direction * gTxVfo->StepFrequency) + gSubMenuSelection;
		if (Offset < 99999990)
		{
			if (Offset < 0)
				Offset = 99999990;
		}
		else
			Offset = 0;

		gSubMenuSelection     = FREQUENCY_RoundToStep(Offset, gTxVfo->StepFrequency);
		gRequestDisplayScreen = DISPLAY_MENU;
		return;
	}

	VFO = 0;

	switch (UI_MENU_GetCurrentMenuId())
	{
		case MENU_DEL_CH:
		case MENU_1_CALL:
		case MENU_MEM_NAME:
			bCheckScanList = false;
			break;

		case MENU_SLIST2:
			VFO = 1;
			[[fallthrough]];
		case MENU_SLIST1:
			bCheckScanList = true;
			break;

		default:
			MENU_ClampSelection(Direction);
			gRequestDisplayScreen = DISPLAY_MENU;
			return;
	}

	Channel = RADIO_FindNextChannel(gSubMenuSelection + Direction, Direction, bCheckScanList, VFO);
	if (Channel != 0xFF)
		gSubMenuSelection = Channel;

	gRequestDisplayScreen = DISPLAY_MENU;
}

void MENU_ProcessKeys(KEY_Code_t Key, bool bKeyPressed, bool bKeyHeld)
{
	switch (Key)
	{
		case KEY_0:
		case KEY_1:
		case KEY_2:
		case KEY_3:
		case KEY_4:
		case KEY_5:
		case KEY_6:
		case KEY_7:
		case KEY_8:
		case KEY_9:
			MENU_Key_0_to_9(Key, bKeyPressed, bKeyHeld);
			break;
		case KEY_MENU:
			MENU_Key_MENU(bKeyPressed, bKeyHeld);
			break;
		case KEY_UP:
			MENU_Key_UP_DOWN(bKeyPressed, bKeyHeld,  1);
			break;
		case KEY_DOWN:
			MENU_Key_UP_DOWN(bKeyPressed, bKeyHeld, -1);
			break;
		case KEY_EXIT:
			MENU_Key_EXIT(bKeyPressed, bKeyHeld);
			break;
		case KEY_STAR:
			MENU_Key_STAR(bKeyPressed, bKeyHeld);
			break;
		case KEY_F:
			if (UI_MENU_GetCurrentMenuId() == MENU_MEM_NAME && edit_index >= 0)
			{	// currently editing the channel name
				if (!bKeyHeld && bKeyPressed)
				{
					gBeepToPlay = BEEP_1KHZ_60MS_OPTIONAL;
					if (edit_index < 10)
					{
						edit[edit_index] = ' ';
						if (++edit_index >= 10)
						{	// exit edit
							gFlagAcceptSetting  = false;
							gAskForConfirmation = 1;
						}
						gRequestDisplayScreen = DISPLAY_MENU;
					}
				}
				break;
			}

			GENERIC_Key_F(bKeyPressed, bKeyHeld);
			break;
		case KEY_PTT:
			GENERIC_Key_PTT(bKeyPressed);
			break;
		default:
			if (!bKeyHeld && bKeyPressed)
				gBeepToPlay = BEEP_500HZ_60MS_DOUBLE_BEEP_OPTIONAL;
			break;
	}

	if (gScreenToDisplay == DISPLAY_MENU)
	{
		if (/*UI_MENU_GetCurrentMenuId() == MENU_VOL||*/
			#ifdef ENABLE_F_CAL_MENU
            	UI_MENU_GetCurrentMenuId() == MENU_F_CALI||
            #endif
            UI_MENU_GetCurrentMenuId() == MENU_BATCAL
            )
		{
			gMenuCountdown = menu_timeout_long_500ms;
		}
		else
		{
			gMenuCountdown = menu_timeout_500ms;
		}
	}
}