235 lines
7.1 KiB
C
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
|