/******************************************************************************/
/* Williams Advanced Engineering Limited                     Copyright(C) 2021*/
/* Grove                                                  All rights reserved */
/*                                                                            */
/******************************************************************************/



#include "FBL_DataMCfg.h"
#include "FBL_DataM.h"
#include "FBL_PortUserCode.h"
#include "DcmDspUds_RequestDownload_Prot.h"
#include "Fls.h"
#include "Fee.h"
#include "NvM.h"

// Removing of compiler warnings and errors because of type re-declaration between hal_stdtypes.h and Std_Types.h
#define _BOOLEAN_DECLARED
#define _UINT8_DECLARED
#define _UINT16_DECLARED
#define _UINT32_DECLARED
#define _UINT64_DECLARED
#define _SINT8_DECLARED
#define _SINT16_DECLARED
#define _SINT32_DECLARED
#define _SINT64_DECLARED
#define _FLOAT32_DECLARED
#define _FLOAT64_DECLARED
#define _STD_RETURN_TYPE_DECLARED
#define _STDVERSION_DECLARED

#include "Ios_ExtFlashNvm.h"
#include "Ios_Std.h"
#include "Ios_Terminal.h"
#include "Ios_Reset.h"


//#define DEBUG_FLASH 1

ExtFlashMngrStatusType g_tExtFlashMngrStatus =
{
 .CurrentExtFlashJobReq = ExtFlsJobReqNone,
 .CurrentExtFlashJobStatus = ExtFlsJobStdby,
};


//#define DEBUG_EXT_FLS




void fnIosExtFlsJobSetRqst(ExtFlashJobType ExtFlashJobReq)
{
    g_tExtFlashMngrStatus.CurrentExtFlashJobReq = ExtFlashJobReq;
}


ExtFlashJobType fnIosExtFlsJobGetRqst(void)
{
    return(g_tExtFlashMngrStatus.CurrentExtFlashJobReq);
}


ExtFlashJobStatusType fnIosExtFlsJobGetCurrentJobStatus(void)
{
    return(g_tExtFlashMngrStatus.CurrentExtFlashJobStatus);
}

void fnIosExtFlsJobResetCurrentJobStatus(void)
{
    g_tExtFlashMngrStatus.CurrentExtFlashJobStatus = ExtFlsJobStdby;
}

