// +FHDR------------------------------------------------------------
//                 Copyright (c) 2022 SmartLogic.
//                       ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename      : ucp_ape_test.c
// Author        : xianfeng.du
// Created On    : 2022-10-19s
// Last Modified :
// -----------------------------------------------------------------
// Description:
//
//
// -FHDR------------------------------------------------------------

#include "ucp_utility.h"
#include "ucp_tick.h"
#include "ucp_port.h"
#include "ucp_printf.h"
#include "phy_para.h"
#include "msg_transfer_layer.h"
#include "osp_type_def.h"
#include "ucp_testcase.h"
#include "ape_mtimer.h"

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 uint32_t g_sfn_no_continuous_cnt  = 0;   //(5)  0xB7E00014
static uint32_t g_slot_no_continuous_cnt = 0;   //(6)  0xB7E00018

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

    if (gSlotFlagInit == 1) {
            gSlotFlagInit = 0;
            gCurrentSlot = slot;
    } else {
        gPreviousSlot = gCurrentSlot;
        gCurrentSlot = slot;
        delta = (10 + gCurrentSlot - gPreviousSlot) % 10;
        if (delta != 1) {
            debug_write(DBG_DDR_COMMON_IDX(apeId,6), ++g_slot_no_continuous_cnt);
            UCP_PRINT_ERROR("ape[%d] slot is not continuous, slot[%d]:[%d], cnt[%d]", apeId, gCurrentSlot, gPreviousSlot, g_slot_no_continuous_cnt);
            //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 apeId = 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(apeId,5), ++g_sfn_no_continuous_cnt);
            UCP_PRINT_ERROR("ape[%d] sfn is not continuous, sfn[%d]:[%d], cnt[%d]", apeId, gCurrentSfn, gPreviousSfn, g_sfn_no_continuous_cnt);
            //UCP_PRINT_ERROR("slot number is not continuous;current sfn[0x%x], previous sfn[0x%x].",gCurrentSfn,gPreviousSfn);
        }
    }

    return;
}

static uint32_t g_slot_update_task_cnt = 0;     //(3)   0xB7E0000C
static uint32_t g_slot_indication_task_cnt = 0; //(4)   0xB7E00010

static inline void send_slot_indication(void)
{
    uint32_t clockBegin,clockEnd;
    int32_t  clockCnt;
    rdmcycle(&clockBegin);

    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 apeId = get_core_id();

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

    UCP_PRINT_DEBUG("ape[0x%x]_slot_indication_task start, current sfn[0x%x], current slot[0x%x].",apeId,sfn,slot);

    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, &availableSize, &offset);
    if (SUCCESS != ret)
    {
        UCP_PRINT_ERROR("send_slot_indication ret[0x%08x]", ret);
        return;
    }

    uint32_t stamp;
    rdmcycle(&stamp);
    do_write(buf, value);
    do_write(buf+4, stamp);	
    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(apeId,4), ++g_slot_indication_task_cnt);
    rdmcycle(&clockEnd);
    clockCnt = clockEnd - clockBegin;
    UCP_PRINT_DEBUG("ape[0x%x]_slot_indication_task end, startTime:[0x%08x], cycle:[0x%08x]",apeId,clockBegin, clockCnt);

    return;
}

uint32_t gu32_ape0_slot_cnt = 0;
static inline void update_sfn_slot(void)
{
    uint32_t clockBegin,clockEnd;
    int32_t  clockCnt;
    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 apeId = get_core_id();
    //UCP_PRINT_DEBUG("ape[0x%x]_slot_update_task start, current sfn[0x%x], current slot[0x%x].",apeId,sfn,slot);
    //UCP_PRINT_ERROR("ape[0x%x]:enter[%d], sfn[0x%x], slot[0x%x].", apeId, ++gu32_ape0_slot_cnt, sfn, slot);

    debug_write(DBG_DDR_COMMON_IDX(apeId,3), ++g_slot_update_task_cnt);
    check_continuous_slot(slot);

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

    rdmcycle(&clockEnd);
    clockCnt = clockEnd - clockBegin;
    UCP_PRINT_DEBUG("ape[0x%x]_slot_update_task end, startTime:[0x%08x], cycle:[0x%08x]",apeId,clockBegin, clockCnt);

    return;
}

//uint16_t  g_u16_slot_task_loop = 0;
static uint32_t g_ape0_slot_process_tick     = 0;   //(7)   0xB7E0001C
static uint32_t g_ape0_slot_process_tick_err = 0;   //(8)   0xB7E00020
static uint32_t g_ape0_slot_process_cnt      = 0;   //(9)   0xB7E00024
void ape_slot_process_task(void)
{
    uint32_t ape_id = get_core_id();
    uint32_t clockTick   = 0;
    uint32_t clockOffset = 0;
    rdmcycle(&clockTick);
    debug_write(((DBG_DDR_IDX_DRV_BASE+10240) + (g_ape0_slot_process_cnt&0x1FF) + (ape_id << 9)), clockTick);   // 0xa000
    g_ape0_slot_process_cnt++;
    debug_write(DBG_DDR_COMMON_IDX(ape_id,9), g_ape0_slot_process_cnt);
    //clockTick = do_read_volatile(&LTBG0_TIME_BASE);
    //debug_write(OSP_DEBUG_POT(ape_id, (480+g_u16_slot_task_loop)), clockTick); /* 多ape时，这段地址会由其他ape使用 */
    //g_u16_slot_task_loop = (g_u16_slot_task_loop+1)&0x1FF;

    uint32_t offset = get_tx_nr_slot_cycle();
    debug_write(DBG_DDR_COMMON_IDX(ape_id,(96+(g_slot_update_task_cnt&0xF))), offset);

    update_sfn_slot();

    send_slot_indication();

    if (0 == g_ape0_slot_process_tick)
    {
        g_ape0_slot_process_tick = clockTick;
    }
    else
    {
        if (clockTick > g_ape0_slot_process_tick)
        {
            clockOffset = clockTick - g_ape0_slot_process_tick;
            if ((clockOffset > TIMER_OFFSET_MAX) || (clockOffset < TIMER_OFFSET_MIN))
            {
                g_ape0_slot_process_tick_err++;
                UCP_PRINT_ERROR("ape[%d] slot_process tick err[%d], cnt[%d]",clockOffset, g_ape0_slot_process_tick_err);
            }
        }
        g_ape0_slot_process_tick = clockTick;
    }
    debug_write(DBG_DDR_COMMON_IDX(ape_id,7), g_ape0_slot_process_tick);
    debug_write(DBG_DDR_COMMON_IDX(ape_id,8), g_ape0_slot_process_tick_err);
    return;
}

