/********************************** (C) COPYRIGHT *******************************
 * File Name          : lwns_adapter_no_mac.c
 * Author             : WCH
 * Version            : V1.1
 * Date               : 2025/04/25
 * Description        : lwns适配器，不使用mac协议，纯透传
 *********************************************************************************
 * Copyright (c) 2025 Nanjing Qinheng Microelectronics Co., Ltd.
 * Attention: This software (modified or not) and binary are used for
 * microcontroller manufactured by Nanjing Qinheng Microelectronics.
 *******************************************************************************/
#include "lwns_adapter_no_mac.h"
#include "lwns_sec.h"

/* 每个文件单独debug打印的开关，置0可以禁止本文件内部打印 */
#define DEBUG_PRINT_IN_THIS_FILE    1
#if DEBUG_PRINT_IN_THIS_FILE
#define PRINTF(...)       PRINT(__VA_ARGS__)
#else
#define PRINTF(...)       do{} while(0)
#endif

#if LWNS_USE_NO_MAC /* 是否使能纯透传mac协议，即mac层不参与任何动作，注意只能使能一个mac层协议。

/* for lwns_packet_buffer save */
__attribute__((aligned(4))) static lwns_qbuf_list_t qbuf_memp[QBUF_MANUAL_NUM];

/* for lwns_route_entry manage */
#if ROUTE_ENTRY_MANUAL_NUM
__attribute__((aligned(4))) static lwns_route_entry_data_t route_entry_memp[ROUTE_ENTRY_MANUAL_NUM];
#endif

/* for neighbor manage */
__attribute__((aligned(4))) static lwns_neighbor_list_t neighbor_memp[LWNS_NEIGHBOR_MAX_NUM];

static void ble_new_neighbor_callback(lwns_addr_t *n);      /* 发现新邻居回调函数 */
static BOOL ble_phy_output(uint8_t *dataptr, uint8_t len);  /* 发送接口函数 */
static void RF_2G4StatusCallBack(uint8_t sta, uint8_t crc, uint8_t *rxBuf);

static uint8_t  lwns_adapter_taskid;
static uint16_t lwns_adapter_ProcessEvent(uint8_t task_id, uint16_t events);
static uint8_t  lwns_phyoutput_taskid;
static uint16_t lwns_phyoutput_ProcessEvent(uint8_t task_id, uint16_t events);

/**
 * lwns必用的函数接口，将指针传递给lwns库内部使用
 */
static lwns_fuc_interface_t ble_lwns_fuc_interface =
{
    .lwns_phy_output = ble_phy_output,
    .lwns_rand = tmos_rand,
    .lwns_memcpy = tmos_memcpy,
    .lwns_memcmp = tmos_memcmp,
    .lwns_memset = tmos_memset,
    .new_neighbor_callback = ble_new_neighbor_callback,
};

static uint8_t ble_phy_manage_state;    /* phy状态管理 */

volatile uint8_t tx_end_flag = 0;

/*********************************************************************
 * @fn      RF_Wait_Tx_End
 *
 * @brief   手动模式等待发送完成，自动模式等待发送-接收完成，必须在RAM中等待，等待时可以执行用户代码，但需要注意执行的代码必须运行在RAM中，否则影响发送
 *
 * @return  none
 */
__HIGH_CODE
__attribute__((noinline))
void RF_Wait_Tx_End()
{
    uint32_t i = 0;
    while (!tx_end_flag)
    {
        i++;
        __nop();
        __nop();
        /* 约5ms超时 */
        if (i > (FREQ_SYS / 1000))
        {
            tx_end_flag = TRUE;
        }
    }
}

/*********************************************************************
 * @fn      RF_2G4StatusCallBack
 *
 * @brief   RF 状态回调，注意：不可在此函数中直接调用RF接收或者发送API，需要使用事件的方式调用
 *
 * @param   sta     -   状态类型
 * @param   crc     -   crc校验结果
 * @param   rxBuf   -   数据buf指针
 *
 * @return  None.
 */
