// +FHDR------------------------------------------------------------
//                 Copyright (c) 2022 SmartLogic.
//                       ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename      : case20_ape0_task.s.c
// Author        : 
// Created On    : 2023-01-05
// Last Modified :
// -----------------------------------------------------------------
// Description:
//
//
// -FHDR------------------------------------------------------------
#include "ucp_utility.h"
#include "ucp_tick.h"
#include "ucp_printf.h"
#include "phy_para.h"
#include "osp_msg.h"
#include "ucp_testcase.h"
#include "msg_transfer_layer.h"
#include "ucp_port.h"
#include "ape_mtimer.h"
#include "osp_heap.h"
#include "osp_task.h"
#include "osp_timer.h"

/***************************************************************/
/*                   事件任务相关打点                                  */
static uint32_t g_u32_case21_ape4_event1_rev_num      = 0; // 30 0xB7E00878
static uint32_t g_u32_case21_ape4_event1_rev_ok       = 0; // 31 0xB7E0087C
static uint32_t g_u32_case21_ape4_event1_addr_err     = 0; // 32 0xB7E00880
static uint32_t g_u32_case21_ape4_event1_tick         = 0;
static uint32_t g_u32_case21_ape4_event1_tick_err     = 0; // 33 0xB7E00884
static uint32_t g_u32_case21_ape4_event1_sfn_slot_err = 0; // 35 0xB7E0088C
static uint32_t g_u32_case21_ape4_event1_alloc1_err   = 0; // 40 0xB7E008A0
static uint32_t g_u32_case21_ape4_event1_send1_err    = 0; // 41 0xB7E008A4
static uint32_t g_u32_case21_ape4_event1_alloc2_err   = 0; // 42 0xB7E008A8
static uint32_t g_u32_case21_ape4_event1_send2_err    = 0; // 43 0xB7E008AC
static uint32_t g_u32_case21_ape4_event1_send_ok      = 0; // 44 0xB7E008B0

static uint32_t g_u32_case21_ape4_event2_num          = 0; // 45 0xB7E008B4
static uint32_t g_u32_case21_ape4_event3_num          = 0; // 46 0xB7E008B8

