/*******************************************************************************
  MPLAB Harmony Application Source File

  Company:
    Microchip Technology Inc.

  File Name:
    app_drv_sdcard.c

  Summary:
    This file contains the source code for the MPLAB Harmony application.

  Description:
    This file contains the source code for the MPLAB Harmony application.  It
    implements the logic of the application's state machine and it may call
    API routines of other MPLAB Harmony modules in the system, such as drivers,
    system services, and middleware.  However, it does not call any of the
    system interfaces (such as the "Initialize" and "Tasks" functions) of any of
    the modules in the system or make any assumptions about when those functions
    are called.  That is the responsibility of the configuration-specific system
    files.
 *******************************************************************************/

// *****************************************************************************
// *****************************************************************************
// Section: Included Files
// *****************************************************************************
// *****************************************************************************

#include "app_drv_sdcard.h"
#include "app_drv_usart1.h"
#include "driver/sdspi/drv_sdspi.h"
#include <stdio.h>
#include <string.h>

// *****************************************************************************
// *****************************************************************************
// Section: Global Data Definitions
// *****************************************************************************
// *****************************************************************************
#define SDCARD_BLOCK_START                 0x2000
#define SDCARD_BUFFER_SIZE                 (4096U)
#define SDCARD_GEOMETRY_TABLE_READ_ENTRY   (0)
#define SDCARD_GEOMETRY_TABLE_WRITE_ENTRY  (1)
#define SDCARD_GEOMETRY_TABLE_ERASE_ENTRY  (2)
SYS_MEDIA_GEOMETRY *SDCardGeometry = NULL;
int SDCardReadBlocks;
int SDCardWriteBlocks;
int SDCardEraseBlocks;

DRV_HANDLE SDCardHandle;
DRV_SDSPI_COMMAND_HANDLE SDCardReadHandle;
DRV_SDSPI_COMMAND_HANDLE SDCardWriteHandle;
volatile int SDCardWriteComplete = false;
volatile int SDCardReadComplete = false;
char SDCardWriteBuf[SDCARD_BUFFER_SIZE];
char SDCardReadBuf[SDCARD_BUFFER_SIZE];
int SDCardResetCount = 1;

// *****************************************************************************
/* Application Data

  Summary:
    Holds application data

  Description:
    This structure holds the application's data.

  Remarks:
    This structure should be initialized by the APP_DRV_SDCARD_Initialize function.

    Application strings and buffers are be defined outside this structure.
*/

APP_DRV_SDCARD_DATA app_drv_sdcardData;

// *****************************************************************************
// *****************************************************************************
// Section: Application Callback Functions
// *****************************************************************************
// *****************************************************************************
void SDCardTransferHandler( SYS_MEDIA_BLOCK_EVENT event, SYS_MEDIA_BLOCK_COMMAND_HANDLE commandHandle, uintptr_t context )
{
    switch( event )
    {
    case SYS_MEDIA_EVENT_BLOCK_COMMAND_COMPLETE:
        if     (commandHandle == SDCardReadHandle)
        { SDCardReadComplete = true; }
        else if(commandHandle == SDCardWriteHandle)
        { SDCardWriteComplete = true; }
        break;

    case SYS_MEDIA_EVENT_BLOCK_COMMAND_ERROR:
        app_drv_sdcardData.state = APP_DRV_SDCARD_STATE_ERROR;
        break;
    }
}

// *****************************************************************************
// *****************************************************************************
// Section: Application Local Functions
// *****************************************************************************
// *****************************************************************************


/* TODO:  Add any necessary local functions.
*/


// *****************************************************************************
// *****************************************************************************
// Section: Application Initialization and State Machine Functions
// *****************************************************************************
// *****************************************************************************

/*******************************************************************************
  Function:
    void APP_DRV_SDCARD_Initialize ( void )

  Remarks:
    See prototype in app_drv_sdcard.h.
 */

void APP_DRV_SDCARD_Initialize ( void )
{
    /* Place the App state machine in its initial state. */
    app_drv_sdcardData.state = APP_DRV_SDCARD_STATE_INIT;



    /* TODO: Initialize your application's state machine and other
     * parameters.
     */
}


/******************************************************************************
  Function:
    void APP_DRV_SDCARD_Tasks ( void )

  Remarks:
    See prototype in app_drv_sdcard.h.
 */

