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

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