/* 收到ARM侧发来的消息（通过RFM转发） */
void ape4_event1_task(uint32_t addr, uint32_t size)
{
    uint32_t ape_id   = get_core_id();
    uint32_t msg_addr = 0;
    uint32_t que_num  = 0;
    uint32_t value    = 0;
    uint16_t scs      = NR_SCS_30K;//30KHz
    uint16_t sfn      = 0;
    uint16_t slot     = 0;
    uint16_t sfn_l    = 0;
    uint16_t slot_l   = 0;
    uint32_t u32_clock_offset = 0;
    uint32_t u32_clock_tick   = 0;
    char     *paddr   = NULL;
    int       ret     = 0;

    g_u32_case21_ape4_event1_rev_num++;
    if (0 == addr)
    {
        g_u32_case21_ape4_event1_addr_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 32), g_u32_case21_ape4_event1_addr_err);
        return ;
    }

    msg_addr = do_read(addr);
    que_num  = do_read(addr+4);

    value = *(uint32_t*)msg_addr;
    sfn  = value >> 16;
    slot = value & 0xffff;
    //msg_transfer_free_msg(TEST_QUE_PORT_ID, que_num, 0, (char*)msg_addr);
    g_u32_case21_ape4_event1_rev_ok++;

    debug_write(DBG_DDR_COMMON_IDX(ape_id, 30), g_u32_case21_ape4_event1_rev_num);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 31), g_u32_case21_ape4_event1_rev_ok);

    rdmcycle(&u32_clock_tick);

    if (0 == g_u32_case21_ape4_event1_tick)
    {
        g_u32_case21_ape4_event1_tick = u32_clock_tick;
    }
    else
    {
        if (u32_clock_tick > g_u32_case21_ape4_event1_tick)
        {
            u32_clock_offset = u32_clock_tick - g_u32_case21_ape4_event1_tick;
            if ((u32_clock_offset > TIMER_OFFSET_MAX) || (u32_clock_offset < TIMER_OFFSET_MIN))
            {
                g_u32_case21_ape4_event1_tick_err++;
                debug_write(DBG_DDR_COMMON_IDX(ape_id, 33), g_u32_case21_ape4_event1_tick_err);
                debug_write(DBG_DDR_COMMON_IDX(ape_id, 34), u32_clock_offset);
            }
        }
        g_u32_case21_ape4_event1_tick = u32_clock_tick;
    }

    sfn_l  = get_tx_nr_sfn(scs);
    slot_l = get_tx_nr_slot(scs);
    if ((sfn != sfn_l) || (slot != slot_l))
    {
        g_u32_case21_ape4_event1_sfn_slot_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 35), g_u32_case21_ape4_event1_sfn_slot_err);
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 36), sfn);
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 37), sfn_l);
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 38), slot);
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 39), slot_l);
    }

    /* 给本核event3发消息 */
    paddr = osp_alloc_msg(TEST_MSG_SIZE);
    if (NULL == paddr)
    {
        g_u32_case21_ape4_event1_alloc1_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 40), g_u32_case21_ape4_event1_alloc1_err);
        return ;
    }

    do_write(paddr, g_u32_case21_ape4_event1_rev_num);
    do_write((paddr+4), 0xA001B002);

    ret = osp_send_msg((uint32_t)(paddr),
                        TEST_MSG_SIZE,
                        UCP4008_KERNEL_INNER,
                        ape_id,   // src que id
                        ape_id,   // dst que id
                        40,       // src task id
                        42);      // dst task id

    if (0 != ret)
    {
        g_u32_case21_ape4_event1_send1_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 41), g_u32_case21_ape4_event1_send1_err);
        //return ;
    }

    /* 给其核event2发消息 */
    paddr = osp_alloc_msg(TEST_MSG_SIZE);
    if (NULL == paddr)
    {
        g_u32_case21_ape4_event1_alloc2_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 42), g_u32_case21_ape4_event1_alloc2_err);
        return ;
    }

    do_write(paddr, g_u32_case21_ape4_event1_rev_num);
    do_write((paddr+4), 0xA001B002);

    ret = osp_send_msg((uint32_t)(paddr),
                        TEST_MSG_SIZE,
                        UCP4008_KERNEL_INTER,
                        ape_id,   // src que id
                        ape_id+1, // dst que id
                        40,       // src task id
                        41);      // dst task id

    if (0 != ret)
    {
        g_u32_case21_ape4_event1_send2_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 43), g_u32_case21_ape4_event1_send2_err);
        return ;
    }

    /* 给ape6 event1发消息 */
    paddr = osp_alloc_msg(TEST_MSG_SIZE);
    if (NULL == paddr)
    {
        //g_u32_case21_ape4_event1_alloc2_err++;
        //debug_write(DBG_DDR_COMMON_IDX(ape_id, 42), g_u32_case21_ape4_event1_alloc2_err);
        return ;
    }

    do_write(paddr, g_u32_case21_ape4_event1_rev_num);
    do_write((paddr+4), 0xA001B002);

    ret = osp_send_msg((uint32_t)(paddr),
                        TEST_MSG_SIZE,
                        UCP4008_KERNEL_INTER,
                        ape_id,   // src que id
                        6,        // ape6
                        40,       // src task id
                        40);      // dst task id

    if (0 != ret)
    {
        //g_u32_case21_ape4_event1_send2_err++;
        //debug_write(DBG_DDR_COMMON_IDX(ape_id, 43), g_u32_case21_ape4_event1_send2_err);
        return ;
    }

    debug_write(DBG_DDR_COMMON_IDX(ape_id, 44), ++g_u32_case21_ape4_event1_send_ok);

    return ;
}

/* 收到他核event1发来的消息 */
void ape4_event2_task(uint32_t addr, uint32_t size)
{
    uint32_t ape_id = get_core_id();
    g_u32_case21_ape4_event2_num++;

    debug_write(DBG_DDR_COMMON_IDX(ape_id, 45), g_u32_case21_ape4_event2_num);
    return ;
}

/* 收到本核event1发来的消息 */
void ape4_event3_task(uint32_t addr, uint32_t size)
{
    uint32_t ape_id = get_core_id();
    g_u32_case21_ape4_event3_num++;

    debug_write(DBG_DDR_COMMON_IDX(ape_id, 46), g_u32_case21_ape4_event3_num);
    return ;
}

