File syn_spi_queue.c¶
File List > drivers > syn_spi_queue.c
Go to the documentation of this file
#include "syn_spi_queue.h"
#include "../port/syn_port_gpio.h"
#include "../port/syn_port_spi.h"
#include <string.h>
SYN_Status syn_spi_queue_init(SYN_SPI_Queue *q, uint8_t bus)
{
if (q == NULL) {
return SYN_INVALID_PARAM;
}
memset(q, 0, sizeof(*q));
q->bus = bus;
q->initialized = true;
return SYN_OK;
}
SYN_Status syn_spi_queue_enqueue(SYN_SPI_Queue *q, const SYN_SPI_Transaction *tx)
{
if (q == NULL || !q->initialized || tx == NULL) {
return SYN_INVALID_PARAM;
}
if (q->count >= SYN_SPI_QUEUE_MAX_DEPTH) {
return SYN_BUSY;
}
q->ring[q->tail] = *tx;
q->tail = (uint16_t)((q->tail + 1) % SYN_SPI_QUEUE_MAX_DEPTH);
q->count++;
return syn_spi_queue_process(q);
}
SYN_Status syn_spi_queue_process(SYN_SPI_Queue *q)
{
if (q == NULL || !q->initialized) {
return SYN_INVALID_PARAM;
}
if (q->active) {
return SYN_OK;
}
while (q->count > 0 && !q->active) {
SYN_SPI_Transaction tx = q->ring[q->head];
q->head = (uint16_t)((q->head + 1) % SYN_SPI_QUEUE_MAX_DEPTH);
q->count--;
q->active = true;
/* Assert target CS pin */
syn_port_gpio_write(tx.cs_pin, SYN_GPIO_LOW);
/* Execute full duplex transfer */
SYN_Status status = syn_port_spi_transfer(q->bus, tx.tx_data, tx.rx_data, tx.len);
/* Deassert CS pin if keep_cs_active is false */
if (!tx.keep_cs_active) {
syn_port_gpio_write(tx.cs_pin, SYN_GPIO_HIGH);
}
q->active = false;
if (tx.callback != NULL) {
tx.callback(q->bus, status, tx.user_data);
}
}
return SYN_OK;
}
SYN_Status syn_spi_queue_cancel_all(SYN_SPI_Queue *q)
{
if (q == NULL || !q->initialized) {
return SYN_INVALID_PARAM;
}
q->head = 0;
q->tail = 0;
q->count = 0;
q->active = false;
return SYN_OK;
}
size_t syn_spi_queue_count(const SYN_SPI_Queue *q)
{
if (q == NULL || !q->initialized) {
return 0;
}
return (size_t)q->count;
}