static void RF_2G4StatusCallBack(uint8_t sta, uint8_t crc, uint8_t *rxBuf)
{
    switch (sta)
    {
    case RX_MODE_RX_DATA:
    {
        if (crc == 0)
        {
            uint8_t *pMsg;
#if LWNS_ENCRYPT_ENABLE /* 是否启用消息加密 */
            if (((rxBuf[1] % 16) == 1) && (rxBuf[1] >= 17) && (rxBuf[1] > rxBuf[2]))
            {
                /* 对齐后数据区最少16个字节，加上真实数据长度一字节 */
                /* 长度校验通过，所以rxBuf[1] - 1必为16的倍数 */
                pMsg = tmos_msg_allocate(rxBuf[1]); /* 申请内存空间，真实数据长度不需要解密 */
                if (pMsg != NULL)
                {
                    lwns_msg_decrypt(rxBuf + 3, pMsg + 1, rxBuf[1] - 1); /* 解密数据 */
                    if ((rxBuf[2] ^ pMsg[rxBuf[2]]) == pMsg[rxBuf[2] + 1])
                    {
                        pMsg[0] = rxBuf[2];      /* 校验通过，存储真实数据长度 */
                        PRINTF("send rx msg\n"); /* 发送接收到的数据到接收进程中 */
                        tmos_msg_send(lwns_adapter_taskid, pMsg);
                    }
                    else
                    {
                        PRINTF("verify rx msg err\n"); /* 校验失败 */
                        tmos_msg_deallocate(pMsg);
                    }
                }
                else
                {
                    PRINTF("send rx msg failed\n"); /* 申请内存失败，无法发送接收到的数据 */
                }
            }
            else
            {
                PRINTF("bad len\n");    /* 包长度不对 */
            }
#else
            if (rxBuf[1] >= LWNS_PHY_OUTPUT_MIN_SIZE)   /* 数据长度符合，才会发送至协议栈内部处理 */
            {
                pMsg = tmos_msg_allocate(rxBuf[1] + 1);
                if (pMsg != NULL)
                {
                    PRINTF("send rx msg\n");    /* 发送接收到的数据到接收进程中 */
                    tmos_memcpy(pMsg, rxBuf + 1, rxBuf[1] + 1);
                    tmos_msg_send(lwns_adapter_taskid, pMsg);
                }
                else
                {
                    PRINTF("rx msg failed\n");  /* 申请内存失败，无法发送接收到的数据 */
                }
            }
            else
            {
                PRINTF("bad len\n");    /* 包长度不对 */
            }
#endif
        }
        else
        {
            if (crc & (1 << 0))
            {
                PRINTF("crc error\n");
            }

            if (crc & (1 << 1))
            {
                PRINTF("match type error\n");
            }
        }
        tmos_set_event(lwns_adapter_taskid, LWNS_PHY_RX_OPEN_EVT);  /* 重新打开接收 */
        break;
    }
    case TX_MODE_TX_FINISH:
    case TX_MODE_TX_FAIL:
        tmos_stop_task(lwns_phyoutput_taskid, LWNS_PHY_OUTPUT_FINISH_EVT); /* 停止超时计数 */
        tmos_set_event(lwns_phyoutput_taskid, LWNS_PHY_OUTPUT_FINISH_EVT); /* 进入发送完成处理 */
        break;
    default:
        break;
    }
}

/*********************************************************************
 * @fn      RF_Init
 *
 * @brief   RF 初始化.
 *
 * @param   None.
 *
 * @return  None.
 */
void RF_Init(void)
{
    uint8_t    state;
    rfConfig_t rfConfig;
    tmos_memset(&rfConfig, 0, sizeof(rfConfig_t));
    rfConfig.accessAddress = 0x17267162; /*  禁止使用0x55555555以及0xAAAAAAAA ( 建议不超过24次位反转，且不超过连续的6个0或1 )，正确符合相应规则的accessaddress接入地址约有23亿个 */
    rfConfig.CRCInit = 0x555555;
    rfConfig.Channel = 8;
    rfConfig.LLEMode = LLE_MODE_BASIC; /* |LLE_MODE_EX_CHANNEL; 使能 LLE_MODE_EX_CHANNEL 表示 选择 rfConfig.Frequency 作为通信频点 */
    rfConfig.rfStatusCB = RF_2G4StatusCallBack;
    state = RF_Config(&rfConfig);
    PRINTF("rf 2.4g init: %x\n", state);
}