/***************************************************************/
/*                  定时时任务相关打点                                  */
static uint32_t g_u32_case21_ape4_timer1_slot_no_continuous = 0; // 50 0xB7E008C8
static uint32_t g_u32_case21_ape4_timer1_sfn_no_continuous  = 0; // 51 0xB7E008CC
static uint32_t g_u32_case21_ape4_timer1_slot_indication    = 0; // 52 0xB7E008D0
static uint32_t g_u32_case21_ape4_timer1_update_sfn_slot    = 0; // 53 0xB7E008D4
static uint32_t g_u32_case21_ape4_timer1_process_cnt        = 0; // 54 0xB7E008D8
static uint32_t g_u32_case21_ape4_timer1_process_tick       = 0; // 55 0xB7E008DC
static uint32_t g_u32_case21_ape4_timer1_process_tick_err   = 0; // 56 0xB7E008E0
static uint32_t g_u32_case21_ape4_timer2_process_cnt        = 0; // 57 0xB7E008E4
static uint32_t g_u32_case21_ape4_timer2_process_tick       = 0; // 58 0xB7E008E8
static uint32_t g_u32_case21_ape4_timer2_process_tick_err   = 0; // 59 0xB7E008EC
static uint32_t g_u32_case21_ape4_timer2_tx_slot_max        = 0; // 64 0xB7E00900
static uint32_t g_u32_case21_ape4_timer2_tx_slot_min        = 0x32000;//65 0xB7E00904
static uint32_t g_u32_case21_ape4_timer2_tx_slot_cur        = 0; // 66 0xB7E00908
static uint32_t g_u32_case21_ape4_timer2_rx_slot_max        = 0; // 67 0xB7E0090C
static uint32_t g_u32_case21_ape4_timer2_rx_slot_min        = 0x32000; // 68 0xB7E00910
static uint32_t g_u32_case21_ape4_timer2_rx_slot_cur        = 0; // 69 0xB7E00914

static uint16_t gPreviousSlot = 0;
static uint16_t gCurrentSlot  = 0;
static uint8_t  gSlotFlagInit = 1;
static uint8_t  gSfnFlagInit  = 1;
static uint16_t gPreviousSfn  = 0;
static uint16_t gCurrentSfn   = 0;

static inline void check_continuous_slot(uint16_t slot)
{
    uint16_t delta = 0;
    uint32_t ape_id = get_core_id();

    if (gSlotFlagInit == 1)
    {
        gSlotFlagInit = 0;
        gCurrentSlot = slot;
    }
    else
    {
        gPreviousSlot = gCurrentSlot;
        gCurrentSlot = slot;
        delta = (20 + gCurrentSlot - gPreviousSlot) % 20;
        if (delta != 1)
        {
            debug_write(DBG_DDR_COMMON_IDX(ape_id, 50), ++g_u32_case21_ape4_timer1_slot_no_continuous);
        }
    }
    return;
}

static inline void check_continuous_sfn(uint16_t sfn)
{
    uint16_t delta = 0;
    uint32_t ape_id = get_core_id();

    if (gSfnFlagInit == 1)
    {
        gSfnFlagInit = 0;
        gCurrentSfn = sfn;
    }
    else
    {
        gPreviousSfn = gCurrentSfn;
        gCurrentSfn = sfn;
        delta = (1024 + gCurrentSfn - gPreviousSfn) % 1024;
        if (delta != 1) {
            debug_write(DBG_DDR_COMMON_IDX(ape_id, 51), ++g_u32_case21_ape4_timer1_sfn_no_continuous);
        }
    }
    return;
}

