RPiPico-Holonome2023/spi_nb.c

173 lines
4.8 KiB
C

#include <stdio.h>
#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;
}