/* SPDX-License-Identifier: LGPL-2.1-only OR BSD-3-Clause */
/******************************************************************************
 *
 * This file is provided under a dual license.  When you use or
 * distribute this software, you may choose to be licensed under
 * version 2.1 of the GNU Lesser General Public License
 * ("LGPLv2.1 License") or BSD License.
 *
 * LGPLv2.1 License
 *
 * Copyright(C) 2019 MediaTek Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2.1 of the GNU Lesser General Public
 * License as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 * See https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html for more
 * details.
 *
 * BSD LICENSE
 *
 * Copyright(C) 2019 MediaTek Inc.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *  * Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *  * Neither the name of the copyright holder nor the names of its
 *    contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 *****************************************************************************/

/*-----------------------------------------------------------------------------
 *
 * $Author: brianpc.huang $
 * $Date  $
 * $RCSfile: util.h,v $
 * $Revision: #1 $
 *
 *---------------------------------------------------------------------------*/

#ifndef _UTIL_H_
#define _UTIL_H_

#include "typedef.h"
#include "x_util.h"
#include "debug.h"
#include "x_timer.h"

extern void vUtInitVar(void) ;


#define DELAY_MACRO 1
#if DELAY_MACRO
#include "x_os.h"

/* some benifit, 1.  value can >255 , 2. *2 or *10  *1000 can be calculate in compiler time */
#define vUtDelay2us(value)	HAL_Delay_us(2*(value))
#define vUtDelay1ms(value)	(((value)<=10)?HAL_Delay_us(1000*(value)):x_thread_delay(value))
#define vUtDelay10ms(value)	x_thread_delay(10*(value))
#define vUtDelay1s(value)		x_thread_delay(1000*(value))

#else
extern void vUtDelay2us(UINT8 bValue) ;
extern void vUtDelay1ms(UINT8 bValue) ;
extern void vUtDelay10ms(UINT8 bValue) ;
extern void vUtDelay1s(UINT8 bValue) ;
#endif

enum
{
    SV_OUT_VSYNC_TIME=0,    // get result at xdata 0x2800[31:0]
    SV_MLOOP_TIME0=1,       // get result at xdata 0x2804[31:0]
    SV_MLOOP_TIME1=2,       // get result at xdata 0x2808[31:0]
    SV_TEST_M=3,            // get result at xdata 0x280C[31:0]

    // PQ Adaptive Function Measurement
    SV_ADAP_LUMA_TIMER=4,   // get result at xdata 0x2810[31:0]
    SV_TTD_TIMER=5,         // get result at xdata 0x2814[31:0]
    SV_NR_TIMER1=6,         // get result at xdata 0x2818[31:0]
    SV_PSCAN_TIMER=7,       // get result at xdata 0x281C[31:0]
    SV_DEPTH_CTRL_TIMER=8,  // get result at xdata 0x2820[31:0]
    SV_ADAP_SHARP_TIMER=9,  // get result at xdata 0x2824[31:0]
    SV_SCALER_TIMER=10,     // get result at xdata 0x2828[31:0]    
    SV_OD_TIMER=11,         // get result at xdata 0x282C[31:0]        
    SV_NR_TIMER2=12,        // get result at xdata 0x2830[31:0]    
    SV_BNR_ACTIVE_TIMER=13, // get result at xdata 0x2834[31:0]
    SV_FRM_SCH_TIMER=14,    
    SV_MAX_SYS_MODULE
};


#if  CC_MEASURE_SYS_TIME
#define TIME_MODULE_STR_LEN                  21

extern HAL_TIME_T rStartMeasureTime[SV_MAX_SYS_MODULE];
extern HAL_TIME_T rEndMeasureTime[SV_MAX_SYS_MODULE];
extern UINT32 _u4SysMeasueTimeEn;
extern CHAR _aszTimeModuleStr[SV_MAX_SYS_MODULE][TIME_MODULE_STR_LEN];


#if CC_TIMER_MASK_USE_SWREG
#define SYS_MEASURE_TIME_START(module) \
{\
    if (fgIsSWRegInit()==TRUE)\
    {\
        if(u4IO32Read4B(SW_MODULE_MASK_EN) & (1<<module))\
        {\
        HAL_GetTime(&(rStartMeasureTime[module]));\
        }\
    }\
}
#else
#define SYS_MEASURE_TIME_START(module) \
{\
    if(_u4SysMeasueTimeEn & (1 << module))\
    {\
    HAL_GetTime(&(rStartMeasureTime[module]));\
    }\
}
#endif


#if CC_TIMER_MASK_USE_SWREG
#define SYS_MEASURE_TIME_END(module) \
{\
    if (fgIsSWRegInit()==TRUE)\
    {\
        if(u4IO32Read4B(SW_MODULE_MASK_EN) & (1<<module))\
        {\
        HAL_GetTime(&(rEndMeasureTime[module]));\
        }\
    }\
}
#else
#define SYS_MEASURE_TIME_END(module) \
{\
    if(_u4SysMeasueTimeEn & (1 << module))\
    {\
    HAL_GetTime(&(rEndMeasureTime[module]));\
    }\
}
#endif

#if CC_TIMER_MASK_USE_SWREG
#define SYS_STORE_TIME_INFO_TO_REG(module) \
{\
    HAL_TIME_T  rDeltaTime;\
    if (fgIsSWRegInit()==TRUE)\
    {\
        if(u4IO32Read4B(SW_MODULE_MASK_EN) & (1<<module))\
        {\
        HAL_GetDeltaTime(&rDeltaTime, &rStartMeasureTime[module], &rEndMeasureTime[module]);\
        vIO32Write4B(SW_MODULE_TIMER_BASE + (module << 2), rDeltaTime.u4Seconds * 1000000 + rDeltaTime.u4Micros);\
        }\
    }\
}
#else
#define SYS_STORE_TIME_INFO_TO_REG(module) \
{\
    HAL_TIME_T  rDeltaTime;\
    if(_u4SysMeasueTimeEn & (1 << module))\
    {\
        HAL_GetDeltaTime(&rDeltaTime, &rStartMeasureTime[module], &rEndMeasureTime[module]);\
        vIO32Write4B(SW_MODULE_TIMER_BASE + (module << 2), rDeltaTime.u4Seconds * 1000000 + rDeltaTime.u4Micros);\
    }\
}
#endif

#define SYS_PRINT_TIME(module) \
{\
    HAL_TIME_T  rDeltaTime;\
    if(_u4SysMeasueTimeEn & (1 << module))\
    {\
        HAL_GetDeltaTime(&rDeltaTime, &rStartMeasureTime[module], &rEndMeasureTime[module]);\
        Printf("[%s] %d.%03d s\n", _aszTimeModuleStr[module], rDeltaTime.u4Seconds,  (rDeltaTime.u4Micros / 1000));\
    }\
}

#else
#define SYS_MEASURE_TIME_START(module)
#define SYS_MEASURE_TIME_END(module)
#define SYS_PRINT_TIME(module)
#define SYS_STORE_TIME_INFO_TO_REG(module)
#endif


#define PRINT_TIMESTAMP_MSG_N(Title, String)                          \
{                                                                   \
    HAL_TIME_T _rTime;                                              \
    HAL_GetTime(&_rTime);                                           \
    Printf(Title);                                                  \
    Printf(" (%06d:%03d) ", _rTime.u4Seconds, _rTime.u4Micros/1000);\
    Printf(String);                                                 \
}


#endif
