RP2040 18bit PIO SPI update

Update RP2040 18bit PIO SPI code for 18 bit SPI displays (tested on  ILI9488)
Add ILI9342_DRIVER option for default landscape display.
This commit is contained in:
Bodmer
2022-03-22 23:29:30 +00:00
parent ba67e95f7c
commit 0c935de08d
9 changed files with 89 additions and 20 deletions

View File

@ -21,8 +21,15 @@
#else // PIO interface used (8 bit parallel or SPI)
#ifdef RP2040_PIO_SPI
#include "pio_SPI.pio.h"
#if defined (SPI_18BIT_DRIVER)
// SPI PIO code for 18 bit colour transmit
#include "pio_SPI_18bit.pio.h"
#else
// SPI PIO code for 16 bit colour transmit
#include "pio_SPI.pio.h"
#endif
#else
// SPI PIO code for 8 bit parallel interface (16 bit colour)
#include "pio_8bit_parallel.pio.h"
#endif
@ -166,7 +173,7 @@ void pioinit(uint32_t clock_freq) {
// The OSR register shifts to the left, sm designed to send MS byte of a colour first, autopull off
sm_config_set_out_shift(&c, false, false, 0);
// Now load the configuration
pio_sm_init(tft_pio, pio_sm, program_offset + tft_io_offset_start_16, &c);
pio_sm_init(tft_pio, pio_sm, program_offset + tft_io_offset_start_tx, &c);
// Start the state machine.
pio_sm_set_enabled(tft_pio, pio_sm, true);
@ -236,7 +243,7 @@ void pioinit(uint16_t clock_div, uint16_t fract_div) {
// The OSR register shifts to the left, sm designed to send MS byte of a colour first
sm_config_set_out_shift(&c, false, false, 0);
// Now load the configuration
pio_sm_init(tft_pio, pio_sm, program_offset + tft_io_offset_start_16, &c);
pio_sm_init(tft_pio, pio_sm, program_offset + tft_io_offset_start_tx, &c);
// Start the state machine.
pio_sm_set_enabled(tft_pio, pio_sm, true);
@ -263,6 +270,16 @@ void pioinit(uint16_t clock_div, uint16_t fract_div) {
// PIO handles pixel block fill writes
void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
{
#if defined (SPI_18BIT_DRIVER)
uint32_t col = ((color & 0xF800)<<8) | ((color & 0x07E0)<<5) | ((color & 0x001F)<<3);
if (len) {
WAIT_FOR_STALL;
tft_pio->sm[pio_sm].instr = pio_instr_fill;
TX_FIFO = col;
TX_FIFO = --len; // Decrement first as PIO sends n+1
}
#else
if (len) {
WAIT_FOR_STALL;
tft_pio->sm[pio_sm].instr = pio_instr_fill;
@ -270,6 +287,7 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len)
TX_FIFO = color;
TX_FIFO = --len; // Decrement first as PIO sends n+1
}
#endif
}
#else
@ -300,7 +318,21 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len){
** Description: Write a sequence of pixels
***************************************************************************************/
void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
#if defined (SPI_18BIT_DRIVER)
uint16_t *data = (uint16_t*)data_in;
if (_swapBytes) {
while ( len-- ) {
uint32_t col = *data++;
tft_Write_16(col);
}
}
else {
while ( len-- ) {
uint32_t col = *data++;
tft_Write_16S(col);
}
}
#else
const uint16_t *data = (uint16_t*)data_in;
// PIO sends MS byte first, so bytes are already swapped on transmit
@ -341,6 +373,7 @@ void TFT_eSPI::pushPixels(const void* data_in, uint32_t len){
}
}
}
#endif
}
/***************************************************************************************

View File

@ -335,7 +335,34 @@
// Temporary - to be deleted
#define dir_mask 0
#if defined (SPI_18BIT_DRIVER) // SPI 18 bit colour
// This writes 8 bits, then switches back to 16 bit mode automatically
// Have already waited for pio stalled (last data write complete) when DC switched to command mode
// The wait for stall allows DC to be changed immediately afterwards
#define tft_Write_8(C) tft_pio->sm[pio_sm].instr = pio_instr_jmp8; \
TX_FIFO = (C); \
WAIT_FOR_STALL
// Used to send last byte for 32 bit macros below since PIO sends 24 bits
#define tft_Write_8L(C) WAIT_FOR_STALL; \
tft_pio->sm[pio_sm].instr = pio_instr_jmp8; \
TX_FIFO = (C)
// Note: the following macros do not wait for the end of transmission
#define tft_Write_16(C) WAIT_FOR_FIFO_FREE(1); TX_FIFO = ((((uint32_t)(C) & 0xF800)<<8) | (((C) & 0x07E0)<<5) | (((C) & 0x001F)<<3))
#define tft_Write_16N(C) WAIT_FOR_FIFO_FREE(1); TX_FIFO = ((((uint32_t)(C) & 0xF800)<<8) | (((C) & 0x07E0)<<5) | (((C) & 0x001F)<<3))
#define tft_Write_16S(C) WAIT_FOR_FIFO_FREE(1); TX_FIFO = ((((uint32_t)(C) & 0xF8) << 16) | (((C) & 0xE000)>>3) | (((C) & 0x07)<<13) | (((C) & 0x1F00)>>5))
#define tft_Write_32(C) WAIT_FOR_FIFO_FREE(2); TX_FIFO = ((C)>>8); WAIT_FOR_STALL; tft_Write_8(C)
#define tft_Write_32C(C,D) WAIT_FOR_FIFO_FREE(2); TX_FIFO = (((C)<<8) | ((D)>>8)); tft_Write_8L(D)
#define tft_Write_32D(C) WAIT_FOR_FIFO_FREE(2); TX_FIFO = (((C)<<8) | ((C)>>8)); tft_Write_8L(C)
#else
// This writes 8 bits, then switches back to 16 bit mode automatically
// Have already waited for pio stalled (last data write complete) when DC switched to command mode
// The wait for stall allows DC to be changed immediately afterwards
@ -356,7 +383,7 @@
#define tft_Write_32C(C,D) WAIT_FOR_FIFO_FREE(2); TX_FIFO = (C); TX_FIFO = (D)
#define tft_Write_32D(C) WAIT_FOR_FIFO_FREE(2); TX_FIFO = (C); TX_FIFO = (C)
#endif
#endif
#ifndef tft_Write_16N

View File

@ -38,7 +38,7 @@ next:
.wrap_target
// Transmit a 16 bit value (LS 16 bits of 32 bits).
public start_16:
public start_tx:
// Fetch the next 32 bit value from the TX FIFO and set TFT_WR high.
pull side 1
// Write the first byte (MSB) and set WR low. This also
@ -49,7 +49,7 @@ public start_16:
// Output the second byte and set TFT_WRITE low.
out pins, 8 side 0 [1]
// Set WR high and jump back to start.
jmp start_16 side 1
jmp start_tx side 1
// Transmit an 8 bit value (LS 8 bits of 32 bits).
public start_8:
@ -59,7 +59,7 @@ public start_8:
// shifts the unused top 24 bits through.
out pins, 32 side 0 [1]
// Jump to start
jmp start_16 side 1
jmp start_tx side 1
// Transmit a set window command sequence.
public set_addr_window:
@ -88,5 +88,5 @@ end_set_addr:
jmp x--, pull_cmd side 1
// Set DC high.
set pins, 1
// Auto-wrap back to start_16.
// Auto-wrap back to start_tx.
.wrap

View File

@ -16,7 +16,7 @@
#define tft_io_wrap 27
#define tft_io_offset_block_fill 0u
#define tft_io_offset_start_16 9u
#define tft_io_offset_start_tx 9u
#define tft_io_offset_start_8 14u
#define tft_io_offset_set_addr_window 17u

View File

@ -37,7 +37,7 @@ next_cmd_bit:
// Set DC high
set pins, 1 side 0
// Finish if 3rd cmd byte ramwr sent (x == 0)
jmp !x, start_16
jmp !x, start_tx
pull
next_xy:
// send 32 bit start and end coordinates
@ -46,7 +46,7 @@ next_xy:
// Loop back for next command
jmp x--, pull_cmd side 0
// End
jmp start_16
jmp start_tx
public block_fill:
// Fetch colour value
@ -73,7 +73,7 @@ next_bit:
// Now drop back to 16 bit output
.wrap_target
public start_16:
public start_tx:
// Pull the next 32 bit value from the TX FIFO.
// Send the bottom 16 bits
pull side 0

View File

@ -18,7 +18,7 @@
#define tft_io_offset_start_8 0u
#define tft_io_offset_set_addr_window 3u
#define tft_io_offset_block_fill 17u
#define tft_io_offset_start_16 27u
#define tft_io_offset_start_tx 27u
static const uint16_t tft_io_program_instructions[] = {
0x90a0, // 0: pull block side 0

View File

@ -1,8 +1,13 @@
// Change the width and height if required (defined in portrait mode)
// or use the constructor to over-ride defaults
#define TFT_WIDTH 240
#define TFT_HEIGHT 320
#if defined (ILI9341_DRIVER) || ILI9341_2_DRIVER
#define TFT_WIDTH 240
#define TFT_HEIGHT 320
#elif defined (ILI9342_DRIVER)
#define TFT_WIDTH 320
#define TFT_HEIGHT 240
#endif
// Color definitions for backwards compatibility with old sketches
// use colour definitions like TFT_BLACK to make sketches more portable

View File

@ -5,7 +5,7 @@
//
// See ST7735_Setup.h file for an alternative format
#if defined (ILI9341_DRIVER)
#if defined (ILI9341_DRIVER) | defined (ILI9342_DRIVER)
{
writecommand(0xEF);
writedata(0x03);

View File

@ -685,7 +685,7 @@ void TFT_eSPI::init(uint8_t tc)
tc = tc; // Suppress warning
// This loads the driver specific initialisation code <<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVERS TO THE LIST HERE <<<<<<<<<<<<<<<<<<<<<<<
#if defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER)
#if defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER) || defined (ILI9342_DRIVER)
#include "TFT_Drivers/ILI9341_Init.h"
#elif defined (ST7735_DRIVER)
@ -777,7 +777,7 @@ void TFT_eSPI::setRotation(uint8_t m)
begin_tft_write();
// This loads the driver specific rotation code <<<<<<<<<<<<<<<<<<<<< ADD NEW DRIVERS TO THE LIST HERE <<<<<<<<<<<<<<<<<<<<<<<
#if defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER)
#if defined (ILI9341_DRIVER) || defined(ILI9341_2_DRIVER) || defined (ILI9342_DRIVER)
#include "TFT_Drivers/ILI9341_Rotation.h"
#elif defined (ST7735_DRIVER)
@ -3484,7 +3484,11 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color)
TX_FIFO = (y<<16) | y;
TX_FIFO = TFT_RAMWR;
//DC set high by PIO
TX_FIFO = color;
#if defined (SPI_18BIT_DRIVER)
TX_FIFO = ((color & 0xF800)<<8) | ((color & 0x07E0)<<5) | ((color & 0x001F)<<3);
#else
TX_FIFO = color;
#endif
#endif