/**************************************************************************** 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 "rx_mpdu_start.h" #include "hw_desc.h" #include "mpdu_header.h" #include "rx_pb_start.h" #include "plc_protocol.h" #include "mac_data_api.h" #include "phy_bb.h" #include "iot_io.h" #include "mac_sched_hw.h" #include "mac_tx_hw.h" #include "mac_hplc_ext_api.h" uint32_t mac_get_nncco_protect_region_offset(uint32_t proto, void *fc) { uint32_t ret = 0; switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: ret = ((frame_control_t *)fc)->vf.nn_cco.sbandoffset; break; #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: ret = ((spg_frame_control_t *)fc)->vf.nn_cco.bwth_start_shift; break; #endif #if SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_GP: /* GP has no this feature */ IOT_ASSERT(0); break; #endif default: // todo break; } return ret; } uint32_t mac_get_nncco_received_nid(uint32_t proto, void *fc) { uint32_t ret = 0; switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: ret = ((frame_control_t *)fc)->vf.nn_cco.receive_nid; break; #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: ret = ((spg_frame_control_t *)fc)->vf.nn_cco.neighbor_network; break; #endif #if SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_GP: /* GP has no this feature */ IOT_ASSERT(0); break; #endif default: // todo break; } return ret; } uint32_t mac_is_unicast(uint32_t proto, void *fc, uint8_t is_rf) { uint32_t ret = 0; (void)is_rf; switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: if (is_rf) { ret = (((frame_control_t *)fc)->vf.rf_sof.dst_tei != 0xfff); } else { ret = (((frame_control_t *)fc)->vf.sof.dst_tei != 0xfff); } break; #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: ret = (((spg_frame_control_t *)fc)->vf.sof.dst_tei != 0xfff); break; #endif #if SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_GP: ret = (((hpav_frame_control *)fc)->vf_av.sof.dst_tei != 0xff); break; #endif default: // todo IOT_ASSERT(0); break; } return ret; } uint32_t mac_get_nncco_protect_dur(uint32_t proto, void *fc) { uint32_t ret = 0; switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: ret = ((frame_control_t *)fc)->vf.nn_cco.duration; break; #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: ret = ((spg_frame_control_t *)fc)->vf.nn_cco.conti_time; break; #endif #if SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_GP: /* GP has no this feature */ IOT_ASSERT(0); break; #endif default: // todo break; } return ret; } uint8_t mac_get_nncco_self_ch_id(uint32_t proto, void *fc) { uint8_t rf_channel; #if HPLC_RF_SUPPORT switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: { rf_channel = (uint8_t)((frame_control_t *)fc)->vf.nn_cco.self_rf_channel; break; } #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: { rf_channel = (uint8_t)((spg_frame_control_t *)fc)->vf.nn_cco.self_rf_channel; break; } #endif default: rf_channel = RF_CHANNEL_ID_INVALID; break; } #else (void)proto; (void)fc; rf_channel = RF_CHANNEL_ID_INVALID; #endif return rf_channel; } uint8_t mac_get_nncco_self_option(uint32_t proto, void *fc) { uint8_t rf_option; #if HPLC_RF_SUPPORT switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: { rf_option = (uint8_t)((frame_control_t *)fc)->vf.nn_cco.self_rf_option; break; } #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: { rf_option = ((spg_frame_control_t *)fc)->vf.nn_cco.self_rf_option; break; } #endif default: rf_option = RF_OPTION_INVALID; break; } #else (void)proto; (void)fc; rf_option = RF_OPTION_INVALID; #endif return rf_option; } uint32_t mac_get_rx_delimiter_from_fc(uint32_t proto, void *fc) { uint32_t deimiter = 0xFF; switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: deimiter = ((frame_control_t *)fc)->delimiter_type; break; #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: deimiter = ((spg_frame_control_t *)fc)->delimiter_type; break; #endif #if SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_GP: deimiter = ((hpav_frame_control *)fc)->delimiter_type; break; #endif default: // todo break; } return deimiter; } uint32_t mac_get_nid_from_fc(uint32_t proto, void *fc) { uint32_t nid = 0xFFFFFFFF; switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: nid = ((frame_control_t *)fc)->nid; break; #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: nid = ((spg_frame_control_t *)fc)->snid; break; #endif #if SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_GP: nid = ((hpav_frame_control *)fc)->snid; break; #endif default: // todo break; } return nid; } void IRAM_ATTR mac_get_rx_frm_msg_from_fc(uint32_t proto, void *fc, rx_fc_msg_t *msg) { uint8_t delimiter = (uint8_t)mac_get_delimi_from_fc(proto, fc); switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: { /* nid share the same place for SG */ frame_control_t *sg_fc = (frame_control_t *)fc; msg->nid = sg_fc->nid; msg->delimiter = delimiter; switch (delimiter) { case FC_DELIM_BEACON: { msg->tmi = sg_fc->vf.bcn.tmi; msg->fccs = sg_fc->vf.bcn.fccs; msg->src_tei = sg_fc->vf.bcn.src_tei; msg->time_stamp = sg_fc->vf.bcn.time_stamp; msg->phase = sg_fc->vf.bcn.phase_num; msg->pb_num = 1; msg->rf_mcs = (uint8_t)sg_fc->vf.rf_bcn.mcs; msg->rf_pb_sz_idx = (uint8_t)sg_fc->vf.rf_bcn.pb_sz_idx; msg->numsym = sg_fc->vf.bcn.sym_num; break; } case FC_DELIM_SOF: { msg->bcast = sg_fc->vf.sof.bcast; msg->src_tei = sg_fc->vf.sof.src_tei; msg->dst_tei = sg_fc->vf.sof.dst_tei; msg->tmi = sg_fc->vf.sof.tmi; msg->lid = sg_fc->vf.sof.lid; msg->retry = sg_fc->vf.sof.retry; msg->tmi_ext = sg_fc->vf.sof.tmi_ext; msg->fccs = sg_fc->vf.sof.fccs; msg->pb_num = (uint8_t)sg_fc->vf.sof.pb_num; msg->rf_mcs = (uint8_t)sg_fc->vf.rf_sof.mcs; msg->rf_pb_sz_idx = (uint8_t)sg_fc->vf.rf_sof.pb_sz_idx; msg->numsym = sg_fc->vf.sof.sym_num; break; } case FC_DELIM_NNCCO: { msg->pb_num = 0; msg->fccs = sg_fc->vf.nn_cco.fccs; break; } case FC_DELIM_SACK: { msg->dst_tei = sg_fc->vf.sack.dtei; msg->src_tei = sg_fc->vf.sack.stei; msg->snr_in_sack = (int8_t)sg_fc->vf.sack.snr; msg->bitmap_in_sack = sg_fc->vf.sack.rx_status; msg->load_in_sack = sg_fc->vf.sack.load; msg->result_in_sack = sg_fc->vf.sack.rx_result; msg->pb_num = (uint8_t)sg_fc->vf.sack.rx_pb; msg->sack_ext_deli = sg_fc->vf.sack.ext_deli; msg->time_stamp = sg_fc->vf.sync.time_stamp; msg->fccs = sg_fc->vf.sack.fccs; break; } case I1901_RTS_CTS: { i1901_frame_control_t *i1901_fc = (i1901_frame_control_t *)fc; msg->pb_num = 0; msg->dst_tei = i1901_fc->vf.rts_cts.dtei; msg->src_tei = i1901_fc->vf.rts_cts.stei; msg->rtsf = i1901_fc->vf.rts_cts.rtsf; break; } default: break; } break; } #endif #if SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_GP: { hpav_frame_control *gp_fc = (hpav_frame_control *)fc; msg->nid = gp_fc->snid; switch (delimiter) { case DT_AV_BEACON: { msg->time_stamp = gp_fc->vf_av.bcn.bts; /* bcn pb size of GP has fixed 136 bytes */ msg->tmi = 2; break; } case DT_AV_SOF: { msg->src_tei = gp_fc->vf_av.sof.src_tei; msg->dst_tei = gp_fc->vf_av.sof.dst_tei; msg->tmi = gp_fc->vf_av.sof.tmi_av; msg->lid = gp_fc->vf_av.sof.lid; msg->fccs = gp_fc->fccs_av.fccs_av0; msg->fccs |= gp_fc->fccs_av.fccs_av1 << 8; msg->fccs |= gp_fc->fccs_av.fccs_av2 << 16; msg->numsym = gp_fc->vf_av.sof.numsym; break; } case DT_AV_SACK: { break; } case DT_AV_RTS_CTS: { msg->src_tei = gp_fc->vf_av.rtscts.src_tei; msg->dst_tei = gp_fc->vf_av.rtscts.dst_tei; msg->lid = gp_fc->vf_av.rtscts.lid; msg->rtsf = gp_fc->vf_av.rtscts.rtsf; break; } case DT_AV_SOUND: { msg->src_tei = gp_fc->vf_av.sound.stei; msg->dst_tei = gp_fc->vf_av.sound.dtei; msg->lid = gp_fc->vf_av.sound.lid; msg->saf = gp_fc->vf_av.sound.saf; break; } case DT_AV_RSOF: { break; } default: break; } break; } #endif #if SUPPORT_GREEN_PHY //Av SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_AV: { // TO BE DONE break; } #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: { spg_frame_control_t *spg_fc = (spg_frame_control_t *)fc; msg->nid = spg_fc->snid; msg->delimiter = delimiter; switch (delimiter) { case FC_DELIM_BEACON: { uint8_t *fccs = spg_fc->vf.bcn.fccs; msg->tmi = spg_fc->vf.bcn.tmi; msg->fccs = fccs[0]; msg->fccs |= fccs[1] << 8; msg->fccs |= fccs[2] << 16; msg->time_stamp = spg_fc->vf.bcn.time_stamp; msg->src_tei = spg_fc->vf.bcn.src_tei; msg->phase = spg_fc->vf.bcn.phase_num; msg->numsym = spg_fc->vf.bcn.sym_num; break; } case FC_DELIM_SOF: { msg->src_tei = spg_fc->vf.sof.src_tei; msg->dst_tei = spg_fc->vf.sof.dst_tei; msg->tmi = spg_fc->vf.sof.tmi; msg->lid = spg_fc->vf.sof.lid; msg->retry = spg_fc->vf.sof.retry; msg->tmi_ext = spg_fc->vf.sof.tmi_ext; msg->fccs = spg_fc->vf.sof.fccs; msg->pb_num = (uint8_t)spg_fc->vf.sof.pb_num; msg->numsym = spg_fc->vf.sof.sym_num; break; } case FC_DELIM_SACK: { msg->dst_tei = spg_fc->vf.sack.dtei; msg->bitmap_in_sack = spg_fc->vf.sack.rx_status; msg->result_in_sack = spg_fc->vf.sack.rx_result; msg->pb_num = (uint8_t)spg_fc->vf.sack.rx_pb; msg->sack_ext_deli = spg_fc->vf.sack.ext_deli; msg->time_stamp = spg_fc->vf.sync.time_stamp; msg->fccs = spg_fc->vf.sack.fccs; break; } case FC_DELIM_NNCCO: { msg->fccs = spg_fc->vf.nn_cco.fccs; break; } case FC_DELIM_SOUND: { break; } default: break; } break; } #endif default: break; } return; } void mac_rf_get_rx_frm_msg_from_fc(uint32_t proto, void *fc, rx_fc_msg_t *msg) { uint8_t delimiter = (uint8_t)mac_get_delimi_from_fc(proto, fc); msg->delimiter = delimiter; switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: { /* nid share the same place for SG */ frame_control_t *sg_fc = (frame_control_t *)fc; msg->nid = sg_fc->nid; switch (delimiter) { case FC_DELIM_BEACON: { msg->time_stamp = sg_fc->vf.rf_bcn.time_stamp; msg->src_tei = sg_fc->vf.rf_bcn.src_tei; msg->rf_mcs = (uint8_t)sg_fc->vf.rf_bcn.mcs; msg->rf_pb_sz_idx = (uint8_t)sg_fc->vf.rf_bcn.pb_sz_idx; msg->pb_num = 1; msg->fccs = sg_fc->vf.rf_bcn.fccs; break; } case FC_DELIM_SOF: { msg->src_tei = sg_fc->vf.rf_sof.src_tei; msg->dst_tei = sg_fc->vf.rf_sof.dst_tei; msg->lid = sg_fc->vf.rf_sof.lid; msg->rf_pb_sz_idx = (uint8_t)sg_fc->vf.rf_sof.pb_sz_idx; msg->bcast = sg_fc->vf.rf_sof.bcast; msg->retry = sg_fc->vf.rf_sof.retry; msg->rf_mcs = (uint8_t)sg_fc->vf.rf_sof.mcs; msg->pb_num = 1; msg->fccs = sg_fc->vf.rf_sof.fccs; break; } case FC_DELIM_SACK: { msg->result_in_sack = sg_fc->vf.rf_sack.rx_result; msg->src_tei = sg_fc->vf.rf_sack.stei; msg->dst_tei = sg_fc->vf.rf_sack.dtei; msg->snr_in_sack = (int8_t)sg_fc->vf.rf_sack.snr; msg->load_in_sack = sg_fc->vf.rf_sack.load; msg->sack_ext_deli = sg_fc->vf.rf_sack.ext_deli; msg->fccs = sg_fc->vf.rf_sack.fccs; break; } default: break; } break; } #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: { spg_frame_control_t *spg_fc = (spg_frame_control_t *)fc; msg->nid = spg_fc->snid; switch (delimiter) { case FC_DELIM_BEACON: { msg->time_stamp = spg_fc->vf.rf_bcn.time_stamp; msg->src_tei = spg_fc->vf.rf_bcn.src_tei; msg->rf_mcs = (uint8_t)spg_fc->vf.rf_bcn.mcs; msg->rf_pb_sz_idx = (uint8_t)spg_fc->vf.rf_bcn.pb_sz_idx; msg->pb_num = 1; msg->fccs = spg_fc->vf.rf_bcn.fccs[0]; msg->fccs |= spg_fc->vf.rf_bcn.fccs[1] << 8; msg->fccs |= spg_fc->vf.rf_bcn.fccs[2] << 16; break; } case FC_DELIM_SOF: { msg->src_tei = spg_fc->vf.rf_sof.src_tei; msg->dst_tei = spg_fc->vf.rf_sof.dst_tei; msg->lid = spg_fc->vf.rf_sof.lid; msg->rf_pb_sz_idx = (uint8_t)spg_fc->vf.rf_sof.pb_sz_idx; msg->retry = spg_fc->vf.rf_sof.retry; msg->rf_mcs = (uint8_t)spg_fc->vf.rf_sof.mcs; msg->pb_num = 1; msg->fccs = spg_fc->vf.rf_sof.fccs; break; } case FC_DELIM_SACK: { msg->result_in_sack = spg_fc->vf.rf_sack.rx_result; msg->dst_tei = spg_fc->vf.rf_sack.dtei; msg->sack_ext_deli = spg_fc->vf.rf_sack.ext_deli; msg->fccs = spg_fc->vf.rf_sack.fccs[0]; msg->fccs |= spg_fc->vf.rf_sack.fccs[1] << 8; msg->fccs |= spg_fc->vf.rf_sack.fccs[2] << 16; break; } default: break; } break; } #endif default: (void)proto; (void)fc; (void)msg; break; } return; } void IRAM_ATTR mac_get_tx_msg_from_fc(uint32_t proto, uint32_t delimiter, void *fc, tx_fc_msg_t *msg) { switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: { switch (delimiter) { case FC_DELIM_BEACON: { frame_control_t *sg_fc = (frame_control_t *)fc; msg->network_type = (uint8_t)sg_fc->network_type; msg->nid = sg_fc->nid; msg->tmi = (uint8_t)sg_fc->vf.bcn.tmi; msg->src_tei = (tei_t)sg_fc->vf.bcn.src_tei; msg->rf_mcs = (uint8_t)sg_fc->vf.rf_bcn.mcs; msg->rf_pb_sz_idx = (uint8_t)sg_fc->vf.rf_bcn.pb_sz_idx; break; } case FC_DELIM_SOF: { frame_control_t *sg_fc = (frame_control_t *)fc; msg->tmi = (uint8_t)sg_fc->vf.sof.tmi; msg->ext_tmi = (uint8_t)sg_fc->vf.sof.tmi_ext; msg->rf_mcs = (uint8_t)sg_fc->vf.rf_sof.mcs; msg->rf_pb_sz_idx = (uint8_t)sg_fc->vf.rf_sof.pb_sz_idx; break; } case FC_DELIM_NNCCO: { break; } case FC_DELIM_SOUND: { break; } default: break; } break; } #endif #if SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_GP: { switch (delimiter) { case DT_AV_BEACON: { hpav_frame_control *gp_fc = (hpav_frame_control *)fc; (void)gp_fc; break; } case DT_AV_SOF: { hpav_frame_control *gp_fc = (hpav_frame_control *)fc; msg->tmi = (uint8_t)gp_fc->vf_av.sof.tmi_av; break; } case DT_AV_SACK: { break; } case DT_AV_RTS_CTS: { break; } case DT_AV_SOUND: { break; } case DT_AV_RSOF: { break; } default: break; } break; } #endif #if SUPPORT_GREEN_PHY //Av use SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_AV: { // TO BE DONE }break; #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: { switch (delimiter) { case FC_DELIM_BEACON: { spg_frame_control_t *spg_fc = (spg_frame_control_t *)fc; msg->network_type = (uint8_t)spg_fc->access_ind; msg->nid = spg_fc->snid; msg->tmi = (uint8_t)spg_fc->vf.bcn.tmi; msg->src_tei = (tei_t)spg_fc->vf.bcn.src_tei; msg->bcn_period_cnt = spg_fc->vf.bcn.bcn_period_cnt; msg->rf_mcs = (uint8_t)spg_fc->vf.rf_bcn.mcs; msg->rf_pb_sz_idx = (uint8_t)spg_fc->vf.rf_bcn.pb_sz_idx; break; } case FC_DELIM_SOF: { spg_frame_control_t *spg_fc = (spg_frame_control_t *)fc; msg->tmi = (uint8_t)spg_fc->vf.sof.tmi; msg->ext_tmi = (uint8_t)spg_fc->vf.sof.tmi_ext; msg->rf_mcs = (uint8_t)spg_fc->vf.rf_sof.mcs; msg->rf_pb_sz_idx = (uint8_t)spg_fc->vf.rf_sof.pb_sz_idx; break; } case FC_DELIM_NNCCO: { break; } case FC_DELIM_SOUND: { break; } default: break; } break; } #endif default: break; } return; } uint32_t IRAM_ATTR mac_get_delimi_from_fc(uint32_t proto, void *fc) { uint32_t deimiter = 0xFF; switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: { #if SUPPORT_IEEE_1901 i1901_frame_control_t *i1901_fc = (i1901_frame_control_t *)fc; deimiter = i1901_fc->delimiter_type; #else frame_control_t *sg_fc = (frame_control_t *)fc; deimiter = sg_fc->delimiter_type; #endif break; } #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: { spg_frame_control_t *spg_fc = (spg_frame_control_t *)fc; deimiter = spg_fc->delimiter_type; break; } #endif #if SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_GP: { hpav_frame_control *gp_fc = (hpav_frame_control *)fc; deimiter = gp_fc->delimiter_type; break; } #endif default: // todo break; } return deimiter; } void mac_beacon_rx_fc_info_get(uint8_t proto, mac_rx_info_t *rx_info, rx_fc_msg_t *msg) { IOT_ASSERT(msg); switch(proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: { frame_control_t *fc = (frame_control_t *)rx_info->fc; msg->nid = fc->nid; if (rx_info->phy.is_rf) { msg->time_stamp = fc->vf.rf_bcn.time_stamp; } else { msg->time_stamp = fc->vf.bcn.time_stamp; } break; } #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: { spg_frame_control_t *fc = (spg_frame_control_t *)rx_info->fc; msg->nid = fc->snid; msg->time_stamp = fc->vf.bcn.time_stamp; break; } #endif default: break; } } uint8_t mac_get_mpdu_fc_len(uint32_t proto) { uint8_t mpdu_fc_len = 0; switch (proto) { #if (SUPPORT_SMART_GRID || SUPPORT_SOUTHERN_POWER_GRID || SUPPORT_GREEN_PHY) case PLC_PROTO_TYPE_SG: case PLC_PROTO_TYPE_SPG: case PLC_PROTO_TYPE_GP: mpdu_fc_len = PLC_MPDU_FC_LEN; break; #endif default: // todo break; } return mpdu_fc_len; } uint8_t mac_get_mpdu_fccs_len(uint32_t proto) { uint8_t mpdu_fccs_len = 0; switch (proto) { #if (SUPPORT_SMART_GRID || SUPPORT_SOUTHERN_POWER_GRID || SUPPORT_GREEN_PHY) case PLC_PROTO_TYPE_SG: case PLC_PROTO_TYPE_SPG: case PLC_PROTO_TYPE_GP: mpdu_fccs_len = PLC_MPDU_FCCS_LEN; break; #endif default: // todo break; } return mpdu_fccs_len; } uint8_t mac_get_pb_hdr_crc_len(uint32_t delimiter, uint32_t proto) { uint8_t pb_hdr_crc_len = 0; switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: switch (delimiter) { case FC_DELIM_BEACON: #if SUPPORT_IEEE_1901 pb_hdr_crc_len = I1901_BCN_PB_HDR_CRC_LEN; #else pb_hdr_crc_len = SG_BCN_PB_HDR_CRC_LEN; #endif break; case FC_DELIM_SOF: #if SUPPORT_IEEE_1901 pb_hdr_crc_len = I1901_SOF_PB_HDR_CRC_LEN; #else pb_hdr_crc_len = SG_SOF_PB_HDR_CRC_LEN; #endif break; case FC_DELIM_NNCCO: pb_hdr_crc_len = 0; break; case FC_DELIM_SOUND: pb_hdr_crc_len = SG_SOF_PB_HDR_CRC_LEN; break; default: pb_hdr_crc_len = 0; break; } break; #endif #if SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_GP: switch (delimiter) { case DT_AV_BEACON: pb_hdr_crc_len = GP_BCN_PB_HDR_CRC_LEN; break; case DT_AV_SOF: pb_hdr_crc_len = GP_SOF_PB_HDR_CRC_LEN; break; case DT_AV_SACK: case DT_AV_RTS_CTS: pb_hdr_crc_len = 0; break; case DT_AV_SOUND: pb_hdr_crc_len = GP_SOUND_PB_HDR_CRC_LEN; break; default: pb_hdr_crc_len = 0; break; } break; #endif #if SUPPORT_GREEN_PHY //Av SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_AV: { // TO BE DONE break; } #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: { switch (delimiter) { case FC_DELIM_BEACON: pb_hdr_crc_len = SPG_BCN_PB_HDR_CRC_LEN; break; case FC_DELIM_SOF: pb_hdr_crc_len = SPG_SOF_PB_HDR_CRC_LEN; break; case FC_DELIM_NNCCO: pb_hdr_crc_len = 0; break; case FC_DELIM_SOUND: pb_hdr_crc_len = SPG_SOF_PB_HDR_CRC_LEN; break; default: pb_hdr_crc_len = 0; break; } break; } #endif default: break; } return pb_hdr_crc_len; } uint8_t mac_get_pb_hdr_resv_crc_len(uint32_t delimiter, uint32_t proto) { uint8_t pb_hdr_resv_crc_len = 0; switch (proto) { #if (SUPPORT_SMART_GRID || SUPPORT_GREEN_PHY) case PLC_PROTO_TYPE_SG: case PLC_PROTO_TYPE_GP: case PLC_PROTO_TYPE_AV: pb_hdr_resv_crc_len = mac_get_pb_hdr_crc_len(delimiter, proto); break; #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: switch (delimiter) { case FC_DELIM_BEACON: pb_hdr_resv_crc_len += SPG_BCN_PB_HDR_CRC_LEN + SPG_BCN_PB_RESV_LEN; break; case FC_DELIM_SOF: pb_hdr_resv_crc_len = SPG_SOF_PB_HDR_CRC_LEN + SPG_SOF_PB_RESV_LEN; break; case FC_DELIM_NNCCO: pb_hdr_resv_crc_len = 0; break; case FC_DELIM_SOUND: pb_hdr_resv_crc_len = SPG_SOF_PB_HDR_CRC_LEN + SPG_SOF_PB_RESV_LEN; break; default: pb_hdr_resv_crc_len = 0; break; } break; #endif default: break; } return pb_hdr_resv_crc_len; } uint8_t mac_get_pb_pld_crc_len(uint32_t delimiter, uint32_t proto) { uint8_t pb_pld_crc_len = 0; switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: { switch (delimiter) { case FC_DELIM_BEACON: #if SUPPORT_IEEE_1901 pb_pld_crc_len = I1901_BCN_PB_PAYLOAD_CRC_LEN; #else pb_pld_crc_len = SG_BCN_PB_PAYLOAD_CRC_LEN; #endif break; case FC_DELIM_SOF: pb_pld_crc_len = 0; break; case FC_DELIM_NNCCO: pb_pld_crc_len = 0; break; case FC_DELIM_SOUND: pb_pld_crc_len = 0; break; default: pb_pld_crc_len = 0; break; } break; } #endif #if SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_GP: { switch (delimiter) { case DT_AV_BEACON: pb_pld_crc_len = 0; break; case DT_AV_SOF: pb_pld_crc_len = 0; break; case DT_AV_SACK: pb_pld_crc_len = 0; break; case DT_AV_RTS_CTS: pb_pld_crc_len = 0; break; case DT_AV_SOUND: pb_pld_crc_len = 0; break; default: pb_pld_crc_len = 0; break; } break; } #endif #if SUPPORT_GREEN_PHY //Av SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_AV: { // TO BE DONE break; } #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: { switch (delimiter) { case FC_DELIM_BEACON: pb_pld_crc_len = SPG_BCN_PB_PAYLOAD_CRC_LEN; break; case FC_DELIM_SOF: pb_pld_crc_len = 0; break; case FC_DELIM_NNCCO: pb_pld_crc_len = 0; break; case FC_DELIM_SOUND: pb_pld_crc_len = 0; break; default: pb_pld_crc_len = 0; break; } break; } #endif default: break; } return pb_pld_crc_len; } uint8_t mac_get_pb_crc_len(uint32_t delimiter, uint32_t proto) { uint8_t pb_pb_crc_len = 0; switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: { switch (delimiter) { case FC_DELIM_BEACON: #if SUPPORT_IEEE_1901 pb_pb_crc_len = I1901_BCN_PB_CRC_LEN; #else pb_pb_crc_len = SG_BCN_PB_CRC_LEN; #endif break; case FC_DELIM_SOF: #if SUPPORT_IEEE_1901 pb_pb_crc_len = I1901_SOF_PB_CRC_LEN; #else pb_pb_crc_len = SG_SOF_PB_CRC_LEN; #endif break; case FC_DELIM_NNCCO: pb_pb_crc_len = 0; break; case FC_DELIM_SOUND: pb_pb_crc_len = SG_SOF_PB_CRC_LEN; break; default: pb_pb_crc_len = 0; break; } break; } #endif #if SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_GP: { switch (delimiter) { case DT_AV_BEACON: pb_pb_crc_len = GP_BCN_PB_CRC_LEN; break; case DT_AV_SOF: pb_pb_crc_len = GP_SOF_PB_CRC_LEN; break; case DT_AV_SACK: case DT_AV_RTS_CTS: pb_pb_crc_len = 0; break; case DT_AV_SOUND: pb_pb_crc_len = GP_SOUND_PB_CRC_LEN; break; default: pb_pb_crc_len = 0; break; } break; } #endif #if SUPPORT_GREEN_PHY //Av use macor of SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_AV: { // TO BE DONE break; } #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: { switch (delimiter) { case FC_DELIM_BEACON: pb_pb_crc_len = SPG_BCN_PB_CRC_LEN; break; case FC_DELIM_SOF: pb_pb_crc_len = SPG_SOF_PB_CRC_LEN; break; case FC_DELIM_NNCCO: pb_pb_crc_len = 0; break; case FC_DELIM_SOUND: pb_pb_crc_len = SPG_SOF_PB_CRC_LEN; break; default: pb_pb_crc_len = 0; break; } break; } #endif default: break; } return pb_pb_crc_len; } uint8_t mac_get_pb_hdr_len(uint32_t delimiter, uint32_t proto) { uint8_t pb_hdr_len = 0; switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: { switch (delimiter) { case FC_DELIM_BEACON: pb_hdr_len = 0; break; case FC_DELIM_SOF: #if SUPPORT_IEEE_1901 pb_hdr_len = I1901_SOF_PB_HDR_LEN; #else pb_hdr_len = SG_SOF_PB_HDR_LEN; #endif break; default: pb_hdr_len = 0; break; } break; } #endif #if SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_GP: { switch (delimiter) { case DT_AV_BEACON: pb_hdr_len = 0; break; case DT_AV_SOF: pb_hdr_len = GP_SOF_PB_HDR_LEN; break; case DT_AV_SACK: case DT_AV_RTS_CTS: pb_hdr_len = 0; break; case DT_AV_SOUND: pb_hdr_len = 0; break; default: break; } break; } #endif #if SUPPORT_GREEN_PHY //Av use macor of SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_AV: { // TO BE DONE break; } #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: { switch (delimiter) { case FC_DELIM_BEACON: pb_hdr_len = 0; break; case FC_DELIM_SOF: pb_hdr_len = SPG_SOF_PB_HDR_LEN; break; default: pb_hdr_len = 0; break; } break; } #endif default: break; } return pb_hdr_len; } uint32_t mac_get_sof_pb_valid_payload_sz(uint32_t proto, uint32_t pb_size) { switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: #if SUPPORT_IEEE_1901 if (!((72 == pb_size) || (136 == pb_size) || (520 == pb_size))) { /* invalid pb size */ return 0; } #else /* SUPPORT_IEEE_1901 */ if (!((72 == pb_size) || (136 == pb_size) || (264 == pb_size) || (520 == pb_size))) { /* invalid pb size */ return 0; } #endif /* SUPPORT_IEEE_1901 */ break; #endif /* SUPPORT_SMART_GRID */ #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: if (!((136 == pb_size) || (520 == pb_size))) { /* invalid pb size */ return 0; } break; #endif /* SUPPORT_SOUTHERN_POWER_GRID */ default: return 0; } return (uint32_t)(pb_size - mac_get_pb_hdr_resv_crc_len(FC_DELIM_SOF, proto)); } void IRAM_ATTR mac_get_nncco_info_from_fc(void *fc, nncco_fc_info_t *nn_fc_info) { IOT_ASSERT(fc); uint32_t proto = PHY_PROTO_TYPE_GET(); uint8_t delimiter = (uint8_t)mac_get_delimi_from_fc(proto, fc); switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: { /* nid share the same place for SG */ frame_control_t *sg_fc = (frame_control_t *)fc; nn_fc_info->nid = sg_fc->nid; nn_fc_info->delimiter = delimiter; switch (delimiter) { case FC_DELIM_NNCCO: { nn_fc_info->receive_nid = sg_fc->vf.nn_cco.receive_nid; nn_fc_info->duration = sg_fc->vf.nn_cco.duration; nn_fc_info->sbandoffset = sg_fc->vf.nn_cco.sbandoffset; nn_fc_info->self_rf_channel = (uint8_t)sg_fc->vf.nn_cco.self_rf_channel; nn_fc_info->self_rf_option = (uint8_t)sg_fc->vf.nn_cco.self_rf_option; break; } default: IOT_ASSERT(0); break; } break; } #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: { spg_frame_control_t *spg_fc = (spg_frame_control_t *)fc; nn_fc_info->nid = spg_fc->snid; nn_fc_info->delimiter = delimiter; switch (delimiter) { case FC_DELIM_NNCCO: { /* nncco info */ nn_fc_info->receive_nid = spg_fc->vf.nn_cco.neighbor_network; nn_fc_info->duration = spg_fc->vf.nn_cco.conti_time; nn_fc_info->bwth_end_flag = spg_fc->vf.nn_cco.bwth_end_flag; nn_fc_info->bwth_end_shift = spg_fc->vf.nn_cco.bwth_end_shift; nn_fc_info->sbandoffset = spg_fc->vf.nn_cco.bwth_start_shift; nn_fc_info->self_rf_channel = spg_fc->vf.nn_cco.self_rf_channel; nn_fc_info->self_rf_option = spg_fc->vf.nn_cco.self_rf_option; break; } default: IOT_ASSERT(0); break; } break; } #endif default: break; } (void)proto; (void)delimiter; return; } /* judge receive nid whether is mynid */ uint32_t mac_nncco_nid_compare(uint32_t nid_in_nncco, uint32_t nid_to_check) { uint32_t proto = PHY_PROTO_TYPE_GET(); if (PLC_PROTO_TYPE_SG == proto) { if (nid_in_nncco == nid_to_check) { return 1; } } else if (PLC_PROTO_TYPE_SPG == proto) { if (nid_in_nncco & (1 << (nid_to_check - 1))) { return 1; } } return 0; } uint32_t mac_debug_nncco_info(void *fc, uint32_t ntb) { uint32_t proto = PHY_PROTO_TYPE_GET(); #if HW_PLATFORM == HW_PLATFORM_SIMU nncco_fc_info_t nn_fc_info = { 0 }; mac_get_nncco_sw_info_from_fc(fc, &nn_fc_info); if (PLC_PROTO_TYPE_SG == proto) { iot_printf("%s proto:%d, nid %lu dur %lu start_ntb %lu, nn nid %lu, " "local ntb %lu\n", __FUNCTION__, proto, nn_fc_info.nid, (uint32_t)nn_fc_info.sw_duration, nn_fc_info.start_ntb_l32, (uint32_t)nn_fc_info.sw_receive_nid, ntb); } else if (PLC_PROTO_TYPE_SPG == proto) { iot_printf("%s proto:%d, nid %lu, dur:%lu, start_ntb:%lu, " "last_ntb_offset:%lu, rece nid %lu, local ntb %lu\n", __FUNCTION__, proto, nn_fc_info.nid, (uint32_t)nn_fc_info.sw_duration, nn_fc_info.start_ntb_l32, nn_fc_info.last_offset, (uint32_t)nn_fc_info.sw_receive_nid, ntb); } #else /* HW_PLATFORM == HW_PLATFORM_SIMU */ nncco_fc_info_t nn_fc_info = { 0 }; mac_get_nncco_info_from_fc(fc, &nn_fc_info); #if SUPPORT_SMART_GRID if (PLC_PROTO_TYPE_SG == proto) { iot_printf("nncco p:%d, n:%lu, d:%lu, ef:%d, es:%d," " so:%lu, nbm:%lu, ln:%lu\n", proto, nn_fc_info.nid, nn_fc_info.duration, nn_fc_info.sbandoffset, nn_fc_info.receive_nid, ntb); } #endif #if SUPPORT_SOUTHERN_POWER_GRID if (PLC_PROTO_TYPE_SPG == proto) { iot_printf("nncco p:%d, n:%lu, d40:%lu, ef:%d, lo4:%lu, " "nsto4:%lu, nbm:%lu, ln %lu\n", proto, nn_fc_info.nid, nn_fc_info.duration, nn_fc_info.bwth_end_flag, nn_fc_info.bwth_end_shift, nn_fc_info.sbandoffset, nn_fc_info.receive_nid, ntb); } #endif #endif /* HW_PLATFORM == HW_PLATFORM_SIMU */ (void)proto; return 0; } void IRAM_ATTR mac_set_bcn_st(void *fc, uint32_t ntb) { #if HW_PLATFORM != HW_PLATFORM_SIMU IOT_ASSERT(fc); uint32_t proto = PHY_PROTO_TYPE_GET(); #if SUPPORT_SMART_GRID frame_control_t *cur_fc_sg; if (PLC_PROTO_TYPE_SG == proto) { cur_fc_sg = (frame_control_t *)fc; cur_fc_sg->vf.bcn.time_stamp = ntb; } #endif #if SUPPORT_SOUTHERN_POWER_GRID spg_frame_control_t *cur_fc_spg; if (PLC_PROTO_TYPE_SPG == proto) { cur_fc_spg = (spg_frame_control_t *)fc; cur_fc_spg->vf.bcn.time_stamp = ntb; } #endif (void)proto; #else (void)fc; (void)ntb; #endif return; } void IRAM_ATTR mac_set_sync_st(void *fc, uint32_t ntb) { #if HW_PLATFORM != HW_PLATFORM_SIMU IOT_ASSERT(fc); uint32_t proto = PHY_PROTO_TYPE_GET(); #if SUPPORT_SMART_GRID if (PLC_PROTO_TYPE_SG == proto) { frame_control_t *cur_fc_sg = (frame_control_t *)fc; if (cur_fc_sg->vf.sync.ext_type == SACK_EXT_TYPE_SYNC) { cur_fc_sg->vf.sync.time_stamp = ntb; } } #endif #if SUPPORT_SOUTHERN_POWER_GRID if (PLC_PROTO_TYPE_SPG == proto) { spg_frame_control_t *cur_fc_spg = (spg_frame_control_t *)fc; if (cur_fc_spg->vf.sync.ext_type == SACK_EXT_TYPE_SYNC) { cur_fc_spg->vf.sync.time_stamp = ntb; } } #endif #else (void)fc; (void)ntb; #endif return; } uint32_t mac_get_sof_frame_len(uint32_t proto, void *fc) { (void)fc; switch(proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: { frame_control_t *sg_fc = fc; return sg_fc->vf.sof.frame_len; } #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: { spg_frame_control_t *spg_fc = fc; return spg_fc->vf.sof.frm_len; } #endif #if SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_AV: case PLC_PROTO_TYPE_GP: { hpav_frame_control *av_fc = fc; return av_fc->vf_av.sof.fl_av; } #endif default: IOT_ASSERT(0); return ERR_FAIL; } } uint32_t mac_get_sof_pbnum(uint32_t proto, void *fc) { (void)fc; switch(proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: { frame_control_t *sg_fc = fc; return sg_fc->vf.sof.pb_num; } #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: { spg_frame_control_t *spg_fc = fc; return spg_fc->vf.sof.pb_num; } #endif default: IOT_ASSERT(0); return ERR_FAIL; } } uint32_t mac_mask_input_nid(uint32_t nid) { /* TODO: sometimes, cvg not clear the higher part of nid * so we need to clean the higher part, remove the * following if cvg clean the higher part */ uint32_t proto = PHY_PROTO_TYPE_GET(); if (proto == PLC_PROTO_TYPE_SG) { /* 24 bit for SG */ nid &= 0xffffff; } else if (proto == PLC_PROTO_TYPE_SPG) { /* 4 bit for SPG */ nid &= 0xf; } else { IOT_ASSERT(0); } return nid; } uint32_t mac_get_bcn_st(uint32_t proto, void *fc) { uint32_t st = 0x0; switch (proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: st = ((frame_control_t *)fc)->vf.bcn.time_stamp; break; #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: st = ((spg_frame_control_t *)fc)->vf.bcn.time_stamp; break; #endif #if SUPPORT_GREEN_PHY case PLC_PROTO_TYPE_GP: st = ((hpav_frame_control *)fc)->vf_av.bcn.bts; break; #endif default: // todo break; } return st; } uint32_t mac_get_fc_dtei(uint32_t proto, void *fc) { (void)fc; switch(proto) { #if SUPPORT_SMART_GRID case PLC_PROTO_TYPE_SG: { frame_control_t *sg_fc = fc; return sg_fc->vf.sof.dst_tei; } #endif #if SUPPORT_SOUTHERN_POWER_GRID case PLC_PROTO_TYPE_SPG: { spg_frame_control_t *spg_fc = fc; return spg_fc->vf.sof.dst_tei; } #endif default: IOT_ASSERT(0); return ERR_FAIL; } } uint32_t mac_get_unicast_sack_ts(void) { #if ENA_WAR_244 return g_phy_cpu_share_ctxt.tx_unicast_sack_ts; #else //TODO: add get sack ts code return 0; #endif } void mac_fc_i1901_to_sg(uint32_t proto, void *fc) { #if (SUPPORT_SMART_GRID && SUPPORT_IEEE_1901) uint32_t tmi, tmi_ext; i1901_frame_control_t *fc_1901 = (i1901_frame_control_t *)fc; frame_control_t sg_fc = {0}; if (PLC_PROTO_TYPE_SG != proto) { iot_printf("1901 to sg proto error %d\n", proto); return; } sg_fc.delimiter_type = fc_1901->delimiter_type; sg_fc.network_type = fc_1901->network_type; sg_fc.nid = fc_1901->nid; switch (fc_1901->delimiter_type) { case FC_DELIM_BEACON: phy_tmi_i1901_to_sg(fc_1901->vf.bcn.tmi, !I1901_IS_EXT_TMI_MODE, &tmi, &tmi_ext); sg_fc.vf.bcn.time_stamp = fc_1901->vf.bcn.time_stamp; sg_fc.vf.bcn.src_tei = fc_1901->vf.bcn.stei; sg_fc.vf.bcn.tmi = (uint16_t)tmi; sg_fc.vf.bcn.sym_num = fc_1901->vf.bcn.pss; sg_fc.vf.bcn.phase_num = fc_1901->vf.bcn.phase_num; sg_fc.vf.bcn.version = fc_1901->vf.bcn.version; sg_fc.vf.bcn.fccs = fc_1901->vf.bcn.fccs; break; case FC_DELIM_SOF: phy_tmi_i1901_to_sg(fc_1901->vf.sof.tmi, fc_1901->vf.sof.tmi_ext, &tmi, &tmi_ext); sg_fc.vf.sof.src_tei = fc_1901->vf.sof.stei; sg_fc.vf.sof.dst_tei = fc_1901->vf.sof.dtei; sg_fc.vf.sof.lid = fc_1901->vf.sof.lid; sg_fc.vf.sof.frame_len = fc_1901->vf.sof.frame_len; sg_fc.vf.sof.pb_num = fc_1901->vf.sof.pb_num; sg_fc.vf.sof.sym_num = fc_1901->vf.sof.pss; sg_fc.vf.sof.bcast = fc_1901->vf.sof.bcast; sg_fc.vf.sof.retry = fc_1901->vf.sof.retry; /* ieee1901: 0x00 cco managed NEKS, 0x03 MPDU unencryed */ sg_fc.vf.sof.encry = !fc_1901->vf.sof.encry; sg_fc.vf.sof.tmi = (uint16_t)tmi; sg_fc.vf.sof.tmi_ext = tmi_ext; sg_fc.vf.sof.version = fc_1901->vf.sof.version; sg_fc.vf.sof.fccs = fc_1901->vf.sof.fccs; break; case FC_DELIM_SACK: if (fc_1901->vf.sack.rx_pb) { sg_fc.vf.sack.rx_result = !(((1 << fc_1901->vf.sack.rx_pb) - 1) & fc_1901->vf.sack.result); } sg_fc.vf.sack.rx_status = fc_1901->vf.sack.result; sg_fc.vf.sack.stei = fc_1901->vf.sack.stei; sg_fc.vf.sack.dtei = fc_1901->vf.sack.dtei; sg_fc.vf.sack.rx_pb = fc_1901->vf.sack.rx_pb; sg_fc.vf.sack.snr = fc_1901->vf.sack.snr; sg_fc.vf.sack.load = fc_1901->vf.sack.load; sg_fc.vf.sack.ext_deli = fc_1901->vf.sack.ext_deli; sg_fc.vf.sack.version = fc_1901->vf.sack.version; sg_fc.vf.sack.fccs = fc_1901->vf.sack.fccs; break; case FC_DELIM_NNCCO: #if (HW_PLATFORM >= HW_PLATFORM_FPGA) /* sg unit: 1ms, ieee1901 unit: 40ms */ sg_fc.vf.nn_cco.duration = fc_1901->vf.nn_cco.duration * 40; /* sg and ieee1901 unit: 1ms */ sg_fc.vf.nn_cco.sbandoffset = fc_1901->vf.nn_cco.sbandoffset; sg_fc.vf.nn_cco.receive_nid = fc_1901->vf.nn_cco.receive_nid; sg_fc.vf.nn_cco.self_rf_channel = RF_CHANNEL_ID_INVALID; sg_fc.vf.nn_cco.self_rf_option = RF_OPTION_INVALID; sg_fc.vf.nn_cco.version = fc_1901->vf.nn_cco.version; sg_fc.vf.nn_cco.fccs = fc_1901->vf.nn_cco.fccs; break; #else return; #endif case I1901_RTS_CTS: default: return; } os_mem_cpy(fc_1901, &sg_fc, sizeof(sg_fc)); #else (void)proto; (void)fc; #endif } void mac_fc_sg_to_i1901(uint32_t proto, void *fc) { #if (SUPPORT_SMART_GRID && SUPPORT_IEEE_1901) uint32_t tmi, tmi_ext; frame_control_t *sg_fc = (frame_control_t *)fc; i1901_frame_control_t fc_1901 = {0}; if (PLC_PROTO_TYPE_SG != proto) { iot_printf("sg to 1901 proto error %d\n", proto); return; } fc_1901.delimiter_type = sg_fc->delimiter_type; fc_1901.network_type = sg_fc->network_type; fc_1901.nid = sg_fc->nid; switch (sg_fc->delimiter_type) { case FC_DELIM_BEACON: phy_tmi_sg_to_i1901(sg_fc->vf.bcn.tmi, !I1901_IS_EXT_TMI_MODE, &tmi, &tmi_ext); fc_1901.vf.bcn.time_stamp = sg_fc->vf.bcn.time_stamp; fc_1901.vf.bcn.stei = sg_fc->vf.bcn.src_tei; fc_1901.vf.bcn.tmi = (uint16_t)tmi; fc_1901.vf.bcn.pss = (uint16_t)phy_get_pss_id(proto, tmi, tmi_ext); fc_1901.vf.bcn.phase_num = sg_fc->vf.bcn.phase_num; fc_1901.vf.bcn.version = sg_fc->vf.bcn.version; fc_1901.vf.bcn.fccs = sg_fc->vf.bcn.fccs; break; case FC_DELIM_SOF: phy_tmi_sg_to_i1901(sg_fc->vf.sof.tmi, sg_fc->vf.sof.tmi_ext, &tmi, &tmi_ext); fc_1901.vf.sof.stei = sg_fc->vf.sof.src_tei; fc_1901.vf.sof.dtei = sg_fc->vf.sof.dst_tei; fc_1901.vf.sof.lid = sg_fc->vf.sof.lid; fc_1901.vf.sof.frame_len = sg_fc->vf.sof.frame_len; fc_1901.vf.sof.pb_num = sg_fc->vf.sof.pb_num; fc_1901.vf.sof.pss = (uint16_t)phy_get_pss_id(proto, tmi, tmi_ext); fc_1901.vf.sof.bcast = sg_fc->vf.sof.bcast; fc_1901.vf.sof.retry = sg_fc->vf.sof.retry; /* ieee1901: 0x00 cco managed NEKS, 0x03 MPDU unencryed */ fc_1901.vf.sof.encry = sg_fc->vf.sof.encry ? 0x00 : 0x03; fc_1901.vf.sof.tmi = (uint16_t)tmi; fc_1901.vf.sof.tmi_ext = (uint16_t)tmi_ext; fc_1901.vf.sof.version = sg_fc->vf.sof.version; fc_1901.vf.sof.fccs = sg_fc->vf.sof.fccs; break; case FC_DELIM_SACK: fc_1901.vf.sack.result = sg_fc->vf.sack.rx_status; fc_1901.vf.sack.stei = sg_fc->vf.sack.stei; fc_1901.vf.sack.dtei = sg_fc->vf.sack.dtei; fc_1901.vf.sack.rx_pb = sg_fc->vf.sack.rx_pb; fc_1901.vf.sack.snr = sg_fc->vf.sack.snr; fc_1901.vf.sack.load = sg_fc->vf.sack.load; fc_1901.vf.sack.ext_deli = sg_fc->vf.sack.ext_deli; fc_1901.vf.sack.version = sg_fc->vf.sack.version; fc_1901.vf.sack.fccs = sg_fc->vf.sack.fccs; break; case FC_DELIM_NNCCO: #if (HW_PLATFORM >= HW_PLATFORM_FPGA) /* sg unit: 1ms, ieee1901 unit: 40ms */ fc_1901.vf.nn_cco.duration = sg_fc->vf.nn_cco.duration / 40; /* sg and ieee1901 unit: 1ms */ fc_1901.vf.nn_cco.sbandoffset = sg_fc->vf.nn_cco.sbandoffset; fc_1901.vf.nn_cco.receive_nid = sg_fc->vf.nn_cco.receive_nid; fc_1901.vf.nn_cco.version = sg_fc->vf.nn_cco.version; fc_1901.vf.nn_cco.fccs = sg_fc->vf.nn_cco.fccs; break; #else return; #endif case I1901_RTS_CTS: default: return; } os_mem_cpy(sg_fc, &fc_1901, sizeof(fc_1901)); #else (void)proto; (void)fc; #endif } #if (ENA_HW_SYNC_PPM_WAR || ENA_SW_SYNC_PPM_WAR) int32_t IRAM_ATTR mac_get_clear_dbg_pkt_ppm_step(void *fc) { int32_t ppm_step = 0; uint32_t proto = PHY_PROTO_TYPE_GET(); uint32_t dbg_pkt_version = 0; if (phy_get_g_mt_mode_sel()) { return 0; } #if SUPPORT_SMART_GRID if (proto == PLC_PROTO_TYPE_SG) { frame_control_t *sg_fc = (frame_control_t*)fc; if (FC_DELIM_BEACON == sg_fc->delimiter_type) { dbg_pkt_version = sg_fc->vf.bcn.version; ppm_step = (int8_t)sg_fc->vf.bcn.fccs; sg_fc->vf.bcn.fccs = 0; sg_fc->vf.bcn.version = SG_STANDARD_VERSION; } else if (FC_DELIM_SOF == sg_fc->delimiter_type) { dbg_pkt_version = sg_fc->vf.sof.version; ppm_step = (int8_t)sg_fc->vf.sof.fccs; sg_fc->vf.sof.fccs = 0; sg_fc->vf.sof.version = SG_STANDARD_VERSION; } } else #endif /* SUPPORT_SMART_GRID */ #if SUPPORT_SOUTHERN_POWER_GRID if (proto == PLC_PROTO_TYPE_SPG) { spg_frame_control_t *spg_fc = (spg_frame_control_t*)fc; if (FC_DELIM_BEACON == spg_fc->delimiter_type) { dbg_pkt_version = spg_fc->vf.bcn.version; ppm_step = (int8_t)spg_fc->vf.bcn.fccs[0]; spg_fc->vf.bcn.fccs[0] = 0; spg_fc->vf.bcn.version = SPG_STANDARD_VERSION; } else if (FC_DELIM_SOF == spg_fc->delimiter_type) { dbg_pkt_version = spg_fc->vf.bcn.version; ppm_step = (int8_t)spg_fc->vf.sof.fccs; spg_fc->vf.sof.fccs = 0; spg_fc->vf.sof.version = SPG_STANDARD_VERSION; } } #endif /* SUPPORT_SOUTHERN_POWER_GRID */ { (void)fc; (void)proto; } return (int32_t)((dbg_pkt_version == DBG_PKT_VERSION) ? ppm_step : 0); } void IRAM_ATTR mac_modify_dbg_pkt_tx_ppm(int32_t step) { phy_ppm_status_ctxt_t *ppm_sts_ctxt = &g_phy_cpu_share_ctxt.ppm_status; BUILD_BUG_ON(PLC_NTB_PPM_SHIFT >= 4); ppm_sts_ctxt->ppm_status[0].ppm_err = (int16_t)((-g_phy_cpu_share_ctxt.phy_ppm_init << (PLC_NTB_PPM_SHIFT - PLC_REG_PPM_SHIFT)) + (step << PLC_NTB_PPM_SHIFT)); } #endif /* (ENA_HW_SYNC_PPM_WAR || ENA_SW_SYNC_PPM_WAR) */