18#include "spi_rp2350.h"
19#include "system_rp2350.h"
22using namespace _IO_BANK0_;
23using namespace _RESETS_;
25function<void(uint8_t)> spi_rp2350::_intHandler[2];
27int8_t spi_rp2350::_spi_miso_pins[2][6] =
28 { { 0, 4, 16, 20, 32, 36 }, { 8, 12, 24, 28, 40, 44 } };
30spi_rp2350::spi_rp2350( gpio_pin_t miso_pin,
34 const bool spi_master,
36 : _miso(miso_pin), _mosi(mosi_pin), _sclk(sclk_pin),
37 _cs(cs_pin), _master(spi_master), _mode(mode), _init(false),
38 _generate_CS(true), _baud(0) {
40 bool miso_found =
false;
41 bool mosi_found =
false;
42 bool sclk_found =
false;
43 for (_index=0; _index < 2; ++_index) {
49 for (
int i = 0; i < 6; ++i) {
50 if (miso_pin == _spi_miso_pins[_index][i]) miso_found =
true;
51 if (mosi_pin == _spi_miso_pins[_index][i]+3) mosi_found =
true;
52 if (sclk_pin == _spi_miso_pins[_index][i]+2) sclk_found =
true;
54 if (miso_found && mosi_found && sclk_found)
break;
56 assert(miso_found && mosi_found && sclk_found);
59 _spi = (_index==0) ? &SPI0 : &SPI1;
60 _spi_set = (_index==0) ? &SPI0_SET : &SPI1_SET;
61 _spi_clr = (_index==0) ? &SPI0_CLR : &SPI1_CLR;
64spi_rp2350::~spi_rp2350() {
68 while(_spi->SSPSR.BSY) ;
70 if (_index) RESETS_SET.RESET.SPI1 <<= 1;
71 else RESETS_SET.RESET.SPI0 <<= 1;
73 _miso.setSEL( GPIO_CTRL_FUNCSEL__null );
74 _mosi.setSEL( GPIO_CTRL_FUNCSEL__null );
75 _sclk.setSEL( GPIO_CTRL_FUNCSEL__null );
78void spi_rp2350::init() {
80 if (_index) RESETS_CLR.RESET.SPI1 <<= 1;
81 else RESETS_CLR.RESET.SPI0 <<= 1;
83 _miso.setSEL(GPIO_CTRL_FUNCSEL__spi);
84 _mosi.setSEL(GPIO_CTRL_FUNCSEL__spi);
85 _sclk.setSEL(GPIO_CTRL_FUNCSEL__spi);
87 _cs.gpioMode(_master ? GPIO::OUTPUT | GPIO::INIT_HIGH : GPIO::INPUT);
89 _spi_set->SSPCR0 = _mode;
91 _spi_set->SSPCR1.MS = 1;
94 _spi_set->SSPCR1.SSE = 1;
98int16_t spi_rp2350::spiTxRx(
const uint8_t *txbuf, uint8_t *rxbuf, uint16_t len)
103 if (_generate_CS) _cs.gpioWrite(LOW);
106 while(_cs.gpioRead()) ;
125 for (
int i = 0; i < len; ++i) {
127 while(_spi->SSPSR.TNF == 0) ;
129 _spi->SSPDR = (uint16_t) (txbuf[i]);
131 while(_spi->SSPSR.RNE == 0) ;
132 rxbuf[i] = (uint8_t)(_spi->SSPDR);
137 if (_generate_CS) _cs.gpioWrite(HIGH);
140 while(!_cs.gpioRead()) ;
145int16_t spi_rp2350::spiTx(
const uint8_t *txbuf, uint16_t len) {
149 if (_generate_CS) _cs.gpioWrite(LOW);
152 while(_cs.gpioRead()) ;
155 for (
int i = 0; i < len; ++i) {
158 while( (_spi->SSPSR.TNF) == 0) ;
160 _spi->SSPDR = (uint16_t) (txbuf[i]);
162 while(_spi->SSPSR.RNE == 0) ;
163 (void)(uint8_t)(_spi->SSPDR);
175 if (_generate_CS) _cs.gpioWrite(HIGH);
178 while(!_cs.gpioRead()) ;
183int16_t spi_rp2350::spiRx(uint8_t tx_byte, uint8_t *rxbuf, uint16_t len) {
187 if (_generate_CS) _cs.gpioWrite(LOW);
190 while(_cs.gpioRead()) ;
193 for (
int i = 0; i < len; ++i)
196 while(_spi->SSPSR.TNF == 0) ;
198 _spi->SSPDR = tx_byte;
200 while(_spi->SSPSR.RNE == 0) ;
201 rxbuf[i] = (uint8_t)(_spi->SSPDR);
206 if (_generate_CS) _cs.gpioWrite(HIGH);
209 while(!_cs.gpioRead()) ;
215void spi_rp2350::setSpeed(uint32_t baud)
219 uint32_t freq_in = CLK_PERI;
220 uint32_t prescale, postdiv;
224 for (prescale = 2; prescale <= 254; prescale += 2) {
225 if (freq_in < (prescale + 2) * 256 * (uint64_t) baud)
228 assert(prescale <= 254);
232 for (postdiv = 256; postdiv > 1; --postdiv) {
233 if (freq_in / (prescale * (postdiv - 1)) > baud)
236 _spi->SSPCPSR = prescale;
237 _spi->SSPCR0.SCR = postdiv - 1;
238 _baud = freq_in / (prescale * postdiv);
243void spi_rp2350::generateCS(
bool val)
249void spi_rp2350::setCS(
bool val) {
254void spi_rp2350::spiAttachRxIrq(function<
void(uint8_t data)> f) {
256 _intHandler[_index] = f;
258 NVIC_EnableIRQ((IRQn_Type)(SPI0_IRQ_IRQn + _index));
265void SPI0_IRQ_Handler(
void) {
266 spi_rp2350::_intHandler[0]( SPI0.SSPDR );
269void SPI1_IRQ_Handler(
void) {
270 spi_rp2350::_intHandler[1]( SPI1.SSPDR );