/*********************************************************************
 * @fn      lwns_init
 *
 * @brief   lwns初始化.
 *
 * @param   None.
 *
 * @return  None.
 */
void lwns_init(void)
{
    uint8_t       s;
    lwns_config_t cfg;
    tmos_memset(&cfg, 0, sizeof(lwns_config_t));
    cfg.lwns_lib_name = (uint8_t *)VER_LWNS_FILE; /* 验证函数库名称，防止版本出错 */
    cfg.qbuf_num = QBUF_MANUAL_NUM;               /* 必须分配，至少1个内存单位，根据你程序中使用的端口数对应模块使用的qbuf单位来定义。 */
    cfg.qbuf_ptr = qbuf_memp;                     /* mesh最多使用3个qbuf单位，(uni/multi)netflood最多使用2个，其他模块都使用1个。 */
    cfg.routetable_num = ROUTE_ENTRY_MANUAL_NUM;  /* 如果需要使用mesh，必须分配路由表内存空间。不然mesh初始化不会成功。 */
#if ROUTE_ENTRY_MANUAL_NUM
    cfg.routetable_ptr = route_entry_memp;
#else
    cfg.routetable_ptr = NULL;
#endif
    cfg.neighbor_num = LWNS_NEIGHBOR_MAX_NUM;                      /* 邻居表数量，必须分配 */
    cfg.neighbor_list_ptr = neighbor_memp;                         /* 邻居表内存空间 */
    cfg.neighbor_mod = LWNS_NEIGHBOR_AUTO_ADD_STATE_RECALL_NOTADD; /* 邻居表初始化默认管理模式为接收所有包，不添加邻居的模式 */
#if LWNS_ADDR_USE_BLE_MAC
    GetMACAddress(cfg.addr.v8); /* 蓝牙硬件的mac地址 */
#else
    /* 自行定义的地址 */
    uint8_t MacAddr[6] = {0, 0, 0, 0, 0, 1};
    tmos_memcpy(cfg.addr.v8, MacAddr, LWNS_ADDR_SIZE);
#endif
    s = lwns_lib_init(&ble_lwns_fuc_interface, &cfg); /* lwns库底层初始化 */
    if (s)
    {
        PRINTF("%s init err:%d\n", VER_LWNS_FILE, s);
    }
    else
    {
        PRINTF("%s init ok\n", VER_LWNS_FILE);
    }
    lwns_adapter_taskid = TMOS_ProcessEventRegister(lwns_adapter_ProcessEvent);
    lwns_phyoutput_taskid = TMOS_ProcessEventRegister(lwns_phyoutput_ProcessEvent);
    tmos_start_reload_task(lwns_phyoutput_taskid, LWNS_HTIMER_PERIOD_EVT, MS1_TO_SYSTEM_TIME(LWNS_HTIMER_PERIOD_MS));
    ble_phy_manage_state = BLE_PHY_MANAGE_STATE_FREE;
    RF_Shut();
    RF_Rx(NULL, 0, USER_RF_RX_TX_TYPE, USER_RF_RX_TX_TYPE); /* 打开RF接收，如果需要低功耗管理，在其他地方打开。 */
}

/*********************************************************************
 * @fn      ble_new_neighbor_callback
 *
 * @brief   当发现一个新邻居时的回调函数.
 *
 * @param   n  - 新邻居的地址.
 *
 * @return  None.
 */
static void ble_new_neighbor_callback(lwns_addr_t *n)
{
    PRINTF("new neighbor: %02x %02x %02x %02x %02x %02x\n", n->v8[0], n->v8[1],
           n->v8[2], n->v8[3], n->v8[4], n->v8[5]);
}

/*********************************************************************
 * @fn      ble_phy_output
 *
 * @brief   lwns发送函数接口
 *
 * @param   dataptr     - 待发送的数据缓冲头指针.
 * @param   len         - 待发送的数据缓冲长度.
 *
 * @return  TRUE if success, FLASE is failed.
 */
