// +FHDR------------------------------------------------------------
//                 Copyright (c) 2022 SmartLogic.
//                       ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename      : case3_ape0_task.s.c
// Author        : 
// Created On    : 2022-11-02
// 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 "ape_mtimer.h"

/***************************************************************/
/*                   事件任务相关打点                                  */
uint32_t g_u32_ape0_event1_allc_err = 0;// (30) 0xB7E0 0078
uint32_t g_u32_ape0_event1_send_err = 0;// (31) 0xB7E0 007C
uint32_t g_u32_ape0_event1_send_ok  = 0;// (32) 0xB7E0 0080
uint32_t g_u32_ape0_event1_num = 0;     // (33) 0xB7E0 0084
uint32_t g_u32_ape0_event2_allc_err = 0;// (34) 0xB7E0 0088
uint32_t g_u32_ape0_event2_send_err = 0;// (35) 0xB7E0 008C
uint32_t g_u32_ape0_event2_send_ok  = 0;// (36) 0xB7E0 0090
uint32_t g_u32_ape0_event2_num = 0;     // (37) 0xB7E0 0094
uint32_t g_u32_ape0_event3_allc_err = 0;// (38) 0xB7E0 0098
uint32_t g_u32_ape0_event3_send_err = 0;// (39) 0xB7E0 009C
uint32_t g_u32_ape0_event3_send_ok  = 0;// (40) 0xB7E0 00A0
uint32_t g_u32_ape0_event3_num = 0;     // (41) 0xB7E0 00A4
uint32_t g_u32_ape0_event4_allc_err = 0;// (42) 0xB7E0 00A8
uint32_t g_u32_ape0_event4_send_err = 0;// (43) 0xB7E0 00AC
uint32_t g_u32_ape0_event4_send_ok  = 0;// (44) 0xB7E0 00B0
uint32_t g_u32_ape0_event4_num = 0;     // (45) 0xB7E0 00B4
uint32_t g_u32_ape0_event5_num = 0;     // (46) 0xB7E0 00B8

/* 收到自己(Timer0)发来的消息后给事件任务(Event2)发消息 */
void ape0_event_task1(uint32_t address, uint32_t size)
{
    uint32_t ape_id = get_core_id();
    int  ret = 0;
    char *addr = NULL;

    g_u32_ape0_event1_num++;

    addr = osp_alloc_msg(TEST_MSG_SIZE);
    if (NULL == addr)
    {
        g_u32_ape0_event1_allc_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 30), g_u32_ape0_event1_allc_err);
        return ;
    }

    do_write(addr, g_u32_ape0_event1_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
                        41,       // src task id
                        42);      // dst task id

    if (0 != ret)
    {
        g_u32_ape0_event1_send_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 31), g_u32_ape0_event1_send_err);
        return ;
    }
    g_u32_ape0_event1_send_ok++;
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 32), g_u32_ape0_event1_send_ok);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 33), g_u32_ape0_event1_num);
    return ;
}

/* 收到自己(Event1)发来的消息后给事件任务(Event3)发消息 */
void ape0_event_task2(uint32_t address, uint32_t size)
{
    uint32_t ape_id = get_core_id();
    int  ret = 0;
    char *addr = NULL;

    g_u32_ape0_event2_num++;

    addr = osp_alloc_msg(TEST_MSG_SIZE);
    if (NULL == addr)
    {
        g_u32_ape0_event2_allc_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 34), g_u32_ape0_event2_allc_err);
        return ;
    }

    do_write(addr, g_u32_ape0_event2_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
                        42,       // src task id
                        43);      // dst task id
    
    if (0 != ret)
    {
        g_u32_ape0_event2_send_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 35), g_u32_ape0_event2_send_err);
        return ;
    }
    g_u32_ape0_event2_send_ok++;
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 36), g_u32_ape0_event2_send_ok);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 37), g_u32_ape0_event2_num);
    return ;
}

