/*
 * SD Card Driver for SPI Interface
 * Shares SPI bus with ST7796 display
 * 
 * Supports standard SD/SDHC cards using SPI mode
 */

#ifndef SD_CARD_H
#define SD_CARD_H

#include "pico/stdlib.h"
#include "hardware/spi.h"

#ifdef __cplusplus
extern "C" {
#endif

// SD Card Commands (SPI mode)
#define SD_CMD0     0   // GO_IDLE_STATE
#define SD_CMD8     8   // SEND_IF_COND
#define SD_CMD9     9   // SEND_CSD
#define SD_CMD10    10  // SEND_CID
#define SD_CMD12    12  // STOP_TRANSMISSION
#define SD_CMD13    13  // SEND_STATUS
#define SD_CMD16    16  // SET_BLOCKLEN
#define SD_CMD17    17  // READ_SINGLE_BLOCK
#define SD_CMD18    18  // READ_MULTIPLE_BLOCK
#define SD_CMD24    24  // WRITE_BLOCK
#define SD_CMD25    25  // WRITE_MULTIPLE_BLOCK
#define SD_CMD55    55  // APP_CMD
#define SD_CMD58    58  // READ_OCR
#define SD_ACMD41   41  // SD_SEND_OP_COND (APP_CMD)

// SD Card Response Tokens
#define SD_R1_IDLE_STATE    0x01
#define SD_R1_READY         0x00
#define SD_START_TOKEN      0xFE
#define SD_DATA_ACCEPTED    0x05

// SD Card Types
#define SD_CARD_TYPE_SD1    1
#define SD_CARD_TYPE_SD2    2
#define SD_CARD_TYPE_SDHC   3

// Block size
#define SD_BLOCK_SIZE       512

// Configuration structure
typedef struct {
    spi_inst_t *spi;
    uint gpio_cs;
    uint gpio_miso;  // Should match display MISO
    uint gpio_mosi;  // Should match display MOSI
    uint gpio_sck;   // Should match display SCK
} sd_card_config_t;

// Card information structure
typedef struct {
    uint8_t type;
    uint32_t capacity_mb;
    bool initialized;
} sd_card_info_t;

/**
 * Initialize the SD card
 * @param config Configuration structure
 * @return true if successful, false otherwise
 */
bool sd_card_init(const sd_card_config_t *config);

/**
 * Initialize the SD card with board-specific configuration
 * Uses pin definitions from board_config.h automatically
 * @return true if successful, false otherwise
 */
bool sd_card_init_with_board_config(void);

/**
 * Get card information
 * @param info Pointer to info structure to fill
 * @return true if successful, false otherwise
 */
bool sd_card_get_info(sd_card_info_t *info);

/**
 * Read a single block from the SD card
 * @param block_addr Block address (in blocks, not bytes)
 * @param buffer Buffer to read into (must be at least 512 bytes)
 * @return true if successful, false otherwise
 */
bool sd_card_read_block(uint32_t block_addr, uint8_t *buffer);

/**
 * Read multiple blocks from the SD card
 * @param block_addr Starting block address
 * @param num_blocks Number of blocks to read
 * @param buffer Buffer to read into (must be at least num_blocks * 512 bytes)
 * @return true if successful, false otherwise
 */
bool sd_card_read_blocks(uint32_t block_addr, uint32_t num_blocks, uint8_t *buffer);

/**
 * Write a single block to the SD card
 * @param block_addr Block address (in blocks, not bytes)
 * @param buffer Buffer containing data to write (must be 512 bytes)
 * @return true if successful, false otherwise
 */
bool sd_card_write_block(uint32_t block_addr, const uint8_t *buffer);

/**
 * Write multiple blocks to the SD card
 * @param block_addr Starting block address
 * @param num_blocks Number of blocks to write
 * @param buffer Buffer containing data to write (must be num_blocks * 512 bytes)
 * @return true if successful, false otherwise
 */
bool sd_card_write_blocks(uint32_t block_addr, uint32_t num_blocks, const uint8_t *buffer);

/**
 * Erase blocks on the SD card
 * @param start_block Starting block address
 * @param end_block Ending block address
 * @return true if successful, false otherwise
 */
bool sd_card_erase_blocks(uint32_t start_block, uint32_t end_block);

/**
 * Check if card is present and initialized
 * @return true if card is ready, false otherwise
 */
bool sd_card_is_ready(void);

/**
 * Test SD card and FatFS functionality
 * Performs comprehensive tests including filesystem mount, directory listing,
 * and file read/write operations. Safely unmounts filesystem after testing.
 * @return true if all tests pass, false otherwise
 */
bool sd_card_test_fatfs(void);

#ifdef __cplusplus
}
#endif

#endif // SD_CARD_H
