#include <hardware/spi.h>
#include <stdio.h>
#include <ff.h>
#include <diskio.h>
#include "spi.h"
#include "sdcard.h"

// pins
#define SD_PIN_SCLK  18
#define SD_PIN_MOSI  19
#define SD_PIN_MISO  16
#define SD_PIN_CSN   17

sdcard_t sd13 = {
    .pin_cs = 13,
    .spi    = spi0,
    .initialized = false,
};

DSTATUS
disk_initialize(BYTE pdrv) {
    spi_cs_init(13);
    spi_pins_init(SD_PIN_SCLK, SD_PIN_MOSI, SD_PIN_MISO);
    spi_init(spi0, 300000);

    sd_init(&sd13);
    return 0;
}

DSTATUS
disk_status(BYTE pdrv) {
    return sd13.initialized ? 0 : STA_NOINIT;
}

DRESULT
disk_read(BYTE pdrv, BYTE *buff, LBA_t sector, UINT count) {
    printf("====== R %d + %d.\n", (int)sector, (int)count);
    for (UINT i=0 ; i<count ; ++i) {
        printf("disk_read block %d\n", sector + i);
        sd_read_block(&sd13, buff, sector + i);
        buff += 512;
    }
    return RES_OK;
}

DRESULT
disk_write(BYTE pdrv, const BYTE* buff, LBA_t sector, UINT count) {
    printf("====== W %d + %d.\n", (int)sector, (int)count);
    for (UINT i=0 ; i<count ; ++i) {
        printf("disk_write block %d\n", sector + i);
        sd_write_block(&sd13, buff, sector + i);
        buff += 512;
    }
    return RES_OK;
}

DRESULT
disk_ioctl(BYTE pdrv, BYTE cmd, void *buff) {
    switch (cmd) {
        case GET_SECTOR_COUNT:
            *(LBA_t*)buff = sd_is_hc(&sd13) ? sd_size_byte(&sd13) << 9 : sd_size_byte(&sd13);
            break;
        case GET_SECTOR_SIZE:
        case GET_BLOCK_SIZE:
            *(WORD*)buff = sd_is_hc(&sd13) ? 1 << 9 : 1;
            break;
        default:
            break;
    }

    return RES_OK;
}
