#include "Internal_EEPROM.h"
#include "R_TypeDefs.h"
#include "R_FDL.h"
#include "FDL_Descriptor.h"
#include "R_EEL.h"
#include "EEL_Descriptor.h"
#include "target.h"
#include "fdl_user.h"
#include "rh850_macros.h"
r_eel_status_t reqStat;

// demo code
// for ( int i = 1; i < 65; i++ )
// {

//     for ( int i = 0; i < 128; i++ )
//     {
//         read [ i ]  = 0;
//         write [ i ] = i;
//     }
//     Internal_EEL_Write(i, write, 64);
//     Internal_EEL_Read(i, read, 64);
// }

extern r_eel_status_t EX_EE_INIT(void);
extern void           SampleApp_EEL_HdrLoop(r_eel_request_t *req);
extern void           SampleApp_EEL_ErrorHdr(r_eel_status_t stat);

void Internal_EEPROM_OPEN(void)
{
    FDL_Open( );
}

void Internal_EEPROM_CLOSE(void)
{
    FDL_Close( );
}

void Internal_EEL_Init(void)
{
    r_eel_request_t       myReq;
    r_eel_driver_status_t driverStatus;
    uint32_t              i;
    reqStat = EX_EE_INIT( );
    if ( R_EEL_ERR_POOL_INCONSISTENT == reqStat )
    {
        myReq.command_enu = R_EEL_CMD_FORMAT;
        R_EEL_Execute(&myReq);
        SampleApp_EEL_HdrLoop(&myReq);

        /* Format procedure ends with EEL re-init */
        reqStat = EX_EE_INIT( );
    }
    SampleApp_EEL_ErrorHdr(reqStat);
    /* ------------------------------------------------------------------------------------------
        Wait for fully operational and access unlock
       ------------------------------------------------------------------------------------------ */
    do
    {
        R_EEL_Handler( );
        R_EEL_GetDriverStatus(&driverStatus);
    }
    /* Wait until the system is completely up and running (or error) */
    while ( R_EEL_OPERATION_STARTUP == driverStatus.operationStatus_enu );
}

r_eel_status_t Internal_EEL_Write(uint16_t blockID, uint8_t pbuf [], uint32_t length)
{
    r_eel_request_t myReq;
    // disable_interrupt( );
    Internal_EEPROM_OPEN( );
    Internal_EEL_Init( );
    myReq.address_pu08   = ( uint8_t * )(&pbuf [ 0 ]);
    myReq.identifier_u16 = blockID;
    myReq.command_enu    = R_EEL_CMD_WRITE;
    R_EEL_Execute(&myReq);
    SampleApp_EEL_HdrLoop(&myReq);
    Internal_EEL_DEINIT( );
    Internal_EEPROM_CLOSE( );
    // enable_interrupt( );
    return myReq.status_enu;
}

r_eel_status_t Internal_EEL_Read(uint8_t blockID, uint8_t pbuf [], uint32_t length)
{
    r_eel_request_t myReq;
    // disable_interrupt( );
    Internal_EEPROM_OPEN( );
    Internal_EEL_Init( );
    myReq.address_pu08   = ( uint8_t * )(&pbuf [ 0 ]);
    myReq.identifier_u16 = blockID;
    myReq.length_u16     = length;
    myReq.offset_u16     = 0x00u;
    myReq.command_enu    = R_EEL_CMD_READ;
    R_EEL_Execute(&myReq);
    SampleApp_EEL_HdrLoop(&myReq);
    Internal_EEL_DEINIT( );
    Internal_EEPROM_CLOSE( );
    // enable_interrupt( );
    return myReq.status_enu;
}

void Internal_EEL_DEINIT(void)
{
    r_eel_driver_status_t driverStatus;

    reqStat = R_EEL_ShutDown( );
    SampleApp_EEL_ErrorHdr(reqStat);

    do
    {
        R_EEL_Handler( );
        R_EEL_GetDriverStatus(&driverStatus);
    } while ( R_EEL_OPERATION_PASSIVE != driverStatus.operationStatus_enu );

    /* Error check of startup processing (with and without Format) */
    SampleApp_EEL_ErrorHdr(driverStatus.backgroundStatus_enu);
}