uint32_t gu32_ape4_send_cnt = 0;
static inline void send_slot_indication(void)
{
    uint16_t scs = 1;
    uint16_t sfn = get_tx_nr_sfn(scs);
    uint16_t slot = get_tx_nr_slot(scs);
    uint32_t value = (sfn << 16) + slot;
    uint32_t ape_id = get_core_id();

    uint32_t size = 8;
    char* buf;
    uint32_t availableSize,offset;

    uint16_t cu_flag = U_PLANE;//C_PLANE;
    HandleId_t handler;
    handler.port_id = get_ucp_port_id();
    handler.inst_id = 1;
    handler.type_id = CU_SPLIT;
    int32_t ret = msg_transfer_send_start(handler.value);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 60), handler.value);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 61), ++gu32_ape4_send_cnt);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 62), slot);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 63), 0xffff);

    ret = msg_transfer_alloc_msg(handler.value, cu_flag, size, &buf, &availableSize, &offset);
    if (SUCCESS != ret)
    {
        UCP_PRINT_ERROR("send_slot_indication C_PLANE ret[0x%08x]", ret);
        return;
    }
    uint32_t clockBegin;
    rdmcycle(&clockBegin);
    do_write(buf, value);
    do_write(buf+4, clockBegin);
    ret = msg_transfer_send_msg(handler.value, cu_flag, (uint8_t *)buf, offset, size);

    ret = msg_transfer_send_end(handler.value);

    debug_write(DBG_DDR_COMMON_IDX(ape_id, 52), ++g_u32_case21_ape4_timer1_slot_indication);

    return;
}

static inline void update_sfn_slot(void)
{
    uint32_t clockBegin;
    rdmcycle(&clockBegin);

    uint16_t scs = 1;//30KHz
    uint16_t sfn = get_tx_nr_sfn(scs);
    uint16_t slot = get_tx_nr_slot(scs);
    uint32_t ape_id = get_core_id();

    debug_write(DBG_DDR_COMMON_IDX(ape_id, 53), ++g_u32_case21_ape4_timer1_update_sfn_slot);

    UCP_PRINT_ERROR("ape[0x%x]:enter[%d], sfn[%d], slot[%d].", ape_id, g_u32_case21_ape4_timer1_update_sfn_slot, sfn, slot);

    check_continuous_slot(slot);

    if (slot == 0) {
        check_continuous_sfn(sfn);
    }

    return;
}


/* 定时点任务 */
void ape4_timer1_task(void)
{
    uint32_t ape_id = get_core_id();
    uint32_t clockTick   = 0;
    uint32_t clockOffset = 0;
    rdmcycle(&clockTick);

    debug_write(DBG_DDR_COMMON_IDX(ape_id, 54), ++g_u32_case21_ape4_timer1_process_cnt);

    update_sfn_slot();

    send_slot_indication();

    if (0 == g_u32_case21_ape4_timer1_process_tick)
    {
        g_u32_case21_ape4_timer1_process_tick = clockTick;
    }
    else
    {
        if (clockTick > g_u32_case21_ape4_timer1_process_tick)
        {
            clockOffset = clockTick - g_u32_case21_ape4_timer1_process_tick;
            if ((clockOffset > TIMER_OFFSET_MAX) || (clockOffset < TIMER_OFFSET_MIN))
            {
                g_u32_case21_ape4_timer1_process_tick_err++;
                debug_write(DBG_DDR_COMMON_IDX(ape_id, 55), clockOffset);
            }
        }
        g_u32_case21_ape4_timer1_process_tick = clockTick;
    }
//    debug_write(DBG_DDR_COMMON_IDX(ape_id, 55), g_u32_case20_ape0_timer1_process_tick);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 56), g_u32_case21_ape4_timer1_process_tick_err);
    return;
}

