#include  <stdio.h> 

#include "stm32f4xx.h"
#include "main.h"
// #include "config.h"
#include "elog.h"

#include "bsp_driver_sd.h"
#include "fatfs.h"

extern osSemaphoreId_t SD_lockHandle;
osSemaphoreId_t SD_lockHandle;
const osSemaphoreAttr_t SD_lock_attributes = {
    .name = "SD_lock"};

// osSemaphoreAcquire(SD_lockHandle, osWaitForever);
// osSemaphoreRelease(SD_lockHandle);
 
HAL_SD_CardInfoTypeDef  SDCardInfo;           
extern SD_HandleTypeDef hsd;
extern DMA_HandleTypeDef hdma_sdio_rx;
extern DMA_HandleTypeDef hdma_sdio_tx;
 
FATFS fs; //工作空间
FIL fil; // 文件项目

extern void printf_sdcard_info(void);
extern int Init_FatFas_Mount(void);
extern int creat_file(char * filename);
extern uint8_t BSP_SD_Init(void);
extern void SD_Test(  void);
extern void SD_Mount(  void);

uint8_t BSP_SD_Init(void)
{
  uint8_t sd_state = MSD_OK;
  /* Check if the SD card is plugged in the slot */
    osSemaphoreRelease(SD_lockHandle);
    osSemaphoreAcquire(SD_lockHandle, osWaitForever);
  if (BSP_SD_IsDetected() != SD_PRESENT)
  {
    return MSD_ERROR;
  }
  /* HAL SD initialization */
  sd_state = HAL_SD_Init(&hsd);
  /* Configure SD Bus width (4 bits mode selected) */
  if (sd_state == MSD_OK)
  {
        hsd.Init.ClockDiv = 10;
        // hsd.Init.ClockDiv = SDIO_TRANSFER_CLK_DIV;
    /* Enable wide operation */
    if (HAL_SD_ConfigWideBusOperation(&hsd, SDIO_BUS_WIDE_4B) != HAL_OK)
    {
      sd_state = MSD_ERROR;
    }
  }
    osSemaphoreRelease(SD_lockHandle);

  return sd_state;
}

void printf_sdcard_info(void)
{
	uint64_t CardCap;      	//SD卡容量
	HAL_SD_CardCIDTypeDef SDCard_CID; 
    char * card_type[8] = {0};

	HAL_SD_GetCardCID(&hsd,&SDCard_CID);	//获取CID
	HAL_SD_GetCardInfo(&hsd,&SDCardInfo);                    //获取SD卡信息
	CardCap=(uint64_t)(SDCardInfo.LogBlockNbr)*(uint64_t)(SDCardInfo.LogBlockSize);	//计算SD卡容量
	switch(SDCardInfo.CardType)
	{
		case CARD_SDSC:
		{
			if(SDCardInfo.CardVersion == CARD_V1_X)
            {
                memcpy(card_type, (void*)("SDSC V1"),7);
				// printf("Card Type:SDSC V1\r\n");
            }

			else  if (SDCardInfo.CardVersion == CARD_V2_X)
            {
                memcpy(card_type, (void*)("SDSC V2"),7);
				// printf("Card Type:SDSC V2\r\n");
            }
		    break;
		}

		case CARD_SDHC_SDXC:
        {
            memcpy(card_type, (void*)("SDHC"),4);
            // printf("Card Type:SDHC\r\n");
            break;
        }

		default:break;
	}	
#if 1		
    log_i("Card Type:           %s ",card_type);				//card 类型	
    log_i("Card ManufacturerID: %d ",SDCard_CID.ManufacturerID);				//制造商ID	
 	log_i("CardVersion:         %d ",(uint32_t)(SDCardInfo.CardVersion));		//卡版本号
	log_i("Class:               %d ",(uint32_t)(SDCardInfo.Class));		    //
 	log_i("Card RCA(RelCardAdd):%d ",SDCardInfo.RelCardAdd);					//卡相对地址
	log_i("Card BlockNbr:       %d ",SDCardInfo.BlockNbr);						//块数量
 	log_i("Card BlockSize:      %d ",SDCardInfo.BlockSize);					//块大小
	log_i("LogBlockNbr:         %d ",(uint32_t)(SDCardInfo.LogBlockNbr));		//逻辑块数量
	log_i("LogBlockSize:        %d ",(uint32_t)(SDCardInfo.LogBlockSize));		//逻辑块大小
	log_i("Card Capacity:       %d MB",(uint32_t)(CardCap>>20));				//卡容量
#endif
#if 0		
    printf("Card ManufacturerID: %d \r\n",SDCard_CID.ManufacturerID);				//制造商ID	
 	printf("CardVersion:         %d \r\n",(uint32_t)(SDCardInfo.CardVersion));		//卡版本号
	printf("Class:               %d \r\n",(uint32_t)(SDCardInfo.Class));		    //
 	printf("Card RCA(RelCardAdd):%d \r\n",SDCardInfo.RelCardAdd);					//卡相对地址
	printf("Card BlockNbr:       %d \r\n",SDCardInfo.BlockNbr);						//块数量
 	printf("Card BlockSize:      %d \r\n",SDCardInfo.BlockSize);					//块大小
	printf("LogBlockNbr:         %d \r\n",(uint32_t)(SDCardInfo.LogBlockNbr));		//逻辑块数量
	printf("LogBlockSize:        %d \r\n",(uint32_t)(SDCardInfo.LogBlockSize));		//逻辑块大小
	printf("Card Capacity:       %d MB\r\n",(uint32_t)(CardCap>>20));				//卡容量
#endif
}

