// +FHDR------------------------------------------------------------
//                 Copyright (c) 2022 SmartLogic.
//                       ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename      : case5_ape0_task.s.c
// Author        : 
// Created On    : 2022-11-10
// 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 "osp_task.h"
#include "osp_timer.h"
#include "ucp_testcase.h"
#include "ape_mtimer.h"

/***************************************************************/
static uint8_t g_u8_ape1_event_timer_flag = 0;
//static uint8_t g_u8_ape1_dle_task_flag    = 0;
/*                   定时点任务相关打点                                 */
static uint32_t g_u32_ape1_timer0_slot_err   = 0;   // (30) 0xB7E0 0278
static uint32_t g_u32_ape1_timer0_sfn_err    = 0;   // (31) 0xB7E0 027C
static uint32_t g_u32_ape1_timer0_tick       = 0;   // (32) 0xB7E0 0280
static uint32_t g_u32_ape1_timer0_tick_err   = 0;   // (33) 0xB7E0 0284
static uint32_t g_u32_ape1_timer0_allc1_err  = 0;   // (34) 0xB7E0 0288
static uint32_t g_u32_ape1_timer0_send1_err  = 0;   // (35) 0xB7E0 028C
static uint32_t g_u32_ape1_timer0_send1_ok   = 0;   // (36) 0xB7E0 0290
static uint32_t g_u32_ape1_timer0_allc2_err  = 0;   // (37) 0xB7E0 0294
static uint32_t g_u32_ape1_timer0_send2_err  = 0;   // (38) 0xB7E0 0298
static uint32_t g_u32_ape1_timer0_send2_ok   = 0;   // (39) 0xB7E0 029C
static uint32_t g_u32_ape1_timer0_allc3_err  = 0;   // (40) 0xB7E0 02A0
static uint32_t g_u32_ape1_timer0_send3_err  = 0;   // (41) 0xB7E0 02A4
static uint32_t g_u32_ape1_timer0_send3_ok   = 0;   // (42) 0xB7E0 02A8
static uint32_t g_u32_ape1_timer0_num        = 0;   // (43) 0xB7E0 02AC

static uint32_t g_u32_ape1_timer0_allc4_err  = 0;   // (56) 0xB7E0 02E0
static uint32_t g_u32_ape1_timer0_send4_err  = 0;   // (57) 0xB7E0 02E4
static uint32_t g_u32_ape1_timer0_send4_ok   = 0;   // (58) 0xB7E0 02E8

static uint32_t g_u32_ape1_timer3_tick       = 0;   // (44) 0xB7E0 02B0
static uint32_t g_u32_ape1_timer3_tick_err   = 0;   // (45) 0xB7E0 02B4
static uint32_t g_u32_ape1_timer3_prio_err   = 0;   // (46) 0xB7E0 02B8
static uint32_t g_u32_ape1_timer3_in         = 0;   // (47) 0xB7E0 02BC
static uint32_t g_u32_ape1_timer3_out        = 0;   // (48) 0xB7E0 02C0

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)
        {
            g_u32_ape1_timer0_slot_err++;
            debug_write(DBG_DDR_COMMON_IDX(ape_id, 30), g_u32_ape1_timer0_slot_err);
            UCP_PRINT_ERROR("slot number is not continuous;current sfn[0x%x], current slot[0x%x],previous slot[0x%x].", gCurrentSfn, gCurrentSlot, gPreviousSlot);
        }
    }
    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)
        {
            g_u32_ape1_timer0_sfn_err++;
            debug_write(DBG_DDR_COMMON_IDX(ape_id, 31), g_u32_ape1_timer0_sfn_err);
            UCP_PRINT_ERROR("slot number is not continuous;current sfn[0x%x], previous sfn[0x%x].", gCurrentSfn, gPreviousSfn);
        }
    }
    return;
}

static inline void update_sfn_slot(void)
{
    uint16_t scs  = 1;//30KHz
    uint16_t sfn  = get_tx_nr_sfn(scs);
    uint16_t slot = get_tx_nr_slot(scs);
    check_continuous_slot(slot);

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

    return;
}

