#ifndef _GW3323_SDIO_H
#define _GW3323_SDIO_H

#include "include.h"

//--------------- SDIO Flag Definition ---------------//
#define SDIO_FLAG_CMD_FINISH            ((uint32_t)0x00001000)
#define SDIO_FLAG_DATA_FINISH           ((uint32_t)0x00002000)
#define SDIO_FLAG_CMD_CRC_ERROR         ((uint32_t)0x00004000)
#define SDIO_FLAG_NO_RESPONSE           ((uint32_t)0x00008000)
#define SDIO_FLAG_DATA_CRC_ERROR        ((uint32_t)0x00010000)
#define SDIO_FLAG_BUSY                  ((uint32_t)0x00100000)

//----------------- SDIO CMD DEFINITION -----------------//
#define SDIO_CK8_EN                     ((uint32_t)0x00000800)
#define SDIO_CCBUSY_EN                  ((uint32_t)0x00000400)
#define SDIO_CMD_RSPEN                  ((uint32_t)0x00000100)

//----------------- SDIO Response Registers -----------------//
#define SDIO_RESP1                      ((uint32_t)0x00000000)
#define SDIO_RESP2                      ((uint32_t)0x00000004)
#define SDIO_RESP3                      ((uint32_t)0x00000008)
#define SDIO_RESP4                      ((uint32_t)0x0000000C)

//----------------- SDIO DMACNT Registers -----------------//
#define SDIO_DMA_WRD                    ((uint32_t)0x00010000)
#define SDIO_DMA_CDBUSY_EN              ((uint32_t)0x00020000)
#define SDIO_DMA_CK8_EN                 ((uint32_t)0x00040000)

//SDIO cmd edge selection enumeration
typedef enum {
    SDIO_OUTEDGE_FALLING      = 0x00,
    SDIO_OUTEDGE_RISING       = 0x04,
} SDIO_OUTEDGE_TYPEDEF;

//SDIO data width enumeration
typedef enum {
    SDIO_DWTH_1BIT        = 0x00,
    SDIO_DWTH_4BIT        = 0x02,
} SDIO_DWTH_TYPEDEF;

//SDIO clk idle state enumeration
typedef enum {
    SDIO_CLK_IDLE_STA_LOW         = 0x000,
    SDIO_CLK_IDLE_STA_HIGH        = 0x400,
} SDIO_CLK_IDLE_STA_TYPEDEF;

//SDIO long response enumeration
typedef enum {
    SDIO_RESPONSE_NO            = 0x0000,
    SDIO_RESPONSE_SHORT         = 0x0100,
    SDIO_RESPONSE_LONG          = 0x0300,
} SDIO_RESPONSE_TYPEDEF;

//SDIO crc status for sent data enumeration
typedef enum {
    SDIO_SEND_DATA_CRC_STA_OK          = 0x02,
    SDIO_SEND_DATA_CRC_STA_ERROR       = 0x05,
    SDIO_SEND_DATA_CRC_STA_FLASH_ERROR = 0x07,
} SDIO_SEND_DATA_CRC_STA_TYPEDEF;

//SDIO cmd_init structure
typedef struct{
    SDIO_RESPONSE_TYPEDEF rsp_type;
    FLAG_STATE ccbusy_en;
    FLAG_STATE ck8_en;
    uint8_t cmd_index;
    uint32_t argument;
} sdio_cmd_init_typedef;

//SDIO init structure
typedef struct{
    SDIO_OUTEDGE_TYPEDEF out_edge;
    SDIO_DWTH_TYPEDEF  dwth;
    uint8_t            baud;
} sdio_init_typedef;

void sdio_init(sdio_init_typedef* sdio_init_struct);
void sdio_cmd(FUNCTIONAL_STATE state);
void sdio_set_baud(uint8_t baud);
void sdio_clk_keep_out_cmd(FUNCTIONAL_STATE state);
void sdio_cmd_it_cmd(FUNCTIONAL_STATE state);
void sdio_data_it_cmd(FUNCTIONAL_STATE state);
void sdio_clk_idle_sta_sel(SDIO_CLK_IDLE_STA_TYPEDEF idle_sta);
FLAG_STATE sdio_get_flag(uint32_t sdio_flag);
void sdio_clear_flag(uint32_t sdio_flag);
void sdio_send_command(sdio_cmd_init_typedef *sdio_cmd_init_struct);
uint8_t sdio_get_cmd_response(void);
uint32_t sdio_get_response(uint32_t sdio_resp);
uint8_t sdio_get_send_data_crc_sta(void);
void sdio_read_data(void *buf, uint16_t len);
void sdio_write_data(void *buf, uint16_t len);
void sdio_set_dma_cnt( uint16_t cnt);
void sdio_set_dma_addr(uint32_t *addr);
#endif