static BOOL ble_phy_output(uint8_t *dataptr, uint8_t len)
{
    uint8_t *pMsg;
#if LWNS_ENCRYPT_ENABLE
    pMsg = tmos_msg_allocate((((len + 1 + 15) & 0xf0) + 1 + 1)); /* 校验位1位加上后再进行16字节对齐，存储发送长度+1，真实数据长度+1 */
#else
    pMsg = tmos_msg_allocate(len + 1); /* 申请内存空间存储消息，存储发送长度+1 */
#endif
    if (pMsg != NULL)    /* 成功申请 */
    {
#if LWNS_ENCRYPT_ENABLE
        /* lwns buffer内部预留有两字节，用户可直接使用dataptr[len]进行赋值两字节内容 */
        dataptr[len] = dataptr[len - 1] ^ len;                      /* 校验字节仅取最后一个字节和长度进行异或运算，首字节相同port是一样的，可能有影响。和校验比较浪费时间，所以不采用 */
        pMsg[1] = len;                                              /* 真实数据长度占一字节，不加密，用来接收做第一步校验 */
        pMsg[0] = lwns_msg_encrypt(dataptr, pMsg + 2, len + 1) + 1; /* 获取数据加密后的长度，也就是需要发送出去的字节数，真实数据长度不加密 */
#else
        pMsg[0] = len;
        tmos_memcpy(pMsg + 1, dataptr, len);
#endif
        tmos_msg_send(lwns_phyoutput_taskid, pMsg);
        return TRUE;
    }
    else
    {
        PRINTF("send failed!\n"); /* 无法申请到内存，则无法发送 */
    }
    return FALSE;
}

/*********************************************************************
 * @fn      lwns_adapter_ProcessEvent
 *
 * @brief   lwns adapter Task event processor.  This function
 *          is called to process all events for the task.  Events
 *          include timers, messages and any other user defined events.
 *
 * @param   task_id - The TMOS assigned task ID.
 * @param   events - events to process.  This is a bit map and can
 *                   contain more than one event.
 *
 * @return  events not processed.
 */
static uint16_t lwns_adapter_ProcessEvent(uint8_t task_id, uint16_t events)
{
    if (events & LWNS_PHY_RX_OPEN_EVT)  /* 重新打开接收 */
    {
        RF_Shut();
        RF_Rx(NULL, 0, USER_RF_RX_TX_TYPE, USER_RF_RX_TX_TYPE); /* 重新打开接收 */
        return (events ^ LWNS_PHY_RX_OPEN_EVT);
    }
    if (events & SYS_EVENT_MSG)
    {
        uint8_t *pMsg;
        if ((pMsg = tmos_msg_receive(task_id)) != NULL)
        {
            /*  Release the TMOS message,tmos_msg_allocate */
            lwns_input(pMsg + 1, pMsg[0]); /* 将数据存入协议栈缓冲区 */
            tmos_msg_deallocate(pMsg);     /* 先释放内存，在数据处理前释放，防止数据处理中需要发送数据，而内存不够。 */
            lwns_dataHandler();            /* 调用协议栈处理数据函数 */
        }
        /*  return unprocessed events */
        return (events ^ SYS_EVENT_MSG);
    }
    /*  Discard unknown events */
    return 0;
}

/*********************************************************************
 * @fn      lwns_phyoutput_ProcessEvent
 *
 * @brief   lwns phyoutput Task event processor.  This function
 *          is called to process all events for the task.  Events
 *          include timers, messages and any other user defined events.
 *
 * @param   task_id - The TMOS assigned task ID.
 * @param   events - events to process.  This is a bit map and can
 *                   contain more than one event.
 *
 * @return  events not processed.
 */
