diff --git a/Makefile b/Makefile index 80aba43..cbeea32 100644 --- a/Makefile +++ b/Makefile @@ -51,6 +51,7 @@ ENABLE_WIDE_RX := 1 ENABLE_TX_WHEN_AM := 0 # Freq calibration 188 B ENABLE_F_CAL_MENU := 0 +ENABLE_FM_DEV_CAL_MENU := 1 ENABLE_TX_UNLOCK_MENU := 0 #ENABLE_TX_POWER_CAL_MENU := 0 ENABLE_TX_POWER_FIX := 1 @@ -392,6 +393,9 @@ endif ifeq ($(ENABLE_F_CAL_MENU),1) CFLAGS += -DENABLE_F_CAL_MENU endif +ifeq ($(ENABLE_FM_DEV_CAL_MENU),1) + CFLAGS += -DENABLE_FM_DEV_CAL_MENU +endif ifeq ($(ENABLE_TX_UNLOCK_MENU),1) CFLAGS += -DENABLE_TX_UNLOCK_MENU endif diff --git a/README.md b/README.md index 1ec859d..dd8cb4f 100644 --- a/README.md +++ b/README.md @@ -71,6 +71,7 @@ ENABLE_TRIM_TRAILING_ZEROS := 1 trim away any trailing zeros on freq ENABLE_WIDE_RX := 1 full 18MHz to 1300MHz RX (though front-end/PA not designed for full range) ENABLE_TX_WHEN_AM := 0 allow TX (always FM) when RX is set to AM ENABLE_F_CAL_MENU := 0 enable frequency calibration hidden menu +ENABLE_FM_DEV_CAL_MENU := 0 enable FM deviation calibration hidden menu ENABLE_TX_UNLOCK_MENU := 0 allow TX everywhere EXCEPT airband (108~137) .. TX harmonic content will cause interference to other services, do so entirely at your own risk ! ENABLE_TX_POWER_CAL_MENU := 0 used to compute the TX power register values .. leave at '0' ENABLE_TX_POWER_FIX := 1 fix the TX output power, L ~ 10mW, M ~ 500mW, H ~ 4W, U ~ user settable diff --git a/app/menu.c b/app/menu.c index c7ed1f1..086ba3e 100644 --- a/app/menu.c +++ b/app/menu.c @@ -140,7 +140,7 @@ int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax) *pMin = 2; // 1 second *pMax = 40; // 20 seconds break; - + case MENU_CROSS_VFO: *pMin = 0; *pMax = ARRAY_SIZE(g_sub_menu_cross_vfo) - 1; @@ -222,7 +222,7 @@ int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax) *pMax = 45; break; #endif - + #ifdef ENABLE_AM_FIX_TEST1 case MENU_AM_FIX_TEST1: *pMin = 0; @@ -334,13 +334,13 @@ int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax) *pMin = 0; *pMax = ARRAY_SIZE(g_sub_menu_mdc1200_mode) - 1; break; - + case MENU_MDC1200_ID: *pMin = 0; *pMax = 0xffff; break; #endif - + case MENU_PTT_ID: *pMin = 0; *pMax = ARRAY_SIZE(g_sub_menu_ptt_id) - 1; @@ -373,6 +373,18 @@ int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax) break; #endif + #ifdef ENABLE_FM_DEV_CAL_MENU + case MENU_TX_FM_DEV_CAL_N: + *pMin = FM_DEV_LIMIT_LOWER_NARROW; + *pMax = FM_DEV_LIMIT_UPPER_NARROW; + break; + + case MENU_TX_FM_DEV_CAL_W: + *pMin = FM_DEV_LIMIT_LOWER_WIDE; + *pMax = FM_DEV_LIMIT_UPPER_WIDE; + break; + #endif + #ifdef ENABLE_F_CAL_MENU case MENU_F_CALI: *pMin = -50; @@ -593,7 +605,7 @@ void MENU_AcceptSetting(void) ST7565_SetContrast(g_eeprom.config.setting.lcd_contrast); break; #endif - + case MENU_DUAL_WATCH: // g_eeprom.config.setting.dual_watch = g_sub_menu_selection; g_eeprom.config.setting.dual_watch = (g_sub_menu_selection > 0) ? 1 + g_eeprom.config.setting.tx_vfo_num : DUAL_WATCH_OFF; @@ -663,7 +675,7 @@ void MENU_AcceptSetting(void) case MENU_S_ADD2: g_tx_vfo->channel_attributes.scanlist2 = g_sub_menu_selection; SETTINGS_save_chan_attribs_name(g_tx_vfo->channel_save, g_tx_vfo); - g_vfo_configure_mode = VFO_CONFIGURE; + g_vfo_configure_mode = VFO_CONFIGURE; g_flag_reset_vfos = true; return; @@ -910,6 +922,26 @@ void MENU_AcceptSetting(void) break; #endif + #ifdef ENABLE_FM_DEV_CAL_MENU + case MENU_TX_FM_DEV_CAL_N: + g_eeprom.calib.deviation_narrow = g_sub_menu_selection; + { + uint16_t index = (uint16_t)(((uint8_t *)&g_eeprom.calib.deviation_narrow) - ((uint8_t *)&g_eeprom)); + index &= ~7u; + EEPROM_WriteBuffer8(index, &g_eeprom.calib.deviation_narrow); + } + break; + + case MENU_TX_FM_DEV_CAL_W: + g_eeprom.calib.deviation_wide = g_sub_menu_selection; + { + uint16_t index = (uint16_t)(((uint8_t *)&g_eeprom.calib.deviation_wide) - ((uint8_t *)&g_eeprom)); + index &= ~7u; + EEPROM_WriteBuffer8(index, &g_eeprom.calib.deviation_wide); + } + break; + #endif + #ifdef ENABLE_F_CAL_MENU case MENU_F_CALI: writeXtalFreqCal(g_sub_menu_selection, true); @@ -1007,7 +1039,7 @@ void MENU_ShowCurrentSetting(void) case MENU_STEP: g_sub_menu_selection = FREQUENCY_get_step_index(STEP_FREQ_TABLE[g_tx_vfo->channel.step_setting]); break; - + case MENU_TX_POWER: g_sub_menu_selection = g_tx_vfo->channel.tx_power; break; @@ -1111,7 +1143,7 @@ void MENU_ShowCurrentSetting(void) g_sub_menu_selection = g_eeprom.config.setting.lcd_contrast; break; #endif - + case MENU_DUAL_WATCH: // g_sub_menu_selection = g_eeprom.config.setting.dual_watch; g_sub_menu_selection = (g_eeprom.config.setting.dual_watch == DUAL_WATCH_OFF) ? 0 : 1; @@ -1389,6 +1421,16 @@ void MENU_ShowCurrentSetting(void) break; #endif + #ifdef ENABLE_FM_DEV_CAL_MENU + case MENU_TX_FM_DEV_CAL_N: + g_sub_menu_selection = g_eeprom.calib.deviation_narrow; + break; + + case MENU_TX_FM_DEV_CAL_W: + g_sub_menu_selection = g_eeprom.calib.deviation_wide; + break; + #endif + #ifdef ENABLE_F_CAL_MENU case MENU_F_CALI: g_sub_menu_selection = g_eeprom.calib.bk4819_xtal_freq_low; @@ -1410,7 +1452,7 @@ static void MENU_Key_0_to_9(key_code_t Key, bool key_pressed, bool key_held) int32_t min; int32_t max; uint32_t value = 0; - + if (key_held || !key_pressed) return; @@ -1428,7 +1470,7 @@ static void MENU_Key_0_to_9(key_code_t Key, bool key_pressed, bool key_held) { #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wtype-limits" - + if (Key >= KEY_0 && Key <= KEY_9) { g_edit[g_edit_index] = '0' + Key - KEY_0; @@ -1530,13 +1572,17 @@ static void MENU_Key_0_to_9(key_code_t Key, bool key_pressed, bool key_held) #if defined(ENABLE_UART) && defined(ENABLE_UART_DEBUG) // UART_printf("offset 4 %u\r\n", Frequency); #endif - + g_sub_menu_selection = Frequency; return; } - if (g_menu_cursor == MENU_BAT_CAL) + #ifdef ENABLE_FM_DEV_CAL_MENU + if (g_menu_cursor == MENU_BAT_CAL || g_menu_cursor == MENU_TX_FM_DEV_CAL_N || g_menu_cursor == MENU_TX_FM_DEV_CAL_W) + #else + if (g_menu_cursor == MENU_BAT_CAL) + #endif { g_sub_menu_selection = INPUTBOX_value(); // get the current value from the input box @@ -1721,7 +1767,7 @@ static void MENU_Key_MENU(const bool key_pressed, const bool key_held) { // save the new power level g_tx_vfo->channel.tx_power_user = g_edit_index; g_request_save_channel = 1; - + g_flag_accept_setting = true; g_in_sub_menu = false; g_edit_index = -1; @@ -1989,10 +2035,10 @@ static void MENU_Key_UP_DOWN(bool key_pressed, bool key_held, int8_t Direction) const int32_t max_freq = MAX_TX_OFFSET; const int32_t step_size = g_tx_vfo->step_freq; int32_t offset = (int32_t)g_sub_menu_selection + (Direction * step_size); - + // wrap if (offset >= max_freq) - offset = 0; + offset = 0; else if (offset < 0) offset = max_freq - step_size; @@ -2006,7 +2052,7 @@ static void MENU_Key_UP_DOWN(bool key_pressed, bool key_held, int8_t Direction) #if defined(ENABLE_UART) && defined(ENABLE_UART_DEBUG) UART_printf("offset 2 %u %u\r\n", offset, step_size); #endif - + g_sub_menu_selection = offset; g_request_display_screen = DISPLAY_MENU; return; diff --git a/driver/bk4819.c b/driver/bk4819.c index cd3695a..2716846 100644 --- a/driver/bk4819.c +++ b/driver/bk4819.c @@ -404,10 +404,10 @@ void BK4819_EnableVox(uint16_t VoxEnableThreshold, uint16_t VoxDisableThreshold) BK4819_write_reg(0x31, BK4819_read_reg(0x31) | (1u << 2)); } -void BK4819_set_TX_deviation(const bool narrow) +void BK4819_set_TX_deviation(uint16_t deviation) { // const uint8_t scrambler = (BK4819_read_reg(0x31) >> 1) & 1u; - uint16_t deviation = narrow ? 900 : 1232; +// uint16_t deviation = narrow ? 900 : 1232; // if (scrambler) // deviation -= 200; if (deviation > 4095) diff --git a/driver/bk4819.h b/driver/bk4819.h index 982587c..e3e5860 100644 --- a/driver/bk4819.h +++ b/driver/bk4819.h @@ -79,7 +79,7 @@ void BK4819_set_CTCSS_freq(const uint32_t control_word); void BK4819_set_tail_detection(const uint32_t freq_10Hz); void BK4819_EnableVox(uint16_t Vox1Threshold, uint16_t Vox0Threshold); -void BK4819_set_TX_deviation(const bool narrow); +void BK4819_set_TX_deviation(uint16_t deviation); void BK4819_SetFilterBandwidth(const BK4819_filter_bandwidth_t Bandwidth); diff --git a/firmware.bin b/firmware.bin index 3eec40c..c6c936a 100644 Binary files a/firmware.bin and b/firmware.bin differ diff --git a/firmware.packed.bin b/firmware.packed.bin index d89b36b..6ae884a 100644 Binary files a/firmware.packed.bin and b/firmware.packed.bin differ diff --git a/radio.c b/radio.c index 1c985df..f040c86 100644 --- a/radio.c +++ b/radio.c @@ -413,8 +413,8 @@ void RADIO_configure_channel(const unsigned int VFO, const unsigned int configur uint16_t threshold_enable; uint16_t threshold_disable; - if (level > (ARRAY_SIZE(g_eeprom.calib.vox[0].threshold) - 1)) - level = ARRAY_SIZE(g_eeprom.calib.vox[0].threshold) - 1; + if (level > (ARRAY_SIZE(g_eeprom.calib.vox_threshold_enable) - 1)) + level = ARRAY_SIZE(g_eeprom.calib.vox_threshold_enable) - 1; // my eeprom values .. // @@ -423,11 +423,11 @@ void RADIO_configure_channel(const unsigned int VFO, const unsigned int configur // #ifdef ENABLE_VOX_MORE_SENSITIVE // more sensitive - threshold_enable = g_eeprom.calib.vox[0].threshold[level] / 3; + threshold_enable = g_eeprom.calib.vox_threshold_enable[level] / 3; threshold_disable = (threshold_enable > 13) ? threshold_enable - 10 : 3; #else - threshold_enable = g_eeprom.calib.vox[0].threshold[level]; - threshold_disable = g_eeprom.calib.vox[1].threshold[level]; + threshold_enable = g_eeprom.calib.vox_threshold_enable[level]; + threshold_disable = g_eeprom.calib.vox_threshold_disable[level]; #endif BK4819_EnableVox(threshold_enable, threshold_disable); @@ -688,6 +688,8 @@ void RADIO_select_vfos(void) BK4819_filter_bandwidth_t RADIO_set_bandwidth(BK4819_filter_bandwidth_t bandwidth, const int mode) { + uint16_t deviation; + switch (bandwidth) { default: @@ -719,6 +721,44 @@ BK4819_filter_bandwidth_t RADIO_set_bandwidth(BK4819_filter_bandwidth_t bandwidt break; } + #ifdef ENABLE_FM_DEV_CAL_MENU + switch (bandwidth) + { + case BK4819_FILTER_BW_WIDE: + if (g_eeprom.calib.deviation_wide < FM_DEV_LIMIT_LOWER_WIDE || g_eeprom.calib.deviation_wide > FM_DEV_LIMIT_UPPER_WIDE) + deviation = FM_DEV_LIMIT_DEFAULT_WIDE; + else + deviation = g_eeprom.calib.deviation_wide; + break; + case BK4819_FILTER_BW_NARROW: + if (g_eeprom.calib.deviation_narrow < FM_DEV_LIMIT_LOWER_NARROW || g_eeprom.calib.deviation_narrow > FM_DEV_LIMIT_UPPER_NARROW) + deviation = FM_DEV_LIMIT_DEFAULT_NARROW; + else + deviation = g_eeprom.calib.deviation_narrow; + break; + case BK4819_FILTER_BW_NARROWER: + if (g_eeprom.calib.deviation_narrow < FM_DEV_LIMIT_LOWER_NARROW || g_eeprom.calib.deviation_narrow > FM_DEV_LIMIT_UPPER_NARROW) + deviation = FM_DEV_LIMIT_DEFAULT_NARROW; + else + deviation = g_eeprom.calib.deviation_narrow; + break; + } + #else + switch (bandwidth) + { + case BK4819_FILTER_BW_WIDE: + deviation = g_eeprom.calib.deviation_wide; + break; + case BK4819_FILTER_BW_NARROW: + deviation = g_eeprom.calib.deviation_narrow; + break; + case BK4819_FILTER_BW_NARROWER: + deviation = g_eeprom.calib.deviation_narrow; + break; + } + #endif + BK4819_set_TX_deviation(deviation); + BK4819_SetFilterBandwidth(bandwidth); return bandwidth; diff --git a/settings.c b/settings.c index 03fe579..9c52d27 100644 --- a/settings.c +++ b/settings.c @@ -52,8 +52,9 @@ void SETTINGS_write_eeprom_config(void) void SETTINGS_write_eeprom_calib(void) { // save the entire EEPROM calibration contents - const unsigned int index = (unsigned int)(((uint8_t *)&g_eeprom.calib) - ((uint8_t *)&g_eeprom)); unsigned int i; + unsigned int index = (unsigned int)(((uint8_t *)&g_eeprom.calib) - ((uint8_t *)&g_eeprom)); + index &= ~7u; for (i = 0; i < sizeof(g_eeprom.calib); i += 8) EEPROM_WriteBuffer8(index + i, ((uint8_t *)&g_eeprom.calib) + i); } @@ -65,9 +66,11 @@ void SETTINGS_write_eeprom_calib(void) unsigned int index; index = (unsigned int)(((uint8_t *)&g_eeprom.config.setting.fm_radio) - ((uint8_t *)&g_eeprom)); + index &= ~7u; EEPROM_WriteBuffer8(index, &g_eeprom.config.setting.fm_radio); index = (unsigned int)(((uint8_t *)&g_eeprom.config.setting.fm_channel) - ((uint8_t *)&g_eeprom)); + index &= ~7u; for (i = 0; i < sizeof(g_eeprom.config.setting.fm_channel); i += 8) EEPROM_WriteBuffer8(index + i, ((uint8_t *)&g_eeprom.config.setting.fm_channel) + i); } @@ -75,14 +78,16 @@ void SETTINGS_write_eeprom_calib(void) void SETTINGS_save_vfo_indices(void) { - const uint16_t index = (uint16_t)(((uint8_t *)&g_eeprom.config.setting.indices) - ((uint8_t *)&g_eeprom)); + uint16_t index = (uint16_t)(((uint8_t *)&g_eeprom.config.setting.indices) - ((uint8_t *)&g_eeprom)); + index &= ~7u; EEPROM_WriteBuffer8(index, &g_eeprom.config.setting.indices); } void SETTINGS_save_attributes(void) { unsigned int i; - const unsigned int index = (unsigned int )(((uint8_t *)&g_eeprom.config.channel_attributes) - ((uint8_t *)&g_eeprom)); + unsigned int index = (unsigned int )(((uint8_t *)&g_eeprom.config.channel_attributes) - ((uint8_t *)&g_eeprom)); + index &= ~7u; for (i = 0; i < sizeof(g_eeprom.config.channel_attributes); i += 8) EEPROM_WriteBuffer8(index + i, ((uint8_t *)&g_eeprom.config.channel_attributes) + i); } @@ -90,7 +95,8 @@ void SETTINGS_save_attributes(void) void SETTINGS_save_channel_names(void) { unsigned int i; - const unsigned int index = (unsigned int)(((uint8_t *)&g_eeprom.config.channel_name) - ((uint8_t *)&g_eeprom)); + unsigned int index = (unsigned int)(((uint8_t *)&g_eeprom.config.channel_name) - ((uint8_t *)&g_eeprom)); + index &= ~7u; for (i = 0; i < sizeof(g_eeprom.config.channel_name); i += 8) EEPROM_WriteBuffer8(index + i, ((uint8_t *)&g_eeprom.config.channel_name) + i); } @@ -116,6 +122,7 @@ void SETTINGS_read_eeprom(void) #if 1 // channel sanity checks .. + for (index = 0; index < ARRAY_SIZE(g_eeprom.config.channel); index++) { // if (g_eeprom.config.channel_attributes[index].band <= BAND7_470MHz) @@ -392,6 +399,13 @@ void SETTINGS_read_eeprom(void) // memset(&g_eeprom.calib.unused3, 0xff, sizeof(g_eeprom.calib.unused3)); +// #ifdef ENABLE_FM_DEV_CAL_MENU + if (g_eeprom.calib.deviation_narrow < FM_DEV_LIMIT_LOWER_NARROW || g_eeprom.calib.deviation_narrow > FM_DEV_LIMIT_UPPER_NARROW) + g_eeprom.calib.deviation_narrow = FM_DEV_LIMIT_DEFAULT_NARROW; + if (g_eeprom.calib.deviation_wide < FM_DEV_LIMIT_LOWER_WIDE || g_eeprom.calib.deviation_wide > FM_DEV_LIMIT_UPPER_WIDE) + g_eeprom.calib.deviation_wide = FM_DEV_LIMIT_DEFAULT_WIDE; +// #endif + if (g_eeprom.calib.battery[0] >= 5000) { g_eeprom.calib.battery[0] = 1900; @@ -485,13 +499,13 @@ void SETTINGS_save_channel(const unsigned int channel, const unsigned int vfo, v const unsigned int chan = CHANNEL_NUM(channel, vfo); const unsigned int addr = sizeof(t_channel) * chan; t_channel m_channel; - + if (p_vfo != NULL) memcpy(&m_channel, &p_vfo->channel, sizeof(t_channel)); else if (channel <= USER_CHANNEL_LAST) memset(&m_channel, 0xff, sizeof(t_channel)); - + #if defined(ENABLE_UART) && defined(ENABLE_UART_DEBUG) // UART_printf("save chan 2 %04X %3u %3u %u %u %uHz %uHz\r\n", addr, chan, channel, vfo, mode, m_channel.frequency * 10, m_channel.tx_offset * 10); #endif diff --git a/settings.h b/settings.h index 7f9702f..84d4b77 100644 --- a/settings.h +++ b/settings.h @@ -24,6 +24,16 @@ #include "dcs.h" #include "frequencies.h" +enum { + FM_DEV_LIMIT_LOWER_NARROW = 700, + FM_DEV_LIMIT_DEFAULT_NARROW = 900, + FM_DEV_LIMIT_UPPER_NARROW = 1100, + + FM_DEV_LIMIT_LOWER_WIDE = 950, + FM_DEV_LIMIT_DEFAULT_WIDE = 1250, + FM_DEV_LIMIT_UPPER_WIDE = 1500 +}; + enum mod_mode_e { MOD_MODE_FM = 0, MOD_MODE_AM, @@ -518,10 +528,19 @@ typedef struct { #endif // 0x1F50 - struct { - uint16_t threshold[10]; // - uint8_t unused[4]; // 0xff's - } __attribute__((packed)) vox[2]; + uint16_t vox_threshold_enable[10]; // + uint8_t unused[4]; // 0xff's + + // 0x1F68 + uint16_t vox_threshold_disable[10]; // +// #ifdef ENABLE_FM_DEV_CAL_MENU + // 1of11 + uint16_t deviation_narrow; // + uint16_t deviation_wide; // +// #else +// // QS +// uint8_t unused[4]; // 0xff's +// #endif // 0x1F80 uint8_t mic_gain_dB2[5]; // diff --git a/ui/menu.c b/ui/menu.c index 53b6a69..060cc01 100644 --- a/ui/menu.c +++ b/ui/menu.c @@ -163,8 +163,13 @@ const t_menu_item g_menu_list[] = {"TX CAL", VOICE_ID_INVALID, MENU_TX_CALI, }, // L/M/H TX power calibration #endif +#ifdef ENABLE_FM_DEV_CAL_MENU + {"FN CAL", VOICE_ID_INVALID, MENU_TX_FM_DEV_CAL_N, }, // narrow FM deviation calibration + {"FW CAL", VOICE_ID_INVALID, MENU_TX_FM_DEV_CAL_W, }, // wide FM deviation calibration +#endif + #ifdef ENABLE_F_CAL_MENU - {"F CAL", VOICE_ID_INVALID, MENU_F_CALI }, // reference xtal calibration + {"FR CAL", VOICE_ID_INVALID, MENU_F_CALI }, // reference xtal calibration #endif {"F LOCK", VOICE_ID_INVALID, MENU_FREQ_LOCK }, // country/area specific @@ -180,8 +185,8 @@ const t_menu_item g_menu_list[] = // ************************************ }; -// number of hidden menu items at the end of the list - KEEP THIS CORRECT -const unsigned int g_hidden_menu_count = 9; +// number of hidden menu items at the end of the list - KEEP THIS CORRECT ! +const unsigned int g_hidden_menu_count = 12; // *************************************************************************************** @@ -441,6 +446,10 @@ void UI_SortMenu(const bool hide_hidden) hidden_menu_count--; #endif + #ifndef ENABLE_FM_DEV_CAL_MENU + hidden_menu_count -= 2; + #endif + #ifndef ENABLE_F_CAL_MENU hidden_menu_count--; #endif @@ -1233,6 +1242,17 @@ void UI_DisplayMenu(void) break; #endif + #ifdef ENABLE_FM_DEV_CAL_MENU + case MENU_TX_FM_DEV_CAL_N: // narrow FM deviation calibration + case MENU_TX_FM_DEV_CAL_W: // wide FM deviation calibration + strcpy(str, "FM DEV "); + strcat(str, (g_menu_cursor == MENU_TX_FM_DEV_CAL_N) ? "N\n" : "W\n"); + sprintf(str + strlen(str), g_in_sub_menu ? "> %04d" : "%d", g_sub_menu_selection); + if (g_current_function == FUNCTION_TRANSMIT) + BK4819_set_TX_deviation(g_sub_menu_selection); + break; + #endif + #ifdef ENABLE_F_CAL_MENU case MENU_F_CALI: { diff --git a/ui/menu.h b/ui/menu.h index a5b4ae4..09457c3 100644 --- a/ui/menu.h +++ b/ui/menu.h @@ -155,6 +155,11 @@ enum MENU_TX_CALI, // L/M/H TX power calibration #endif +#ifdef ENABLE_FM_DEV_CAL_MENU + MENU_TX_FM_DEV_CAL_N, // narrow FM deviation calibration + MENU_TX_FM_DEV_CAL_W, // wide FM deviation calibration +#endif + #ifdef ENABLE_F_CAL_MENU MENU_F_CALI, // 26MHz reference xtal calibration #endif