void fnIosExtFlsJobRqstManager(void)
{
    Std_ReturnType retval = E_NOT_OK;
    MemIf_JobResultType tMemIfJobReslt;
    MemIf_StatusType tMemIfStatus;
    static uint8  bSectorNumber=0, bSectorIndex = 0, bNumRefusedRequests = 0;
    static uint32 ulSectorSize=0;

    if(ExtFlsJobStdby == g_tExtFlashMngrStatus.CurrentExtFlashJobStatus)
    {
        if(ExtFlsJobReqNone != g_tExtFlashMngrStatus.CurrentExtFlashJobReq)
        {
            bSectorIndex = 0;
            g_tExtFlashMngrStatus.CurrentExtFlashJobStatus = ExtFlsJobInit;
        }
        else
        {
            // do nothing - Wait for previous request to be completed
        }
    }
    else
    {
        switch(g_tExtFlashMngrStatus.CurrentExtFlashJobStatus)
        {
        case(ExtFlsJobInit):
            if(MEMIF_IDLE == Fls_GetStatus())
            {
                //Get Ext Flash characteristics
                bSectorNumber = Fls_MemConfig.ulFlsSectorListSize;
                ulSectorSize = Fls_MemConfig.ulFlsSectorSize;
                g_tExtFlashMngrStatus.CurrentExtFlashJobStatus = ExtFlsJobEraseSectorRequest;
            }
            else
            {
                // Do Nothing wait for memory operation to be completed
            }
            break;

        case(ExtFlsJobEraseSectorRequest):

            if(bSectorIndex < bSectorNumber)
            {
                tMemIfStatus = Fls_GetStatus();
                if(MEMIF_IDLE == tMemIfStatus)
                {
                    wcu_printf("Erase NvM sector %d - address 0x%x\n", bSectorIndex, Fls_MemConfig.pFlsSectorList[bSectorIndex].ulFlsSectorStartaddress);
                    retval = Fls_Erase(Fls_MemConfig.pFlsSectorList[bSectorIndex].ulFlsSectorStartaddress, ulSectorSize);
                    if(E_NOT_OK != retval)
                    {
                        bSectorIndex++;
                        g_tExtFlashMngrStatus.CurrentExtFlashJobStatus = ExtFlsJobCheckEraseRslt;
                    }
                    else
                    {
                        //request not accepted
                        bNumRefusedRequests++;
                        if(bNumRefusedRequests >= NUM_MAX_REFUSED_ERASE_REQUESTS)
                        {
                            wcu_printf("Erase request refused. Stopping NVM erase request\n");
                            bSectorIndex = 0;
                            g_tExtFlashMngrStatus.CurrentExtFlashJobStatus = ExtFlsJobFailed;
                            g_tExtFlashMngrStatus.CurrentExtFlashJobReq = ExtFlsJobReqNone;
                        }
                        else
                        {
                            // retry
                        }
                    }
                }
                else
                {
                    // Do Nothing wait for memory operation to be completed
                }
            }
            else
            {
                g_tExtFlashMngrStatus.CurrentExtFlashJobStatus = ExtFlsJobReInitMemoryStack;
            }
        break;

        case(ExtFlsJobCheckEraseRslt):
            tMemIfJobReslt = Fls_GetJobResult();
            tMemIfStatus = Fls_GetStatus() ;

            if(( MEMIF_IDLE == tMemIfStatus) && (MEMIF_JOB_OK == tMemIfJobReslt))
            {
                // Go back to request earse for the next sector
                g_tExtFlashMngrStatus.CurrentExtFlashJobStatus = ExtFlsJobEraseSectorRequest;
            }
            else if(( MEMIF_IDLE == tMemIfStatus) &&
                    ((MEMIF_JOB_FAILED == tMemIfJobReslt) || (MEMIF_JOB_CANCELED == tMemIfJobReslt) ||(MEMIF_BLOCK_INCONSISTENT == tMemIfJobReslt) || (MEMIF_BLOCK_INVALID == tMemIfJobReslt)))
            {
                wcu_printf("Erase sector %d failed - Fls Ctlr Error.\n",bSectorIndex);
                g_tExtFlashMngrStatus.CurrentExtFlashJobStatus = ExtFlsJobFailed;
            }
            else
            {
               //Do nothing memory is busy
            }
        break;


        case(ExtFlsJobReInitMemoryStack):
            wcu_printf("Erase NvM Complete - PowerCycle to ReInit Memory Stack\n");
            bSectorIndex = 0;
            g_tExtFlashMngrStatus.CurrentExtFlashJobStatus = ExtFlsJobCompleteOK;
            g_tExtFlashMngrStatus.CurrentExtFlashJobReq = ExtFlsJobReqNone;
            fnIosFlushTxQueue();
//            while(1)
//            {
//                fnIosResetMcu();
//            }
        break;


        case(ExtFlsJobFailed):
            wcu_printf("Erase NvM Failed - PowerCycle to ReInit Memory Stack\n");
            bSectorIndex = 0;
            g_tExtFlashMngrStatus.CurrentExtFlashJobStatus = ExtFlsJobFailed;
            g_tExtFlashMngrStatus.CurrentExtFlashJobReq = ExtFlsJobReqNone;
            fnIosFlushTxQueue();
//            while(1)
//            {
//                fnIosResetMcu();
//            }
        break;

        default:
            break;
        }
    }

}

//void fnIosTestFlashJobs(const uint8* bDataToProgram, uint32 ulDataToProgramLengthBytes)
//{
//
//    switch(g_tTestFlashJob)
//    {
//    case FlsJobNone:
//        break;
//
//    case FlsJobErase:
//        Fls_Erase(APP_START_ADDRESS, 0x1000);
//        g_tTestFlashJob = FlsJobNone;
//        break;
//
//    case FlsJobProgram:
//        Fls_Write(APP_START_ADDRESS, bDataToProgram, ulDataToProgramLengthBytes);
//        Fls_Compare(APP_START_ADDRESS, bDataToProgram, ulDataToProgramLengthBytes);
//        g_tTestFlashJob = FlsJobNone;
//        break;
//
//    default:
//        g_tTestFlashJob = FlsJobNone;
//        break;
//    }
//}
