// +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 "msg_transfer_layer.h"
#include "ucp_testcase.h"
#include "ape_mtimer.h"

/***************************************************************/
/*                   定时点任务相关打点                                 */
static uint32_t g_u32_timer0_slot_err   = 0;   // (30) 0xB7E0 0078
static uint32_t g_u32_timer0_sfn_err    = 0;   // (31) 0xB7E0 007C
static uint32_t g_u32_timer0_allc_err   = 0;   // (32) 0xB7E0 0080
static uint32_t g_u32_timer0_tick       = 0;   // 不打点
static uint32_t g_u32_timer0_tick_err   = 0;   // (33) 0xB7E0 0084
static uint32_t g_u32_timer0_out        = 0;   // (34) 0xB7E0 0088
static uint32_t g_u32_timer0_num        = 0;   // (35) 0xB7E0 008C

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, 30), 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, 31), 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;
}

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 = 4;
    char* buf = NULL;
    uint32_t availableSize,offset;

	uint16_t cu_flag = C_PLANE;    
	HandleId_t handler;
	handler.port_id = get_ucp_port_id();	
	handler.inst_id = 0;
	handler.type_id = CU_SPLIT;    
	int32_t ret = msg_transfer_send_start(handler.value);
    ret = msg_transfer_alloc_msg(handler.value, cu_flag, size, &buf, &size, &offset);
    if (SUCCESS != ret)
    {
        UCP_PRINT_ERROR("send_slot_indication 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);
	
    return;
}

void ape0_timer_task1(void)
{
    uint32_t ape_id = get_core_id();
    uint32_t clock_tick = 0;
    uint32_t tick_offset = 0;
    g_u32_timer0_num++;
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 35), 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();
    send_slot_indication();
    g_u32_timer0_out++;
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 33), g_u32_timer0_tick_err);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 34), g_u32_timer0_out);
    return ;
}


/***************************************************************/
/*                   事件任务相关打点                                  */
static uint32_t g_u32_ape0_event1_tick      = 0; // (36) 0xB7E0 0090
static uint32_t g_u32_ape0_event1_num       = 0; // (37) 0xB7E0 0094
static uint32_t g_u32_ape0_event1_alloc_err = 0; // (38) 0xB7E0 0098
static uint32_t g_u32_ape0_event1_send_err  = 0; // (39) 0xB7E0 009C
static uint32_t g_u32_ape0_event1_send_ok   = 0; // (40) 0xB7E0 00A0

static uint32_t g_u32_ape0_event2_tick      = 0; // (41) 0xB7E0 00A4
static uint32_t g_u32_ape0_event2_num       = 0; // (42) 0xB7E0 00A8

static uint32_t g_u32_ape0_event3_tick      = 0; // (43) 0xB7E0 00AC
static uint32_t g_u32_ape0_event3_num       = 0; // (44) 0xB7E0 00B0

/* 收到RFM0发来的消息 */
void ape0_event_task1(uint32_t address, uint32_t size)
{
    uint32_t ape_id = get_core_id();
    g_u32_ape0_event1_num++;
    rdmcycle(&g_u32_ape0_event1_tick);

    debug_write(DBG_DDR_COMMON_IDX(ape_id, 36), g_u32_ape0_event1_tick);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 37), g_u32_ape0_event1_num);

    int  ret = 0;
    char *addr = NULL;
    uint32_t msg_addr = 0;
    uint32_t que_num  = 0;

    if (0 != address)
    {
        msg_addr = do_read(address);
        que_num  = do_read(address+4);
        msg_transfer_free_msg(0, que_num, 0, (char*)msg_addr);
    }

    addr = osp_alloc_msg(TEST_MSG_SIZE);
    if (NULL == addr)
    {
        g_u32_ape0_event1_alloc_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 38), g_u32_ape0_event1_alloc_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_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_ape0_event1_send_err++;
        debug_write(DBG_DDR_COMMON_IDX(ape_id, 39), g_u32_ape0_event1_send_err);
        return ;
    }
    g_u32_ape0_event1_send_ok++;
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 40), g_u32_ape0_event1_send_ok);

    return ;
}

/* 收到对方(event1)发来的消息 */
void ape0_event_task2(uint32_t address, uint32_t size)
{
    uint32_t ape_id = get_core_id();
    g_u32_ape0_event2_num++;
    rdmcycle(&g_u32_ape0_event2_tick);

    debug_write(DBG_DDR_COMMON_IDX(ape_id, 41), g_u32_ape0_event2_tick);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 42), g_u32_ape0_event2_num);
    return ;
}

/* 收到本方(event1)发来的消息 */
void ape0_event_task3(uint32_t address, uint32_t size)
{
    uint32_t ape_id = get_core_id();
    g_u32_ape0_event3_num++;
    rdmcycle(&g_u32_ape0_event3_tick);

    debug_write(DBG_DDR_COMMON_IDX(ape_id, 43), g_u32_ape0_event3_tick);
    debug_write(DBG_DDR_COMMON_IDX(ape_id, 44), g_u32_ape0_event3_num);
    return;
}

