#include #include "spi_nb.h" #include "hardware/gpio.h" #include "hardware/structs/spi.h" #include "hardware/spi.h" #include "hardware/regs/dreq.h" #define SPI_ERR_TRANSMIT_FIFO_FULL 1 #define SPI_OK 0 #define SPI_BUSY 1 #define SPI_IDLE 0 #define PIN_CS 1 static inline void cs_select() { asm volatile("nop \n nop \n nop"); gpio_put(PIN_CS, 0); // Active low asm volatile("nop \n nop \n nop"); } static inline void cs_deselect() { asm volatile("nop \n nop \n nop"); gpio_put(PIN_CS, 1); asm volatile("nop \n nop \n nop"); } int spi_nb_read_register_8bits(spi_inst_t * spi, uint16_t spi_slave_register, uint8_t *buffer, uint8_t nb_data_to_read){ uint16_t dummy_buffer[8]={0, 0, 0, 0,0, 0, 0, 0}; uint8_t nb_data_read; static enum { INIT, WAIT_SPI_IDLE, SEND_REGISTER_ADRESS, WAIT_SENDING_DATA, SEND_DUMMY_DATA, WAIT_RECIEVING_DATA, READ_DATA, SPI_IN_ERROR, }status=INIT; switch(status){ case INIT: cs_select(); case WAIT_SPI_IDLE: if(spi_nb_busy(spi) == SPI_IDLE){ status = SEND_REGISTER_ADRESS; puts("SEND_REGISTER_ADRESS"); } break; case SEND_REGISTER_ADRESS: spi_slave_register = spi_slave_register | 0x80 | 0X40; if(spi_nb_write_data(spi, &spi_slave_register, 1) == SPI_OK){ status = WAIT_SENDING_DATA; puts("WAIT_SENDING_DATA"); }else{ status = SPI_IN_ERROR; } break; case WAIT_SENDING_DATA: if(!spi_nb_busy(spi)){ spi_nb_flush_recieve_fifo(spi); status = SEND_DUMMY_DATA; puts("SEND_DUMMY_DATA"); } break; case SEND_DUMMY_DATA: if(spi_nb_write_data(spi, dummy_buffer, nb_data_to_read) == SPI_OK){ status = WAIT_RECIEVING_DATA; puts("WAIT_RECIEVING_DATA"); }else{ status = SPI_IN_ERROR; } break; case WAIT_RECIEVING_DATA: if(!spi_nb_busy(spi)){ status = READ_DATA; puts("READ_DATA"); } break; case READ_DATA: cs_deselect(); nb_data_read = spi_nb_read_data_8bits(spi, buffer); if(nb_data_read == nb_data_to_read){ puts("SPI_SUCCESS"); status = INIT; return SPI_SUCCESS; } puts("SPI_FAILED"); status = SPI_IN_ERROR; return SPI_FAILED; break; case SPI_IN_ERROR: puts("SPI_IN_ERROR"); spi_nb_flush_recieve_fifo(spi); cs_deselect(); status = INIT; return SPI_FAILED; break; } return SPI_IN_PROGRESS; } /// @brief Tell if the SPI is busy /// @param spi SPI device to use (spi0 or spi1) /// @return SPI_BUSY of SPI_IDLE int spi_nb_busy(spi_inst_t * spi){ return (spi_get_hw(spi)->sr & SPI_SSPSR_BSY_BITS); } /// @brief Empty SPI Recieve FIFO /// @param spi SPI device to use (spi0 or spi1) void spi_nb_flush_recieve_fifo(spi_inst_t * spi){ uint16_t dummy; while(spi_get_hw(spi)->sr & SPI_SSPSR_RNE_BITS){ dummy = spi_get_hw(spi)->dr; } } /// @brief read the SPI Recieve FIFO /// @param spi SPI device to use (spi0 or spi1) /// @param buffer To store data recieved /// @return Number of byte read uint8_t spi_nb_read_data_8bits(spi_inst_t * spi, uint8_t * buffer){ uint8_t index = 0; char debug[2]="x"; while(spi_get_hw(spi)->sr & SPI_SSPSR_RNE_BITS){ buffer[index] = (uint8_t)spi_get_hw(spi)->dr & SPI_SSPDR_DATA_BITS; debug[0] = buffer[index]; puts(debug); index++; } return index; } /// @brief Write severals byte to the SPI Transmit FIFO /// @param spi SPI device to use (spi0 or spi1) /// @param buffer data to transmit /// @param size size of the data to transmit /// @return SPI_OK or SPI_ERR_TRANSMIT_FIFO_FULL inline int spi_nb_write_data(spi_inst_t * spi, uint16_t * buffer, uint8_t size){ int statu_spi = SPI_OK; uint8_t index=0; do { statu_spi = spi_nb_write_byte(spi, buffer[index]); index++; } while ( (statu_spi == SPI_OK) && (index < size)); return statu_spi; } /// @brief Write one "byte", 4 to 16 bits to the SPI Transmit FIFO. /// @param spi /// @param data : Data to send /// @return SPI_OK if Ok, SPI_ERR_TRANSMIT_FIFO_FULL if fifo is full int spi_nb_write_byte(spi_inst_t * spi, uint16_t data){ if(spi_get_hw(spi)->sr & SPI_SSPSR_TNF_BITS){ spi_get_hw(spi)->dr = data; return SPI_OK; } return SPI_ERR_TRANSMIT_FIFO_FULL; }