Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
T
TFT_eSPI
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
xpstem
TFT_eSPI
Commits
8a8ad475
Commit
8a8ad475
authored
Apr 18, 2021
by
Bodmer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add DMA for RP2040 with SPI displays
parent
168a73fe
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
153 additions
and
10 deletions
+153
-10
Processors/TFT_eSPI_ESP32.c
Processors/TFT_eSPI_ESP32.c
+1
-1
Processors/TFT_eSPI_RP2040.c
Processors/TFT_eSPI_RP2040.c
+143
-8
Processors/TFT_eSPI_RP2040.h
Processors/TFT_eSPI_RP2040.h
+9
-1
No files found.
Processors/TFT_eSPI_ESP32.c
View file @
8a8ad475
...
@@ -644,7 +644,7 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t
...
@@ -644,7 +644,7 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t
}
}
}
}
if
(
spiBusyCheck
)
dmaWait
();
// Incase we did not wait earlier
if
(
spiBusyCheck
)
dmaWait
();
// In
case we did not wait earlier
setAddrWindow
(
x
,
y
,
dw
,
dh
);
setAddrWindow
(
x
,
y
,
dw
,
dh
);
...
...
Processors/TFT_eSPI_RP2040.c
View file @
8a8ad475
...
@@ -9,6 +9,11 @@
...
@@ -9,6 +9,11 @@
// Select the SPI port to use
// Select the SPI port to use
SPIClass
&
spi
=
SPI
;
SPIClass
&
spi
=
SPI
;
#ifdef RP2040_DMA
uint32_t
dma_tx_channel
;
dma_channel_config
dma_tx_config
;
#endif
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
#if defined (TFT_SDA_READ) && !defined (TFT_PARALLEL_8_BIT)
#if defined (TFT_SDA_READ) && !defined (TFT_PARALLEL_8_BIT)
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
...
@@ -258,18 +263,148 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
...
@@ -258,18 +263,148 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
// DMA FUNCTIONS
#if defined (RP2040_DMA) && !defined (TFT_PARALLEL_8_BIT) // DMA FUNCTIONS
////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////
// Placeholder for DMA functions
/*
/*
Minimal function set to support DMA:
Minimal function set to support DMA:
uint32_t dma_tx_channel;
dma_channel_config dma_tx_config;
*/
bool TFT_eSPI::initDMA(void)
/***************************************************************************************
void TFT_eSPI::deInitDMA(void)
** Function name: dmaBusy
bool TFT_eSPI::dmaBusy(void)
** Description: Check if DMA is busy
***************************************************************************************/
bool
TFT_eSPI
::
dmaBusy
(
void
)
{
if
(
!
DMA_Enabled
)
return
false
;
if
(
dma_channel_is_busy
(
dma_tx_channel
))
return
true
;
while
(
spi_get_hw
(
spi0
)
->
sr
&
SPI_SSPSR_BSY_BITS
)
{};
spi_set_format
(
spi0
,
16
,
(
spi_cpol_t
)
0
,
(
spi_cpha_t
)
0
,
SPI_MSB_FIRST
);
return
false
;
}
/***************************************************************************************
** Function name: dmaWait
** Description: Wait until DMA is over (blocking!)
***************************************************************************************/
void
TFT_eSPI
::
dmaWait
(
void
)
{
while
(
dma_channel_is_busy
(
dma_tx_channel
));
while
(
spi_get_hw
(
spi0
)
->
sr
&
SPI_SSPSR_BSY_BITS
)
{};
spi_set_format
(
spi0
,
16
,
(
spi_cpol_t
)
0
,
(
spi_cpha_t
)
0
,
SPI_MSB_FIRST
);
}
/***************************************************************************************
** Function name: pushPixelsDMA
** Description: Push pixels to TFT (len must be less than 32767)
***************************************************************************************/
// This will byte swap the original image if setSwapBytes(true) was called by sketch.
void
TFT_eSPI
::
pushPixelsDMA
(
uint16_t
*
image
,
uint32_t
len
)
void
TFT_eSPI
::
pushPixelsDMA
(
uint16_t
*
image
,
uint32_t
len
)
void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t* image)
{
if
((
len
==
0
)
||
(
!
DMA_Enabled
))
return
;
*/
dmaWait
();
if
(
_swapBytes
)
{
channel_config_set_transfer_data_size
(
&
dma_tx_config
,
DMA_SIZE_16
);
dma_channel_configure
(
dma_tx_channel
,
&
dma_tx_config
,
&
spi_get_hw
(
spi0
)
->
dr
,
(
uint16_t
*
)
image
,
len
,
true
);
}
else
{
spi_set_format
(
spi0
,
8
,
(
spi_cpol_t
)
0
,
(
spi_cpha_t
)
0
,
SPI_MSB_FIRST
);
channel_config_set_transfer_data_size
(
&
dma_tx_config
,
DMA_SIZE_8
);
dma_channel_configure
(
dma_tx_channel
,
&
dma_tx_config
,
&
spi_get_hw
(
spi0
)
->
dr
,
(
uint8_t
*
)
image
,
len
*
2
,
true
);
}
}
/***************************************************************************************
** Function name: pushImageDMA
** Description: Push image to a window (w*h must be less than 65536)
***************************************************************************************/
// This will clip and also swap bytes if setSwapBytes(true) was called by sketch
void
TFT_eSPI
::
pushImageDMA
(
int32_t
x
,
int32_t
y
,
int32_t
w
,
int32_t
h
,
uint16_t
*
image
,
uint16_t
*
buffer
)
{
if
((
x
>=
_vpW
)
||
(
y
>=
_vpH
)
||
(
!
DMA_Enabled
))
return
;
int32_t
dx
=
0
;
int32_t
dy
=
0
;
int32_t
dw
=
w
;
int32_t
dh
=
h
;
if
(
x
<
_vpX
)
{
dx
=
_vpX
-
x
;
dw
-=
dx
;
x
=
_vpX
;
}
if
(
y
<
_vpY
)
{
dy
=
_vpY
-
y
;
dh
-=
dy
;
y
=
_vpY
;
}
if
((
x
+
dw
)
>
_vpW
)
dw
=
_vpW
-
x
;
if
((
y
+
dh
)
>
_vpH
)
dh
=
_vpH
-
y
;
if
(
dw
<
1
||
dh
<
1
)
return
;
uint32_t
len
=
dw
*
dh
;
if
(
buffer
==
nullptr
)
{
buffer
=
image
;
dmaWait
();
}
// If image is clipped, copy pixels into a contiguous block
if
(
(
dw
!=
w
)
||
(
dh
!=
h
)
)
{
for
(
int32_t
yb
=
0
;
yb
<
dh
;
yb
++
)
{
memcpy
((
uint8_t
*
)
(
buffer
+
yb
*
dw
),
(
uint8_t
*
)
(
image
+
dx
+
w
*
(
yb
+
dy
)),
dw
<<
1
);
}
}
// else, if a buffer pointer has been provided copy whole image to the buffer
else
if
(
buffer
!=
image
||
_swapBytes
)
{
memcpy
(
buffer
,
image
,
len
*
2
);
}
dmaWait
();
// In case we did not wait earlier
setAddrWindow
(
x
,
y
,
dw
,
dh
);
if
(
_swapBytes
)
{
channel_config_set_transfer_data_size
(
&
dma_tx_config
,
DMA_SIZE_16
);
dma_channel_configure
(
dma_tx_channel
,
&
dma_tx_config
,
&
spi_get_hw
(
spi0
)
->
dr
,
(
uint16_t
*
)
buffer
,
len
,
true
);
}
else
{
spi_set_format
(
spi0
,
8
,
(
spi_cpol_t
)
0
,
(
spi_cpha_t
)
0
,
SPI_MSB_FIRST
);
channel_config_set_transfer_data_size
(
&
dma_tx_config
,
DMA_SIZE_8
);
dma_channel_configure
(
dma_tx_channel
,
&
dma_tx_config
,
&
spi_get_hw
(
spi0
)
->
dr
,
(
uint8_t
*
)
buffer
,
len
*
2
,
true
);
}
}
/***************************************************************************************
** Function name: initDMA
** Description: Initialise the DMA engine - returns true if init OK
***************************************************************************************/
bool
TFT_eSPI
::
initDMA
(
bool
ctrl_cs
)
{
if
(
DMA_Enabled
)
return
false
;
dma_tx_channel
=
dma_claim_unused_channel
(
true
);
dma_tx_config
=
dma_channel_get_default_config
(
dma_tx_channel
);
channel_config_set_transfer_data_size
(
&
dma_tx_config
,
DMA_SIZE_16
);
channel_config_set_dreq
(
&
dma_tx_config
,
spi_get_index
(
spi0
)
?
DREQ_SPI1_TX
:
DREQ_SPI0_TX
);
DMA_Enabled
=
true
;
return
true
;
}
/***************************************************************************************
** Function name: deInitDMA
** Description: Disconnect the DMA engine from SPI
***************************************************************************************/
void
TFT_eSPI
::
deInitDMA
(
void
)
{
if
(
!
DMA_Enabled
)
return
;
dma_channel_unclaim
(
dma_tx_channel
);
DMA_Enabled
=
false
;
}
////////////////////////////////////////////////////////////////////////////////////////
#endif // End of DMA FUNCTIONS
////////////////////////////////////////////////////////////////////////////////////////
Processors/TFT_eSPI_RP2040.h
View file @
8a8ad475
...
@@ -8,6 +8,8 @@
...
@@ -8,6 +8,8 @@
#ifndef _TFT_eSPI_RP2040H_
#ifndef _TFT_eSPI_RP2040H_
#define _TFT_eSPI_RP2040H_
#define _TFT_eSPI_RP2040H_
#include "hardware/dma.h"
// Processor ID reported by getSetup()
// Processor ID reported by getSetup()
#define PROCESSOR_ID 0x2040
#define PROCESSOR_ID 0x2040
...
@@ -19,7 +21,13 @@
...
@@ -19,7 +21,13 @@
#define SET_BUS_READ_MODE // spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST)
#define SET_BUS_READ_MODE // spi_set_format(spi0, 8, (spi_cpol_t)0, (spi_cpha_t)0, SPI_MSB_FIRST)
// Code to check if SPI or DMA is busy, used by SPI bus transaction startWrite and/or endWrite functions
// Code to check if SPI or DMA is busy, used by SPI bus transaction startWrite and/or endWrite functions
#define DMA_BUSY_CHECK // Not used so leave blank
#if !defined(TFT_PARALLEL_8_BIT) && !defined(SPI_18BIT_DRIVER)
#define RP2040_DMA
// Code to check if DMA is busy, used by SPI DMA + transaction + endWrite functions
#define DMA_BUSY_CHECK dmaWait()
#else
#define DMA_BUSY_CHECK
#endif
// Wait for tx to end, flush rx FIFO, clear rx overrun
// Wait for tx to end, flush rx FIFO, clear rx overrun
#define SPI_BUSY_CHECK while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {}; \
#define SPI_BUSY_CHECK while (spi_get_hw(spi0)->sr & SPI_SSPSR_BSY_BITS) {}; \
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment