#include "flash_iface_bf609.h"
#include "chip.h"
#include <string.h>


#define SPI_FIFO_SIZE 8
#define SPI_FIFO_RX_RDY(stat)  !(stat & BITM_SPI_STAT_RFE)

#include "../shared/flash_iface_spi_fifo.inc"

typedef struct {
    t_flash_iface_spi_fifo_data fifo;
    unsigned spi_port;
    unsigned cs_pin;    
} t_flash_iface_spi_data;

static t_flash_iface_spi_data f_spi_data;



static t_flash_errs f_select(t_flash_iface *iface, size_t total_size) {
    t_flash_iface_spi_data *spi_data = (t_flash_iface_spi_data *)iface->port_data;
    CHIP_PIN_OUT(spi_data->cs_pin, 0);
    spi_fifo_drop(iface);
    csync();
    return 0;
}

static t_flash_errs f_unselect(t_flash_iface *iface) {
    t_flash_iface_spi_data *spi_data = (t_flash_iface_spi_data *)iface->port_data;
    CHIP_PIN_OUT(spi_data->cs_pin, 1);
    return 0;
}


t_flash_errs flash_iface_init_bf609_spi(t_flash_iface *iface, unsigned spi_port, unsigned cs_pin) {
    int err = iface==NULL ? FLASH_ERR_INVALID_PARAMS : 0;
    if (!err) {
        t_flash_iface_spi_data *spi_data = &f_spi_data;
        if (spi_port==0) {
            spi_data->fifo.tx_reg = pREG_SPI0_TFIFO;
            spi_data->fifo.rx_reg = pREG_SPI0_RFIFO;
            spi_data->fifo.st_reg = pREG_SPI0_STAT;

            CHIP_PIN_CONFIG(CHIP_PIN_PD02_SPI0_MISO);
            CHIP_PIN_CONFIG(CHIP_PIN_PD03_SPI0_MOSI);
            CHIP_PIN_CONFIG(CHIP_PIN_PD04_SPI0_CLK);
        } else if (spi_port==1)  {
            spi_data->fifo.tx_reg = pREG_SPI1_TFIFO;
            spi_data->fifo.rx_reg = pREG_SPI1_RFIFO;
            spi_data->fifo.st_reg = pREG_SPI1_STAT;

            CHIP_PIN_CONFIG(CHIP_PIN_PD14_SPI1_MISO);
            CHIP_PIN_CONFIG(CHIP_PIN_PD13_SPI1_MOSI);
            CHIP_PIN_CONFIG(CHIP_PIN_PD05_SPI1_CLK);
        } else {
            err = FLASH_ERR_INVALID_PARAMS;
        }

        CHIP_PIN_CONFIG(cs_pin);
        CHIP_PIN_DIR_OUT(cs_pin);
        CHIP_PIN_OUT(cs_pin, 1);

        if (!err) {
            memset(iface, 0, sizeof(t_flash_iface));
            spi_data->cs_pin = cs_pin;
            spi_data->spi_port = spi_port;

            iface->port_exec_tout = 2;
            iface->port_data = spi_data;
            iface->select = f_select;
            iface->unselect = f_unselect;
            iface->send = spi_fifo_send;
            iface->recv = spi_fifo_recv_recv;
            iface->flush = NULL;
        }
    }
    return err;
}
