/*
 * readerApp.c
 *
 *  Created on: Feb 24, 2020
 *      Author: hyuny
 */


#include "readerApp.h"
#include "main.h"
#include "utils.h"
#include "rfal_st25xv.h"
#include <stdlib.h>

#define MAX_NFCREADER 1

/* Definition of possible states the demo state machine could have */
#define ST25R39_NOTINIT               0     /*!< NFC State:  Not initialized        */
#define ST25R39_DISCOVERY             1     /*!< NFC State:  Discovery              */
#define ST25R39_INIT_TAG              2     /*!< NFC State:  Discovery              */
#define ST25R39_READY_TO_ACT          3     /*!< NFC State:  Ready to act           */

static uint8_t state = ST25R39_NOTINIT;

const nfcSpiConf nfcSpiConfs[MAX_NFCREADER] =
{
        {NFC1_CS_GPIO_Port, NFC1_CS_Pin},
};

static nfcReader nfcReaderDevices[MAX_NFCREADER] =
{
        {&nfcSpiConfs[0], ST25R39_NOTINIT},
};

void nfcTargetChange(uint8_t num)
{
    rfalNfcSetInstance(&nfcReaderDevices[num].nfcInstance);
    gSpiCs_Pin = nfcReaderDevices[num].spiConf->spiCs_Pin;
    gSpiCs_Port = nfcReaderDevices[num].spiConf->spiCs_Port;
}

nfcReader* nfcReaderInstanceGet(uint8_t num)
{
    return &nfcReaderDevices[num];
}

static void nfcTagInit(uint8_t num)
{
    uint8_t regData = 0;

    //Present Password
    uint8_t pwd[8] = {0,};
    (void) rfalST25xVPollerPresentPassword( (uint8_t)RFAL_NFCV_REQ_FLAG_DEFAULT, nfcReaderDevices[num].tagUID,
                                            0, pwd, 8 );
    //GPO Mode Clear for stable action
    regData = 0x00;
    (void) rfalST25xVPollerWriteConfiguration( (uint8_t)RFAL_NFCV_REQ_FLAG_DEFAULT, nfcReaderDevices[num].tagUID,
    												ST25DV_POINTER_GPO, regData);

    //GPO Mode Set - GPO, RF_PUT_MSG
    regData = GPO_STATIC_REG_RF_PUT_MSG_EN | GPO_STATIC_REG_GPO_EN;
    (void) rfalST25xVPollerWriteConfiguration( (uint8_t)RFAL_NFCV_REQ_FLAG_DEFAULT, nfcReaderDevices[num].tagUID,
    												ST25DV_POINTER_GPO, regData);
    regData = 0;
    (void) rfalST25xVPollerReadConfiguration( (uint8_t)RFAL_NFCV_REQ_FLAG_DEFAULT, nfcReaderDevices[num].tagUID,
    												ST25DV_POINTER_GPO, &regData);

    //IT_TIME 302us
    regData = 0;
    (void) rfalST25xVPollerWriteConfiguration( (uint8_t)RFAL_NFCV_REQ_FLAG_DEFAULT, nfcReaderDevices[num].tagUID,
    												ST25DV_POINTER_IT_TIME, regData);

    //MB_WDG
    regData = 0;
    (void) rfalST25xVPollerWriteConfiguration( (uint8_t)RFAL_NFCV_REQ_FLAG_DEFAULT, nfcReaderDevices[num].tagUID,
    												ST25DV_POINTER_MB_WDG, regData);

    //Energy Harvesting Mode ON
    regData = EH_EN_ENABLE | EH_ON_ENABLE;
    (void) rfalST25xVPollerFastWriteDynamicConfiguration( (uint8_t)RFAL_NFCV_REQ_FLAG_DEFAULT, nfcReaderDevices[num].tagUID,
                                                        ST25DV_EH_CTRL_Dyn, regData);
    regData = 0;
    (void) rfalST25xVPollerFastReadDynamicConfiguration( (uint8_t)RFAL_NFCV_REQ_FLAG_DEFAULT, nfcReaderDevices[num].tagUID,
                                                        ST25DV_EH_CTRL_Dyn, &regData);

    //Mailbox Enable
    regData = MB_EN_ENABLE;
    (void) rfalST25xVPollerFastWriteDynamicConfiguration( (uint8_t)RFAL_NFCV_REQ_FLAG_DEFAULT, nfcReaderDevices[num].tagUID,
    													ST25DV_MB_CTRL_Dyn, regData);
    regData= 0;
    (void) rfalST25xVPollerFastReadDynamicConfiguration( (uint8_t)RFAL_NFCV_REQ_FLAG_DEFAULT, nfcReaderDevices[num].tagUID,
    													ST25DV_MB_CTRL_Dyn, &regData);
} 


