189 lines
5.4 KiB
C
189 lines
5.4 KiB
C
/*
|
|
* Display_SPI.c
|
|
*
|
|
* Created: Sun Mar 21 2021 11:51:35
|
|
* Author Chris
|
|
*/
|
|
#include "Display_SPI.h"
|
|
#include "Display_Config.h"
|
|
|
|
#include "pico/stdlib.h"
|
|
#include "hardware/spi.h"
|
|
#include "hardware/dma.h"
|
|
#include "hardware/irq.h"
|
|
#include "pico/binary_info.h"
|
|
#include "hardware/structs/spi.h"
|
|
|
|
|
|
// ============================================================================================
|
|
// Defines
|
|
|
|
|
|
// ============================================================================================
|
|
// Variables
|
|
static uint _Baudrate;
|
|
static bool _SPI_Received_Initialized;
|
|
volatile bool _DMA_Transfer_Complete;
|
|
static uint _DMA_Transmit_Claim;
|
|
static dma_channel_config _DMA_Transmit_Channel;
|
|
|
|
|
|
// ============================================================================================
|
|
// Function Declarations
|
|
static inline void Display_SPI_CS_Select();
|
|
static inline void Display_SPI_CS_Deselect();
|
|
|
|
|
|
/*******************************************************************
|
|
Interrupt Service Routines
|
|
*******************************************************************/
|
|
void ISR_SPI_DMA_Transmit_Complete()
|
|
{
|
|
dma_hw->ints0 = (1u << _DMA_Transmit_Claim);
|
|
Display_SPI_CS_Deselect();
|
|
|
|
_DMA_Transfer_Complete = true;
|
|
}
|
|
|
|
/*******************************************************************
|
|
Functions
|
|
*******************************************************************/
|
|
void Display_SPI_Init(bool init_spi_receive)
|
|
{
|
|
_SPI_Received_Initialized = init_spi_receive;
|
|
|
|
_Baudrate = spi_init(DISPLAY_SPI_PORT, DISPLAY_SPI_BAUDRATE);
|
|
|
|
// Initialize SPI Pinss defined in Config-Struct
|
|
gpio_set_slew_rate (DISPLAY_SPI_PIN_SCK, GPIO_SLEW_RATE_FAST);
|
|
gpio_set_slew_rate (DISPLAY_SPI_PIN_MOSI, GPIO_SLEW_RATE_FAST);
|
|
gpio_set_function (DISPLAY_SPI_PIN_SCK, GPIO_FUNC_SPI);
|
|
gpio_set_function (DISPLAY_SPI_PIN_MOSI, GPIO_FUNC_SPI);
|
|
|
|
if(_SPI_Received_Initialized == true) {
|
|
gpio_set_function(DISPLAY_SPI_PIN_MISO, GPIO_FUNC_SPI);
|
|
}
|
|
|
|
// Initialize CS-Pin as regular GPIO
|
|
gpio_init (DISPLAY_SPI_PIN_CS);
|
|
gpio_set_dir (DISPLAY_SPI_PIN_CS, GPIO_OUT);
|
|
gpio_set_slew_rate (DISPLAY_SPI_PIN_CS, GPIO_SLEW_RATE_FAST);
|
|
|
|
Display_SPI_CS_Deselect();
|
|
|
|
|
|
// Configura DMA Channel for SPI Transmit function
|
|
_DMA_Transmit_Claim = dma_claim_unused_channel(true);
|
|
_DMA_Transmit_Channel = dma_channel_get_default_config(_DMA_Transmit_Claim);
|
|
channel_config_set_transfer_data_size(&_DMA_Transmit_Channel, DMA_SIZE_8);
|
|
channel_config_set_dreq(&_DMA_Transmit_Channel, spi_get_index(DISPLAY_SPI_PORT) ? DREQ_SPI1_TX : DREQ_SPI0_TX);
|
|
dma_channel_configure( _DMA_Transmit_Claim,
|
|
&_DMA_Transmit_Channel,
|
|
&spi_get_hw(DISPLAY_SPI_PORT)->dr, // Write Address
|
|
NULL, // Read Address
|
|
0, // Element Count (Each element is of size transfer_data_size)
|
|
false); // DO NOT start directly
|
|
|
|
|
|
dma_channel_set_irq0_enabled(_DMA_Transmit_Claim, true);
|
|
|
|
// Configure the processor to run the ISR when DMA IRQ 0 is asserted
|
|
irq_set_exclusive_handler(DMA_IRQ_0, ISR_SPI_DMA_Transmit_Complete);
|
|
irq_set_enabled(DMA_IRQ_0, true);
|
|
|
|
_DMA_Transfer_Complete = true;
|
|
}
|
|
|
|
void Display_SPI_Start_Command(uint8_t command)
|
|
{
|
|
DISPLAY_MODE_SET_CMD();
|
|
Display_SPI_CS_Select();
|
|
spi_write_blocking(DISPLAY_SPI_PORT, &command, 1);
|
|
DISPLAY_MODE_SET_DATA();
|
|
}
|
|
|
|
void Display_SPI_Start_Parameter(uint8_t parameter)
|
|
{
|
|
spi_write_blocking(DISPLAY_SPI_PORT, ¶meter, 1);
|
|
}
|
|
|
|
void Display_SPI_Start_Parameter_Array(uint8_t* parameter_array, uint length)
|
|
{
|
|
spi_write_blocking(DISPLAY_SPI_PORT, parameter_array, length);
|
|
}
|
|
|
|
void Display_SPI_Finish_Command(void)
|
|
{
|
|
Display_SPI_CS_Deselect();
|
|
}
|
|
|
|
void Display_SPI_Send_Data(uint8_t* data, uint length, bool use_dma)
|
|
{
|
|
Display_SPI_CS_Select();
|
|
if(use_dma) {
|
|
if(dma_channel_is_busy(_DMA_Transmit_Claim)) {
|
|
return;
|
|
}
|
|
|
|
dma_channel_set_read_addr (_DMA_Transmit_Claim, data , false);
|
|
dma_channel_set_trans_count (_DMA_Transmit_Claim, length, true);
|
|
} else {
|
|
spi_write_blocking(DISPLAY_SPI_PORT, data, length);
|
|
Display_SPI_CS_Deselect();
|
|
}
|
|
}
|
|
|
|
void Display_SPI_Set_Baudrate(uint baudrate)
|
|
{
|
|
_Baudrate = spi_init(DISPLAY_SPI_PORT, baudrate); // This works when changing the Baudrate during runtime
|
|
// Using the function 'spi_set_baudrate' bring some problems
|
|
// _Baudrate = spi_set_baudrate(DISPLAY_SPI_PORT, baudrate);
|
|
}
|
|
|
|
uint Display_SPI_Get_Baudrate(void)
|
|
{
|
|
return _Baudrate;
|
|
}
|
|
|
|
bool Display_SPI_DMA_Transfer_Ongoing(void)
|
|
{
|
|
return dma_channel_is_busy(_DMA_Transmit_Claim);
|
|
}
|
|
|
|
bool Display_SPI_DMA_Transfer_Completed(void)
|
|
{
|
|
bool Return_Value = _DMA_Transfer_Complete;
|
|
|
|
_DMA_Transfer_Complete = false;
|
|
|
|
return Return_Value;
|
|
}
|
|
|
|
bool Display_SPI_Read_Write(const uint8_t* write_data, uint8_t* read_data, uint length_both_buffers)
|
|
{
|
|
if(_SPI_Received_Initialized == false) {
|
|
return false;
|
|
}
|
|
|
|
int Bytes_Read_Write;
|
|
Bytes_Read_Write = spi_write_read_blocking(DISPLAY_SPI_PORT, write_data, read_data, length_both_buffers);
|
|
|
|
return (Bytes_Read_Write == length_both_buffers);
|
|
}
|
|
|
|
/*******************************************************************
|
|
Internal Functions
|
|
*******************************************************************/
|
|
static inline void Display_SPI_CS_Select()
|
|
{
|
|
asm volatile("nop \n nop \n nop");
|
|
gpio_put(DISPLAY_SPI_PIN_CS, 0); // Active low
|
|
asm volatile("nop \n nop \n nop");
|
|
}
|
|
|
|
static inline void Display_SPI_CS_Deselect()
|
|
{
|
|
asm volatile("nop \n nop \n nop");
|
|
gpio_put(DISPLAY_SPI_PIN_CS, 1);
|
|
asm volatile("nop \n nop \n nop");
|
|
} |