diff --git a/CMakeLists.txt b/CMakeLists.txt index ad59a31..96bce14 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,12 +6,13 @@ set(CMAKE_CXX_STANDARD 17) pico_sdk_init() add_executable(test test.c +spi_nb.c gyro.c ) pico_enable_stdio_usb(test 1) pico_enable_stdio_uart(test 1) pico_add_extra_outputs(test) -target_link_libraries(test pico_stdlib hardware_spi hardware_i2c) +target_link_libraries(test pico_stdlib hardware_spi hardware_structs) add_custom_target(Flash DEPENDS test diff --git a/gyro.c b/gyro.c index 96cbd1f..f7fdca8 100644 --- a/gyro.c +++ b/gyro.c @@ -2,6 +2,8 @@ #include "pico/stdlib.h" #include "hardware/gpio.h" #include "hardware/spi.h" +#include "hardware/structs/spi.h" +#include "spi_nb.h" const uint PIN_CS = 1; @@ -27,6 +29,22 @@ void Gyro_Init(void){ //Ça doit être les valeurs par défaut, mais ça marche ! spi_set_format(spi0, 8, SPI_CPHA_1, SPI_CPOL_1, SPI_MSB_FIRST); + // Pour chaque SPI nous avons les registres suivants : + + // SSPCR0 : Configuré par spi_init() + // SSPCR1 : Configuré par spi_init() + // SSPDR : Lecture ou écriture des données (avec FIFO) + // SSPSR : C'est les status qui permettent de savoir si on a des données à recevoir ou à envoyer. + // SSPCPSR : Configuré par spi_init() ou baudrate + // SSPIMSC : Activation ou désactivation des interruptions + // SSPRIS : Etat des drapeaux des interrutions - sans tenir compte des masquages + // SSPMIS : Etat des drapeaux des interrutions - en tenant compte des masquages + // SSPICR : Pour effacer les interruptions + // SSPDMACR : DMA + // + + + // Test de la présence du gyroscope : if(gyro_init_check()){ puts("Gyroscope non trouve"); @@ -66,20 +84,12 @@ void Gyro_Read(void){ int nb_recu; // Lire l'adresse d'identification // WHO_AM_I : 0x0F + puts("Lecture 0x0F"); cs_select(); - puts("Envoi"); - - spi_write_blocking(spi0, reg, 1); - // Doit répondre : 0b1101 0111 - puts(reg); - puts("Lecture"); - sleep_ms(10); - - nb_recu = spi_read_blocking(spi0, 0x55, tampon, 1); - tampon[nb_recu]='\0'; - puts(tampon); + while(spi_nb_read_register_8bits(spi0, 0x0F, tampon, 1) == SPI_IN_PROGRESS); cs_deselect(); - + tampon[1]='\0'; + puts(tampon); diff --git a/spi_nb.c b/spi_nb.c new file mode 100644 index 0000000..452e90b --- /dev/null +++ b/spi_nb.c @@ -0,0 +1,173 @@ +#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; +} \ No newline at end of file diff --git a/spi_nb.h b/spi_nb.h new file mode 100644 index 0000000..5c61609 --- /dev/null +++ b/spi_nb.h @@ -0,0 +1,12 @@ +#include "hardware/spi.h" + +#define SPI_SUCCESS 0 +#define SPI_IN_PROGRESS 1 +#define SPI_FAILED 2 + +int spi_nb_busy(spi_inst_t * spi); +void spi_nb_flush_recieve_fifo(spi_inst_t * spi); +int spi_nb_write_byte(spi_inst_t * spi, uint16_t data); +int spi_nb_write_data(spi_inst_t * spi, uint16_t * buffer, uint8_t size); +uint8_t spi_nb_read_data_8bits(spi_inst_t * spi, uint8_t * buffer); +int spi_nb_read_register_8bits(spi_inst_t * spi, uint16_t spi_slave_register, uint8_t *buffer, uint8_t nb_data_to_read); \ No newline at end of file diff --git a/test.c b/test.c index f62a087..4a83707 100644 --- a/test.c +++ b/test.c @@ -1,7 +1,6 @@ #include #include "pico/stdlib.h" #include "hardware/gpio.h" -#include "hardware/i2c.h" #include "pico/binary_info.h" #include "gyro.h" @@ -18,6 +17,7 @@ int main() { gpio_set_dir(LED_PIN, GPIO_OUT); gpio_put(LED_PIN, 1); + sleep_ms(3000); Gyro_Init();