static uint16_t lwns_phyoutput_ProcessEvent(uint8_t task_id, uint16_t events)
{
    if (events & LWNS_HTIMER_PERIOD_EVT)
    {
        lwns_htimer_update();                   /* htimer更新 */
        return (events ^ LWNS_HTIMER_PERIOD_EVT);
    }
    if (events & LWNS_PHY_OUTPUT_FINISH_EVT)    /* 发送完成任务 */
    {
        RF_Shut();
        RF_Rx(NULL, 0, USER_RF_RX_TX_TYPE, USER_RF_RX_TX_TYPE); /* 重新打开接收 */
        ble_phy_manage_state = BLE_PHY_MANAGE_STATE_FREE;       /* 发送完成，释放phy */
        return (events ^ LWNS_PHY_OUTPUT_FINISH_EVT);
    }
    if (events & SYS_EVENT_MSG)
    {
        uint8_t *pMsg;
        if (ble_phy_manage_state == BLE_PHY_MANAGE_STATE_SENDING)
        {
            PRINTF("phy busy\n");
            return 0; /* 发送过程中，不再发送新的数据包，直接返回 */
        }
        if ((pMsg = tmos_msg_receive(lwns_phyoutput_taskid)) != NULL)
        {
            /*  Release the TMOS message,tmos_msg_allocate */
            tmos_clear_event(lwns_adapter_taskid, LWNS_PHY_RX_OPEN_EVT); /* 停止可能已经置位的、可能会打开接收的任务 */
            tmos_start_task(lwns_phyoutput_taskid, LWNS_PHY_OUTPUT_FINISH_EVT, MS1_TO_SYSTEM_TIME(LWNS_PHY_OUTPUT_TIMEOUT_MS)); /* 开始发送超时计数，防止有意外打断发送，导致无法继续发送 */
            RF_Shut();
            tx_end_flag = 0;
            if (!RF_Tx((uint8_t *)(pMsg + 1), pMsg[0], USER_RF_RX_TX_TYPE, USER_RF_RX_TX_TYPE))
            {
                RF_Wait_Tx_End();
            }
            tmos_msg_deallocate(pMsg);  /* 释放内存 */
        }
        /*  return unprocessed events */
        return (events ^ SYS_EVENT_MSG);
    }
    return 0;
}

/*********************************************************************
 * @fn      lwns_shut
 *
 * @brief   停止lwns，不可以在这lwns_phyoutput_taskid和lwns_adapter_taskid的processEvent中调用。
 *
 * @param   None.
 *
 * @return  None.
 */
void lwns_shut()
{
    uint8_t *pMsg;
    RF_Shut();  /* 关闭RF接收 */
    /* 超时重发全部清除 */
    lwns_htimer_flush_all();
    tmos_stop_task(lwns_phyoutput_taskid, LWNS_HTIMER_PERIOD_EVT);
    tmos_clear_event(lwns_phyoutput_taskid, LWNS_HTIMER_PERIOD_EVT);

    tmos_stop_task(lwns_phyoutput_taskid, LWNS_PHY_OUTPUT_FINISH_EVT); /* 停止Htimer心跳时钟和发送列表检测 */
    tmos_clear_event(lwns_phyoutput_taskid, LWNS_PHY_OUTPUT_FINISH_EVT);

    while ((pMsg = tmos_msg_receive(lwns_phyoutput_taskid)) != NULL)
    {
        /* 清除所有缓存的消息 */
        tmos_msg_deallocate(pMsg);
    }
    tmos_clear_event(lwns_phyoutput_taskid, SYS_EVENT_MSG);

    while ((pMsg = tmos_msg_receive(lwns_adapter_taskid)) != NULL)
    {
        /* 清除所有缓存的消息 */
        tmos_msg_deallocate(pMsg);
    }
    tmos_stop_task(lwns_adapter_taskid, LWNS_PHY_RX_OPEN_EVT);
    tmos_clear_event(lwns_adapter_taskid, LWNS_PHY_RX_OPEN_EVT);
    tmos_clear_event(lwns_adapter_taskid, SYS_EVENT_MSG);
}

/*********************************************************************
 * @fn      lwns_start
 *
 * @brief   lwns开始运行，在使用lwns_shut后，重新开始时使用。
 *
 * @param   None.
 *
 * @return  None.
 */
void lwns_start()
{
    RF_Shut();
    RF_Rx(NULL, 0, USER_RF_RX_TX_TYPE, USER_RF_RX_TX_TYPE); /* 打开RF接收，如果需要低功耗管理，在其他地方打开。 */
    tmos_start_reload_task(lwns_phyoutput_taskid, LWNS_HTIMER_PERIOD_EVT, MS1_TO_SYSTEM_TIME(LWNS_HTIMER_PERIOD_MS));
}

#endif /* LWNS_USE_NO_MAC */