void ape1_test_timer0(void)
{
    uint32_t ape_id = get_core_id();
    uint32_t clock_tick = 0;
    uint32_t tick_offset = 0;
    int  ret = 0;
    char *addr = NULL;
    g_u32_ape1_timer0_num++;
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 43), g_u32_ape1_timer0_num);
    rdmcycle(&clock_tick);

    if (0 == g_u32_ape1_timer0_tick)
    {
        g_u32_ape1_timer0_tick = clock_tick;
    }
    else
    {
        if (clock_tick > g_u32_ape1_timer0_tick)
        {
            tick_offset = clock_tick - g_u32_ape1_timer0_tick;
            if ((tick_offset > TIMER_OFFSET_MAX) || (tick_offset < TIMER_OFFSET_MIN))
            {
                g_u32_ape1_timer0_tick_err++;
            }
        }
        g_u32_ape1_timer0_tick = clock_tick;
    }

    update_sfn_slot();
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 32), g_u32_ape1_timer0_tick);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 33), g_u32_ape1_timer0_tick_err);

    if (1000 == g_u32_ape1_timer0_num)
    {
        /* 第1000子帧时，发消息通知本核event3，开始删除所有任务 */
        addr = osp_alloc_msg(TEST_MSG_SIZE);
        if (NULL == addr)
        {
            g_u32_ape1_timer0_allc4_err++;
            debug_write(DBG_DDR_COMMON_IDX(ape_id, 56), g_u32_ape1_timer0_allc4_err);
            return ;
        }

        do_write(addr, g_u32_ape1_timer0_num);
        do_write((addr+4), 0xA001B002);

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

        if (0 != ret)
        {
            g_u32_ape1_timer0_send4_err++;
            debug_write(DBG_DDR_COMMON_IDX(ape_id, 57), g_u32_ape1_timer0_send4_err);
            return ;
        }
        g_u32_ape1_timer0_send4_ok++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 58), g_u32_ape1_timer0_send4_ok);

    }

    /* 给本核发消息 */
    addr = osp_alloc_msg(TEST_MSG_SIZE);
    if (NULL == addr)
    {
        g_u32_ape1_timer0_allc1_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 34), g_u32_ape1_timer0_allc1_err);
        return ;
    }

    do_write(addr, g_u32_ape1_timer0_num);
    do_write((addr+4), 0xA001B002);

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

    if (0 != ret)
    {
        g_u32_ape1_timer0_send1_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 35), g_u32_ape1_timer0_send1_err);
        return ;
    }
    g_u32_ape1_timer0_send1_ok++;
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 36), g_u32_ape1_timer0_send1_ok);

    /* 核间发消息 */
    addr = osp_alloc_msg(TEST_MSG_SIZE);
    if (NULL == addr)
    {
        g_u32_ape1_timer0_allc2_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 37), g_u32_ape1_timer0_allc2_err);
        return ;
    }

    do_write(addr, g_u32_ape1_timer0_num);
    do_write((addr+4), 0xA001B002);

    ret = osp_send_msg((uint32_t)(addr),
                        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_ape1_timer0_send2_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 38), g_u32_ape1_timer0_send2_err);
        return ;
    }
    g_u32_ape1_timer0_send2_ok++;
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 39), g_u32_ape1_timer0_send2_ok);

    /* 核间发消息 */
    addr = osp_alloc_msg(TEST_MSG_SIZE);
    if (NULL == addr)
    {
        g_u32_ape1_timer0_allc3_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 40), g_u32_ape1_timer0_allc3_err);
        return ;
    }

    do_write(addr, g_u32_ape1_timer0_num);
    do_write((addr+4), 0xA001B002);

    ret = osp_send_msg((uint32_t)(addr),
                        TEST_MSG_SIZE,
                        UCP4008_KERNEL_INTER,
                        ape_id,   // src que id
                        ape_id-1, // dst que id
                        40,       // src task id
                        42);      // dst task id

    if (0 != ret)
    {
        g_u32_ape1_timer0_send3_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 41), g_u32_ape1_timer0_send3_err);
        return ;
    }
    g_u32_ape1_timer0_send3_ok++;
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 42), g_u32_ape1_timer0_send3_ok);
    return ;
}

void ape1_test_timer3(void)
{
    uint32_t ape_id = get_core_id();
    uint32_t clock_tick = 0;
    uint32_t tick_offset = 0;
    g_u32_ape1_timer3_in++;
    rdmcycle(&clock_tick);

    if (0 == g_u32_ape1_timer3_tick)
    {
        g_u32_ape1_timer3_tick = clock_tick;
    }
    else
    {
        if (clock_tick > g_u32_ape1_timer3_tick)
        {
            tick_offset = clock_tick - g_u32_ape1_timer3_tick;
            if ((tick_offset > TIMER_OFFSET_MAX) || (tick_offset < TIMER_OFFSET_MIN))
            {
                g_u32_ape1_timer3_tick_err++;
            }
        }
        g_u32_ape1_timer3_tick = clock_tick;
    }
    if (1 != g_u8_ape1_event_timer_flag)
    {
        g_u32_ape1_timer3_prio_err++;
    }
    g_u8_ape1_event_timer_flag = 0;
    g_u32_ape1_timer3_out++;
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 44), g_u32_ape1_timer3_tick);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 45), g_u32_ape1_timer3_tick_err);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 46), g_u32_ape1_timer3_tick_err);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 47), g_u32_ape1_timer3_in);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 48), g_u32_ape1_timer3_out);
    return ;
}

