#include "hal_fatfs.h"
#include "ff.h"
#include "diskio_blkdev.h"
#include "nrf_block_dev_sdc.h"

#define FILE_NAME   "IMU.TXT"
#define TEST_STRING "SD card example."

#define SDC_SCK_PIN     SPI_SCK_PIN  ///< SDC serial clock (SCK) pin.
#define SDC_MOSI_PIN    SPI_MOSI_PIN  ///< SDC serial data in (DI) pin.
#define SDC_MISO_PIN    SPI_MISO_PIN  ///< SDC serial data out (DO) pin.
#define SDC_CS_PIN      SPI_SS_PIN  ///< SDC chip select (CS) pin.


static FATFS fs;
static DIR dir;
static FILINFO fno;
static FIL file;
	
/**
 * @brief  SDC block device definition
 * */
NRF_BLOCK_DEV_SDC_DEFINE(
        m_block_dev_sdc,
        NRF_BLOCK_DEV_SDC_CONFIG(
                SDC_SECTOR_SIZE,
                APP_SDCARD_CONFIG(SDC_MOSI_PIN, SDC_MISO_PIN, SDC_SCK_PIN, SDC_CS_PIN)
         ),
         NFR_BLOCK_DEV_INFO_CONFIG("Nordic", "SDC", "1.00")
);

uint32_t FATFS_WriteString(char * p)
{
	uint32_t bytes_written;
	
    if (f_write(&file, (char *)p, strlen(p), (UINT *) &bytes_written) == FR_OK){f_sync(&file); return bytes_written;} //success
    SEGGER_RTT_printf(0,"FATFS_WriteString fail");
	return 0; //fail
}

uint32_t FATFS_WriteBuff_8b(uint8_t * p,uint32_t len)
{
	uint32_t bytes_written;
	
    if (f_write(&file, (uint8_t *)p, len, (UINT *) &bytes_written) == FR_OK){ return bytes_written;} //success
    else return 0; //fail
}
void FATFS_CloseFile(void)
{
//	FRESULT ff_result;
//	ff_result = f_mount(NULL, "", 1);
//    if (ff_result)
//    {
//       SEGGER_RTT_printf(0,"Umount failed.\n");
//    }
	f_close(&file);
}
void FATFS_OpenFile(char * filename)
{
	FRESULT ff_result;
	SEGGER_RTT_printf(0,"\r\n Listing directory: /\n");
    ff_result = f_opendir(&dir, "/");
    if (ff_result)
    {
       SEGGER_RTT_printf(0,"Directory listing failed!\n");
        return;
    }

    do
    {
        ff_result = f_readdir(&dir, &fno);
        if (ff_result != FR_OK)
        {
           SEGGER_RTT_printf(0,"Directory read failed.\n");
            return;
        }

        if (fno.fname[0])
        {
            if (fno.fattrib & AM_DIR)
            {
               SEGGER_RTT_printf(0,"   <DIR>   %s\n",(uint32_t)fno.fname);
            }
            else
            {
                SEGGER_RTT_printf(0,"%9lu  %s\n", fno.fsize, (uint32_t)fno.fname);
            }
        }
    }
    while (fno.fname[0]);
    SEGGER_RTT_printf(0,"\n");

   SEGGER_RTT_printf(0,"Writing to file %s ...\n",filename);
    ff_result = f_open(&file, filename, FA_READ | FA_WRITE | FA_CREATE_ALWAYS);
    if (ff_result != FR_OK)
    {
       SEGGER_RTT_printf(0,"Unable to open or create file:%s.\n",filename);
        return;
    }
}

void FATFS_Init(void)
{
	FRESULT ff_result;
    
    DSTATUS disk_state = STA_NOINIT;

	SEGGER_RTT_printf(0,"FATFS example started.\n");
    // Initialize FATFS disk I/O interface by providing the block device.
    static diskio_blkdev_t drives[] =
    {
            DISKIO_BLOCKDEV_CONFIG(NRF_BLOCKDEV_BASE_ADDR(m_block_dev_sdc, block_dev), NULL)
    };

    diskio_blockdev_register(drives, ARRAY_SIZE(drives));

   SEGGER_RTT_printf(0,"Initializing disk 0 (SDC)...\n");
    for (uint32_t retries = 3; retries && disk_state; --retries)
    {
        disk_state = disk_initialize(0);
    }
    if (disk_state)
    {
       SEGGER_RTT_printf(0,"Disk initialization failed.\n");
        return;
    }

    uint32_t blocks_per_mb = (1024uL * 1024uL) / m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_size;
    uint32_t capacity = m_block_dev_sdc.block_dev.p_ops->geometry(&m_block_dev_sdc.block_dev)->blk_count / blocks_per_mb;
   SEGGER_RTT_printf(0,"Capacity: %d MB\n", capacity);

   SEGGER_RTT_printf(0,"Mounting volume...\n");
    ff_result = f_mount(&fs, "", 1);
    if (ff_result)
    {
//       SEGGER_RTT_printf(0,"Mount failed.\n");
		SEGGER_RTT_printf(0,"Umounting volume...\n");
		ff_result = f_mount(NULL, "", 1);
		if (ff_result) SEGGER_RTT_printf(0,"Umount failed.\n");
		ff_result = f_mount(&fs, "", 1);
		if (ff_result) SEGGER_RTT_printf(0,"Mount failed.\n");
    }
}