void APP_DRV_SDCARD_Tasks ( void )
{
    switch ( app_drv_sdcardData.state )
    {
    case APP_DRV_SDCARD_STATE_INIT:
        SDCardHandle = DRV_SDSPI_Open(DRV_SDSPI_INDEX_0, DRV_IO_INTENT_READWRITE);
        if(SDCardHandle == DRV_HANDLE_INVALID)
        {
            app_drv_sdcardData.state = APP_DRV_SDCARD_STATE_ERROR;
            break;
        }

        DRV_SDSPI_EventHandlerSet(SDCardHandle, SDCardTransferHandler, 0);

        app_drv_sdcardData.state = APP_DRV_SDCARD_STATE_WAIT_ATTACH;
        break;

    case APP_DRV_SDCARD_STATE_WAIT_ATTACH:
        if( DRV_SDSPI_IsAttached(SDCardHandle) == false )
            break;
		
        USART1printf("\r\nSDCard attached!\r\n");
		
        SDCardGeometry = DRV_SDSPI_GeometryGet(SDCardHandle);
        if (SDCardGeometry == NULL)
        {
            app_drv_sdcardData.state = APP_DRV_SDCARD_STATE_ERROR;
            break;
        }
        SDCardReadBlocks  = (SDCARD_BUFFER_SIZE / SDCardGeometry->geometryTable[SDCARD_GEOMETRY_TABLE_READ_ENTRY].blockSize);
        SDCardWriteBlocks = (SDCARD_BUFFER_SIZE / SDCardGeometry->geometryTable[SDCARD_GEOMETRY_TABLE_WRITE_ENTRY].blockSize);
        SDCardEraseBlocks = (SDCARD_BUFFER_SIZE / SDCardGeometry->geometryTable[SDCARD_GEOMETRY_TABLE_ERASE_ENTRY].blockSize);
		
        app_drv_sdcardData.state = APP_DRV_SDCARD_STATE_READ;
        break;
        
    case APP_DRV_SDCARD_STATE_READ:
        DRV_SDSPI_AsyncRead(SDCardHandle, &SDCardReadHandle, SDCardReadBuf, SDCARD_BLOCK_START, SDCardReadBlocks);
        if(SDCardReadHandle == DRV_SDSPI_COMMAND_HANDLE_INVALID)
        {
            app_drv_sdcardData.state = APP_DRV_SDCARD_STATE_ERROR;
            break;
        }

        app_drv_sdcardData.state = APP_DRV_SDCARD_STATE_READ_WAIT_COMPLETE;
        break;
        
    case APP_DRV_SDCARD_STATE_READ_WAIT_COMPLETE:
        if(SDCardReadComplete == true)
        {
            SDCardReadComplete = false;

            if( !strncmp((char*)SDCardReadBuf, "Count SDCard: ", 14) )
            {
                USART1printf("%s\r\n", SDCardReadBuf);
                sscanf(SDCardReadBuf, "Count SDCard: %d", &SDCardResetCount);
                SDCardResetCount = (SDCardResetCount+1)%10;
            }
            else
            {
                USART1printf("Geometry SDCard: Buff(%d), R(%d), W(%d), E(%d)\r\n",
                                  SDCARD_BUFFER_SIZE, SDCardReadBlocks, SDCardWriteBlocks, SDCardEraseBlocks);
            }

            app_drv_sdcardData.state = APP_DRV_SDCARD_STATE_WRITE;				
        }
        break;
        
    case APP_DRV_SDCARD_STATE_WRITE:
        sprintf( SDCardWriteBuf, "Count SDCard: %d", SDCardResetCount);
        DRV_SDSPI_AsyncWrite(SDCardHandle, &SDCardWriteHandle, SDCardWriteBuf, SDCARD_BLOCK_START, SDCardWriteBlocks);

        if(SDCardWriteHandle == DRV_SDSPI_COMMAND_HANDLE_INVALID)
        {
            app_drv_sdcardData.state = APP_DRV_SDCARD_STATE_ERROR;
        }
        else
        {
            app_drv_sdcardData.state = APP_DRV_SDCARD_STATE_WRITE_WAIT_COMPLETE;
        }
        break;
        
    case APP_DRV_SDCARD_STATE_WRITE_WAIT_COMPLETE:
        if(SDCardWriteComplete == true)
        {
            SDCardWriteComplete = false;

            DRV_SDSPI_Close( SDCardHandle );

            app_drv_sdcardData.state = APP_DRV_SDCARD_STATE_IDLE;
        }
        break;

    case APP_DRV_SDCARD_STATE_ERROR:
        USART1printf("DRV_SDCARD error!\r\n");

        app_drv_sdcardData.state = APP_DRV_SDCARD_STATE_IDLE;
        break;

    case APP_DRV_SDCARD_STATE_IDLE:
        break;
    }
}


/*******************************************************************************
 End of File
 */
