/* Файл для включения с реалицией стандартного приема-передачи данных
   по SPI с очередью с использованием регистра для записи, для чтения
   и статуса.
   Для использования данного файла должны быть определены макросы:
    SPI_FIFO_SIZE       - размер очереди SPI в байтах
    SPI_FIFO_RX_RDY(st) - проверка, есть ли слово в очереди на прием, по значению
                          ригистра статуса.
   Кроме того, данные интерфейса должны начинаться с полей структуры
   t_flash_iface_spi_fifo_data, которые должны быть заполнены
   при инициализации */


typedef struct {
    volatile uint32_t *tx_reg;
    volatile uint32_t *rx_reg;
    volatile uint32_t *st_reg;
    unsigned onfly;
} t_flash_iface_spi_fifo_data;


static t_flash_errs spi_fifo_send(struct st_flash_iface *iface,
                           const unsigned char* vals, size_t *psize) {
    t_flash_iface_spi_fifo_data *spi_data = (t_flash_iface_spi_fifo_data *)iface->port_data;

    size_t snd_size = *psize;

    while (snd_size && (spi_data->onfly < SPI_FIFO_SIZE)) {
        uint8_t put_val = vals == NULL ? 0xFF : *vals++;
        *spi_data->tx_reg = put_val;
        snd_size--;
        spi_data->onfly++;
    }
    *psize = snd_size;
    return 0;
}


static t_flash_errs spi_fifo_recv_recv(struct st_flash_iface *iface,
                           unsigned char* vals, size_t *psize) {
    t_flash_iface_spi_fifo_data *spi_data = (t_flash_iface_spi_fifo_data *)iface->port_data;
    size_t rcv_size = *psize;

    while ((rcv_size!=0) && SPI_FIFO_RX_RDY(*spi_data->st_reg)) {
        volatile unsigned char ret;
        ret = *spi_data->rx_reg;
        if (vals != NULL)
            *vals++ = ret;
        rcv_size--;
        spi_data->onfly--;
    }
    *psize = rcv_size;
    return 0;
}

static t_flash_errs spi_fifo_drop(struct st_flash_iface *iface) {
    t_flash_iface_spi_fifo_data *spi_data = (t_flash_iface_spi_fifo_data *)iface->port_data;
    spi_data->onfly = 0;

    while (SPI_FIFO_RX_RDY(*spi_data->st_reg)) {
        volatile unsigned char ret __attribute__((unused));
        ret = *spi_data->rx_reg;
    }
    return 0;
}
