/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs     (C)ChaN, 2007        */
/*-----------------------------------------------------------------------*/
/* This is a stub disk I/O module that acts as front end of the existing */
/* disk I/O modules and attach it to FatFs module with common interface. */
/*-----------------------------------------------------------------------*/

#include "diskio.h"
#include "at32f403a_407.h"
#include "ffconf.h"
//#include "systick.h"

//#include "usbh_mcs_fatfs.h"
#include "drivers/fatfs_spi_flash.h"

/*-----------------------------------------------------------------------*/
/* Correspondence between physical drive number and physical drive.      */
/*-----------------------------------------------------------------------*/

#define SECTOR_SIZE 512

/*-----------------------------------------------------------------------*/
/* Inidialize a Drive                                                    */
/*-----------------------------------------------------------------------*/

DSTATUS disk_initialize (
	BYTE drv				/* Physical drive nmuber (0..) */
)
{
    /* Set NOINIT bit */
    int res = STA_NOINIT;

    switch (drv) {
    case ATA:
        break;

    case MMC:
        break;

    case SD:
        break;
    case SPI_FLASH:
        res = ff_spi_flash_init();
        break;
    }
    return (DSTATUS)res;
}



/*-----------------------------------------------------------------------*/
/* Return Disk Status                                                    */
/*-----------------------------------------------------------------------*/

DSTATUS disk_status (
	BYTE drv		/* Physical drive nmuber (0) */
)
{

//  if (drv) return STA_NOINIT;		/* Supports only single drive */
//  return 0;

    DSTATUS stat = 0;
    //int result;

    switch (drv) {
    case ATA :
        //result = ATA_disk_status();

        // translate the reslut code here

        return stat;

    case MMC :
        //result = MMC_disk_status();

        // translate the reslut code here

        return stat;

    case SD :
        //result = SD_disk_status();

        // translate the reslut code here

        return stat;

    case SPI_FLASH :
        //result = USB_disk_status();

        // translate the reslut code here

        return stat;
    }
    return STA_NOINIT;
}


/*-----------------------------------------------------------------------*/
/* Read Sector(s)                                                        */
/*-----------------------------------------------------------------------*/

DRESULT disk_read (
	BYTE drv,		/* Physical drive nmuber (0..) */
	BYTE *buff,		/* Data buffer to store read data */
	DWORD sector,	/* Sector address (LBA) */
	UINT count		/* Number of sectors to read (1..255) */
)
{
    DRESULT res = RES_NOTRDY;

    switch (drv) {
    case ATA:
        break;

    case MMC:
        break;

    case SD:
        break;

    case SPI_FLASH:

        //DBG start_time_meas(); /* Debug measure of function calls duration */

        res = (DRESULT)ff_spi_flash_read(buff, sector,  count);

        //DBG printf("\tSPI read sector: %dus\r\n",  stop_time_meas());

        break;
    }

    return res;
}



/*-----------------------------------------------------------------------*/
/* Write Sector(s)                                                       */
/*-----------------------------------------------------------------------*/
/* The FatFs module will issue multiple sector transfer request
/  (count > 1) to the disk I/O layer. The disk function should process
/  the multiple sector transfer properly Do. not translate it into
/  multiple single sector transfers to the media, or the data read/write
/  performance may be drasticaly decreased. */

#if _READONLY == 0
DRESULT disk_write (
	BYTE drv,			/* Physical drive nmuber (0..) */
	const BYTE *buff,	/* Data to be written */
	DWORD sector,		/* Sector address (LBA) */
	UINT count			/* Number of sectors to write (1..255) */
)
{
   DRESULT res = RES_NOTRDY;

   switch (drv) {
   case ATA:
       break;

   case MMC:
       break;

   case SD:
       break;

   case SPI_FLASH:

       //DBG start_time_meas(); /* Debug measure of function calls duration */

       res = (DRESULT)ff_spi_flash_write(buff, sector, count);

       //DBG printf("\tSPI write sector: %dus\r\n",  stop_time_meas());

       break;
   }

   return res;
}
#endif /* _READONLY */

/*-----------------------------------------------------------------------*/
/* Get current time                                                      */
/*-----------------------------------------------------------------------*/

DWORD get_fattime ()
{
  return ((2006UL-1980) << 25)	      // Year = 2006
          | (2UL << 21)	      // Month = Feb
          | (9UL << 16)	      // Day = 9
          | (22U << 11)	      // Hour = 22
          | (30U << 5)	      // Min = 30
          | (0U >> 1)	      // Sec = 0
          ;
}

/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions                                               */
/*-----------------------------------------------------------------------*/

DRESULT disk_ioctl (
	BYTE drv,		/* Physical drive nmuber (0..) */
	BYTE ctrl,		/* Control code */
	void *buff		/* Buffer to send/receive control data */
)
{
  DRESULT res = RES_OK;

  switch (drv) {
    case ATA:
        break;

    case MMC:
        break;

    case SD:
        break;

    case SPI_FLASH:
        switch (ctrl) {
          case GET_SECTOR_COUNT :   // Get number of sectors on the disk (DWORD)
            *(DWORD*)buff = SPI_FLASH_BLOCK_SIZE * SPI_FLASH_BLOCK_NUMBER;
            res = RES_OK;
            break;

          case GET_SECTOR_SIZE :    // Get R/W sector size (WORD)
            *(WORD*)buff = SPI_FLASH_SECTOR_SIZE;
            res = RES_OK;
            break;

          case GET_BLOCK_SIZE :       // Get erase block size in unit of sector (DWORD)
            *(DWORD*)buff = SPI_FLASH_SECTORS_IN_BLOCK_NUMBER;
            res = RES_OK;
            break;
        }
        break;
    }

  return res;
}
