From 1727ea150173d3e8be3f36b4a3075c8782f0eeb6 Mon Sep 17 00:00:00 2001 From: Bodmer Date: Mon, 18 Apr 2022 23:39:20 +0100 Subject: [PATCH] Add 16 bit parallel support for RP2040 processor The parallel support is implemented with PIO as write only to the display. DMA to the display is supported. --- Processors/TFT_eSPI_RP2040.c | 23 +- Processors/TFT_eSPI_RP2040.h | 37 +++- Processors/pio_16bit_parallel.pio | 84 +++++++ Processors/pio_16bit_parallel.pio.h | 65 ++++++ TFT_Drivers/HX8357B_Defines.h | 52 +++++ TFT_Drivers/HX8357B_Init.h | 76 +++++++ TFT_Drivers/HX8357B_Rotation.h | 47 ++++ TFT_Drivers/HX8357C_Defines.h | 52 +++++ TFT_Drivers/HX8357C_Init.h | 116 ++++++++++ TFT_Drivers/HX8357C_Rotation.h | 47 ++++ TFT_Drivers/ILI9481_Init.h | 205 +++++++++++++++++- TFT_Drivers/ILI9486_Init.h | 4 +- TFT_Drivers/ILI9488_Init.h | 2 +- TFT_eSPI.cpp | 20 +- TFT_eSPI.h | 4 +- User_Setup.h | 3 +- User_Setup_Select.h | 4 +- .../Setup107_RP2040_ILI9341_16bit_parallel.h | 64 ++++++ library.json | 2 +- library.properties | 2 +- 20 files changed, 866 insertions(+), 43 deletions(-) create mode 100644 Processors/pio_16bit_parallel.pio create mode 100644 Processors/pio_16bit_parallel.pio.h create mode 100644 TFT_Drivers/HX8357B_Defines.h create mode 100644 TFT_Drivers/HX8357B_Init.h create mode 100644 TFT_Drivers/HX8357B_Rotation.h create mode 100644 TFT_Drivers/HX8357C_Defines.h create mode 100644 TFT_Drivers/HX8357C_Init.h create mode 100644 TFT_Drivers/HX8357C_Rotation.h create mode 100644 User_Setups/Setup107_RP2040_ILI9341_16bit_parallel.h diff --git a/Processors/TFT_eSPI_RP2040.c b/Processors/TFT_eSPI_RP2040.c index ea71ae5..4e3ab4f 100644 --- a/Processors/TFT_eSPI_RP2040.c +++ b/Processors/TFT_eSPI_RP2040.c @@ -28,9 +28,12 @@ // SPI PIO code for 16 bit colour transmit #include "pio_SPI.pio.h" #endif - #else + #elif defined (TFT_PARALLEL_8_BIT) // SPI PIO code for 8 bit parallel interface (16 bit colour) #include "pio_8bit_parallel.pio.h" + #else // must be TFT_PARALLEL_16_BIT + // SPI PIO code for 16 bit parallel interface (16 bit colour) + #include "pio_16bit_parallel.pio.h" #endif // Board package specific differences @@ -189,7 +192,7 @@ void pioinit(uint32_t clock_freq) { pio_instr_set_dc = pio_encode_set((pio_src_dest)0, 1); pio_instr_clr_dc = pio_encode_set((pio_src_dest)0, 0); } -#else +#else // 8 or 16 bit parallel void pioinit(uint16_t clock_div, uint16_t fract_div) { // Find a free SM on one of the PIO's @@ -212,21 +215,27 @@ void pioinit(uint16_t clock_div, uint16_t fract_div) { } } */ - + #if defined (TFT_PARALLEL_8_BIT) + uint8_t bits = 8; + #else // must be TFT_PARALLEL_16_BIT + uint8_t bits = 16; + #endif + // Load the PIO program program_offset = pio_add_program(tft_pio, &tft_io_program); // Associate pins with the PIO pio_gpio_init(tft_pio, TFT_DC); pio_gpio_init(tft_pio, TFT_WR); - for (int i = 0; i < 8; i++) { + + for (int i = 0; i < bits; i++) { pio_gpio_init(tft_pio, TFT_D0 + i); } // Configure the pins to be outputs pio_sm_set_consecutive_pindirs(tft_pio, pio_sm, TFT_DC, 1, true); pio_sm_set_consecutive_pindirs(tft_pio, pio_sm, TFT_WR, 1, true); - pio_sm_set_consecutive_pindirs(tft_pio, pio_sm, TFT_D0, 8, true); + pio_sm_set_consecutive_pindirs(tft_pio, pio_sm, TFT_D0, bits, true); // Configure the state machine pio_sm_config c = tft_io_program_get_default_config(program_offset); @@ -234,8 +243,8 @@ void pioinit(uint16_t clock_div, uint16_t fract_div) { sm_config_set_set_pins(&c, TFT_DC, 1); // Define the single side-set pin sm_config_set_sideset_pins(&c, TFT_WR); - // Define the 8 consecutive pins that are used for data output - sm_config_set_out_pins(&c, TFT_D0, 8); + // Define the consecutive pins that are used for data output + sm_config_set_out_pins(&c, TFT_D0, bits); // Set clock divider and fractional divider sm_config_set_clkdiv_int_frac(&c, clock_div, fract_div); // Make a single 8 words FIFO from the 4 words TX and RX FIFOs diff --git a/Processors/TFT_eSPI_RP2040.h b/Processors/TFT_eSPI_RP2040.h index f3495b6..09c7e03 100644 --- a/Processors/TFT_eSPI_RP2040.h +++ b/Processors/TFT_eSPI_RP2040.h @@ -30,7 +30,7 @@ // Include processor specific header // None -#if defined (TFT_PARALLEL_8_BIT) || defined (RP2040_PIO_SPI) +#if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RP2040_PIO_SPI) #define RP2040_PIO_INTERFACE #define RP2040_PIO_PUSHBLOCK #endif @@ -80,18 +80,33 @@ #endif #else - // ILI9481 needs a slower cycle time - // Byte rate = (CPU clock/(4 * divider)) - #ifdef ILI9481_DRIVER - #define DIV_UNITS 1 - #define DIV_FRACT 160 - #else - #define DIV_UNITS 1 - #define DIV_FRACT 0 + // Different controllers have different minimum write cycle periods, so the PIO clock is changed accordingly + // The PIO clock is a division of the CPU clock so scales when the processor is overclocked + // PIO write frequency = (CPU clock/(4 * DIV_UNITS)) + #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RP2040_PIO_SPI) + #if defined (TFT_PARALLEL_16_BIT) + // Different display drivers have different minimum write cycle times + #if defined (HX8357C_DRIVER) || defined (SSD1963_DRIVER) + #define DIV_UNITS 1 // 32ns write cycle time SSD1963, HX8357C (maybe HX8357D?) + #elif defined (ILI9486_DRIVER) || defined (HX8357B_DRIVER) || defined (HX8357D_DRIVER) + #define DIV_UNITS 2 // 64ns write cycle time ILI9486, HX8357D, HX8357B + #else // ILI9481 needs a slower cycle time + #define DIV_UNITS 3 // 96ns write cycle time + #endif + #define DIV_FRACT 0 + #else // 8 bit parallel mode + #ifdef ILI9481_DRIVER + #define DIV_UNITS 1 + #define DIV_FRACT 160 // Note: Fractional values done with clock period dithering + #else + #define DIV_UNITS 1 + #define DIV_FRACT 0 + #endif + #endif #endif // Initialise TFT data bus - #if defined (TFT_PARALLEL_8_BIT) + #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) #define INIT_TFT_DATA_BUS pioinit(DIV_UNITS, DIV_FRACT); #elif defined (RP2040_PIO_SPI) #define INIT_TFT_DATA_BUS pioinit(SPI_FREQUENCY); @@ -184,7 +199,7 @@ //////////////////////////////////////////////////////////////////////////////////////// // Define the WR (TFT Write) pin drive code //////////////////////////////////////////////////////////////////////////////////////// -#if !defined (TFT_PARALLEL_8_BIT) // SPI +#if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) // SPI #ifdef TFT_WR #define WR_L digitalWrite(TFT_WR, LOW) #define WR_H digitalWrite(TFT_WR, HIGH) diff --git a/Processors/pio_16bit_parallel.pio b/Processors/pio_16bit_parallel.pio new file mode 100644 index 0000000..b0b3599 --- /dev/null +++ b/Processors/pio_16bit_parallel.pio @@ -0,0 +1,84 @@ +// Raspberry Pi Pico PIO program to output data to a TFT +// controller via a 16 bit 8080 style data path. + +// Original sourced from: +// https://github.com/zapta/pio_tft + +// Side set: 1 output pin, TFT_WR. Active low. +// Data set: 16 consecutive output pins, TFT_D0 .. TFT_D15 + +.program tft_io +.side_set 1 opt ; The TFT_WR output. + +// The C++ code switches between the different SM routines +// by waiting for the SM to be idle and setting its PC. +// The default SM routine is a 16 bit transfer + +// Do a block fill of N+1 pixels. +public block_fill: + // Fetch colour value. + pull side 1 + // Move colour to x. + mov x, osr + // Fetch pixel count N (sends N+1 pixels). + pull + // Move pixel count to y. + mov y, osr +next: + // Copy colour value into osr, colour in LS 16 bits. + mov osr, x side 1 + // Output colour 16 bits, unwanted top 16 bits shifted through. + out pins, 32 side 0 [1] + // Decrement pixel count and loop. + jmp y--, next side 1 + +.wrap_target +// Transmit a 16 bit value (LS 16 bits of 32 bits). +public start_tx: + // Fetch the next 32 bit value from the TX FIFO and set TFT_WR high. + pull side 1 + // Write the 16 bits and set WR low. This also + // shifts the unused top 16 bits through. + out pins, 32 side 0 [1] + // Set WR high and jump back to start. + jmp start_tx side 1 + +// Transmit an 8 bit value (LS 8 bits of 32 bits). +public start_8: + // Fetch the next 32 bit value from the TX FIFO and set TFT_WR high. + pull side 1 + // Write the first byte (LSB) and sets WR low. This also + // shifts the unused top 16 bits through. + out pins, 32 side 0 [1] + // Jump to start + jmp start_tx side 1 + +// Transmit a set window command sequence. +public set_addr_window: + // Loop count in x (to send caset, paset and ramwr commands). + set x, 2 side 1 +pull_cmd: + // Set TFT_DC low. + set pins, 0 + // Fetch caset, paset or ramwr. + pull + // Output LS byte (caset, paset or ramwr), discarding top 16 bits, set TFT_WR low. + out pins, 32 side 0 + // Jump to end if 3rd cmd byte ramwr sent (x == 0) + jmp !x, end_set_addr + // pull next start and end coordinates, TFT_WR high. + pull side 1 + // Set TFT_DC high. + set pins, 1 +send_xy: + // Output byte, TFT_WR low. + out pins, 8 side 0 [1] + // Loop until 4 bytes sent, TFT_WR high. + jmp !osre, send_xy side 1 [1] +end_set_addr: + // Loop back for next command and write last command. + jmp x--, pull_cmd side 1 + // Set DC high. + set pins, 1 + // Auto-wrap back to start_tx. +.wrap \ No newline at end of file diff --git a/Processors/pio_16bit_parallel.pio.h b/Processors/pio_16bit_parallel.pio.h new file mode 100644 index 0000000..b9cd4c7 --- /dev/null +++ b/Processors/pio_16bit_parallel.pio.h @@ -0,0 +1,65 @@ +// -------------------------------------------------- // +// This file is autogenerated by pioasm; do not edit! // +// -------------------------------------------------- // + +#pragma once + +#if !PICO_NO_HARDWARE +#include "hardware/pio.h" +#endif + +// ------ // +// tft_io // +// ------ // + +#define tft_io_wrap_target 7 +#define tft_io_wrap 23 + +#define tft_io_offset_block_fill 0u +#define tft_io_offset_start_tx 7u +#define tft_io_offset_start_8 10u +#define tft_io_offset_set_addr_window 13u + +static const uint16_t tft_io_program_instructions[] = { + 0x98a0, // 0: pull block side 1 + 0xa027, // 1: mov x, osr + 0x80a0, // 2: pull block + 0xa047, // 3: mov y, osr + 0xb8e1, // 4: mov osr, x side 1 + 0x7100, // 5: out pins, 32 side 0 [1] + 0x1884, // 6: jmp y--, 4 side 1 + // .wrap_target + 0x98a0, // 7: pull block side 1 + 0x7100, // 8: out pins, 32 side 0 [1] + 0x1807, // 9: jmp 7 side 1 + 0x98a0, // 10: pull block side 1 + 0x7100, // 11: out pins, 32 side 0 [1] + 0x1807, // 12: jmp 7 side 1 + 0xf822, // 13: set x, 2 side 1 + 0xe000, // 14: set pins, 0 + 0x80a0, // 15: pull block + 0x7000, // 16: out pins, 32 side 0 + 0x0036, // 17: jmp !x, 22 + 0x98a0, // 18: pull block side 1 + 0xe001, // 19: set pins, 1 + 0x7108, // 20: out pins, 8 side 0 [1] + 0x19f4, // 21: jmp !osre, 20 side 1 [1] + 0x184e, // 22: jmp x--, 14 side 1 + 0xe001, // 23: set pins, 1 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program tft_io_program = { + .instructions = tft_io_program_instructions, + .length = 24, + .origin = -1, +}; + +static inline pio_sm_config tft_io_program_get_default_config(uint offset) { + pio_sm_config c = pio_get_default_sm_config(); + sm_config_set_wrap(&c, offset + tft_io_wrap_target, offset + tft_io_wrap); + sm_config_set_sideset(&c, 2, true, false); + return c; +} +#endif diff --git a/TFT_Drivers/HX8357B_Defines.h b/TFT_Drivers/HX8357B_Defines.h new file mode 100644 index 0000000..d2f3cf9 --- /dev/null +++ b/TFT_Drivers/HX8357B_Defines.h @@ -0,0 +1,52 @@ +// Change the width and height if required (defined in portrait mode) +// or use the constructor to over-ride defaults +#define TFT_WIDTH 320 +#define TFT_HEIGHT 480 + + +// Delay between some initialisation commands +#define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked + + +// Generic commands used by TFT_eSPar.cpp +#define TFT_NOP 0x00 +#define TFT_SWRST 0x01 + +#define TFT_SLPIN 0x10 +#define TFT_SLPOUT 0x11 + +#define TFT_INVOFF 0x20 +#define TFT_INVON 0x21 + +#define TFT_DISPOFF 0x28 +#define TFT_DISPON 0x29 + +#define TFT_CASET 0x2A +#define TFT_PASET 0x2B +#define TFT_RAMWR 0x2C + +#define TFT_RAMRD 0x2E + +#define TFT_MADCTL 0x36 + +#define TFT_MAD_MY 0x80 +#define TFT_MAD_MX 0x40 +#define TFT_MAD_MV 0x20 +#define TFT_MAD_ML 0x10 +#define TFT_MAD_RGB 0x00 +#define TFT_MAD_BGR 0x08 +#define TFT_MAD_MH 0x04 +#define TFT_MAD_SS 0x02 +#define TFT_MAD_GS 0x01 + +#ifdef TFT_RGB_ORDER + #if (TFT_RGB_ORDER == 1) + #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB + #else + #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR + #endif +#else + #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR +#endif + +#define TFT_IDXRD 0x00 // ILI9341 only, indexed control register read diff --git a/TFT_Drivers/HX8357B_Init.h b/TFT_Drivers/HX8357B_Init.h new file mode 100644 index 0000000..b5f8c2e --- /dev/null +++ b/TFT_Drivers/HX8357B_Init.h @@ -0,0 +1,76 @@ + +// This is the command sequence that initialises the HX8357B driver +// +// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// +// See ST7735_Setup.h file for an alternative format + + +// Configure HX8357-B display + writecommand(0x11); + delay(20); + writecommand(0xD0); + writedata(0x07); + writedata(0x42); + writedata(0x18); + + writecommand(0xD1); + writedata(0x00); + writedata(0x07); + writedata(0x10); + + writecommand(0xD2); + writedata(0x01); + writedata(0x02); + + writecommand(0xC0); + writedata(0x10); + writedata(0x3B); + writedata(0x00); + writedata(0x02); + writedata(0x11); + + writecommand(0xC5); + writedata(0x08); + + writecommand(0xC8); + writedata(0x00); + writedata(0x32); + writedata(0x36); + writedata(0x45); + writedata(0x06); + writedata(0x16); + writedata(0x37); + writedata(0x75); + writedata(0x77); + writedata(0x54); + writedata(0x0C); + writedata(0x00); + + writecommand(0x36); + writedata(0x0a); + + writecommand(0x3A); + writedata(0x55); + + writecommand(0x2A); + writedata(0x00); + writedata(0x00); + writedata(0x01); + writedata(0x3F); + + writecommand(0x2B); + writedata(0x00); + writedata(0x00); + writedata(0x01); + writedata(0xDF); + + delay(120); + writecommand(0x29); + + delay(25); + +// End of HX8357B display configuration + + + diff --git a/TFT_Drivers/HX8357B_Rotation.h b/TFT_Drivers/HX8357B_Rotation.h new file mode 100644 index 0000000..d3644f8 --- /dev/null +++ b/TFT_Drivers/HX8357B_Rotation.h @@ -0,0 +1,47 @@ + // This is the command sequence that rotates the HX8357C driver coordinate frame + + writecommand(TFT_MADCTL); + rotation = m % 8; + switch (rotation) { + case 0: // Portrait + writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MX); + _width = _init_width; + _height = _init_height; + break; + case 1: // Landscape (Portrait + 90) + writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MV); + _width = _init_height; + _height = _init_width; + break; + case 2: // Inverter portrait + writedata( TFT_MAD_COLOR_ORDER | TFT_MAD_MY); + _width = _init_width; + _height = _init_height; + break; + case 3: // Inverted landscape + writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_MY); + _width = _init_height; + _height = _init_width; + break; + case 4: // Portrait + writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MX | TFT_MAD_MY); + _width = _init_width; + _height = _init_height; + break; + case 5: // Landscape (Portrait + 90) + writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MV | TFT_MAD_MX); + _width = _init_height; + _height = _init_width; + break; + case 6: // Inverter portrait + writedata( TFT_MAD_COLOR_ORDER); + _width = _init_width; + _height = _init_height; + break; + case 7: // Inverted landscape + writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MV | TFT_MAD_MY); + _width = _init_height; + _height = _init_width; + break; + } + \ No newline at end of file diff --git a/TFT_Drivers/HX8357C_Defines.h b/TFT_Drivers/HX8357C_Defines.h new file mode 100644 index 0000000..d2f3cf9 --- /dev/null +++ b/TFT_Drivers/HX8357C_Defines.h @@ -0,0 +1,52 @@ +// Change the width and height if required (defined in portrait mode) +// or use the constructor to over-ride defaults +#define TFT_WIDTH 320 +#define TFT_HEIGHT 480 + + +// Delay between some initialisation commands +#define TFT_INIT_DELAY 0x80 // Not used unless commandlist invoked + + +// Generic commands used by TFT_eSPar.cpp +#define TFT_NOP 0x00 +#define TFT_SWRST 0x01 + +#define TFT_SLPIN 0x10 +#define TFT_SLPOUT 0x11 + +#define TFT_INVOFF 0x20 +#define TFT_INVON 0x21 + +#define TFT_DISPOFF 0x28 +#define TFT_DISPON 0x29 + +#define TFT_CASET 0x2A +#define TFT_PASET 0x2B +#define TFT_RAMWR 0x2C + +#define TFT_RAMRD 0x2E + +#define TFT_MADCTL 0x36 + +#define TFT_MAD_MY 0x80 +#define TFT_MAD_MX 0x40 +#define TFT_MAD_MV 0x20 +#define TFT_MAD_ML 0x10 +#define TFT_MAD_RGB 0x00 +#define TFT_MAD_BGR 0x08 +#define TFT_MAD_MH 0x04 +#define TFT_MAD_SS 0x02 +#define TFT_MAD_GS 0x01 + +#ifdef TFT_RGB_ORDER + #if (TFT_RGB_ORDER == 1) + #define TFT_MAD_COLOR_ORDER TFT_MAD_RGB + #else + #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR + #endif +#else + #define TFT_MAD_COLOR_ORDER TFT_MAD_BGR +#endif + +#define TFT_IDXRD 0x00 // ILI9341 only, indexed control register read diff --git a/TFT_Drivers/HX8357C_Init.h b/TFT_Drivers/HX8357C_Init.h new file mode 100644 index 0000000..35cde5c --- /dev/null +++ b/TFT_Drivers/HX8357C_Init.h @@ -0,0 +1,116 @@ + +// This is the command sequence that initialises the HX8357C driver +// +// This setup information uses simple 8 bit SPI writecommand() and writedata() functions +// +// See ST7735_Setup.h file for an alternative format + + +// Configure HX8357C display + + writecommand(0xB9); // Enable extension command + writedata(0xFF); + writedata(0x83); + writedata(0x57); + delay(50); + + writecommand(0xB6); //Set VCOM voltage + writedata(0x2C); //0x52 for HSD 3.0" + + writecommand(0x11); // Sleep off + delay(200); + + writecommand(0x35); // Tearing effect on + writedata(0x00); // Added parameter + + writecommand(0x3A); // Interface pixel format + writedata(0x55); // 16 bits per pixel + + //writecommand(0xCC); // Set panel characteristic + //writedata(0x09); // S960>S1, G1>G480, R-G-B, normally black + + //writecommand(0xB3); // RGB interface + //writedata(0x43); + //writedata(0x00); + //writedata(0x06); + //writedata(0x06); + + writecommand(0xB1); // Power control + writedata(0x00); + writedata(0x15); + writedata(0x0D); + writedata(0x0D); + writedata(0x83); + writedata(0x48); + + + writecommand(0xC0); // Does this do anything? + writedata(0x24); + writedata(0x24); + writedata(0x01); + writedata(0x3C); + writedata(0xC8); + writedata(0x08); + + writecommand(0xB4); // Display cycle + writedata(0x02); + writedata(0x40); + writedata(0x00); + writedata(0x2A); + writedata(0x2A); + writedata(0x0D); + writedata(0x4F); + + writecommand(0xE0); // Gamma curve + writedata(0x00); + writedata(0x15); + writedata(0x1D); + writedata(0x2A); + writedata(0x31); + writedata(0x42); + writedata(0x4C); + writedata(0x53); + writedata(0x45); + writedata(0x40); + writedata(0x3B); + writedata(0x32); + writedata(0x2E); + writedata(0x28); + + writedata(0x24); + writedata(0x03); + writedata(0x00); + writedata(0x15); + writedata(0x1D); + writedata(0x2A); + writedata(0x31); + writedata(0x42); + writedata(0x4C); + writedata(0x53); + writedata(0x45); + writedata(0x40); + writedata(0x3B); + writedata(0x32); + + writedata(0x2E); + writedata(0x28); + writedata(0x24); + writedata(0x03); + writedata(0x00); + writedata(0x01); + + writecommand(0x36); // MADCTL Memory access control + writedata(0x48); + delay(20); + + writecommand(0x21); //Display inversion on + delay(20); + + writecommand(0x29); // Display on + + delay(120); + +// End of HX8357C display configuration + + + diff --git a/TFT_Drivers/HX8357C_Rotation.h b/TFT_Drivers/HX8357C_Rotation.h new file mode 100644 index 0000000..d3644f8 --- /dev/null +++ b/TFT_Drivers/HX8357C_Rotation.h @@ -0,0 +1,47 @@ + // This is the command sequence that rotates the HX8357C driver coordinate frame + + writecommand(TFT_MADCTL); + rotation = m % 8; + switch (rotation) { + case 0: // Portrait + writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MX); + _width = _init_width; + _height = _init_height; + break; + case 1: // Landscape (Portrait + 90) + writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MV); + _width = _init_height; + _height = _init_width; + break; + case 2: // Inverter portrait + writedata( TFT_MAD_COLOR_ORDER | TFT_MAD_MY); + _width = _init_width; + _height = _init_height; + break; + case 3: // Inverted landscape + writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MV | TFT_MAD_MX | TFT_MAD_MY); + _width = _init_height; + _height = _init_width; + break; + case 4: // Portrait + writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MX | TFT_MAD_MY); + _width = _init_width; + _height = _init_height; + break; + case 5: // Landscape (Portrait + 90) + writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MV | TFT_MAD_MX); + _width = _init_height; + _height = _init_width; + break; + case 6: // Inverter portrait + writedata( TFT_MAD_COLOR_ORDER); + _width = _init_width; + _height = _init_height; + break; + case 7: // Inverted landscape + writedata(TFT_MAD_COLOR_ORDER | TFT_MAD_MV | TFT_MAD_MY); + _width = _init_height; + _height = _init_width; + break; + } + \ No newline at end of file diff --git a/TFT_Drivers/ILI9481_Init.h b/TFT_Drivers/ILI9481_Init.h index 2d2d8cc..fe45ff4 100644 --- a/TFT_Drivers/ILI9481_Init.h +++ b/TFT_Drivers/ILI9481_Init.h @@ -11,6 +11,8 @@ //#define ILI9481_INIT_4 // AUO317 //#define ILI9481_INIT_5 // CMO35 ***** //#define ILI9481_INIT_6 // RGB +//#define ILI9481_INIT_7 // From #1774 +//#define ILI9481_INIT_8 // From #1774 ///////////////////////////////////////////////////////////////////////////////////////// #ifdef ILI9481_INIT_1 @@ -61,13 +63,13 @@ writedata(0x0A); writecommand(0x3A); - #if defined (TFT_PARALLEL_8_BIT) || defined (RPI_DISPLAY_TYPE) + #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) writedata(0x55); // 16 bit colour interface #else writedata(0x66); // 18 bit colour interface #endif - #ifndef TFT_PARALLEL_8_BIT + #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) writecommand(TFT_INVON); #endif @@ -150,13 +152,13 @@ writedata(0x0A); writecommand(0x3A); - #if defined (TFT_PARALLEL_8_BIT) || defined (RPI_DISPLAY_TYPE) + #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) writedata(0x55); // 16 bit colour interface #else writedata(0x66); // 18 bit colour interface #endif - #ifndef TFT_PARALLEL_8_BIT + #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) writecommand(TFT_INVON); #endif @@ -239,13 +241,13 @@ writedata(0x0A); writecommand(0x3A); - #if defined (TFT_PARALLEL_8_BIT) || defined (RPI_DISPLAY_TYPE) + #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) writedata(0x55); // 16 bit colour interface #else writedata(0x66); // 18 bit colour interface #endif - #ifndef TFT_PARALLEL_8_BIT + #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) writecommand(TFT_INVON); #endif @@ -324,13 +326,13 @@ writedata(0x0A); writecommand(0x3A); - #if defined (TFT_PARALLEL_8_BIT) || defined (RPI_DISPLAY_TYPE) + #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) writedata(0x55); // 16 bit colour interface #else writedata(0x66); // 18 bit colour interface #endif - #ifndef TFT_PARALLEL_8_BIT + #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) writecommand(TFT_INVON); #endif @@ -412,13 +414,13 @@ writedata(0x0A); writecommand(0x3A); - #if defined (TFT_PARALLEL_8_BIT) || defined (RPI_DISPLAY_TYPE) + #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) writedata(0x55); // 16 bit colour interface #else writedata(0x66); // 18 bit colour interface #endif - #ifndef TFT_PARALLEL_8_BIT + #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) writecommand(TFT_INVON); #endif @@ -524,13 +526,13 @@ writedata(0x0A); writecommand(0x3A); - #if defined (TFT_PARALLEL_8_BIT) || defined (RPI_DISPLAY_TYPE) + #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) writedata(0x55); // 16 bit colour interface #else writedata(0x66); // 18 bit colour interface #endif - #ifndef TFT_PARALLEL_8_BIT + #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) writecommand(TFT_INVON); #endif @@ -552,4 +554,183 @@ delay(25); // End of ILI9481 display configuration ///////////////////////////////////////////////////////////////////////////////////////// + + +// From #1774 +#elif defined (ILI9481_INIT_7) + ///ili9481+cmi3.5ips //效果不好 + //************* Start Initial Sequence **********// + writecommand(0x11); + delay(20); + writecommand(0xD0); + writedata(0x07); + writedata(0x42); + writedata(0x1B); + + writecommand(0xD1); + writedata(0x00); + writedata(0x14); + writedata(0x1B); + + writecommand(0xD2); + writedata(0x01); + writedata(0x12); + + writecommand(0xC0); + writedata(0x10); + writedata(0x3B); + writedata(0x00); + writedata(0x02); + writedata(0x01); + + writecommand(0xC5); + writedata(0x03); + + writecommand(0xC8); + writedata(0x00); + writedata(0x46); + writedata(0x44); + writedata(0x50); + writedata(0x04); + writedata(0x16); + writedata(0x33); + writedata(0x13); + writedata(0x77); + writedata(0x05); + writedata(0x0F); + writedata(0x00); + + writecommand(0x36); + writedata(0x0A); + + writecommand(0x3A); + #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) + writedata(0x55); // 16 bit colour interface + #else + writedata(0x66); // 18 bit colour interface + #endif + + #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) + writecommand(TFT_INVON); + #endif + + writecommand(0x22); + writedata(0x00); + writedata(0x00); + writedata(0x01); + writedata(0x3F); + + writecommand(0x2B); + writedata(0x00); + writedata(0x00); + writedata(0x01); + writedata(0xE0); + delay(120); + writecommand(0x29); + +#elif defined (ILI9481_INIT_8) + + //3.5IPS ILI9481+CMI + writecommand(0x01); //Soft_rese + delay(220); + + writecommand(0x11); + delay(280); + + writecommand(0xd0); //Power_Setting + writedata(0x07);//07 VC[2:0] Sets the ratio factor of Vci to generate the reference voltages Vci1 + writedata(0x44);//41 BT[2:0] Sets the Step up factor and output voltage level from the reference voltages Vci1 + writedata(0x1E);//1f 17 1C VRH[3:0]: Sets the factor to generate VREG1OUT from VCILVL + delay(220); + + writecommand(0xd1); //VCOM Control + writedata(0x00);//00 + writedata(0x0C);//1A VCM [6:0] is used to set factor to generate VCOMH voltage from the reference voltage VREG1OUT 15 09 + writedata(0x1A);//1F VDV[4:0] is used to set the VCOM alternating amplitude in the range of VREG1OUT x 0.70 to VREG1OUT 1F 18 + + writecommand(0xC5); //Frame Rate + writedata(0x03); // 03 02 + + writecommand(0xd2); //Power_Setting for Normal Mode + writedata(0x01); //01 + writedata(0x11); //11 + + writecommand(0xE4); //? + writedata(0xa0); + writecommand(0xf3); + writedata(0x00); + writedata(0x2a); + + //1 OK + writecommand(0xc8); + writedata(0x00); + writedata(0x26); + writedata(0x21); + writedata(0x00); + writedata(0x00); + writedata(0x1f); + writedata(0x65); + writedata(0x23); + writedata(0x77); + writedata(0x00); + writedata(0x0f); + writedata(0x00); + //GAMMA SETTING + + writecommand(0xC0); //Panel Driving Setting + writedata(0x00); //1//00 REV SM GS + writedata(0x3B); //2//NL[5:0]: Sets the number of lines to drive the LCD at an interval of 8 lines. + writedata(0x00); //3//SCN[6:0] + writedata(0x02); //4//PTV: Sets the Vcom output in non-display area drive period + writedata(0x11); //5//NDL: Sets the source output level in non-display area. PTG: Sets the scan mode in non-display area. + + writecommand(0xc6); //Interface Control + writedata(0x83); + //GAMMA SETTING + + writecommand(0xf0); //? + writedata(0x01); + + writecommand(0xE4);//? + writedata(0xa0); + + //////倒装设置 NG + writecommand(0x36); + writedata(0x0A); // 8C:出来两行 CA:出来一个点 + + writecommand(0x3a); + #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) + writedata(0x55); // 16 bit colour interface + #else + writedata(0x66); // 18 bit colour interface + #endif + + #if !defined (TFT_PARALLEL_8_BIT) && !defined (TFT_PARALLEL_16_BIT) + writecommand(TFT_INVON); + #endif + + writecommand(0xb4);//Display Mode and Frame Memory Write Mode Setting + writedata(0x02); + writedata(0x00); //? + writedata(0x00); + writedata(0x01); + + delay(280); + + writecommand(0x2a); + writedata(0x00); + writedata(0x00); + writedata(0x01); + writedata(0x3F); //3F + + writecommand(0x2b); + writedata(0x00); + writedata(0x00); + writedata(0x01); + writedata(0xDf); //DF + + //writecommand(0x21); + writecommand(0x29); + writecommand(0x2c); + #endif \ No newline at end of file diff --git a/TFT_Drivers/ILI9486_Init.h b/TFT_Drivers/ILI9486_Init.h index 483e5f9..899c47f 100644 --- a/TFT_Drivers/ILI9486_Init.h +++ b/TFT_Drivers/ILI9486_Init.h @@ -15,7 +15,7 @@ delay(120); writecommand(0x3A); - #if defined (TFT_PARALLEL_8_BIT) || defined (RPI_DISPLAY_TYPE) + #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) writedata(0x55); // 16 bit colour interface #else writedata(0x66); // 18 bit colour interface @@ -64,7 +64,7 @@ writedata(0x20); writedata(0x00); - #if defined (TFT_PARALLEL_8_BIT) || defined (RPI_DISPLAY_TYPE) + #if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) writecommand(TFT_INVOFF); #else writecommand(TFT_INVON); diff --git a/TFT_Drivers/ILI9488_Init.h b/TFT_Drivers/ILI9488_Init.h index a593dd7..d487187 100644 --- a/TFT_Drivers/ILI9488_Init.h +++ b/TFT_Drivers/ILI9488_Init.h @@ -58,7 +58,7 @@ writedata(0x48); // MX, BGR writecommand(0x3A); // Pixel Interface Format -#if defined (TFT_PARALLEL_8_BIT) || defined (RPI_DISPLAY_TYPE) +#if defined (TFT_PARALLEL_8_BIT) || defined (TFT_PARALLEL_16_BIT) || defined (RPI_DISPLAY_TYPE) writedata(0x55); // 16 bit colour for parallel #else writedata(0x66); // 18 bit colour for SPI diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 9ec4312..eb8cdaf 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -743,6 +743,12 @@ void TFT_eSPI::init(uint8_t tc) #elif defined (RM68120_DRIVER) #include "TFT_Drivers/RM68120_Init.h" +#elif defined (HX8357B_DRIVER) + #include "TFT_Drivers/HX8357B_Init.h" + +#elif defined (HX8357C_DRIVER) + #include "TFT_Drivers/HX8357C_Init.h" + #endif #ifdef TFT_INVERSION_ON @@ -834,6 +840,12 @@ void TFT_eSPI::setRotation(uint8_t m) #elif defined (RM68120_DRIVER) #include "TFT_Drivers/RM68120_Rotation.h" +#elif defined (HX8357B_DRIVER) + #include "TFT_Drivers/HX8357B_Rotation.h" + +#elif defined (HX8357C_DRIVER) + #include "TFT_Drivers/HX8357C_Rotation.h" + #endif delayMicroseconds(10); @@ -3418,7 +3430,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) // write to RAM DC_C; tft_Write_8(TFT_RAMWR); - #if defined(TFT_PARALLEL_8_BIT) || !defined(ESP32) + #if defined(TFT_PARALLEL_8_BIT) || defined(TFT_PARALLEL_16_BIT) || !defined(ESP32) DC_D; tft_Write_16(color); #else DC_D; tft_Write_16N(color); @@ -3546,7 +3558,7 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) DC_C; tft_Write_8(TFT_RAMWR); - #if defined(TFT_PARALLEL_8_BIT) || !defined(ESP32) + #if defined(TFT_PARALLEL_8_BIT) || defined(TFT_PARALLEL_16_BIT) || !defined(ESP32) DC_D; tft_Write_16(color); #else DC_D; tft_Write_16N(color); @@ -5371,7 +5383,7 @@ void TFT_eSPI::getSetup(setup_t &tft_settings) tft_settings.trans = false; #endif -#if defined (TFT_PARALLEL_8_BIT) +#if defined (TFT_PARALLEL_8_BIT) || defined(TFT_PARALLEL_16_BIT) tft_settings.serial = false; tft_settings.tft_spi_freq = 0; #else @@ -5470,7 +5482,7 @@ void TFT_eSPI::getSetup(setup_t &tft_settings) tft_settings.pin_tft_rst = -1; #endif -#if defined (TFT_PARALLEL_8_BIT) +#if defined (TFT_PARALLEL_8_BIT) || defined(TFT_PARALLEL_16_BIT) tft_settings.pin_tft_d0 = TFT_D0; tft_settings.pin_tft_d1 = TFT_D1; tft_settings.pin_tft_d2 = TFT_D2; diff --git a/TFT_eSPI.h b/TFT_eSPI.h index a03a24d..b0e89f9 100644 --- a/TFT_eSPI.h +++ b/TFT_eSPI.h @@ -16,7 +16,7 @@ #ifndef _TFT_eSPIH_ #define _TFT_eSPIH_ -#define TFT_ESPI_VERSION "2.4.50" +#define TFT_ESPI_VERSION "2.4.51" // Bit level feature flags // Bit 0 set: viewport capability @@ -868,7 +868,7 @@ class TFT_eSPI : public Print { friend class TFT_eSprite; // Sprite class has ac // Load the Touch extension #ifdef TOUCH_CS #if defined (TFT_PARALLEL_8_BIT) || defined (RP2040_PIO_INTERFACE) - #error >>>>------>> Touch functions not supported in 8 bit parallel mode or with RP2040 PIO. + #error >>>>------>> Touch functions not supported in 8/16 bit parallel mode or with RP2040 PIO. #else #include "Extensions/Touch.h" // Loaded if TOUCH_CS is defined by user #endif diff --git a/User_Setup.h b/User_Setup.h index 16ea89e..c656962 100644 --- a/User_Setup.h +++ b/User_Setup.h @@ -31,8 +31,9 @@ //#define STM_PORTA_DATA_BUS //#define STM_PORTB_DATA_BUS -// Tell the library to use 8 bit parallel mode (otherwise SPI is assumed) +// Tell the library to use 8 or bit parallel mode (otherwise SPI is assumed) //#define TFT_PARALLEL_8_BIT +//#defined TFT_PARALLEL_16_BIT // **** 16 bit parallel ONLY for RP2040 processor **** // Display type - only define if RPi display //#define RPI_DISPLAY_TYPE // 20MHz maximum SPI diff --git a/User_Setup_Select.h b/User_Setup_Select.h index 1f2d881..948a538 100644 --- a/User_Setup_Select.h +++ b/User_Setup_Select.h @@ -19,7 +19,7 @@ // Only ONE line below should be uncommented. Add extra lines and files as needed. -#include // Default setup is root library folder +//#include // Default setup is root library folder //#include // Setup file configured for my ILI9341 //#include // Setup file configured for my ST7735 @@ -94,6 +94,8 @@ //#include //#include //#include // Setup file for Raspberry Pi Pico with SPI PIO interface and ILI9341 +//#include // Setup file for RP2040 16 bit parallel display +#include // Setup file for RP2040 16 bit parallel display //#include // Setup file for ESP8266 and ST7789 135 x 240 TFT diff --git a/User_Setups/Setup107_RP2040_ILI9341_16bit_parallel.h b/User_Setups/Setup107_RP2040_ILI9341_16bit_parallel.h new file mode 100644 index 0000000..d3b6067 --- /dev/null +++ b/User_Setups/Setup107_RP2040_ILI9341_16bit_parallel.h @@ -0,0 +1,64 @@ +// This setup is for the RP2040 processor only when used with 8 bit parallel displays +// See SetupX_Template.h for all options available +#define USER_SETUP_ID 107 + +//////////////////////////////////////////////////////////////////////////////////////////// +// Interface +//////////////////////////////////////////////////////////////////////////////////////////// +//#define TFT_PARALLEL_8_BIT +#define TFT_PARALLEL_16_BIT + +//////////////////////////////////////////////////////////////////////////////////////////// +// Display driver type +//////////////////////////////////////////////////////////////////////////////////////////// +#define ILI9341_DRIVER +//#define ILI9481_DRIVER // Tested +//#define HX8357B_DRIVER // Tested +//#define HX8357C_DRIVER // Tested + +//////////////////////////////////////////////////////////////////////////////////////////// +// RP2040 pins used +//////////////////////////////////////////////////////////////////////////////////////////// + +// These pins can be moved and are controlled directly by the library software +#define TFT_RST 18 // Reset pin +#define TFT_CS 19 // Do not define if chip select control pin permanently connected to 0V +//#define TFT_RD -1 // Do not define, read pin must be permanently connected to 3V3 + +// Note: All the following pins are PIO hardware configured and driven + #define TFT_WR 16 // Write strobe pin + #define TFT_DC 17 // Data Command control pin + + // PIO requires these to be sequentially increasing - do not change + #define TFT_D0 0 + #define TFT_D1 1 + #define TFT_D2 2 + #define TFT_D3 3 + #define TFT_D4 4 + #define TFT_D5 5 + #define TFT_D6 6 + #define TFT_D7 7 + #define TFT_D8 8 + #define TFT_D9 9 + #define TFT_D10 10 + #define TFT_D11 11 + #define TFT_D12 12 + #define TFT_D13 13 + #define TFT_D14 14 + #define TFT_D15 15 +//*/ + +//////////////////////////////////////////////////////////////////////////////////////////// +// Fonts to be available +//////////////////////////////////////////////////////////////////////////////////////////// +#define LOAD_GLCD // Font 1. Original Adafruit 8 pixel font needs ~1820 bytes in FLASH +#define LOAD_FONT2 // Font 2. Small 16 pixel high font, needs ~3534 bytes in FLASH, 96 characters +#define LOAD_FONT4 // Font 4. Medium 26 pixel high font, needs ~5848 bytes in FLASH, 96 characters +#define LOAD_FONT6 // Font 6. Large 48 pixel font, needs ~2666 bytes in FLASH, only characters 1234567890:-.apm +#define LOAD_FONT7 // Font 7. 7 segment 48 pixel font, needs ~2438 bytes in FLASH, only characters 1234567890:. +#define LOAD_FONT8 // Font 8. Large 75 pixel font needs ~3256 bytes in FLASH, only characters 1234567890:-. +#define LOAD_GFXFF // FreeFonts. Include access to the 48 Adafruit_GFX free fonts FF1 to FF48 and custom fonts + +#define SMOOTH_FONT + +//////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/library.json b/library.json index bae9906..b9e8b86 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "2.4.50", + "version": "2.4.51", "keywords": "Arduino, tft, display, ttgo, LilyPi, WT32-SC01, ePaper, display, Pico, RP2040 Nano Connect, RP2040, STM32, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9481, ILI9486, ILI9488, ST7789, ST7796, RM68140, SSD1351, SSD1963, ILI9225, HX8357D, GC9A01, R61581", "description": "A TFT and ePaper SPI graphics library with optimisation for Raspberry Pi Pico, RP2040, ESP8266, ESP32 and STM32", "repository": diff --git a/library.properties b/library.properties index 0143f09..7668857 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=2.4.50 +version=2.4.51 author=Bodmer maintainer=Bodmer sentence=TFT graphics library for Arduino processors with performance optimisation for RP2040, STM32, ESP8266 and ESP32