diff --git a/Processors/TFT_eSPI_RP2040.c b/Processors/TFT_eSPI_RP2040.c index a902571..6ca1fef 100644 --- a/Processors/TFT_eSPI_RP2040.c +++ b/Processors/TFT_eSPI_RP2040.c @@ -29,10 +29,15 @@ #include "pio_SPI.pio.h" #endif #elif defined (TFT_PARALLEL_8_BIT) - // SPI PIO code for 8 bit parallel interface (16 bit colour) - #include "pio_8bit_parallel.pio.h" + #if defined (SSD1963_DRIVER) + // PIO code for 8 bit parallel interface (18 bit colour) + #include "pio_8bit_parallel_18bpp.pio.h" + #else + // PIO code for 8 bit parallel interface (16 bit colour) + #include "pio_8bit_parallel.pio.h" + #endif #else // must be TFT_PARALLEL_16_BIT - // SPI PIO code for 16 bit parallel interface (16 bit colour) + // PIO code for 16 bit parallel interface (16 bit colour) #include "pio_16bit_parallel.pio.h" #endif @@ -279,7 +284,7 @@ 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) +#if defined (SPI_18BIT_DRIVER) || (defined (SSD1963_DRIVER) && defined (TFT_PARALLEL_8_BIT)) uint32_t col = ((color & 0xF800)<<8) | ((color & 0x07E0)<<5) | ((color & 0x001F)<<3); if (len) { WAIT_FOR_STALL; @@ -327,7 +332,7 @@ 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) +#if defined (SPI_18BIT_DRIVER) || (defined (SSD1963_DRIVER) && defined (TFT_PARALLEL_8_BIT)) uint16_t *data = (uint16_t*)data_in; if (_swapBytes) { while ( len-- ) { diff --git a/Processors/TFT_eSPI_RP2040.h b/Processors/TFT_eSPI_RP2040.h index c0e0086..52adc51 100644 --- a/Processors/TFT_eSPI_RP2040.h +++ b/Processors/TFT_eSPI_RP2040.h @@ -408,7 +408,7 @@ // Temporary - to be deleted #define GPIO_DIR_MASK 0 - #if defined (SPI_18BIT_DRIVER) // SPI 18 bit colour + #if defined (SPI_18BIT_DRIVER) || defined (SSD1963_DRIVER) // 18 bit colour (3 bytes) // 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 diff --git a/Processors/pio_8bit_parallel_18bpp.pio.h b/Processors/pio_8bit_parallel_18bpp.pio.h new file mode 100644 index 0000000..b2aaff4 --- /dev/null +++ b/Processors/pio_8bit_parallel_18bpp.pio.h @@ -0,0 +1,73 @@ +// -------------------------------------------------- // +// 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 11 +#define tft_io_wrap 31 + +#define tft_io_offset_block_fill 0u +#define tft_io_offset_start_tx 11u +#define tft_io_offset_start_8 18u +#define tft_io_offset_set_addr_window 21u + +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 + 0x7110, // 5: out pins, 16 side 0 [1] + 0xb942, // 6: nop side 1 [1] + 0x7108, // 7: out pins, 8 side 0 [1] + 0xb942, // 8: nop side 1 [1] + 0x7108, // 9: out pins, 8 side 0 [1] + 0x1884, // 10: jmp y--, 4 side 1 + // .wrap_target + 0x98a0, // 11: pull block side 1 + 0x7110, // 12: out pins, 16 side 0 [1] + 0xb942, // 13: nop side 1 [1] + 0x7108, // 14: out pins, 8 side 0 [1] + 0xb942, // 15: nop side 1 [1] + 0x7108, // 16: out pins, 8 side 0 [1] + 0x180b, // 17: jmp 11 side 1 + 0x98a0, // 18: pull block side 1 + 0x7100, // 19: out pins, 32 side 0 [1] + 0x180b, // 20: jmp 11 side 1 + 0xf822, // 21: set x, 2 side 1 + 0xe000, // 22: set pins, 0 + 0x80a0, // 23: pull block + 0x7000, // 24: out pins, 32 side 0 + 0x003e, // 25: jmp !x, 30 + 0x98a0, // 26: pull block side 1 + 0xe001, // 27: set pins, 1 + 0x7108, // 28: out pins, 8 side 0 [1] + 0x19fc, // 29: jmp !osre, 28 side 1 [1] + 0x1856, // 30: jmp x--, 22 side 1 + 0xe001, // 31: set pins, 1 + // .wrap +}; + +#if !PICO_NO_HARDWARE +static const struct pio_program tft_io_program = { + .instructions = tft_io_program_instructions, + .length = 32, + .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_eSPI.cpp b/TFT_eSPI.cpp index 0dce6ca..ca45ee7 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -3640,7 +3640,7 @@ 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 - #if defined (SPI_18BIT_DRIVER) + #if defined (SPI_18BIT_DRIVER) || (defined (SSD1963_DRIVER) && defined (TFT_PARALLEL_8_BIT)) TX_FIFO = ((color & 0xF800)<<8) | ((color & 0x07E0)<<5) | ((color & 0x001F)<<3); #else TX_FIFO = color; @@ -4031,13 +4031,13 @@ void TFT_eSPI::drawArc(int32_t x, int32_t y, int32_t r, int32_t ir, uint32_t slope = (fabscos/(fabssin + minDivisor)) * (float)(1<<16); // Update slope table, add slope for arc start - if (startAngle < 90) { + if (startAngle <= 90) { startSlope[0] = slope; } - else if (startAngle < 180) { + else if (startAngle <= 180) { startSlope[1] = slope; } - else if (startAngle < 270) { + else if (startAngle <= 270) { startSlope[1] = 0xFFFFFFFF; startSlope[2] = slope; } @@ -4055,16 +4055,16 @@ void TFT_eSPI::drawArc(int32_t x, int32_t y, int32_t r, int32_t ir, slope = (uint32_t)((fabscos/(fabssin + minDivisor)) * (float)(1<<16)); // Work out which quadrants will need to be drawn and add slope for arc end - if (endAngle < 90) { + if (endAngle <= 90) { endSlope[0] = slope; endSlope[1] = 0; - endSlope[2] = 0xFFFFFFFF; + startSlope[2] = 0; } - else if (endAngle < 180) { + else if (endAngle <= 180) { endSlope[1] = slope; - endSlope[2] = 0xFFFFFFFF; + startSlope[2] = 0; } - else if (endAngle < 270) { + else if (endAngle <= 270) { endSlope[2] = slope; } else { @@ -4093,24 +4093,28 @@ void TFT_eSPI::drawArc(int32_t x, int32_t y, int32_t r, int32_t ir, } // If within arc fill zone, get line start and lengths for each quadrant else if (hyp >= r3) { - // Calculate U16.16 slope - slope = ((r - cy) << 16)/(r - cx); - if (slope <= startSlope[0] && slope >= endSlope[0]) { // slope hi -> lo - xst[0] = cx; // Bottom left line end - len[0]++; - } - if (slope >= startSlope[1] && slope <= endSlope[1]) { // slope lo -> hi - xst[1] = cx; // Top left line end - len[1]++; - } - if (slope <= startSlope[2] && slope >= endSlope[2]) { // slope hi -> lo - xst[2] = cx; // Bottom right line start - len[2]++; - } - if (slope >= startSlope[3] && slope <= endSlope[3]) { // slope lo -> hi - xst[3] = cx; // Top right line start - len[3]++; - } + do { + // Calculate U16.16 slope + slope = ((r - cy) << 16)/(r - cx); + if (slope <= startSlope[0] && slope >= endSlope[0]) { // slope hi -> lo + xst[0] = cx; // Bottom left line end + len[0]++; + } + if (slope >= startSlope[1] && slope <= endSlope[1]) { // slope lo -> hi + xst[1] = cx; // Top left line end + len[1]++; + } + if (slope <= startSlope[2] && slope >= endSlope[2]) { // slope hi -> lo + xst[2] = cx; // Bottom right line start + len[2]++; + } + if (slope <= endSlope[3] && slope >= startSlope[3]) { // slope lo -> hi + xst[3] = cx; // Top right line start + len[3]++; + } + cx++; + } while ((r - cx) * (r - cx) + dy2 >= r3 && cx < r); + cx--; continue; // Next x } else { @@ -4131,7 +4135,7 @@ void TFT_eSPI::drawArc(int32_t x, int32_t y, int32_t r, int32_t ir, drawPixel(x + cx - r, y + cy - r, pcol); if (slope <= startSlope[2] && slope >= endSlope[2]) // TR drawPixel(x - cx + r, y + cy - r, pcol); - if (slope >= startSlope[3] && slope <= endSlope[3]) // BR + if (slope <= endSlope[3] && slope >= startSlope[3]) // BR drawPixel(x - cx + r, y - cy + r, pcol); } // Add line in inner zone @@ -4905,10 +4909,13 @@ uint16_t TFT_eSPI::decodeUTF8(uint8_t *buf, uint16_t *index, uint16_t remaining) *************************************************************************************x*/ inline uint16_t TFT_eSPI::alphaBlend(uint8_t alpha, uint16_t fgc, uint16_t bgc) { + // Split out and blend 5 bit red and blue channels uint32_t rxb = bgc & 0xF81F; rxb += ((fgc & 0xF81F) - rxb) * (alpha >> 2) >> 6; + // Split out and blend 6 bit green channel uint32_t xgx = bgc & 0x07E0; xgx += ((fgc & 0x07E0) - xgx) * alpha >> 8; + // Recombine channels return (rxb & 0xF81F) | (xgx & 0x07E0); }