/*--------------------------------------------------------------------------
  Project:  Manual 2D Library - m2d
  File:     m2d_touchPanel.cpp

  Copyright (C)2007-2009 Nintendo  All Rights Reserved.

  These coded instructions, statements, and computer programs contain
  proprietary information of Nintendo of America Inc. and/or Nintendo
  Company Ltd., and are protected by Federal copyright law. They may
  not be disclosed to third parties or copied or duplicated in any form,
  in whole or in part, without the prior written consent of Nintendo.

  $Revision: 1758 $
 *-------------------------------------------------------------------------*/

#include <nitro.h>
#include <nnsys/misc.h>
#include <ntmv/m2d/common.h>
#include <ntmv/m2d/touchPanel.h>
#include <ntmv/m2d/touchPanelData.h>

namespace ntmv
{
namespace m2d
{

TouchPanel::TouchPanel()
:
    mOnCnt(0),
    mOffCnt(0),
    mbOn(false),
    mRawX(0),
    mRawY(0)
{
    for (int i = 0; i < SAMPLING_BUFSIZE; ++i)
    {
        mTpBuf[i].touch    = 0;
        mTpBuf[i].validity = 0;
        mTpBuf[i].x        = 0;
        mTpBuf[i].y        = 0;
    }
}

void
TouchPanel::InitHardware()
{
    // Related to initializing the Touch Panel
    TP_Init();

    /*
        It has been established as a guideline to call TP_SetCalibrateParam() only when TP_GetUserInfo() has succeeded.
        
        Strange values will be obtained from GetCalibratedPoint() when calibration settings have not been run, but applications do not need to handle this.
        
        
    */
    TPCalibrateParam calibrate;
    if (TP_GetUserInfo(&calibrate))
    {
        TP_SetCalibrateParam(&calibrate);
    }
    else
    {
        NNS_WARNING(false, "TP_GetUserInfo() fail.\n");
    }

    u32 errCode = TP_RequestAutoSamplingStart(SAMPLING_START_VCOUNT, SAMPLING_FREQUENCE, mTpBuf, SAMPLING_BUFSIZE);
    NNS_ASSERT(errCode == 0);
}

bool
TouchPanel::GetData(TouchPanelData* pData)
{
    const bool bPreOn  = mbOn;

    const u16 lastIdx = TP_GetLatestIndexInAuto();

    for (s32 i = 0; i < SAMPLING_FREQUENCE; i++)
    {
        s32 idx = lastIdx + i - SAMPLING_FREQUENCE + 1;
        if (idx < 0)
        {
            idx += SAMPLING_BUFSIZE;
        }

        if (mTpBuf[idx].touch == TP_TOUCH_OFF)
        {
            mOnCnt = 0;  // Reset the ON count value
            if (mOffCnt < SEQUENCE_COUNT)
            {
                mOffCnt++;
            }

            if (mOffCnt >= SEQUENCE_COUNT)
            {
                mbOn = false;
            }
        }
        else
        {
            mOffCnt = 0; // Reset the OFF count value
            if (mOnCnt < SEQUENCE_COUNT)
            {
                mOnCnt++;
            }

            if (mOnCnt  >= SEQUENCE_COUNT)
            {
                mbOn = true;
            }

            if (mbOn && mTpBuf[idx].validity == TP_VALIDITY_VALID)
            {
                mRawX = mTpBuf[idx].x;
                mRawY = mTpBuf[idx].y;
            }
        }
    }

    pData->bTouchOn = mbOn;
    pData->bTouchOnTrigger  = ! bPreOn &&   mbOn;
    pData->bTouchOffTrigger =   bPreOn && ! mbOn;

#if 0
    if (mbOn)
#endif
    {
        TPData rawWork = { mRawX, mRawY, TP_TOUCH_ON, TP_VALIDITY_VALID };
        TPData calWork;
        TP_GetCalibratedPoint(&calWork, &rawWork);

        pData->point.x = static_cast<s16>(calWork.x);
        pData->point.y = static_cast<s16>(calWork.y);
    }
#if 0
    else
    {
        pData->point.x = 0;
        pData->point.y = 0;
    }
#endif

    return pData->bTouchOnTrigger;
}

}   // namespace m2d
}   // namespace ntmv
