diff --git a/Makefile b/Makefile index 609c065..40d4a2e 100644 --- a/Makefile +++ b/Makefile @@ -19,7 +19,7 @@ ENABLE_AIRCOPY_RX_REBOOT := 0 ENABLE_FMRADIO_64_76 := 0 ENABLE_FMRADIO_76_90 := 0 ENABLE_FMRADIO_76_108 := 0 -ENABLE_FMRADIO_875_108 := 1 +ENABLE_FMRADIO_875_108 := 0 ENABLE_FMRADIO_64_108 := 0 # NOAA 1.2 kB ENABLE_NOAA := 0 @@ -29,7 +29,6 @@ ENABLE_MUTE_RADIO_FOR_VOICE := 0 # Tx on Voice 1.0 kB ENABLE_VOX := 0 ENABLE_VOX_MORE_SENSITIVE := 1 -ENABLE_REDUCE_LOW_MID_TX_POWER := 1 # Tx Alarm 600 B ENABLE_ALARM := 0 ENABLE_TX1750 := 0 @@ -51,7 +50,9 @@ ENABLE_WIDE_RX := 1 ENABLE_TX_WHEN_AM := 0 # Freq calibration 188 B ENABLE_F_CAL_MENU := 0 -ENABLE_TX_UNLOCK := 0 +ENABLE_TX_UNLOCK_MENU := 0 +ENABLE_TX_POWER_CAL_MENU := 0 +ENABLE_FIX_TX_POWER := 1 ENABLE_CTCSS_TAIL_PHASE_SHIFT := 1 ENABLE_CONTRAST := 0 ENABLE_BOOT_BEEPS := 0 @@ -354,8 +355,8 @@ endif ifeq ($(ENABLE_VOX_MORE_SENSITIVE),1) CFLAGS += -DENABLE_VOX_MORE_SENSITIVE endif -ifeq ($(ENABLE_REDUCE_LOW_MID_TX_POWER),1) - CFLAGS += -DENABLE_REDUCE_LOW_MID_TX_POWER +ifeq ($(ENABLE_FIX_TX_POWER),1) + CFLAGS += -DENABLE_FIX_TX_POWER endif ifeq ($(ENABLE_ALARM),1) CFLAGS += -DENABLE_ALARM @@ -387,8 +388,11 @@ endif ifeq ($(ENABLE_F_CAL_MENU),1) CFLAGS += -DENABLE_F_CAL_MENU endif -ifeq ($(ENABLE_TX_UNLOCK),1) - CFLAGS += -DENABLE_TX_UNLOCK +ifeq ($(ENABLE_TX_UNLOCK_MENU),1) + CFLAGS += -DENABLE_TX_UNLOCK_MENU +endif +ifeq ($(ENABLE_TX_POWER_CAL_MENU),1) + CFLAGS += -DENABLE_TX_POWER_CAL_MENU endif ifeq ($(ENABLE_CTCSS_TAIL_PHASE_SHIFT),1) CFLAGS += -DENABLE_CTCSS_TAIL_PHASE_SHIFT diff --git a/README.md b/README.md index b54b4e3..2152a57 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,6 @@ ENABLE_VOICE := 0 want to hear voices ? ENABLE_MUTE_RADIO_FOR_VOICE := 1 mute the radios audio when a voice is playing ENABLE_VOX := 0 voice operated transmission ENABLE_VOX_MORE_SENSITIVE := 1 make VOX more sensitive -ENABLE_REDUCE_LOW_MID_TX_POWER := 1 reduce the low and mid TX power levels (high remains unchanged) ENABLE_ALARM := 0 TX alarms ENABLE_1750HZ := 0 side key 1750Hz TX tone (older style repeater access) ENABLE_MDC1200 := 0 enable MDC1200 TX/RX + menu TX option @@ -70,8 +69,10 @@ ENABLE_SMALL_BOLD := 1 bold channel name/no. (when name + f ENABLE_TRIM_TRAILING_ZEROS := 1 trim away any trailing zeros on frequencies 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/disable the radios hidden frequency calibration menu -ENABLE_TX_UNLOCK := 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_F_CAL_MENU := 0 enable frequency 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_FIX_TX_POWER := 1 fix the TX output power, L ~ 10mW, M ~ 500mW, H ~ 4W ENABLE_CTCSS_TAIL_PHASE_SHIFT := 0 standard CTCSS tail phase shift rather than QS's own 55Hz tone method ENABLE_CONTRAST := 0 add contrast menu ENABLE_BOOT_BEEPS := 0 gives user audio feedback on volume knob position at boot-up diff --git a/app/menu.c b/app/menu.c index 66d70e2..a3681b6 100644 --- a/app/menu.c +++ b/app/menu.c @@ -34,6 +34,7 @@ #include "driver/uart.h" #endif #include "frequencies.h" +#include "functions.h" #include "helper/battery.h" #include "misc.h" #include "settings.h" @@ -367,6 +368,13 @@ int MENU_GetLimits(uint8_t Cursor, int32_t *pMin, int32_t *pMax) *pMax = 16; break; + #ifdef ENABLE_TX_POWER_CAL_MENU + case MENU_TX_CALI: + *pMin = 0; + *pMax = 255; + break; + #endif + #ifdef ENABLE_F_CAL_MENU case MENU_F_CALI: *pMin = -50; @@ -884,11 +892,29 @@ void MENU_AcceptSetting(void) g_eeprom.config.setting.tx_enable = g_sub_menu_selection; break; -#ifdef ENABLE_F_CAL_MENU + #ifdef ENABLE_TX_POWER_CAL_MENU + case MENU_TX_CALI: + { + const unsigned int seg = FREQUENCY_band_segment(g_current_vfo->p_tx->frequency); + const unsigned int band = (unsigned int)FREQUENCY_GetBand(g_current_vfo->p_tx->frequency); + + g_eeprom.calib.tx_band_power[band].level[g_current_vfo->channel.tx_power][seg] = g_sub_menu_selection; + + SETTINGS_write_eeprom_calib(); + + RADIO_ConfigureTXPower(g_current_vfo); + + if (g_current_function == FUNCTION_TRANSMIT && g_current_display_screen != DISPLAY_AIRCOPY) + BK4819_SetupPowerAmplifier(g_current_vfo->txp_calculated_setting, g_current_vfo->p_tx->frequency); + } + break; + #endif + + #ifdef ENABLE_F_CAL_MENU case MENU_F_CALI: writeXtalFreqCal(g_sub_menu_selection, true); return; -#endif + #endif case MENU_BAT_CAL: { @@ -1351,6 +1377,16 @@ void MENU_ShowCurrentSetting(void) g_sub_menu_selection = g_eeprom.config.setting.tx_enable; break; + #ifdef ENABLE_TX_POWER_CAL_MENU + case MENU_TX_CALI: + { + const unsigned int seg = FREQUENCY_band_segment(g_current_vfo->p_tx->frequency); + const unsigned int band = (unsigned int)FREQUENCY_GetBand(g_current_vfo->p_tx->frequency); + g_sub_menu_selection = g_eeprom.calib.tx_band_power[band].level[g_current_vfo->channel.tx_power][seg]; + } + break; + #endif + #ifdef ENABLE_F_CAL_MENU case MENU_F_CALI: g_sub_menu_selection = g_eeprom.calib.bk4819_xtal_freq_low; @@ -2033,9 +2069,9 @@ void MENU_process_key(key_code_t Key, bool key_pressed, bool key_held) if (g_current_display_screen == DISPLAY_MENU) { if (g_menu_cursor == MENU_VOLTAGE || -#ifdef ENABLE_F_CAL_MENU - g_menu_cursor == MENU_F_CALI || -#endif + #ifdef ENABLE_F_CAL_MENU + g_menu_cursor == MENU_F_CALI || + #endif g_menu_cursor == MENU_BAT_CAL) { g_menu_tick_10ms = menu_timeout_long_500ms; diff --git a/firmware.bin b/firmware.bin index 64dc0bf..5904811 100644 Binary files a/firmware.bin and b/firmware.bin differ diff --git a/firmware.packed.bin b/firmware.packed.bin index c4596f9..b37d80b 100644 Binary files a/firmware.packed.bin and b/firmware.packed.bin differ diff --git a/frequencies.c b/frequencies.c index 0c31e61..1c97268 100644 --- a/frequencies.c +++ b/frequencies.c @@ -136,22 +136,42 @@ frequency_band_t FREQUENCY_GetBand(uint32_t Frequency) // return BAND_NONE; } -uint8_t FREQUENCY_CalculateOutputPower(uint8_t TxpLow, uint8_t TxpMid, uint8_t TxpHigh, int32_t LowerLimit, int32_t Middle, int32_t UpperLimit, int32_t Frequency) +unsigned int FREQUENCY_band_segment(const uint32_t freq) { - uint8_t pwr = TxpMid; + const unsigned int band = (unsigned int)FREQUENCY_GetBand(freq); + const uint32_t low_freq = FREQ_BAND_TABLE[band].lower; + const uint32_t high_freq = FREQ_BAND_TABLE[band].upper; + const uint32_t mid_freq = (low_freq + high_freq) / 2; - if (Frequency <= LowerLimit) - return TxpLow; + if (freq < ((low_freq + mid_freq) / 2)) + return 0; + if (freq >= ((mid_freq + high_freq) / 2)) + return 2; + return 1; +} - if (Frequency >= UpperLimit) - return TxpHigh; +uint8_t FREQUENCY_CalculateOutputPower(const int16_t low_tx_pwr, const int32_t mid_tx_pwr, const int16_t high_tx_pwr, const uint32_t freq) +{ + const unsigned int band = (unsigned int)FREQUENCY_GetBand(freq); + const uint32_t low_freq = FREQ_BAND_TABLE[band].lower; + const uint32_t high_freq = FREQ_BAND_TABLE[band].upper; + const uint32_t mid_freq = (low_freq + high_freq) / 2; + + int16_t value; + + if (freq <= low_freq) + return low_tx_pwr; + + if (freq >= high_freq) + return high_tx_pwr; // linear interpolation - if (Frequency <= Middle) - pwr += ((TxpMid - TxpLow) * (Frequency - LowerLimit)) / (Middle - LowerLimit); + if (freq < mid_freq) + value = low_tx_pwr + (((mid_tx_pwr - low_tx_pwr) * (freq - low_freq)) / (mid_freq - low_freq)); else - pwr += ((TxpHigh - TxpMid) * (Frequency - Middle)) / (UpperLimit - Middle); - return pwr; + value = mid_tx_pwr + (((high_tx_pwr - mid_tx_pwr) * (freq - mid_freq)) / (high_freq - mid_freq)); + + return (value < 0) ? 0 : (value > 255) ? 255 : value; } uint32_t FREQUENCY_floor_to_step(uint32_t freq, const uint32_t step_size, const uint32_t lower, const uint32_t upper) @@ -307,7 +327,7 @@ int FREQUENCY_tx_freq_check(const uint32_t Frequency) return 0; break; - #ifdef ENABLE_TX_UNLOCK + #ifdef ENABLE_TX_UNLOCK_MENU case FREQ_LOCK_TX_UNLOCK: { unsigned int i; diff --git a/frequencies.h b/frequencies.h index 0e0ea29..cf1411d 100644 --- a/frequencies.h +++ b/frequencies.h @@ -94,7 +94,9 @@ unsigned int FREQUENCY_get_step_index(const unsigned int step_size); void FREQUENCY_init(void); frequency_band_t FREQUENCY_GetBand(uint32_t Frequency); -uint8_t FREQUENCY_CalculateOutputPower(uint8_t TxpLow, uint8_t TxpMid, uint8_t TxpHigh, int32_t LowerLimit, int32_t Middle, int32_t UpperLimit, int32_t Frequency); + +unsigned int FREQUENCY_band_segment(const uint32_t freq); +uint8_t FREQUENCY_CalculateOutputPower(const int16_t low_tx_pwr, const int32_t mid_tx_pwr, const int16_t high_tx_pwr, const uint32_t freq); uint32_t FREQUENCY_floor_to_step(uint32_t freq, const uint32_t step_size, const uint32_t lower, const uint32_t upper); diff --git a/radio.c b/radio.c index bcb2ca7..be9f3dc 100644 --- a/radio.c +++ b/radio.c @@ -570,38 +570,64 @@ void RADIO_ConfigureTXPower(vfo_info_t *p_vfo) // 1F20 5A 5A 5A 64 64 64 8F 91 8A FF FF FF FF FF FF FF .. 400 MHz // 1F30 32 32 32 64 64 64 8C 8C 8C FF FF FF FF FF FF FF .. 470 MHz - uint8_t tx_power[3]; const unsigned int band = (unsigned int)FREQUENCY_GetBand(p_vfo->p_tx->frequency); + uint8_t tx_power[3]; -// EEPROM_ReadBuffer(0x1ED0 + (band * 16) + (p_vfo->output_power * 3), tx_power, 3); - memcpy(&tx_power, &g_eeprom.calib.tx_band_power[band].level[p_vfo->channel.tx_power], 3); + memcpy(tx_power, g_eeprom.calib.tx_band_power[band].level[p_vfo->channel.tx_power], 3); - #ifdef ENABLE_REDUCE_LOW_MID_TX_POWER - // make low and mid lower - if (p_vfo->channel.tx_power == OUTPUT_POWER_LOW) + #if defined(ENABLE_FIX_TX_POWER) && !defined(ENABLE_TX_POWER_CAL_MENU) + switch (p_vfo->channel.tx_power) { - tx_power[0] /= 10; - tx_power[1] /= 10; - tx_power[2] /= 10; - } - else - if (p_vfo->channel.tx_power == OUTPUT_POWER_MID) - { - tx_power[0] /= 2; - tx_power[1] /= 2; - tx_power[2] /= 2; + case OUTPUT_POWER_LOW: // ~ 10mW +// if (p_vfo->p_tx->frequency <= 26000000) +// { // 137 ~ 174 +// tx_power[0] = 0x13; +// tx_power[1] = 0x13; +// tx_power[2] = 0x13; +// } +// else +// { // 400 ~ 470 + tx_power[0] = 0x13; + tx_power[1] = 0x13; + tx_power[2] = 0x13; +// } + break; + + default: + case OUTPUT_POWER_MID: // ~ 500mW + if (p_vfo->p_tx->frequency <= 26000000) + { // 137 ~ 174 + tx_power[0] = 0x29; + tx_power[1] = 0x29; + tx_power[2] = 0x29; + } + else + { // 400 ~ 470 + tx_power[0] = 0x37; + tx_power[1] = 0x37; + tx_power[2] = 0x37; + } + break; + + case OUTPUT_POWER_HIGH: // ~ 4W + if (p_vfo->p_tx->frequency <= 26000000) + { // 137 ~ 174 + tx_power[0] = 0x7F; + tx_power[1] = 0x84; + tx_power[2] = 0x8C; + } + else + { // 400 ~ 470 + tx_power[0] = 0x96; + tx_power[1] = 0x96; + tx_power[2] = 0x8C; + } + break; } #endif // set the TX power registers - p_vfo->txp_calculated_setting = FREQUENCY_CalculateOutputPower( - tx_power[0], - tx_power[1], - tx_power[2], - FREQ_BAND_TABLE[band].lower, - (FREQ_BAND_TABLE[band].lower + FREQ_BAND_TABLE[band].upper) / 2, - FREQ_BAND_TABLE[band].upper, - p_vfo->p_tx->frequency); + p_vfo->txp_calculated_setting = FREQUENCY_CalculateOutputPower(tx_power[0], tx_power[1], tx_power[2], p_vfo->p_tx->frequency); } void RADIO_apply_offset(vfo_info_t *p_vfo, const bool set_pees) @@ -958,11 +984,17 @@ void RADIO_enableTX(const bool fsk_tx) BK4819_SetCompander((!fsk_tx && g_rx_vfo->channel.mod_mode == MOD_MODE_FM && (g_rx_vfo->channel.compand == 1 || g_rx_vfo->channel.compand >= 3)) ? g_rx_vfo->channel.compand : 0); + // ****************** + BK4819_set_rf_frequency(g_current_vfo->p_tx->frequency, true); BK4819_set_rf_filter_path(g_current_vfo->p_tx->frequency); + BK4819_PrepareTransmit(); + RADIO_ConfigureTXPower(g_current_vfo); + BK4819_set_GPIO_pin(BK4819_GPIO1_PIN29_PA_ENABLE, true); // PA on + if (g_current_display_screen != DISPLAY_AIRCOPY) BK4819_SetupPowerAmplifier(g_current_vfo->txp_calculated_setting, g_current_vfo->p_tx->frequency); else @@ -970,6 +1002,8 @@ void RADIO_enableTX(const bool fsk_tx) BK4819_set_GPIO_pin(BK4819_GPIO5_PIN1_RED, true); // turn the RED LED on + // ****************** + if (fsk_tx) { BK4819_disable_sub_audible(); diff --git a/settings.c b/settings.c index 3fb80a6..837809e 100644 --- a/settings.c +++ b/settings.c @@ -50,6 +50,14 @@ void SETTINGS_write_eeprom_config(void) EEPROM_WriteBuffer8(index, ((uint8_t *)&g_eeprom) + index); } +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; + for (i = 0; i < sizeof(g_eeprom.calib); i += 8) + EEPROM_WriteBuffer8(index + i, ((uint8_t *)&g_eeprom.calib) + i); +} + #ifdef ENABLE_FMRADIO void SETTINGS_save_fm(void) { diff --git a/settings.h b/settings.h index 31679a7..66486d7 100644 --- a/settings.h +++ b/settings.h @@ -48,7 +48,7 @@ enum { FREQ_LOCK_430, FREQ_LOCK_438, FREQ_LOCK_446, -#ifdef ENABLE_TX_UNLOCK +#ifdef ENABLE_TX_UNLOCK_MENU FREQ_LOCK_TX_UNLOCK, #endif FREQ_LOCK_LAST @@ -623,6 +623,7 @@ extern t_eeprom g_eeprom; void SETTINGS_read_eeprom(void); void SETTINGS_write_eeprom_config(void); +void SETTINGS_write_eeprom_calib(void); #ifdef ENABLE_FMRADIO void SETTINGS_save_fm(void); diff --git a/ui/menu.c b/ui/menu.c index 8f4067b..e28e8f1 100644 --- a/ui/menu.c +++ b/ui/menu.c @@ -28,6 +28,7 @@ #endif #include "external/printf/printf.h" #include "frequencies.h" +#include "functions.h" #include "helper/battery.h" #include "misc.h" #include "radio.h" @@ -156,6 +157,10 @@ const t_menu_item g_menu_list[] = {"BatCAL", VOICE_ID_INVALID, MENU_BAT_CAL }, // battery voltage calibration +#ifdef ENABLE_TX_POWER_CAL_MENU + {"TX CAL", VOICE_ID_INVALID, MENU_TX_CALI, }, // L/M/H TX power calibration +#endif + #ifdef ENABLE_F_CAL_MENU {"F CAL", VOICE_ID_INVALID, MENU_F_CALI }, // reference xtal calibration #endif @@ -435,6 +440,10 @@ void UI_SortMenu(const bool hide_hidden) unsigned int hidden_menu_count = g_hidden_menu_count; + #ifndef ENABLE_TX_POWER_CAL_MENU + hidden_menu_count--; + #endif + #ifndef ENABLE_F_CAL_MENU hidden_menu_count--; #endif @@ -1190,7 +1199,7 @@ void UI_DisplayMenu(void) case FREQ_LOCK_446: strcpy(str, "446.00625\n~\n446.19375"); break; - #ifdef ENABLE_TX_UNLOCK + #ifdef ENABLE_TX_UNLOCK_MENU case FREQ_LOCK_TX_UNLOCK: sprintf(str, "UNLOCKED\n%u~%u", BX4819_BAND1.lower / 100000, BX4819_BAND2.upper / 100000); break; @@ -1198,6 +1207,27 @@ void UI_DisplayMenu(void) } break; + #ifdef ENABLE_TX_POWER_CAL_MENU + case MENU_TX_CALI: + { + const unsigned int seg = FREQUENCY_band_segment(g_current_vfo->p_tx->frequency); + const unsigned int band = (unsigned int)FREQUENCY_GetBand(g_current_vfo->p_tx->frequency); + const uint32_t f1 = FREQ_BAND_TABLE[band].lower; + const uint32_t f3 = FREQ_BAND_TABLE[band].upper; + const uint32_t f2 = (f1 + f3) / 2; + + sprintf(str, "B%u S%u\nTX %s\n", band, seg, g_sub_menu_tx_power[g_current_vfo->channel.tx_power]); + sprintf(str + strlen(str), "%u\n", g_sub_menu_selection); + sprintf(str + strlen(str), "%u.%05u\n", f1 / 100000, f1 % 100000); + sprintf(str + strlen(str), "%u.%05u\n", f2 / 100000, f2 % 100000); + sprintf(str + strlen(str), "%u.%05u", f3 / 100000, f3 % 100000); + + if (g_current_function == FUNCTION_TRANSMIT && g_current_display_screen != DISPLAY_AIRCOPY) + BK4819_SetupPowerAmplifier(g_sub_menu_selection, g_current_vfo->p_tx->frequency); + } + break; + #endif + #ifdef ENABLE_F_CAL_MENU case MENU_F_CALI: { diff --git a/ui/menu.h b/ui/menu.h index f318660..4fd2283 100644 --- a/ui/menu.h +++ b/ui/menu.h @@ -148,6 +148,10 @@ enum MENU_BAT_CAL, // battery voltage calibration +#ifdef ENABLE_TX_POWER_CAL_MENU + MENU_TX_CALI, // L/M/H TX power calibration +#endif + #ifdef ENABLE_F_CAL_MENU MENU_F_CALI, // 26MHz reference xtal calibration #endif