diff --git a/docs/drivers/spi.md b/docs/drivers/spi.md index 43d2a056d5db..140b204945fb 100644 --- a/docs/drivers/spi.md +++ b/docs/drivers/spi.md @@ -88,7 +88,7 @@ Start an SPI transaction. #### Arguments {#api-spi-start-arguments} - `pin_t slavePin` - The QMK pin to assert as the slave select pin, eg. `B4`. + The GPIO pin connected to the desired device's `SS` line. - `bool lsbFirst` Determines the endianness of the transmission. If `true`, the least significant bit of each byte is sent first. - `uint8_t mode` @@ -106,7 +106,7 @@ Start an SPI transaction. #### Return Value {#api-spi-start-return} -`false` if the supplied parameters are invalid or the SPI peripheral is already in use, or `true`. +`true` if the operation was successful, otherwise `false` if the supplied parameters are invalid or the SPI peripheral is already in use. --- @@ -131,7 +131,7 @@ Read a byte from the selected SPI device. #### Return Value {#api-spi-read-return} -`SPI_STATUS_TIMEOUT` if the timeout period elapses, or the byte read from the device. +`SPI_STATUS_TIMEOUT` if the timeout period elapses, otherwise the byte read from the device. --- @@ -159,7 +159,7 @@ Receive multiple bytes from the selected SPI device. #### Arguments {#api-spi-receive-arguments} - `uint8_t *data` - A pointer to the buffer to read into. + A pointer to a buffer to read into. - `uint16_t length` The number of bytes to read. Take care not to overrun the length of `data`. diff --git a/drivers/spi_master.h b/drivers/spi_master.h new file mode 100644 index 000000000000..d206b812bfd3 --- /dev/null +++ b/drivers/spi_master.h @@ -0,0 +1,116 @@ +// Copyright 2025 QMK +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include +#include +#include "gpio.h" + +/** + * \file + * + * \defgroup spi_master SPI Master API + * + * \brief API to communicate with SPI devices. + * \{ + */ + +// Hardware SS pin is defined in the header so that user code can refer to it +#ifdef __AVR__ +# 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__) +# define SPI_SS_PIN B0 +# elif defined(__AVR_ATmega32A__) +# define SPI_SS_PIN B4 +# elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) +# define SPI_SS_PIN B2 +# endif +#endif + +typedef int16_t spi_status_t; + +#define SPI_STATUS_SUCCESS (0) +#define SPI_STATUS_ERROR (-1) +#define SPI_STATUS_TIMEOUT (-2) + +#define SPI_TIMEOUT_IMMEDIATE (0) +#define SPI_TIMEOUT_INFINITE (0xFFFF) + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct spi_start_config_t { + pin_t slave_pin; + bool lsb_first; + uint8_t mode; + uint16_t divisor; + bool cs_active_low; +} spi_start_config_t; + +/** + * \brief Initialize the SPI driver. This function must be called only once, before any of the below functions can be called. + */ +void spi_init(void); + +/** + * \brief Start an SPI transaction. + * + * \param slavePin The GPIO pin connected to the desired device's `SS` line. + * \param lsbFirst Determines the endianness of the transmission. If `true`, the least significant bit of each byte is sent first. + * \param mode The SPI mode to use. + * \param divisor The SPI clock divisor. + * + * \return `true` if the operation was successful, otherwise `false` if the supplied parameters are invalid or the SPI peripheral is already in use. + */ +bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor); + +bool spi_start_extended(spi_start_config_t *start_config); + +/** + * \brief Write a byte to the selected SPI device. + * + * \param data The byte to write. + * + * \return `SPI_STATUS_TIMEOUT` if the timeout period elapses, or `SPI_STATUS_SUCCESS`. + */ +spi_status_t spi_write(uint8_t data); + +/** + * \brief Read a byte from the selected SPI device. + * + * \return `SPI_STATUS_TIMEOUT` if the timeout period elapses, otherwise the byte read from the device. + */ +spi_status_t spi_read(void); + +/** + * \brief Send multiple bytes to the selected SPI device. + * + * \param data A pointer to the data to write from. + * \param length The number of bytes to write. Take care not to overrun the length of `data`. + * + * \return `SPI_STATUS_TIMEOUT` if the timeout period elapses, `SPI_STATUS_ERROR` if some other error occurs, otherwise `SPI_STATUS_SUCCESS`. + */ +spi_status_t spi_transmit(const uint8_t *data, uint16_t length); + +/** + * \brief Receive multiple bytes from the selected SPI device. + * + * \param data A pointer to a buffer to read into. + * \param length The number of bytes to read. Take care not to overrun the length of `data`. + * + * \return `SPI_STATUS_TIMEOUT` if the timeout period elapses, `SPI_STATUS_ERROR` if some other error occurs, otherwise `SPI_STATUS_SUCCESS`. + */ +spi_status_t spi_receive(uint8_t *data, uint16_t length); + +/** + * \brief End the current SPI transaction. This will deassert the slave select pin and reset the endianness, mode and divisor configured by `spi_start()`. + * + */ +void spi_stop(void); + +#ifdef __cplusplus +} +#endif + +/** \} */ diff --git a/keyboards/darkproject/kd83a_bfg_edition/config.h b/keyboards/darkproject/kd83a_bfg_edition/config.h index 880aabd5d718..fce00d29aba4 100644 --- a/keyboards/darkproject/kd83a_bfg_edition/config.h +++ b/keyboards/darkproject/kd83a_bfg_edition/config.h @@ -22,8 +22,11 @@ /* SPI Config for LED Driver */ #define SPI_DRIVER SPIDQ #define SPI_SCK_PIN A5 +#define SPI_SCK_PAL_MODE 5 #define SPI_MOSI_PIN A7 +#define SPI_MOSI_PAL_MODE 5 #define SPI_MISO_PIN A6 +#define SPI_MISO_PAL_MODE 5 #define AW20216S_CS_PIN_1 A15 #define AW20216S_CS_PIN_2 B15 diff --git a/keyboards/darkproject/kd87a_bfg_edition/config.h b/keyboards/darkproject/kd87a_bfg_edition/config.h index a32f7122311e..9e68844dafda 100644 --- a/keyboards/darkproject/kd87a_bfg_edition/config.h +++ b/keyboards/darkproject/kd87a_bfg_edition/config.h @@ -22,8 +22,11 @@ /* SPI Config for LED Driver */ #define SPI_DRIVER SPIDQ #define SPI_SCK_PIN A5 +#define SPI_SCK_PAL_MODE 5 #define SPI_MOSI_PIN A7 +#define SPI_MOSI_PAL_MODE 5 #define SPI_MISO_PIN A6 +#define SPI_MISO_PAL_MODE 5 #define AW20216S_CS_PIN_1 A15 #define AW20216S_CS_PIN_2 B15 diff --git a/keyboards/gmmk/gmmk2/p96/config.h b/keyboards/gmmk/gmmk2/p96/config.h index 1b246e4f3fad..852d29df653b 100644 --- a/keyboards/gmmk/gmmk2/p96/config.h +++ b/keyboards/gmmk/gmmk2/p96/config.h @@ -22,8 +22,11 @@ /* SPI Config for LED Driver */ #define SPI_DRIVER SPIDQ #define SPI_SCK_PIN A5 +#define SPI_SCK_PAL_MODE 5 #define SPI_MOSI_PIN A7 +#define SPI_MOSI_PAL_MODE 5 #define SPI_MISO_PIN A6 +#define SPI_MISO_PAL_MODE 5 #define AW20216S_CS_PIN_1 A15 #define AW20216S_CS_PIN_2 B15 diff --git a/keyboards/jukaie/jk01/config.h b/keyboards/jukaie/jk01/config.h index d8dfb9f53545..41534ce6c466 100644 --- a/keyboards/jukaie/jk01/config.h +++ b/keyboards/jukaie/jk01/config.h @@ -22,8 +22,11 @@ /* SPI Config for LED Driver */ #define SPI_DRIVER SPIDQ #define SPI_SCK_PIN A5 +#define SPI_SCK_PAL_MODE 5 #define SPI_MOSI_PIN A7 +#define SPI_MOSI_PAL_MODE 5 #define SPI_MISO_PIN A6 +#define SPI_MISO_PAL_MODE 5 #define AW20216S_CS_PIN_1 A15 #define AW20216S_CS_PIN_2 B15 diff --git a/keyboards/projectd/65/projectd_65_ansi/config.h b/keyboards/projectd/65/projectd_65_ansi/config.h index c8da5c42a7cc..6e23afc90201 100644 --- a/keyboards/projectd/65/projectd_65_ansi/config.h +++ b/keyboards/projectd/65/projectd_65_ansi/config.h @@ -22,8 +22,11 @@ /* SPI Config for LED Driver */ #define SPI_DRIVER SPIDQ #define SPI_SCK_PIN A5 +#define SPI_SCK_PAL_MODE 5 #define SPI_MOSI_PIN A7 +#define SPI_MOSI_PAL_MODE 5 #define SPI_MISO_PIN A6 +#define SPI_MISO_PAL_MODE 5 #define AW20216S_CS_PIN_1 A15 #define AW20216S_EN_PIN C13 diff --git a/keyboards/projectd/75/ansi/config.h b/keyboards/projectd/75/ansi/config.h index 282e20a8e2bf..acbe853949c9 100644 --- a/keyboards/projectd/75/ansi/config.h +++ b/keyboards/projectd/75/ansi/config.h @@ -22,8 +22,11 @@ /* SPI Config for LED Driver */ #define SPI_DRIVER SPIDQ #define SPI_SCK_PIN A5 +#define SPI_SCK_PAL_MODE 5 #define SPI_MOSI_PIN A7 +#define SPI_MOSI_PAL_MODE 5 #define SPI_MISO_PIN A6 +#define SPI_MISO_PAL_MODE 5 #define AW20216S_CS_PIN_1 A15 #define AW20216S_CS_PIN_2 B15 diff --git a/keyboards/projectd/75/iso/config.h b/keyboards/projectd/75/iso/config.h index 282e20a8e2bf..acbe853949c9 100644 --- a/keyboards/projectd/75/iso/config.h +++ b/keyboards/projectd/75/iso/config.h @@ -22,8 +22,11 @@ /* SPI Config for LED Driver */ #define SPI_DRIVER SPIDQ #define SPI_SCK_PIN A5 +#define SPI_SCK_PAL_MODE 5 #define SPI_MOSI_PIN A7 +#define SPI_MOSI_PAL_MODE 5 #define SPI_MISO_PIN A6 +#define SPI_MISO_PAL_MODE 5 #define AW20216S_CS_PIN_1 A15 #define AW20216S_CS_PIN_2 B15 diff --git a/platforms/avr/drivers/spi_master.h b/platforms/avr/drivers/spi_master.h deleted file mode 100644 index ebbf7ddeab93..000000000000 --- a/platforms/avr/drivers/spi_master.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright 2020 - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include - -#include "gpio.h" - -typedef int16_t spi_status_t; - -// Hardware SS pin is defined in the header so that user code can refer to it -#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__) -# define SPI_SS_PIN B0 -#elif defined(__AVR_ATmega32A__) -# define SPI_SS_PIN B4 -#elif defined(__AVR_ATmega328P__) || defined(__AVR_ATmega328__) -# define SPI_SS_PIN B2 -#endif - -#define SPI_STATUS_SUCCESS (0) -#define SPI_STATUS_ERROR (-1) -#define SPI_STATUS_TIMEOUT (-2) - -#define SPI_TIMEOUT_IMMEDIATE (0) -#define SPI_TIMEOUT_INFINITE (0xFFFF) - -#ifdef __cplusplus -extern "C" { -#endif -typedef struct spi_start_config_t { - pin_t slave_pin; - bool lsb_first; - uint8_t mode; - uint16_t divisor; - bool cs_active_low; -} spi_start_config_t; - -void spi_init(void); - -bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor); -bool spi_start_extended(spi_start_config_t *start_config); - -spi_status_t spi_write(uint8_t data); - -spi_status_t spi_read(void); - -spi_status_t spi_transmit(const uint8_t *data, uint16_t length); - -spi_status_t spi_receive(uint8_t *data, uint16_t length); - -void spi_stop(void); -#ifdef __cplusplus -} -#endif diff --git a/platforms/chibios/drivers/spi_master.c b/platforms/chibios/drivers/spi_master.c index 414e5b10a31a..f5e48edfda54 100644 --- a/platforms/chibios/drivers/spi_master.c +++ b/platforms/chibios/drivers/spi_master.c @@ -15,8 +15,49 @@ */ #include "spi_master.h" +#include "chibios_config.h" +#include +#include -#include "timer.h" +#ifndef SPI_DRIVER +# define SPI_DRIVER SPID2 +#endif + +#ifndef SPI_SCK_PIN +# define SPI_SCK_PIN B13 +#endif + +#ifndef SPI_SCK_PAL_MODE +# ifdef USE_GPIOV1 +# define SPI_SCK_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL +# else +# define SPI_SCK_PAL_MODE 5 +# endif +#endif + +#ifndef SPI_MOSI_PIN +# define SPI_MOSI_PIN B15 +#endif + +#ifndef SPI_MOSI_PAL_MODE +# ifdef USE_GPIOV1 +# define SPI_MOSI_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL +# else +# define SPI_MOSI_PAL_MODE 5 +# endif +#endif + +#ifndef SPI_MISO_PIN +# define SPI_MISO_PIN B14 +#endif + +#ifndef SPI_MISO_PAL_MODE +# ifdef USE_GPIOV1 +# define SPI_MISO_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL +# else +# define SPI_MISO_PAL_MODE 5 +# endif +#endif static bool spiStarted = false; #if SPI_SELECT_MODE == SPI_SELECT_MODE_NONE diff --git a/platforms/chibios/drivers/spi_master.h b/platforms/chibios/drivers/spi_master.h deleted file mode 100644 index 4ad6144091e0..000000000000 --- a/platforms/chibios/drivers/spi_master.h +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright 2020 Nick Brassel (tzarc) - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#pragma once - -#include -#include -#include - -#include "gpio.h" -#include "chibios_config.h" - -#ifndef SPI_DRIVER -# define SPI_DRIVER SPID2 -#endif - -#ifndef SPI_SCK_PIN -# define SPI_SCK_PIN B13 -#endif - -#ifndef SPI_SCK_PAL_MODE -# if defined(USE_GPIOV1) -# define SPI_SCK_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL -# else -# define SPI_SCK_PAL_MODE 5 -# endif -#endif - -#ifndef SPI_MOSI_PIN -# define SPI_MOSI_PIN B15 -#endif - -#ifndef SPI_MOSI_PAL_MODE -# if defined(USE_GPIOV1) -# define SPI_MOSI_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL -# else -# define SPI_MOSI_PAL_MODE 5 -# endif -#endif - -#ifndef SPI_MISO_PIN -# define SPI_MISO_PIN B14 -#endif - -#ifndef SPI_MISO_PAL_MODE -# if defined(USE_GPIOV1) -# define SPI_MISO_PAL_MODE PAL_MODE_ALTERNATE_PUSHPULL -# else -# define SPI_MISO_PAL_MODE 5 -# endif -#endif - -typedef int16_t spi_status_t; - -#define SPI_STATUS_SUCCESS (0) -#define SPI_STATUS_ERROR (-1) -#define SPI_STATUS_TIMEOUT (-2) - -#define SPI_TIMEOUT_IMMEDIATE (0) -#define SPI_TIMEOUT_INFINITE (0xFFFF) - -#ifdef __cplusplus -extern "C" { -#endif -typedef struct spi_start_config_t { - pin_t slave_pin; - bool lsb_first; - uint8_t mode; - uint16_t divisor; - bool cs_active_low; -} spi_start_config_t; - -void spi_init(void); - -bool spi_start(pin_t slavePin, bool lsbFirst, uint8_t mode, uint16_t divisor); -bool spi_start_extended(spi_start_config_t *start_config); - -spi_status_t spi_write(uint8_t data); - -spi_status_t spi_read(void); - -spi_status_t spi_transmit(const uint8_t *data, uint16_t length); - -spi_status_t spi_receive(uint8_t *data, uint16_t length); - -void spi_stop(void); -#ifdef __cplusplus -} -#endif