static bool isTagInit(uint8_t num)
{
    uint8_t res = 0;
    uint8_t regData = 0;
    // 고전압 인가 여부 확인
    (void) rfalST25xVPollerFastReadDynamicConfiguration( (uint8_t)RFAL_NFCV_REQ_FLAG_DEFAULT, nfcReaderDevices[num].tagUID,
                                                        ST25DV_EH_CTRL_Dyn, &regData);
    res = (regData >> EH_CTRL_DYN_of_VCC_ON_BIT_POS) & 0x01;

    // MailBox 초기화 확인
	(void) rfalST25xVPollerFastReadDynamicConfiguration( (uint8_t)RFAL_NFCV_REQ_FLAG_DEFAULT, nfcReaderDevices[num].tagUID,
														ST25DV_EH_CTRL_Dyn, &regData);

	res &= (regData >> MB_CTRL_DYN_of_MB_EN_BIT_POS & 0x01);
    return res;
}

static void nfcReaderProcess(uint8_t num)
{
	// 1. MB Length 확인
	// 2. 읽
}

static rfalNfcDiscoverParam discParam;
void static nfcReaderDiscoveryTag(uint8_t num)
{
    /* Start nfc tag discovery */
    static rfalNfcDevice *nfcDevice;
    rfalNfcDeactivate( false );
    rfalNfcDiscover( &discParam );
    uint32_t preTime = HAL_GetTick();
    do {
        rfalNfcWorker();
        if( rfalNfcIsDevActivated( rfalNfcGetState() ) )
        {
            if ((rfalNfcGetActiveDevice( &nfcDevice ) == ERR_NONE) &&
                    nfcDevice->type == RFAL_NFC_LISTEN_TYPE_NFCV)
            {
                memcpy(nfcReaderDevices[num].tagUID, nfcDevice->nfcid, RFAL_NFCV_UID_LEN);
                platformLog("NFC-V TAG found. UID: %s\r\n", hex2Str(nfcReaderDevices[num].tagUID, RFAL_NFCV_UID_LEN));
                nfcReaderDevices[num].state = ST25R39_INIT_TAG;
                nfcTagInit(num);
            }
        }
    } while (HAL_GetTick() - preTime < 1);

}

void nfcReaderInit()
{
    for (int i = 0; i < MAX_NFCREADER; i++)
    {
        nfcTargetChange(i);
        /* Set discovery configuration */
        if (rfalNfcInitialize() == ERR_NONE)
        {
            discParam.compMode      = RFAL_COMPLIANCE_MODE_NFC;
            discParam.devLimit      = 1U;
            discParam.nfcfBR        = RFAL_BR_212;
            discParam.ap2pBR        = RFAL_BR_424;

            discParam.totalDuration        = 10U;
            discParam.wakeupEnabled        = false;
            discParam.wakeupConfigDefault  = true;
            discParam.techs2Find           = RFAL_NFC_POLL_TECH_V;
            state = ST25R39_DISCOVERY;
        }

        nfcReaderDiscoveryTag(i);
        if (isTagInit(i))
        {
            nfcReaderDevices[i].state = ST25R39_READY_TO_ACT;
        }
        else
        {
	        platformLog("NFC[%d] Discovery Timeout\r\n", i);
        }
    }
}

void nfcReaderCycle(uint8_t num)
{
    if (nfcReaderDevices[num].state == ST25R39_READY_TO_ACT)
    {
        nfcReaderProcess(num);
    }
    else         /* TAG가 정상적으로 초기화 되지 않은 상황 */
    {
        switch (nfcReaderDevices[num].state)
        {
            case ST25R39_INIT_TAG:
                nfcTagInit(num);
                if (isTagInit(num))
                    nfcReaderDevices[num].state = ST25R39_READY_TO_ACT;
                break;
            default: //스위치는 인식되었으나, TAG를 찾지 못한 경우..
                platformLog("Do not initialization TAG\r\n");
                /* */
                break;
        }
        
    }
}


