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

292 lines
8.6 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 "phy_bb.h"
#include "mac_tx_power.h"
#include "os_types.h"
#include "os_utils_api.h"
#include "plc_protocol.h"
#include "hw_phy_api.h"
#include "mac_sched_hw.h"
#include "mac_vdev_api.h"
#include "mac_vdev.h"
#include "mac_pdev.h"
#include "mac_peer.h"
#include "mac_msdu.h"
#include "mac_dsr.h"
#include "mac_cfg.h"
#include "iot_io.h"
#include "iot_board.h"
#include "mac.h"
#include "phy_isr.h"
#include "iot_utils_api.h"
#include "iot_oem_api.h"
#include "mac_tx_hw.h"
#include "tx_mpdu_start.h"
#include "phy_txrx_pwr.h"
#include "iot_dbglog_api.h"
#include "iot_dbglog_parser.h"
#include "phy_txrx_pwr.h"
#include "phy_overstress.h"
#include "mac_rf_tx_power.h"
void IRAM_ATTR mac_over_stress_isr_handle(void *param, uint8_t is_from_isr)
{
(void)param;
uint32_t value = 0;
value |= 1 << MAC_DSR_OVER_STRESS_ID;
if (value) {
if (is_from_isr) {
/* deliver the DSR events to mac task context */
os_set_task_event_with_v_from_isr(p_mac_glb->task_h, value);
} else {
os_set_task_event_with_v(p_mac_glb->task_h, value);
}
}
}
void mac_over_stress_dsr_handle()
{
phy_overstress_ctxt_t *ovs_ctxt = &g_phy_ctxt.indep.ovs_ctxt;
if (ovs_ctxt->ovr_stress) {
phy_overstress_power_down(PHY_OVR_STRESS_PWR_DOWN_VAL);
} else {
phy_overstress_power_up();
}
iot_printf("overstress:%d, over_pwr:%d, cnt:%d\n", ovs_ctxt->ovr_stress,
ovs_ctxt->ovr_pwr, ovs_ctxt->os_cnt);
}
uint32_t mac_get_def_tx_power(uint32_t proto, uint32_t proto_band_id,
uint32_t *ret_tx_power)
{
uint8_t tx_power_int, tx_power_frac;
(void)proto;
(void)proto_band_id;
phy_get_def_tx_power(0, HW_FULL_BAND, &tx_power_int, &tx_power_frac);
*ret_tx_power = tx_power_int;
return 0;
}
static uint8_t mac_plc_high_power_check(void *vdev_ptr)
{
mac_vdev_t *vdev = (mac_vdev_t*)vdev_ptr;
if (!vdev->high_power_plc_allow) {
if (iot_oem_get_module_type() == MODULE_TYPE_CCO
&& iot_board_is_5v_power_in()
&& os_boot_time64() < (15 * 60 * 1000)) {
vdev->high_power_plc_allow = 0;
} else {
vdev->high_power_plc_allow = 1;
}
}
return (uint8_t)vdev->high_power_plc_allow;
}
void mac_fix_power_apply(void *vdev_ptr)
{
IOT_ASSERT(vdev_ptr);
mac_vdev_t *vdev = (mac_vdev_t*)vdev_ptr;
/* only for lp ver
* and cert ver return
*/
if (g_phy_cpu_share_ctxt.tx_pwr_ctl_ena || CPLC_IOT_CERT_ENABLE) {
return;
}
if (vdev->fixed_power_cap_flag) {
phy_pwr_adjust_set((uint8_t)vdev->power_cap);
} else {
if (phy_band_id_get() == IOT_SUPPORT_TONE_231_490_CE) {
return;
}
if (vdev->high_power_req_ena == 0) {
phy_pwr_adjust_set(0);
} else {
if (vdev->high_power_req_reason_bitmap != 0
&& mac_plc_high_power_check(vdev_ptr)) {
#if PLC_MAC_TX_DEBUG_LOG >= PLC_MAC_LOG_LEVEL_2
iot_dbglog_input(PLC_MAC_TX_MID, DBGLOG_INFO_LVL_2, \
IOT_MAC_TX_POWER_CHANGE_ID, 1, \
vdev->high_power_req_reason_bitmap);
#endif
phy_pwr_adjust_set(mac_cfg_get_auto_high_power_dbuv());
} else {
phy_pwr_adjust_set(0);
}
}
}
}
void mac_high_power_req_ena(void *vdev_ptr, uint8_t ena)
{
IOT_ASSERT(vdev_ptr);
mac_vdev_t *vdev = (mac_vdev_t*)vdev_ptr;
if (g_phy_cpu_share_ctxt.tx_pwr_ctl_ena == 0) {
vdev->high_power_req_ena = !!ena;
mac_fix_power_apply(vdev);
}
}
void mac_check_power_by_level(void *vdev_ptr, uint8_t sta_level)
{
IOT_ASSERT(vdev_ptr);
mac_vdev_t *vdev = (mac_vdev_t*)vdev_ptr;
mac_peer_t *self_peer = (mac_peer_t *)vdev->self_peer;
if (self_peer == NULL || self_peer->tei == 0) {
return;
}
if (sta_level >= HIGH_PWR_LVL_THRE) {
mac_high_power_req(vdev, HIGH_PWR_REQ_BY_STA_LVL, true);
} else {
mac_high_power_req(vdev, HIGH_PWR_REQ_BY_STA_LVL, false);
}
}
void mac_high_power_req(void *vdev, uint8_t reason, uint8_t flag)
{
if (g_phy_cpu_share_ctxt.tx_pwr_ctl_ena == 0) {
IOT_ASSERT(vdev);
mac_vdev_t *vdev_ptr = (mac_vdev_t*)vdev;
IOT_ASSERT(reason < 32);
uint32_t reason_bitmap = 1 << reason;
if (!!flag) {
vdev_ptr->high_power_req_reason_bitmap |= reason_bitmap;
} else {
vdev_ptr->high_power_req_reason_bitmap &= ~reason_bitmap;
}
mac_fix_power_apply(vdev_ptr);
/* rf high power */
mac_rf_fix_power_apply();
}
}
uint8_t mac_get_final_min_tx_power(uint8_t band_id)
{
uint8_t power_dbuv;
switch (band_id) {
case IOT_SUPPORT_TONE_231_490_CE:
power_dbuv = MAC_TX_POWER_CE_MIN;
break;
//TODO: add code
default:
power_dbuv = MIN_TX_POWER;
break;
}
return power_dbuv;
}
void mac_set_tx_power_cap(void *vdev_ptr, uint8_t *hplc_power,
int8_t *rf_power, uint8_t is_force)
{
IOT_ASSERT(vdev_ptr);
uint8_t band_id;
mac_vdev_t *vdev = (mac_vdev_t*)vdev_ptr;
if (hplc_power) {
/* is hplc set power */
uint8_t power = *hplc_power;
mac_pdev_t *pdev_ptr = get_pdev_ptr(vdev->ref_pdev_id);
if (!is_force && pdev_ptr->mac_pm.mac_pm_flag) {
/* if power off happen, not care set power cap */
return;
}
if (g_phy_cpu_share_ctxt.tx_pwr_ctl_ena == 0) {
band_id = (uint8_t)phy_band_id_get();
if (power == 0) {
/* clear power cap */
vdev->fixed_power_cap_flag = 0;
} else if (power >= PHY_FULL_PWR_DBUV) {
/* high power */
vdev->fixed_power_cap_flag = 1;
vdev->power_cap = PHY_FULL_PWR_DBUV;
} else {
/* low power */
vdev->fixed_power_cap_flag = 1;
vdev->power_cap = max(power,
mac_get_final_min_tx_power(band_id));
}
mac_fix_power_apply(vdev);
}
}
if (rf_power) {
int8_t tmp_powre = *rf_power;
mac_rf_vdev_t *rf_vdev = get_rf_vdev_ptr(vdev->ref_pdev_id,
RF_PDEV_ID, vdev->rf_vdev_id);
mac_rf_set_tx_power_cap(rf_vdev, tmp_powre, is_force);
}
}
void mac_fix_power_init(void *vdev_ptr)
{
IOT_ASSERT(vdev_ptr);
mac_vdev_t *vdev = (mac_vdev_t*)vdev_ptr;
#if CPLC_IOT_CERT_ENABLE
vdev->high_power_req_ena = 0;
#else
vdev->high_power_req_ena = mac_cfg_get_auto_high_power_req_ena();
#endif
vdev->fixed_power_cap_flag = 0;
vdev->high_power_req_reason_bitmap = 0;
}
#if CERT_WAR_TX_PWR == 1
uint32_t mac_cert_war_tx_pwr(uint8_t *mac_addr)
{
IOT_ASSERT(mac_addr);
uint32_t is_pwr_rise = 0;
const uint8_t box3[6]={0x01,0x12,0x01,0x00,0x00,0x01};
const uint8_t box4[6]={0x01,0x11,0x00,0x01,0x00,0x01};
const uint8_t box5[6]={0x01,0x14,0x00,0x01,0x00,0x01};
const uint8_t box4_1[6]={0x01,0x11,0x01,0x00,0x00,0x01};
const uint8_t box5_1[6]={0x01,0x14,0x01,0x00,0x00,0x01};
iot_printf("---%s:"
"0x%02x:0x%02x:0x%02x:0x%02x:0x%02x:0x%02x\n",
__FUNCTION__,
mac_addr[0],
mac_addr[1],
mac_addr[2],
mac_addr[3],
mac_addr[4],
mac_addr[5]
);
if (iot_mac_addr_cmp(mac_addr, box4) || iot_mac_addr_cmp(mac_addr, box5) ||
iot_mac_addr_cmp(mac_addr, box4_1) ||
iot_mac_addr_cmp(mac_addr, box5_1) ||
iot_mac_addr_cmp(mac_addr, box3)) {
/* if box4 or box5, rise the power */
phy_pwr_adjust_set(PHY_FULL_PWR_DBUV);
is_pwr_rise = 1;
phy_rise_pwr_flag_set(true);
iot_printf("***tx power calculated:%d.***\n", is_pwr_rise);
}
return is_pwr_rise;
}
#endif