int Init_FatFas_Mount(void)
{
    int retSD = f_mount(&fs, "0:", 1);
    return retSD;
}


/**
 * @brief  创建文件
 * @param [in] filename  "0:aa.txt"
 * 
 * @details  
 *          creat_file( "0:aa.txt" );
 */
int creat_file(char * filename)
{
    // f_mkfs( );
    int retSD = f_open(&fil, filename, FA_CREATE_ALWAYS | FA_WRITE); //打开文件，权限包括创建、写（如果没有该文件，会创建该文件）
    if(retSD==FR_OK) 
    {
        // printf("\r\ncreate file success!!! \r\n");
        // log_i("\r\ncreate file success!!! \r\n");
        f_close(&fil); //关闭该文件
        return retSD;
    }
    else 
    {
        // printf("\r\ncreater file error : %d\r\n",retSD);
        // log_i("\r\ncreater file error : %d\r\n",retSD);
        f_close(&fil); //关闭该文件
        return retSD;
    }
//    f_close(&fil); //关闭该文件
    // HAL_Delay(100);
}

void write_file( char * data, uint32_t len )
{
    uint32_t byteswritten;
    /*##-3- Write data to the text files ###############################*/
    int retSD = f_write(&fil, data, len, (void *)&byteswritten);
    if(retSD)
        printf(" write file error : %d\r\n",retSD);
    else
    {
        printf(" write file sucess!!! \r\n");
        printf(" write Data[%d] : %s\r\n",byteswritten,data);
    }
    /*##-4- Close the open text files ################################*/
    retSD = f_close(&fil);
    if(retSD)
        printf(" close error : %d\r\n",retSD);
    else
        printf(" close sucess!!! \r\n");
}

void SD_Read_block_Test(void)
{
    // uint8_t read_buf[512];	
    // int	sdcard_status = HAL_SD_ReadBlocks(&hsd, (uint8_t *)read_buf, 0, 1, 0xffff);
    // if(sdcard_status == HAL_OK)
    // { 
    //     printf("Read block data ok! \r\n");
    // }
    // else
    // {
    //     printf("Read block data fail! status = %d \r\n", sdcard_status);
    // }
}

void SD_Mount(  void)
{
        int res;
    res = BSP_SD_Init();
    if (res == 0 )
    {
        log_i(" BSP_SD_Init  ok  .. ");
    }
    else
    {
        log_i(" BSP_SD_Init failure.. " );
    }
    printf_sdcard_info( );
    res = Init_FatFas_Mount();
    if (res == 0 )
    {
        log_i(" mount success  .. ");
    }
    else
    {
        log_i(" mount failure.. res  %d",res);
    }
}

void SD_Test(  void)
{
        int res;
 
    printf_sdcard_info( );
 
    res = creat_file("0:aa.txt");
    if (res==0)
    {
        log_i(" create file success .. ");
    }
    else
    {
        log_i(" create file failure .. res : %d",res);
    }
}


void SDIO_IRQHandler(void)
{

    log_i(" SDIO_IRQHandler ..  sd status %d", hsd.State);
  HAL_SD_IRQHandler(&hsd);

}


void DMA2_Stream3_IRQHandler(void)
{

 
    log_i(" hdma_sdio_rx  it ..  sd status %d", hsd.State);
     hsd.State = HAL_SD_STATE_READY;
    HAL_DMA_IRQHandler(&hdma_sdio_rx);

}


void DMA2_Stream6_IRQHandler(void)
{

    log_i(" hdma_sdio_tx  it .. ");
    hsd.State = HAL_SD_STATE_READY;
    HAL_DMA_IRQHandler(&hdma_sdio_tx);

}




// void SDIO_IRQHandler(void)
// {

//   HAL_SD_IRQHandler(&hsd);

// }


// void DMA2_Stream3_IRQHandler(void)
// {

//   HAL_DMA_IRQHandler(&hdma_sdio_rx);

// }


// void DMA2_Stream6_IRQHandler(void)
// {

//   HAL_DMA_IRQHandler(&hdma_sdio_tx);

// }