338 lines
10 KiB
C
Executable File
338 lines
10 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 "mac_channel.h"
|
|
#include "iot_config.h"
|
|
#include "iot_gpio_api.h"
|
|
#include "os_types.h"
|
|
#include "mac_vdev.h"
|
|
#include "mac_pdev.h"
|
|
#include "iot_io.h"
|
|
#include "gpio_mtx.h"
|
|
|
|
#include "phy_bb.h"
|
|
#include "phy_phase.h"
|
|
#include "plc_protocol.h"
|
|
#include "hw_phy_init.h"
|
|
#include "hw_phy_api.h"
|
|
|
|
/* ch 0 - A channel
|
|
1 - B channel
|
|
2 - C channel
|
|
|
|
A channel: GPIO23 GPIO28 -> 1 others 0
|
|
B channel: GPIO22 GPIO35 -> 1 others 0
|
|
C channel: GPIO23 GPIO35 -> 1 others 0
|
|
*/
|
|
void iot_mac_k48sta_setchannel_gpio(uint8_t ch)
|
|
{
|
|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
|
|
if (ch == MAC_CHANNEL_L_PE) {
|
|
/* L - PE */
|
|
iot_gpio_value_set(22, 0);
|
|
iot_gpio_value_set(23, 0);
|
|
iot_gpio_value_set(28, 0);
|
|
iot_gpio_value_set(9, 0);
|
|
iot_gpio_value_set(23, 1);
|
|
iot_gpio_value_set(9, 1);
|
|
} else if(ch == MAC_CHANNEL_L_N) {
|
|
/* L - N */
|
|
iot_gpio_value_set(22, 0);
|
|
iot_gpio_value_set(23, 0);
|
|
iot_gpio_value_set(28, 0);
|
|
iot_gpio_value_set(9, 0);
|
|
iot_gpio_value_set(23, 1);
|
|
iot_gpio_value_set(28, 1);
|
|
} else if(ch == MAC_CHANNEL_N_PE) {
|
|
/* N - PE */
|
|
iot_gpio_value_set(22, 0);
|
|
iot_gpio_value_set(23, 0);
|
|
iot_gpio_value_set(28, 0);
|
|
iot_gpio_value_set(9, 0);
|
|
iot_gpio_value_set(22, 1);
|
|
iot_gpio_value_set(9, 1);
|
|
} else {
|
|
iot_gpio_value_set(22, 0);
|
|
iot_gpio_value_set(23, 0);
|
|
iot_gpio_value_set(28, 0);
|
|
iot_gpio_value_set(9, 0);
|
|
}
|
|
#else
|
|
(void)ch;
|
|
#endif
|
|
}
|
|
|
|
void iot_mac_chan_select(uint8_t phase)
|
|
{
|
|
#if K48_STA_MULTI_CHANNEL_SELECT_ENABLE
|
|
if(PLC_PHASE_A == phase) {
|
|
iot_mac_k48sta_setchannel_gpio(MAC_CHANNEL_L_PE);
|
|
} else if(PLC_PHASE_B == phase) {
|
|
iot_mac_k48sta_setchannel_gpio(MAC_CHANNEL_L_N);
|
|
} else if(PLC_PHASE_C == phase) {
|
|
iot_mac_k48sta_setchannel_gpio(MAC_CHANNEL_N_PE);
|
|
} else {
|
|
iot_printf("Error: Phase index mismatched, configure failed...\n");
|
|
return;
|
|
}
|
|
iot_printf("K48 STA Switch Phase to %d...\n", phase);
|
|
#else
|
|
phy_trx_phase_switch_gpio_init();
|
|
phy_set_trx_switch_gpio_phase(phase);
|
|
|
|
iot_printf("Switch Phase to %d...\n", phase);
|
|
if (phy_is_sta_role()) {
|
|
phy_rx_phase_force_set(true, PLC_PHASE_A);
|
|
} else {
|
|
phy_rx_phase_force_set(true, phase);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void iot_mac_k48sta_init_channelgpio(void)
|
|
{
|
|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
|
|
iot_gpio_open_as_output(23);
|
|
iot_gpio_set_pull_mode(23, GPIO_PULL_UP);
|
|
iot_gpio_open_as_output(28);
|
|
iot_gpio_set_pull_mode(28, GPIO_PULL_UP);
|
|
iot_gpio_open_as_output(22);
|
|
iot_gpio_set_pull_mode(22, GPIO_PULL_UP);
|
|
iot_gpio_open_as_output(9);
|
|
iot_gpio_set_pull_mode(9, GPIO_PULL_UP);
|
|
#endif
|
|
}
|
|
|
|
void iot_mac_k48cco_init_channelgpio(void)
|
|
{
|
|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
|
|
gpio_mtx_enable();
|
|
gpio_sig_info_t info1 = {
|
|
3,
|
|
{
|
|
{IO_TYPE_OUT, 0, 23, 0xff, 67},
|
|
{IO_TYPE_OUT, 0, 22, 0xff, 68},
|
|
{IO_TYPE_OUT, 0, 28, 0xff, 69},
|
|
}
|
|
};
|
|
gpio_module_pin_select(&info1);
|
|
gpio_module_sig_select(&info1, GPIO_MTX_MODE_MATRIX);
|
|
#endif
|
|
}
|
|
|
|
void mac_channel_scan_timer_handler(timer_id_t timer_id, void * arg) {
|
|
(void) timer_id;
|
|
mac_pdev_t *pdev = (mac_pdev_t*) arg;
|
|
|
|
/* timer context */
|
|
mac_msg_t *msg = mac_alloc_msg();
|
|
|
|
if (msg == NULL) {
|
|
IOT_ASSERT(0);
|
|
return;
|
|
}
|
|
|
|
msg->type = MAC_MSG_TYPE_TIMER;
|
|
msg->id = MAC_MSG_ID_CHANNEL_SCAN_TIMER;
|
|
msg->data1 = 0;
|
|
msg->data2 = pdev;
|
|
mac_queue_msg(msg, MAC_MSG_QUEUE_HP);
|
|
return;
|
|
}
|
|
|
|
void iot_mac_k48sta_switch_next_channel(void *pdev)
|
|
{
|
|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
|
|
mac_pdev_t *pdev_ptr = (mac_pdev_t*)pdev;
|
|
|
|
if (pdev_ptr->channel_scan.k48_cur_channel == MAC_CHANNEL_MAX_NUM) {
|
|
pdev_ptr->channel_scan.k48_cur_channel = MAC_CHANNEL_L_N;
|
|
} else {
|
|
pdev_ptr->channel_scan.k48_cur_channel = \
|
|
(pdev_ptr->channel_scan.k48_cur_channel == MAC_CHANNEL_N_PE) ? \
|
|
MAC_CHANNEL_L_PE: (pdev_ptr->channel_scan.k48_cur_channel + 1);
|
|
}
|
|
|
|
iot_printf("mac channel scan next %d\n", pdev_ptr->channel_scan.k48_cur_channel);
|
|
iot_mac_k48sta_setchannel_gpio((uint8_t)pdev_ptr->channel_scan.k48_cur_channel);
|
|
|
|
#else
|
|
(void)pdev;
|
|
#endif
|
|
}
|
|
|
|
void iot_mac_k48sta_scan_channel_init(void *pdev)
|
|
{
|
|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
|
|
mac_pdev_t *pdev_ptr = (mac_pdev_t*)pdev;
|
|
|
|
for (uint8_t i = 0; i < MAC_CHANNEL_MAX_NUM; i++) {
|
|
pdev_ptr->channel_scan.k48_channel_snr[i] = INV_SNR;
|
|
}
|
|
pdev_ptr->channel_scan.k48_cur_channel = MAC_CHANNEL_L_N;
|
|
iot_mac_k48sta_setchannel_gpio(MAC_CHANNEL_L_N);
|
|
pdev_ptr->channel_scan.k48_channel_rx_count = 0;
|
|
pdev_ptr->channel_scan.k48_channel_is_sel = 0;
|
|
pdev_ptr->channel_scan.dwell_time_s = 180; //180s
|
|
|
|
#if K48_STA_MULTI_CHANNEL_SELECT_ENABLE
|
|
if (pdev_ptr->channel_scan.scan_timer == 0) {
|
|
pdev_ptr->channel_scan.scan_timer =
|
|
os_create_timer(PLC_MAC_CHANNEL_SCAN_MID, true,
|
|
mac_channel_scan_timer_handler, pdev);
|
|
}
|
|
#else
|
|
pdev_ptr->channel_scan.scan_timer = 0;
|
|
#endif
|
|
#else
|
|
(void)pdev;
|
|
#endif
|
|
}
|
|
|
|
uint32_t iot_mac_k48sta_scan_channel_start(void *pdev)
|
|
{
|
|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
|
|
mac_pdev_t *pdev_ptr = (mac_pdev_t*)pdev;
|
|
|
|
if (pdev_ptr == NULL) {
|
|
IOT_ASSERT(0);
|
|
return ERR_INVAL;
|
|
}
|
|
|
|
pdev_ptr->channel_scan.k48_cur_channel = MAC_CHANNEL_L_N;
|
|
iot_mac_k48sta_setchannel_gpio(MAC_CHANNEL_L_N);
|
|
|
|
//iot_mac_k48sta_scan_channel_init(pdev_ptr);
|
|
if (pdev_ptr->channel_scan.scan_timer) {
|
|
os_start_timer(pdev_ptr->channel_scan.scan_timer, \
|
|
pdev_ptr->channel_scan.dwell_time_s * 1000);
|
|
} else {
|
|
return ERR_INVAL;
|
|
}
|
|
return ERR_OK;
|
|
#else
|
|
(void)pdev;
|
|
return ERR_OK;
|
|
#endif
|
|
}
|
|
|
|
uint32_t iot_mac_k48sta_scan_channel_stop(void *pdev)
|
|
{
|
|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
|
|
mac_pdev_t *pdev_ptr = (mac_pdev_t*)pdev;
|
|
|
|
if (pdev_ptr == NULL) {
|
|
IOT_ASSERT(0);
|
|
return ERR_INVAL;
|
|
}
|
|
|
|
if (pdev_ptr->channel_scan.scan_timer) {
|
|
os_stop_timer(pdev_ptr->channel_scan.scan_timer);
|
|
iot_printf("channel is selected %d, stop scan\n", \
|
|
pdev_ptr->channel_scan.k48_cur_channel);
|
|
} else {
|
|
return ERR_INVAL;
|
|
}
|
|
|
|
return ERR_OK;
|
|
#else
|
|
(void)pdev;
|
|
return ERR_OK;
|
|
#endif
|
|
}
|
|
|
|
|
|
#if 0
|
|
uint32_t iot_mac_k48sta_channel_snr_cal(void *pdev, int8_t snr, int8_t ppm)
|
|
{
|
|
#if HW_PLATFORM >= HW_PLATFORM_FPGA
|
|
mac_pdev_t *pdev_ptr = (mac_pdev_t*)pdev;
|
|
uint8_t cur_channel;
|
|
|
|
if (pdev_ptr == NULL) {
|
|
IOT_ASSERT(0);
|
|
return ERR_INVAL;
|
|
}
|
|
|
|
/* if channel is selected, return */
|
|
if (pdev_ptr->channel_scan.k48_channel_is_sel) {
|
|
return ERR_OK;
|
|
}
|
|
|
|
/* if cur rx ppm is not sync or channel scan is not start, ignore it */
|
|
if ((ppm < -5 || ppm > 5) || \
|
|
(pdev_ptr->channel_scan.k48_cur_channel == MAC_CHANNEL_MAX_NUM)) {
|
|
return ERR_INVAL;
|
|
}
|
|
|
|
/* if cur channel rx snr is very well, select cur channel and stop scan */
|
|
if (snr >= MIN_SNR_STOP_SCAN) {
|
|
iot_mac_k48sta_scan_channel_stop(pdev_ptr);
|
|
iot_mac_k48sta_setchannel_gpio((uint8_t)pdev_ptr->channel_scan.k48_cur_channel);
|
|
pdev_ptr->channel_scan.k48_channel_is_sel = 1;
|
|
iot_printf("cur bcn snr is %d, stop scan and mac channel is selected %d\n", \
|
|
snr, pdev_ptr->channel_scan.k48_cur_channel);
|
|
return ERR_OK;
|
|
}
|
|
|
|
/* cal cur channel rx snr avg */
|
|
cur_channel = pdev_ptr->channel_scan.k48_cur_channel;
|
|
switch(cur_channel)
|
|
{
|
|
case MAC_CHANNEL_L_PE:
|
|
case MAC_CHANNEL_L_N:
|
|
case MAC_CHANNEL_N_PE:
|
|
{
|
|
if (pdev_ptr->channel_scan.k48_channel_snr[cur_channel] != INV_SNR) {
|
|
pdev_ptr->channel_scan.k48_channel_snr[cur_channel] = \
|
|
CHANNL_CAL_AVG_SNR(pdev_ptr->channel_scan.k48_channel_snr[cur_channel], snr);
|
|
} else {
|
|
pdev_ptr->channel_scan.k48_channel_snr[cur_channel] = snr;
|
|
}
|
|
iot_printf("snr = %d,channel %d avg snr = %d\n", snr, cur_channel, \
|
|
pdev_ptr->channel_scan.k48_channel_snr[cur_channel]);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
iot_printf("cur channel %d is invalid\n",cur_channel);
|
|
IOT_ASSERT(0);
|
|
}
|
|
}
|
|
pdev_ptr->channel_scan.k48_channel_rx_count++;
|
|
|
|
/* stop channel scan */
|
|
if (pdev_ptr->channel_scan.k48_channel_rx_count >= MAX_BCN_RX_CNT) {
|
|
iot_mac_k48sta_scan_channel_stop(pdev_ptr);
|
|
|
|
/* find the max avg snr and select the channel */
|
|
pdev_ptr->channel_scan.k48_cur_channel= \
|
|
GET_BEST_CHANNEL(pdev_ptr->channel_scan.k48_channel_snr[MAC_CHANNEL_L_PE], \
|
|
pdev_ptr->channel_scan.k48_channel_snr[MAC_CHANNEL_L_N], \
|
|
pdev_ptr->channel_scan.k48_channel_snr[MAC_CHANNEL_N_PE]);
|
|
|
|
iot_mac_k48sta_setchannel_gpio((uint8_t)pdev_ptr->channel_scan.k48_cur_channel);
|
|
pdev_ptr->channel_scan.k48_channel_is_sel = 1;
|
|
iot_printf("mac channel is selected %d\n", pdev_ptr->channel_scan.k48_cur_channel);
|
|
}
|
|
|
|
return ERR_OK;
|
|
#else
|
|
(void)pdev;
|
|
(void)snr;
|
|
return ERR_OK;
|
|
#endif
|
|
}
|
|
#endif
|