spi_master.h (3543B)
1 // Copyright 2025 QMK 2 // SPDX-License-Identifier: GPL-2.0-or-later 3 4 #pragma once 5 6 #include <stdint.h> 7 #include <stdbool.h> 8 #include "gpio.h" 9 10 /** 11 * \file 12 * 13 * \defgroup spi_master SPI Master API 14 * 15 * \brief API to communicate with SPI devices. 16 * \{ 17 */ 18 19 // Hardware SS pin is defined in the header so that user code can refer to it 20 #ifdef __AVR__ 21 # if defined(__AVR_AT90USB162__) || defined(__AVR_ATmega16U2__) || defined(__AVR_ATmega32U2__) || defined(__AVR_ATmega16U4__) || defined(__AVR_ATmega32U4__) || defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB647__) || defined(__AVR_AT90USB1286__) || defined(__AVR_AT90USB1287__) 22 # define SPI_SS_PIN B0 23 # elif defined(__AVR_ATmega32A__) 24 # define SPI_SS_PIN B4 25 # elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) 26 # define SPI_SS_PIN B2 27 # endif 28 #endif 29 30 typedef int16_t spi_status_t; 31 32 #define SPI_STATUS_SUCCESS (0) 33 #define SPI_STATUS_ERROR (-1) 34 #define SPI_STATUS_TIMEOUT (-2) 35 36 #define SPI_TIMEOUT_IMMEDIATE (0) 37 #define SPI_TIMEOUT_INFINITE (0xFFFF) 38 39 #ifdef __cplusplus 40 extern "C" { 41 #endif 42 43 typedef struct spi_start_config_t { 44 pin_t slave_pin; 45 bool lsb_first; 46 uint8_t mode; 47 uint16_t divisor; 48 bool cs_active_low; 49 } spi_start_config_t; 50 51 /** 52 * \brief Initialize the SPI driver. This function must be called only once, before any of the below functions can be called. 53 */ 54 void spi_init(void); 55 56 /** 57 * \brief Start an SPI transaction. 58 * 59 * \param slavePin The GPIO pin connected to the desired device's `SS` line. 60 * \param lsbFirst Determines the endianness of the transmission. If `true`, the least significant bit of each byte is sent first. 61 * \param mode The SPI mode to use. 62 * \param divisor The SPI clock divisor. 63 * 64 * \return `true` if the operation was successful, otherwise `false` if the supplied parameters are invalid or the SPI peripheral is already in use. 65 */ 66 bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor); 67 68 bool spi_start_extended(spi_start_config_t *start_config); 69 70 /** 71 * \brief Write a byte to the selected SPI device. 72 * 73 * \param data The byte to write. 74 * 75 * \return `SPI_STATUS_TIMEOUT` if the timeout period elapses, or `SPI_STATUS_SUCCESS`. 76 */ 77 spi_status_t spi_write(uint8_t data); 78 79 /** 80 * \brief Read a byte from the selected SPI device. 81 * 82 * \return `SPI_STATUS_TIMEOUT` if the timeout period elapses, otherwise the byte read from the device. 83 */ 84 spi_status_t spi_read(void); 85 86 /** 87 * \brief Send multiple bytes to the selected SPI device. 88 * 89 * \param data A pointer to the data to write from. 90 * \param length The number of bytes to write. Take care not to overrun the length of `data`. 91 * 92 * \return `SPI_STATUS_TIMEOUT` if the timeout period elapses, `SPI_STATUS_ERROR` if some other error occurs, otherwise `SPI_STATUS_SUCCESS`. 93 */ 94 spi_status_t spi_transmit(const uint8_t *data, uint16_t length); 95 96 /** 97 * \brief Receive multiple bytes from the selected SPI device. 98 * 99 * \param data A pointer to a buffer to read into. 100 * \param length The number of bytes to read. Take care not to overrun the length of `data`. 101 * 102 * \return `SPI_STATUS_TIMEOUT` if the timeout period elapses, `SPI_STATUS_ERROR` if some other error occurs, otherwise `SPI_STATUS_SUCCESS`. 103 */ 104 spi_status_t spi_receive(uint8_t *data, uint16_t length); 105 106 /** 107 * \brief End the current SPI transaction. This will deassert the slave select pin and reset the endianness, mode and divisor configured by `spi_start()`. 108 * 109 */ 110 void spi_stop(void); 111 112 #ifdef __cplusplus 113 } 114 #endif 115 116 /** \} */