/***************************************************************/
static uint8_t  g_u8_ape1_event_flag = 0;
/*                   事件任务相关打点                                  */
static uint32_t g_u32_ape1_event1_tick      = 0; // (49) 0xB7E0 02C4
static uint32_t g_u32_ape1_event1_num       = 0; // (50) 0xB7E0 02C8
static uint32_t g_u32_ape1_event1_pro_err   = 0; // (51) 0xB7E0 02CC

static uint32_t g_u32_ape1_event2_tick      = 0; // (52) 0xB7E0 02D0
static uint32_t g_u32_ape1_event2_num       = 0; // (53) 0xB7E0 02D4
static uint32_t g_u32_ape1_event2_pro_err   = 0; // (54) 0xB7E0 02D8
static uint32_t g_u32_ape1_event2_timer_err = 0; // (55) 0xB7E0 02DC

static uint32_t g_u32_ape1_event3_tick      = 0; // (59) 0xB7E0 02EC
static uint32_t g_u32_ape1_event3_num       = 0; // (60) 0xB7E0 02F0

/* 收到本方(Timer0)发来的消息 */
void ape1_event_task1(uint32_t address, uint32_t size)
{
    uint32_t ape_id = get_core_id();
    g_u32_ape1_event1_num++;
    rdmcycle(&g_u32_ape1_event1_tick);

    if (0 != g_u8_ape1_event_flag)
    {
        g_u32_ape1_event1_pro_err++;
    }
    g_u8_ape1_event_flag = 1;

    debug_write(DBG_DDR_COMMON_IDX(ape_id, 49), g_u32_ape1_event1_tick);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 50), g_u32_ape1_event1_num);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 51), g_u32_ape1_event1_pro_err);
    return ;
}

/* 收到对方(Timer0)发来的消息 */
void ape1_event_task2(uint32_t address, uint32_t size)
{
    uint32_t ape_id = get_core_id();
    g_u32_ape1_event2_num++;
    rdmcycle(&g_u32_ape1_event2_tick);

    if (1 != g_u8_ape1_event_flag)
    {
        g_u32_ape1_event2_pro_err++;
    }
    g_u8_ape1_event_flag = 0;

    if (0 != g_u8_ape1_event_timer_flag)
    {
        g_u32_ape1_event2_timer_err++;
    }
    g_u8_ape1_event_timer_flag = 1;

    debug_write(DBG_DDR_COMMON_IDX(ape_id, 52), g_u32_ape1_event2_tick);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 53), g_u32_ape1_event2_num);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 54), g_u32_ape1_event2_pro_err);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 55), g_u32_ape1_event2_timer_err);
    return ;
}

/* 收到本方(Timer0)发来的消息 -- 删除任务 */
void ape1_event_task3(uint32_t address, uint32_t size)
{
    uint32_t ape_id = get_core_id();
    g_u32_ape1_event3_num++;
    rdmcycle(&g_u32_ape1_event3_tick);

    debug_write(DBG_DDR_COMMON_IDX(ape_id, 59), g_u32_ape1_event3_tick);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 60), g_u32_ape1_event3_num);

    /* 删除任务 */
    osp_del_task(40); /* 查看71：0xB7E0031C(28)，72打点：0xB7E00320(2B) */
    osp_del_task(41); /* 查看61打点：0xB7E002F4(29) */
    osp_del_task(42); /* 查看62打点：0xB7E002F8(2A) */

    osp_delay_cycle(1);

    osp_task_info_ex ape1_timer_0 = {40, (int8_t*)"ape1_test_timer0", 40, 1024, OSP_TIMER_TYPE, 0, 0x3FF, 10,  NULL, (OSP_TASKENTRY_FUNC)ape1_test_timer0};
    osp_task_info_ex ape1_event_1 = {41, (int8_t*)"ape1_test_event1", 41, 1024, OSP_EVENT_TYPE, 0, 0,     0,   NULL, (OSP_TASKENTRY_FUNC)ape1_event_task1};
    osp_task_info_ex ape1_event_2 = {42, (int8_t*)"ape1_test_event2", 42, 1024, OSP_EVENT_TYPE, 0, 0,     0,   NULL, (OSP_TASKENTRY_FUNC)ape1_event_task2};
    osp_task_info_ex ape1_timer_3 = {43, (int8_t*)"ape1_test_timer3", 43, 1024, OSP_TIMER_TYPE, 0, 0x3FF, 300, NULL, (OSP_TASKENTRY_FUNC)ape1_test_timer3};

    osp_task_create(&ape1_timer_0);
    osp_task_create(&ape1_event_1);
    osp_task_create(&ape1_event_2);
    osp_task_create(&ape1_timer_3);

    osp_timer_sync(500);

    return ;
}

