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

235 lines
7.1 KiB
C

/****************************************************************************
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 "os_utils_api.h"
#include "iot_io.h"
#include "iot_dbglog_api.h"
#include "iot_dbglog_parser.h"
#include "mac_peer.h"
#include "mpdu_header.h"
#include "rf_rate_control.h"
#include "phy_rf_chn.h"
#if HPLC_RF_DEV_SUPPORT
#include "rf_hw_tonemap.h"
uint32_t mac_rf_bcn_get_rate(uint32_t bcn_len, uint32_t option, uint8_t is_csma,
uint32_t slot_dur, uint8_t *blkz, uint8_t *phr_mcs, uint8_t *mcs)
{
uint8_t idx_start, idx_end, idx;
uint32_t fix_fl, calc_fl;
IOT_ASSERT(option < PHY_RF_OPTION_MAX);
uint32_t t_pbsz =
(
(bcn_len > PB_SIZE_264) ? PB_SIZE_520 :
(bcn_len > PB_SIZE_136) ? PB_SIZE_264 :
(bcn_len > PB_SIZE_72) ? PB_SIZE_136 :
(bcn_len > PB_SIZE_40) ? PB_SIZE_72 :
(bcn_len > PB_SIZE_16) ? PB_SIZE_40 :
PB_SIZE_16
);
*blkz = phy_rf_get_blkz(t_pbsz);
if (is_csma) {
const rf_mcs_table_t *fix_mcs = phy_rf_get_bcn_fix_mcs(option, *blkz);
IOT_ASSERT(fix_mcs != NULL);
*phr_mcs = fix_mcs->phr_mcs;
*mcs = fix_mcs->psdu_mcs;
} else {
fix_fl = phy_rf_get_g_stf_ltf_fl() + phy_rf_get_g_sig_fl()
+ RF_MAC_BIFS_US + RF_BCN_TX_RESERVE_US;
IOT_ASSERT(slot_dur >= fix_fl);
phy_rf_get_ra_idx_range((uint8_t)option, &idx_start, &idx_end);
*phr_mcs = MCS_ID_MAX;
*mcs = MCS_ID_MAX;
for (idx = idx_start; idx < idx_end; idx++) {
if (ERR_OK == phy_rf_get_ra_idx_mcs((uint8_t)option, idx,
phr_mcs, mcs)) {
calc_fl = fix_fl + phy_rf_get_g_phr_fl(*phr_mcs)
+ phy_rf_get_g_psdu_fl(*mcs, *blkz);
if (calc_fl <= slot_dur) {
break;
}
}
}
}
iot_printf("%s phr_mcs:%d, pldmcs:%d, blkz:%d\n", __FUNCTION__, *phr_mcs,
*mcs, *blkz);
IOT_ASSERT(*blkz < BLOCK_SIZE_MAX && *phr_mcs < MCS_ID_MAX &&
*mcs < MCS_ID_MAX);
return 0;
}
uint32_t mac_rf_data_get_rate(uint32_t msdu_len, uint32_t option,
uint8_t is_bcast, uint8_t *blkz, uint8_t *phr_mcs, uint8_t *mcs,
uint32_t retry_cnt, tei_t dtei)
{
IOT_ASSERT(option < PHY_RF_OPTION_MAX);
uint8_t phcl = mac_get_pb_hdr_resv_crc_len(FC_DELIM_SOF,
PHY_PROTO_TYPE_GET());
// use fix rate
uint32_t t_pbsz =
(
(msdu_len > (uint32_t)(PB_SIZE_264 - phcl)) ? PB_SIZE_520 :
(msdu_len > (uint32_t)(PB_SIZE_136 - phcl)) ? PB_SIZE_264 :
(msdu_len > (uint32_t)(PB_SIZE_72 - phcl)) ? PB_SIZE_136 :
(msdu_len > (uint32_t)(PB_SIZE_40 - phcl)) ? PB_SIZE_72 :
(msdu_len > (uint32_t)(PB_SIZE_16 - phcl)) ? PB_SIZE_40 :
PB_SIZE_16
);
*blkz = phy_rf_get_blkz(t_pbsz);
const rf_mcs_table_t *fix_ms = phy_rf_get_sof_fix_mcs(option, *blkz);
IOT_ASSERT(fix_ms != NULL);
*phr_mcs = fix_ms->phr_mcs;
*mcs = fix_ms->psdu_mcs;
// TODO: use some rules to select phr_mcs and mcs.
if (is_bcast) {
iot_printf("---rf ra bc_rate:%d, retrycnt:%d, phr_mcs:%d, pld_mcs:%d, "
"blkz:%d, pbsz:%d\n", 0, retry_cnt, *phr_mcs, *mcs, *blkz,
phy_rf_get_pbsz(*blkz));
} else {
iot_printf("---rf ra dtei:%d, fix_rate:%d, retrycnt:%d, phr_mcs:%d, pld_mcs:%d, "
"blkz:%d, pbsz:%d\n", dtei, 0, retry_cnt, *phr_mcs, *mcs, *blkz,
phy_rf_get_pbsz(*blkz));
}
return 0;
}
uint32_t mac_rf_rate_ctxt_init(mac_peer_t *peer)
{
if (peer == NULL) {
IOT_ASSERT(0);
return ERR_INVAL;
}
peer->rf_rate_info.avg_snr = RF_INVALID_SNR;
peer->rf_rate_info.last_rx_ts = os_boot_time32();
return ERR_OK;
}
uint32_t mac_rf_rate_update(void *peer_in, void *arg)
{
IOT_ASSERT(peer_in && arg);
mac_peer_t *peer = (mac_peer_t*)peer_in;
rx_fc_msg_t *sack = (rx_fc_msg_t*)arg;
int8_t snr = sack->snr_in_sack;
#if (RF_MAC_RX_DEBUG_LOG >= PLC_MAC_LOG_LEVEL_1)
iot_printf("---rf_snr=%d,load=%d," \
"result=%d," \
"dtei=%d," \
"stei=%d," \
"nid=0x%x," \
"peer_tei=%d," \
"peer_sub=%d," \
"peer_snr=%d\n", \
sack->snr_in_sack, \
sack->load_in_sack, \
sack->result_in_sack, \
sack->dst_tei, \
sack->src_tei, \
sack->nid, \
peer->tei, \
peer->is_sub_peer, \
peer->rate_info.avg_snr);
#endif
if (snr > RF_MAX_FD_SNR) {
/* snr is grater than MAX_FD_SNR, igiore the result */
return ERR_INVAL;
} else if (snr < RF_MIN_FD_SNR) {
/* snr is less than MIN_FD_SNR, rewrite snr = MIN_FD_SNR */
snr = RF_MIN_FD_SNR;
}
if (peer->rate_info.avg_snr == RF_INVALID_SNR) {
/* for the first time */
peer->rate_info.avg_snr = snr;
} else if (sack->result_in_sack == 0) {
/* if all pb success */
int8_t avg = peer->rf_rate_info.avg_snr;
avg = (avg - (avg >> 3)) + (snr >> 3);
peer->rf_rate_info.avg_snr = avg;
} else {
/* if at least one pb fail */
ra_inc_con_sack_err_cnt(&peer->rf_rate_info);
}
return 0;
}
uint32_t rf_ra_init(mac_rf_vdev_t * vdev, uint32_t ena_ra)
{
(void)ena_ra;
/* set cb when rx sack */
rf_vdev_set_ra(vdev, mac_rf_rate_update);
return (0);
}
void rf_ra_add_no_sack_cnt(rate_info_t *ra)
{
if (!ra) {
return;
}
if (++ra->con_no_sack_cnt > RF_RA_CON_NOSACK_PENALTY_CNT_THRE) {
if (ra->avg_snr > RF_RA_LOW_THRE_SNR_VAL) {
ra->avg_snr -= RF_RA_CON_NOSACK_PENALTY_SNR_STEP;
iot_printf("rf reduce snr to %d\n", ra->avg_snr);
}
}
return;
}
void rf_ra_clr_no_sack_cnt(rate_info_t *ra)
{
if (!ra) {
return;
}
ra->con_no_sack_cnt = 0;
return;
}
void rf_ra_inc_con_sack_err_cnt(rate_info_t *ra)
{
if (!ra) {
return;
}
if (++ra->con_sack_err_cnt > RF_RA_CON_SACKERR_PENALTY_CNT_THRE) {
if (ra->avg_snr > RF_RA_LOW_THRE_SNR_VAL) {
ra->avg_snr -= RF_RA_CON_SACKERR_PENALTY_SNR_STEP;
iot_printf("rf reduce snr to %d\n", ra->avg_snr);
}
}
return;
}
void rf_ra_clr_con_sack_err_cnt(rate_info_t *ra)
{
if (!ra) {
return;
}
ra->con_sack_err_cnt = 0;
return;
}
#endif