diff --git a/openrtx/include/core/cps.h b/openrtx/include/core/cps.h index 8c7d72f9..76e06d0d 100644 --- a/openrtx/include/core/cps.h +++ b/openrtx/include/core/cps.h @@ -195,7 +195,7 @@ typedef struct rx_only : 1, //< 1 means RX-only channel _unused : 5; //< Padding to 8 bits - uint8_t power; //< P = 10dBm + n*0.2dBm, we store n + uint32_t power; //< Tx power, in mW freq_t rx_frequency; //< RX Frequency, in Hz freq_t tx_frequency; //< TX Frequency, in Hz diff --git a/openrtx/include/core/utils.h b/openrtx/include/core/utils.h index eea6dbfd..a407c2de 100644 --- a/openrtx/include/core/utils.h +++ b/openrtx/include/core/utils.h @@ -47,16 +47,6 @@ extern "C" { uint8_t interpCalParameter(const freq_t freq, const freq_t *calPoints, const uint8_t *param, const uint8_t elems); -/** - * Convert from "OpenRTX dBm" to watt. - * In OpenRTX cps power is stored as the coefficient n of the equation - * P(dBm) = 10 + 2*0.2. - * - * @param n: coefficient of the dBm equation. - * @return power in watt. - */ -float dBmToWatt(const uint8_t n); - /** * \internal Utility function to convert 4 byte BCD values into a 32-bit * unsigned integer ones. diff --git a/openrtx/include/core/voicePromptUtils.h b/openrtx/include/core/voicePromptUtils.h index f62c2e29..3a35bbf7 100644 --- a/openrtx/include/core/voicePromptUtils.h +++ b/openrtx/include/core/voicePromptUtils.h @@ -114,7 +114,7 @@ void vp_announceCTCSS(const bool rxToneEnabled, const uint8_t rxTone, /** * */ -void vp_anouncePower(const float power, const vpQueueFlags_t flags); +void vp_announcePower(const uint32_t power, const vpQueueFlags_t flags); /** * diff --git a/openrtx/include/rtx/rtx.h b/openrtx/include/rtx/rtx.h index 092cd4bb..55b9484a 100644 --- a/openrtx/include/rtx/rtx.h +++ b/openrtx/include/rtx/rtx.h @@ -43,7 +43,7 @@ typedef struct freq_t rxFrequency; /**< RX frequency, in Hz */ freq_t txFrequency; /**< TX frequency, in Hz */ - float txPower; /**< TX power, in W */ + uint32_t txPower; /**< TX power, in mW */ uint8_t sqlLevel; /**< Squelch opening level */ uint16_t rxToneEn : 1, /**< RX CTC/DCS tone enable */ diff --git a/openrtx/src/core/threads.c b/openrtx/src/core/threads.c index 986c277c..27c05a4d 100644 --- a/openrtx/src/core/threads.c +++ b/openrtx/src/core/threads.c @@ -85,14 +85,12 @@ void *ui_threadFunc(void *arg) // If synchronization needed take mutex and update RTX configuration if(sync_rtx) { - float power = dBmToWatt(state.channel.power); - pthread_mutex_lock(&rtx_mutex); rtx_cfg.opMode = state.channel.mode; rtx_cfg.bandwidth = state.channel.bandwidth; rtx_cfg.rxFrequency = state.channel.rx_frequency; rtx_cfg.txFrequency = state.channel.tx_frequency; - rtx_cfg.txPower = power; + rtx_cfg.txPower = state.channel.power; rtx_cfg.sqlLevel = state.settings.sqlLevel; rtx_cfg.rxToneEn = state.channel.fm.rxToneEn; rtx_cfg.rxTone = ctcss_tone[state.channel.fm.rxTone]; diff --git a/openrtx/src/core/utils.c b/openrtx/src/core/utils.c index ba33dace..647fa004 100644 --- a/openrtx/src/core/utils.c +++ b/openrtx/src/core/utils.c @@ -51,14 +51,6 @@ uint8_t interpCalParameter(const freq_t freq, const freq_t *calPoints, return interpValue; } -float dBmToWatt(const uint8_t n) -{ - float dBm = 10.0f + ((float) n) * 0.2f; - float power = pow(10.0f, (dBm - 30.0f)/10.0f); - - return power; -} - uint32_t bcdToBin(uint32_t bcd) { return ((bcd >> 28) & 0x0F) * 10000000 + diff --git a/openrtx/src/core/voicePromptUtils.c b/openrtx/src/core/voicePromptUtils.c index fd86c075..d65a4157 100644 --- a/openrtx/src/core/voicePromptUtils.c +++ b/openrtx/src/core/voicePromptUtils.c @@ -179,7 +179,7 @@ void vp_announceBandwidth(const uint8_t bandwidth, const vpQueueFlags_t flags) playIfNeeded(flags); } -void vp_anouncePower(const float power, const vpQueueFlags_t flags) +void vp_announcePower(const uint32_t power, const vpQueueFlags_t flags) { clearCurrPromptIfNeeded(flags); @@ -188,8 +188,10 @@ void vp_anouncePower(const float power, const vpQueueFlags_t flags) vp_queuePrompt(PROMPT_POWER); } + // Compute x.y format avoiding to pull in floating point math. + // Remember that power is expressed in mW! char buffer[16] = "\0"; - snprintf(buffer, 16, "%1.1f", power); + snprintf(buffer, 16, "%d.%d", (power / 1000), (power % 1000) / 100); vp_queueString(buffer, vpAnnounceCommonSymbols); vp_queuePrompt(PROMPT_WATTS); @@ -281,8 +283,7 @@ void vp_announceChannelSummary(const channel_t* channel, if ((infoFlags & vpPower) != 0) { - float power = dBmToWatt(channel->power); - vp_anouncePower(power, localFlags); + vp_announcePower(channel->power, localFlags); addSilenceIfNeeded(localFlags); } @@ -1042,7 +1043,7 @@ void vp_announceSplashScreen() { if (state.settings.vpLevel < vpBeep) return; - + vp_flush(); if (state.settings.vpLevel == vpBeep) @@ -1050,7 +1051,7 @@ void vp_announceSplashScreen() vp_beepSeries(BOOT_MELODY); return; } - + vpQueueFlags_t localFlags = vpqAddSeparatingSilence; // Force on the descriptions for level 3. @@ -1061,7 +1062,7 @@ void vp_announceSplashScreen() vp_queueStringTableEntry(¤tLanguage->openRTX); vp_queuePrompt(PROMPT_VFO); - vp_announceFrequencies(state.channel.rx_frequency, + vp_announceFrequencies(state.channel.rx_frequency, state.channel.tx_frequency, localFlags); vp_announceRadioMode(state.channel.mode, localFlags); diff --git a/openrtx/src/ui/default/ui.c b/openrtx/src/ui/default/ui.c index 19c5af46..451abe8b 100644 --- a/openrtx/src/ui/default/ui.c +++ b/openrtx/src/ui/default/ui.c @@ -996,13 +996,12 @@ static void _ui_fsm_menuMacro(kbd_msg_t msg, bool *sync_rtx) vp_announceRadioMode(state.channel.mode, queueFlags); break; case 6: - if (state.channel.power == 100) - state.channel.power = 135; + if (state.channel.power == 1000) + state.channel.power = 5000; else - state.channel.power = 100; + state.channel.power = 1000; *sync_rtx = true; - float power = dBmToWatt(state.channel.power); - vp_anouncePower(power, queueFlags); + vp_announcePower(state.channel.power, queueFlags); break; #ifdef CONFIG_SCREEN_BRIGHTNESS case 7: diff --git a/openrtx/src/ui/default/ui_menu.c b/openrtx/src/ui/default/ui_menu.c index 9119ae32..12c2ee16 100644 --- a/openrtx/src/ui/default/ui_menu.c +++ b/openrtx/src/ui/default/ui_menu.c @@ -1156,8 +1156,13 @@ bool _ui_drawMacroMenu(ui_state_t* ui_state) #endif // CONFIG_UI_NO_KEYBOARD gfx_print(pos_2, layout.top_font, TEXT_ALIGN_RIGHT, yellow_fab413, "6 "); + + // Compute x.y format for TX power avoiding to pull in floating point math. + // Remember that power is expressed in mW! + unsigned int power_int = (last_state.channel.power / 1000); + unsigned int power_dec = (last_state.channel.power % 1000) / 100; gfx_print(pos_2, layout.top_font, TEXT_ALIGN_RIGHT, - color_white, "%.1gW", dBmToWatt(last_state.channel.power)); + color_white, "%d.%dW", power_int, power_dec); // Third row #if defined(CONFIG_UI_NO_KEYBOARD) diff --git a/platform/drivers/CPS/cps_io_native_GDx.c b/platform/drivers/CPS/cps_io_native_GDx.c index a36d5325..71eb7984 100644 --- a/platform/drivers/CPS/cps_io_native_GDx.c +++ b/platform/drivers/CPS/cps_io_native_GDx.c @@ -137,7 +137,7 @@ int cps_readChannel(channel_t *channel, uint16_t pos) channel->mode = chData.channel_mode + 1; channel->bandwidth = chData.bandwidth; channel->rx_only = chData.rx_only; - channel->power = ((chData.power == 1) ? 135 : 100); + channel->power = ((chData.power == 1) ? 5000 : 1000); // 5W or 1W channel->rx_frequency = bcdToBin(chData.rx_frequency) * 10; channel->tx_frequency = bcdToBin(chData.tx_frequency) * 10; channel->scanList_index = chData.scan_list_index; diff --git a/platform/drivers/CPS/cps_io_native_MD3x0.c b/platform/drivers/CPS/cps_io_native_MD3x0.c index a81800c8..5ab4ade6 100644 --- a/platform/drivers/CPS/cps_io_native_MD3x0.c +++ b/platform/drivers/CPS/cps_io_native_MD3x0.c @@ -77,7 +77,7 @@ int cps_readChannel(channel_t *channel, uint16_t pos) channel->mode = chData.channel_mode; channel->bandwidth = chData.bandwidth; channel->rx_only = chData.rx_only; - channel->power = ((chData.power == 1) ? 135 : 100); + channel->power = ((chData.power == 1) ? 5000 : 1000); // 5W or 1W channel->rx_frequency = bcdToBin(chData.rx_frequency) * 10; channel->tx_frequency = bcdToBin(chData.tx_frequency) * 10; channel->scanList_index = chData.scan_list_index; diff --git a/platform/drivers/CPS/cps_io_native_MD9600.c b/platform/drivers/CPS/cps_io_native_MD9600.c index ee366074..a2208743 100644 --- a/platform/drivers/CPS/cps_io_native_MD9600.c +++ b/platform/drivers/CPS/cps_io_native_MD9600.c @@ -62,15 +62,15 @@ static int _readChannelAtAddress(channel_t *channel, uint32_t addr) if(chData.power == 3) { - channel->power = 135; /* High power -> 5W = 37dBm */ + channel->power = 5000; /* High power, 5W */ } else if(chData.power == 2) { - channel->power = 120; /* Mid power -> 2.5W = 34dBm */ + channel->power = 2500; /* Mid power, 2.5W */ } else { - channel->power = 100; /* Low power -> 1W = 30dBm */ + channel->power = 1000; /* Low power, 1W */ } /* diff --git a/platform/drivers/CPS/cps_io_native_MDUV3x0.c b/platform/drivers/CPS/cps_io_native_MDUV3x0.c index 67f0d6a4..c2b2a473 100644 --- a/platform/drivers/CPS/cps_io_native_MDUV3x0.c +++ b/platform/drivers/CPS/cps_io_native_MDUV3x0.c @@ -60,15 +60,15 @@ static int _readChannelAtAddress(channel_t *channel, uint32_t addr) if(chData.power == 3) { - channel->power = 135; /* High power -> 5W = 37dBm */ + channel->power = 5000; /* High power, 5W */ } else if(chData.power == 2) { - channel->power = 120; /* Mid power -> 2.5W = 34dBm */ + channel->power = 2500; /* Mid power, 2.5W */ } else { - channel->power = 100; /* Low power -> 1W = 30dBm */ + channel->power = 1000; /* Low power, 1W */ } /* diff --git a/platform/drivers/baseband/SA8x8.c b/platform/drivers/baseband/SA8x8.c index 373fa57d..b936b77d 100644 --- a/platform/drivers/baseband/SA8x8.c +++ b/platform/drivers/baseband/SA8x8.c @@ -272,12 +272,12 @@ int sa8x8_enableHSMode() return 0; } -void sa8x8_setTxPower(const float power) +void sa8x8_setTxPower(const uint32_t power) { char buf[SA8X8_MSG_SIZE] = { 0 }; // TODO: Implement fine-grained power control through PA_BIAS SA8x8 register - uint8_t amp_enable = (power > 1.0f) ? 1 : 0; + uint8_t amp_enable = (power > 1000) ? 1 : 0; int ret = gpio_pin_set_dt(&radio_pwr, amp_enable); if(ret != 0) printk("SA8x8: failed to change power mode"); diff --git a/platform/drivers/baseband/SA8x8.h b/platform/drivers/baseband/SA8x8.h index d9a30eb0..025957c4 100644 --- a/platform/drivers/baseband/SA8x8.h +++ b/platform/drivers/baseband/SA8x8.h @@ -58,9 +58,9 @@ int sa8x8_enableHSMode(); /** * Set the transmission power. * - * @param power: transmission power in Watt. + * @param power: transmission power in mW. */ -void sa8x8_setTxPower(const float power); +void sa8x8_setTxPower(const uint32_t power); /** * Enable or disable the speaker power amplifier. diff --git a/platform/drivers/baseband/radio_GDx.cpp b/platform/drivers/baseband/radio_GDx.cpp index caed49d1..25137950 100644 --- a/platform/drivers/baseband/radio_GDx.cpp +++ b/platform/drivers/baseband/radio_GDx.cpp @@ -331,7 +331,8 @@ void radio_updateConfiguration() C6000.setModAmplitude(0, mod1Amp); // Calculate APC voltage, constraining output power between 1W and 5W. - float power = std::max(std::min(config->txPower, 5.0f), 1.0f); + float power = static_cast < float >(config->txPower) / 1000.0f; + power = std::max(std::min(power, 5.0f), 1.0f); float pwrHi = static_cast< float >(txpwr_hi); float pwrLo = static_cast< float >(txpwr_lo); float apc = pwrLo + (pwrHi - pwrLo)/4.0f*(power - 1.0f); diff --git a/platform/drivers/baseband/radio_MD3x0.cpp b/platform/drivers/baseband/radio_MD3x0.cpp index a3a1671a..af9cc772 100644 --- a/platform/drivers/baseband/radio_MD3x0.cpp +++ b/platform/drivers/baseband/radio_MD3x0.cpp @@ -280,7 +280,8 @@ void radio_enableTx() SKY73210_setFrequency(pllFreq, 5); // Set TX output power, constrain between 1W and 5W. - float power = std::max(std::min(config->txPower, 5.0f), 1.0f); + float power = static_cast < float >(config->txPower) / 1000.0f; + power = std::max(std::min(power, 5.0f), 1.0f); float pwrHi = static_cast< float >(txpwr_hi); float pwrLo = static_cast< float >(txpwr_lo); float apc = pwrLo + (pwrHi - pwrLo)/4.0f*(power - 1.0f); diff --git a/platform/drivers/baseband/radio_UV3x0.cpp b/platform/drivers/baseband/radio_UV3x0.cpp index f077abe4..d3085c86 100644 --- a/platform/drivers/baseband/radio_UV3x0.cpp +++ b/platform/drivers/baseband/radio_UV3x0.cpp @@ -211,7 +211,8 @@ void radio_enableTx() at1846s.setFrequency(config->txFrequency); // Constrain output power between 1W and 5W. - float power = std::max(std::min(config->txPower, 5.0f), 1.0f); + float power = static_cast < float >(config->txPower) / 1000.0f; + power = std::max(std::min(power, 5.0f), 1.0f); float pwrHi = static_cast< float >(txpwr_hi); float pwrLo = static_cast< float >(txpwr_lo); float apc = pwrLo + (pwrHi - pwrLo)/4.0f*(power - 1.0f); diff --git a/platform/drivers/baseband/radio_ttwrplus.cpp b/platform/drivers/baseband/radio_ttwrplus.cpp index 96442300..e7fc45ff 100644 --- a/platform/drivers/baseband/radio_ttwrplus.cpp +++ b/platform/drivers/baseband/radio_ttwrplus.cpp @@ -131,7 +131,7 @@ void radio_enableTx() if(config->txDisable == 1) return; // Constrain output power between 1W and 5W. - float power = std::max(std::min(config->txPower, 5.0f), 1.0f); + uint32_t power = std::max(std::min(config->txPower, 5000U), 1000U); sa8x8_setTxPower(power); at1846s.setFrequency(config->txFrequency);