Files
kunlun/plc/halmac/tx_power/mac_rf_tx_power.c
2024-09-28 14:24:04 +08:00

213 lines
7.0 KiB
C
Executable File

/****************************************************************************
Copyright(c) 2019 by Aerospace C.Power (Chongqing) Microelectronics. ALL RIGHTS RESERVED.
This Information is proprietary to Aerospace C.Power (Chongqing) Microelectronics and MAY NOT
be copied by any method or incorporated into another program without
the express written consent of Aerospace C.Power. This Information or any portion
thereof remains the property of Aerospace C.Power. The Information contained herein
is believed to be accurate and Aerospace C.Power assumes no responsibility or
liability for its use in any way and conveys no license or title under
any patent or copyright and makes no representation or warranty that this
Information is free from patent or copyright infringement.
****************************************************************************/
#include "iot_config.h"
#include "mac_rf_tx_power.h"
#include "os_types.h"
#include "iot_io.h"
#include "iot_utils_api.h"
#include "phy_txrx_pwr.h"
#include "plc_const.h"
#include "mac_cfg.h"
#include "mac_pdev.h"
#include "mac_vdev.h"
#include "phy_temperature.h"
#include "phy_nf.h"
#if HPLC_RF_DEV_SUPPORT
#include "mac_rf_common_hw.h"
/* define the stability period of the temperature compensation check */
#define MAC_RF_TX_POWER_TEMP_COMPEN_STABLE_THR 10
/* define threshold exit hysteresis interval of the temperature compensation
* check, unit is 0.1 centigrade
*/
#define MAC_RF_TX_POWER_TEMP_COMPEN_THR_HYST 50
/* definition of temperature compensation region */
typedef struct {
/* start threshold for compensation region, unit is 0.1 centigrade */
int16_t start_thr;
/* end threshold for compensation region, unit is 0.1 centigrade */
int16_t end_thr;
/* max tx power for current compensation region, unit is 1dBm */
int8_t max_tx_power;
} rf_temp_compen_region_t;
/* temperature compensation region table */
static const rf_temp_compen_region_t rf_power_compen_tab[] = {
{-1000, -50, 10},
{ 600, 2000, 10},
};
void mac_rf_fix_power_apply()
{
int8_t tx_pwr_by_temp;
int8_t pwr = 0;
uint32_t ret;
mac_vdev_t *vdev = get_vdev_ptr(PLC_PDEV_ID, PLC_DEFAULT_VDEV);
mac_rf_vdev_t *rf_vdev = get_rf_vdev_ptr(PLC_PDEV_ID, RF_PDEV_ID,
PLC_DEFAULT_VDEV);
if (phy_get_pwr_ctl_en()) {
return;
}
if (rf_vdev->fixed_rf_power_flag) {
mac_rf_set_target_tx_power(rf_vdev->fixed_rf_power_cap);
} else {
if (vdev->high_power_req_ena == 0) {
mac_rf_set_target_tx_power(RF_TX_PWR_INVALID);
} else {
if (vdev->high_power_req_reason_bitmap != 0) {
mac_rf_set_target_tx_power(mac_cfg_get_rf_auto_high_power_dbm());
} else {
mac_rf_set_target_tx_power(RF_TX_PWR_INVALID);
}
}
}
if (rf_vdev->power_temp_compen_idx != -1) {
tx_pwr_by_temp =
rf_power_compen_tab[rf_vdev->power_temp_compen_idx].max_tx_power;
ret = mac_rf_get_target_tx_power(&pwr);
if (ret != ERR_OK) {
IOT_ASSERT(0);
}
if (tx_pwr_by_temp < pwr) {
iot_printf("%s temperature compen apply, power:%d\n", __FUNCTION__,
tx_pwr_by_temp);
mac_rf_set_target_tx_power(tx_pwr_by_temp);
}
}
}
static void mac_rf_tx_power_compen_check(void)
{
mac_rf_vdev_t *rf_vdev = get_rf_vdev_ptr(PLC_PDEV_ID, RF_PDEV_ID,
PLC_DEFAULT_VDEV);
const rf_temp_compen_region_t *tab = rf_power_compen_tab;
uint8_t i, change = 0;
int8_t chk_idx = -1;
int16_t cur_temp;
if (!rf_vdev->power_temp_compen_en) {
return;
}
cur_temp = (int16_t)(phy_temperature_val_get() * 10);
for (i = 0; i < IOT_ARRAY_CNT(rf_power_compen_tab); i++) {
if (cur_temp >= tab[i].start_thr &&
cur_temp <= tab[i].end_thr) {
chk_idx = i;
break;
}
}
if (rf_vdev->power_temp_compen_idx != -1
&& chk_idx == -1) {
i = rf_vdev->power_temp_compen_idx;
if (cur_temp > (tab[i].start_thr -
MAC_RF_TX_POWER_TEMP_COMPEN_THR_HYST)
&& cur_temp < (tab[i].end_thr +
MAC_RF_TX_POWER_TEMP_COMPEN_THR_HYST)) {
chk_idx = i;
}
}
if (rf_vdev->last_temp_compen_chk_idx != chk_idx) {
rf_vdev->stable_cnt = 0;
rf_vdev->last_temp_compen_chk_idx = chk_idx;
} else {
rf_vdev->stable_cnt++;
if (rf_vdev->stable_cnt == MAC_RF_TX_POWER_TEMP_COMPEN_STABLE_THR) {
if (rf_vdev->power_temp_compen_idx !=
rf_vdev->last_temp_compen_chk_idx) {
rf_vdev->power_temp_compen_idx =
rf_vdev->last_temp_compen_chk_idx;
change = 1;
}
}
}
iot_printf("%s temp:%d, chk_idx:%d, temp_compen_idx:%d, stable_cnt:%lu, "
"change:%lu\n", __FUNCTION__, cur_temp, chk_idx,
rf_vdev->power_temp_compen_idx, rf_vdev->stable_cnt, change);
if (change) {
mac_rf_fix_power_apply();
}
}
void mac_rf_set_tx_power_cap(mac_rf_vdev_t *rf_vdev, int8_t power,
uint8_t is_force)
{
IOT_ASSERT(rf_vdev);
mac_pdev_t *pdev = get_pdev_ptr(PLC_PDEV_ID);
int8_t min_pwr, max_pwr;
if (phy_get_pwr_ctl_en()) {
return;
}
if (!is_force && pdev->mac_pm.mac_pm_flag) {
/* if power off happen, not care set power cap */
return;
}
phy_rf_get_power(&min_pwr, &max_pwr, NULL, NULL);
if (power == RF_TX_PWR_INVALID) {
/* clear power cap */
rf_vdev->fixed_rf_power_flag = 0;
} else if (power >= max_pwr) {
/* high power */
rf_vdev->fixed_rf_power_flag = 1;
rf_vdev->fixed_rf_power_cap = max_pwr;
} else {
/* low power */
rf_vdev->fixed_rf_power_flag = 1;
rf_vdev->fixed_rf_power_cap = (uint8_t)max(power, min_pwr);
}
mac_rf_fix_power_apply();
}
void mac_rf_fix_power_init()
{
mac_rf_vdev_t *rf_vdev = get_rf_vdev_ptr(PLC_PDEV_ID, RF_PDEV_ID,
PLC_DEFAULT_VDEV);
rf_vdev->fixed_rf_power_flag = 0;
rf_vdev->power_temp_compen_idx = -1;
rf_vdev->last_temp_compen_chk_idx = -1;
rf_vdev->stable_cnt = 0;
rf_vdev->fixed_rf_power_cap = 0;
rf_vdev->power_temp_compen_en = !!HPLC_RF_TX_POWER_TEMP_COMPEN_EN_DEFAULT;
#if HW_PLATFORM != HW_PLATFORM_SIMU
register_phy_rf_tx_power_comen_cb(mac_rf_tx_power_compen_check);
#endif
}
void mac_rf_tx_power_comen_en(uint8_t en)
{
mac_rf_vdev_t *rf_vdev = get_rf_vdev_ptr(PLC_PDEV_ID, RF_PDEV_ID,
PLC_DEFAULT_VDEV);
if (rf_vdev->power_temp_compen_en && !en) {
/* disable rf tx power temperature compensation function */
rf_vdev->power_temp_compen_en = 0;
rf_vdev->stable_cnt = 0;
rf_vdev->power_temp_compen_idx = -1;
rf_vdev->last_temp_compen_chk_idx = -1;
mac_rf_fix_power_apply();
} else if (!rf_vdev->power_temp_compen_en && en) {
/* enable rf tx power temperature compensation function */
rf_vdev->power_temp_compen_en = 1;
}
}
#endif /* HPLC_RF_DEV_SUPPORT */