void ape4_timer2_task(void)
{
    uint32_t ape_id = get_core_id();
    uint32_t clockTick   = 0;
    uint32_t clockOffset = 0;
    rdmcycle(&clockTick);

    g_u32_case21_ape4_timer2_tx_slot_cur = get_tx_nr_slot_cycle();
    g_u32_case21_ape4_timer2_rx_slot_cur = get_rx_nr_slot_cycle();

    g_u32_case21_ape4_timer2_tx_slot_max = get_max(g_u32_case21_ape4_timer2_tx_slot_cur, g_u32_case21_ape4_timer2_tx_slot_max);
    g_u32_case21_ape4_timer2_tx_slot_min = get_min(g_u32_case21_ape4_timer2_tx_slot_cur, g_u32_case21_ape4_timer2_tx_slot_min);

    g_u32_case21_ape4_timer2_rx_slot_max = get_max(g_u32_case21_ape4_timer2_rx_slot_cur, g_u32_case21_ape4_timer2_rx_slot_max);
    g_u32_case21_ape4_timer2_rx_slot_min = get_min(g_u32_case21_ape4_timer2_rx_slot_cur, g_u32_case21_ape4_timer2_rx_slot_min);

    g_u32_case21_ape4_timer2_process_cnt++;
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 57), g_u32_case21_ape4_timer2_process_cnt);

    if (0 == g_u32_case21_ape4_timer2_process_tick)
    {
        g_u32_case21_ape4_timer2_process_tick = clockTick;
    }
    else
    {
        if (clockTick > g_u32_case21_ape4_timer2_process_tick)
        {
            clockOffset = clockTick - g_u32_case21_ape4_timer2_process_tick;
            if ((clockOffset > TIMER_OFFSET_MAX) || (clockOffset < TIMER_OFFSET_MIN))
            {
                g_u32_case21_ape4_timer2_process_tick_err++;
            }
        }
        g_u32_case21_ape4_timer2_process_tick = clockTick;
    }
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 58), g_u32_case21_ape4_timer2_process_tick);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 59), g_u32_case21_ape4_timer2_process_tick_err);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 64), g_u32_case21_ape4_timer2_tx_slot_max);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 65), g_u32_case21_ape4_timer2_tx_slot_min);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 66), g_u32_case21_ape4_timer2_tx_slot_cur);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 67), g_u32_case21_ape4_timer2_rx_slot_max);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 68), g_u32_case21_ape4_timer2_rx_slot_min);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 69), g_u32_case21_ape4_timer2_rx_slot_cur);

    return ;
}

/*************************************************************************/
/* 收到消息后创建任务 */
void ape4_event_task(uint32_t addr, uint32_t size)
{
    uint32_t ape_id = get_core_id();
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 29), 0x01010101);

    osp_task_info_ex ape4_task_event1 = {40, (int8_t*)"ape4_task_event1", 40, 2048, OSP_EVENT_TYPE, 0, 0,     0,   NULL, (OSP_TASKENTRY_FUNC)ape4_event1_task};
    osp_task_info_ex ape4_task_event2 = {41, (int8_t*)"ape4_task_event2", 41, 2048, OSP_EVENT_TYPE, 0, 0,     0,   NULL, (OSP_TASKENTRY_FUNC)ape4_event2_task};
    osp_task_info_ex ape4_task_event3 = {42, (int8_t*)"ape4_task_event3", 42, 2048, OSP_EVENT_TYPE, 0, 0,     0,   NULL, (OSP_TASKENTRY_FUNC)ape4_event3_task};
    osp_task_info_ex ape4_task_timer1 = {43, (int8_t*)"ape4_task_timer1", 43, 2048, OSP_TIMER_TYPE, 0, 0x3ff, 0,   NULL, (OSP_TASKENTRY_FUNC)ape4_timer1_task};
    osp_task_info_ex ape4_task_timer2 = {44, (int8_t*)"ape4_task_timer2", 44, 2048, OSP_TIMER_TYPE, 0, 0x3ff, 200, NULL, (OSP_TASKENTRY_FUNC)ape4_timer2_task};

    osp_task_create(&ape4_task_event1);
    osp_task_create(&ape4_task_event2);
    osp_task_create(&ape4_task_event3);
    osp_task_create(&ape4_task_timer1);
    osp_task_create(&ape4_task_timer2);

    osp_timer_sync(NR_SCS_30K);

    debug_write(DBG_DDR_COMMON_IDX(ape_id, 29), 0x03030303);
    return ;
}

/* 收到消息后删除任务 */
void ape4_event_task_del(uint32_t addr, uint32_t size)
{
    uint32_t ape_id = get_core_id();
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 29), 0x05050505);

    //osp_del_task_all(NR_SCS_30K);
    osp_del_task(40, NR_SCS_30K);
    osp_del_task(41, NR_SCS_30K);
    osp_del_task(42, NR_SCS_30K);
	
	osp_timer_unsync(NR_SCS_30K);

    debug_write(DBG_DDR_COMMON_IDX(ape_id, 29), 0x06060606);
    return;
}