/* 收到自己(Event2)发来的消息后给事件任务(Event4)发消息 */
void ape0_event_task3(uint32_t address, uint32_t size)
{
    uint32_t ape_id = get_core_id();
    int  ret = 0;
    char *addr = NULL;

    g_u32_ape0_event3_num++;

    addr = osp_alloc_msg(TEST_MSG_SIZE);
    if (NULL == addr)
    {
        g_u32_ape0_event3_allc_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 38), g_u32_ape0_event3_allc_err);
        return ;
    }

    do_write(addr, g_u32_ape0_event3_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
                        43,       // src task id
                        44);      // dst task id
    
    if (0 != ret)
    {
        g_u32_ape0_event3_send_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 39), g_u32_ape0_event3_send_err);
        return ;
    }
    g_u32_ape0_event3_send_ok++;
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 40), g_u32_ape0_event3_send_ok);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 41), g_u32_ape0_event3_num);
    return ;
}

/* 收到自己(Event3)发来的消息后给事件任务(Event5)发消息 */
void ape0_event_task4(uint32_t address, uint32_t size)
{
    uint32_t ape_id = get_core_id();
    int  ret = 0;
    char *addr = NULL;

    g_u32_ape0_event4_num++;

    addr = osp_alloc_msg(TEST_MSG_SIZE);
    if (NULL == addr)
    {
        g_u32_ape0_event4_allc_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 42), g_u32_ape0_event4_allc_err);
        return ;
    }

    do_write(addr, g_u32_ape0_event4_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
                        44,       // src task id
                        45);      // dst task id
    
    if (0 != ret)
    {
        g_u32_ape0_event4_send_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 43), g_u32_ape0_event4_send_err);
        return ;
    }
    g_u32_ape0_event4_send_ok++;
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 44), g_u32_ape0_event4_send_ok);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 45), g_u32_ape0_event4_num);
    return ;
}

void ape0_event_task5(uint32_t address, uint32_t size)
{
    uint32_t ape_id = get_core_id();
    g_u32_ape0_event5_num++;
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 46), g_u32_ape0_event5_num);
    return ;
}

/***************************************************************/
/*                   定时点任务相关打点                                 */
uint32_t g_u32_timer0_slot_err   = 0;   // (47) 0xB7E0 00BC
uint32_t g_u32_timer0_sfn_err    = 0;   // (48) 0xB7E0 00C0
uint32_t g_u32_timer0_tick       = 0;   // (49) 0xB7E0 00C4
uint32_t g_u32_timer0_tick_err   = 0;   // (50) 0xB7E0 00C8
uint32_t g_u32_timer0_allc_err   = 0;   // (51) 0xB7E0 00CC
uint32_t g_u32_timer0_send_err   = 0;   // (52) 0xB7E0 00D0
uint32_t g_u32_timer0_send_ok    = 0;   // (53) 0xB7E0 00D4
uint32_t g_u32_timer0_num        = 0;   // (54) 0xB7E0 00D8

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_timer0_slot_err++;
            debug_write(DBG_DDR_COMMON_IDX(ape_id, 47), g_u32_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_timer0_sfn_err++;
            debug_write(DBG_DDR_COMMON_IDX(ape_id, 48), g_u32_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 ape0_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_timer0_num++;
    rdmcycle(&clock_tick);

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

    update_sfn_slot();
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 49), g_u32_timer0_tick);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 50), g_u32_timer0_tick_err);


    addr = osp_alloc_msg(TEST_MSG_SIZE);
    if (NULL == addr)
    {
        g_u32_timer0_allc_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 51), g_u32_timer0_allc_err);
        return ;
    }

    do_write(addr, g_u32_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_timer0_send_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 52), g_u32_timer0_send_err);
        return ;
    }
    g_u32_timer0_send_ok++;
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 53), g_u32_timer0_send_ok);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 54), g_u32_timer0_num);

    return ;
}

