diff --git a/Processors/TFT_eSPI_ESP8266.h b/Processors/TFT_eSPI_ESP8266.h index 2858c6b..24d8fff 100644 --- a/Processors/TFT_eSPI_ESP8266.h +++ b/Processors/TFT_eSPI_ESP8266.h @@ -191,6 +191,11 @@ SPI1CMD |= SPIBUSY; \ while(SPI1CMD & SPIBUSY) {;} + #define tft_Write_16N(C) \ + SPI1U1 = (15 << SPILMOSI) | (15 << SPILMISO); \ + SPI1W0 = ((C)<<8 | (C)>>8); \ + SPI1CMD |= SPIBUSY + #define tft_Write_16S(C) \ SPI1U1 = (15 << SPILMOSI) | (15 << SPILMISO); \ SPI1W0 = C; \ diff --git a/Processors/TFT_eSPI_RP2040.c b/Processors/TFT_eSPI_RP2040.c index 2b5486c..90b17c3 100644 --- a/Processors/TFT_eSPI_RP2040.c +++ b/Processors/TFT_eSPI_RP2040.c @@ -33,7 +33,7 @@ #endif // Community RP2040 board package by Earle Philhower - PIO pio = pio0; // Code will try both pio's to find a free SM + PIO tft_pio = pio0; // Code will try both pio's to find a free SM int8_t pio_sm = 0; // pioinit will claim a free one // Updated later with the loading offset of the PIO program. uint32_t program_offset = 0; @@ -53,7 +53,7 @@ #endif #ifdef RP2040_DMA - uint32_t dma_tx_channel; + int32_t dma_tx_channel; dma_channel_config dma_tx_config; #endif @@ -114,26 +114,41 @@ void TFT_eSPI::end_SDA_Read(void) void pioinit(uint32_t clock_freq) { // Find a free SM on one of the PIO's - pio = pio0; - pio_sm = pio_claim_unused_sm(pio, false); // false means don't panic + tft_pio = pio0; + + /* + pio_sm = pio_claim_unused_sm(tft_pio, false); // false means don't panic // Try pio1 if SM not found if (pio_sm < 0) { - pio = pio1; - pio_sm = pio_claim_unused_sm(pio, true); // panic this time if no SM is free + tft_pio = pio1; + pio_sm = pio_claim_unused_sm(tft_pio, true); // panic this time if no SM is free + } + */ + + // Find enough free space on one of the PIO's + tft_pio = pio0; + if (!pio_can_add_program(tft_pio, &tft_io_program)) { + tft_pio = pio1; + if (!pio_can_add_program(tft_pio, &tft_io_program)) { + Serial.println("No room for PIO program!"); + return; + } } + pio_sm = pio_claim_unused_sm(tft_pio, false); + // Load the PIO program - program_offset = pio_add_program(pio, &tft_io_program); + program_offset = pio_add_program(tft_pio, &tft_io_program); // Associate pins with the PIO - pio_gpio_init(pio, TFT_DC); - pio_gpio_init(pio, TFT_SCLK); - pio_gpio_init(pio, TFT_MOSI); + pio_gpio_init(tft_pio, TFT_DC); + pio_gpio_init(tft_pio, TFT_SCLK); + pio_gpio_init(tft_pio, TFT_MOSI); // Configure the pins to be outputs - pio_sm_set_consecutive_pindirs(pio, pio_sm, TFT_DC, 1, true); - pio_sm_set_consecutive_pindirs(pio, pio_sm, TFT_SCLK, 1, true); - pio_sm_set_consecutive_pindirs(pio, pio_sm, TFT_MOSI, 1, true); + pio_sm_set_consecutive_pindirs(tft_pio, pio_sm, TFT_DC, 1, true); + pio_sm_set_consecutive_pindirs(tft_pio, pio_sm, TFT_SCLK, 1, true); + pio_sm_set_consecutive_pindirs(tft_pio, pio_sm, TFT_MOSI, 1, true); // Configure the state machine pio_sm_config c = tft_io_program_get_default_config(program_offset); @@ -151,10 +166,10 @@ 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(pio, pio_sm, program_offset + tft_io_offset_start_16, &c); + pio_sm_init(tft_pio, pio_sm, program_offset + tft_io_offset_start_16, &c); // Start the state machine. - pio_sm_set_enabled(pio, pio_sm, true); + pio_sm_set_enabled(tft_pio, pio_sm, true); // Create the pull stall bit mask pull_stall_mask = 1u << (PIO_FDEBUG_TXSTALL_LSB + pio_sm); @@ -171,28 +186,40 @@ void pioinit(uint32_t clock_freq) { void pioinit(uint16_t clock_div, uint16_t fract_div) { // Find a free SM on one of the PIO's - pio = pio0; - pio_sm = pio_claim_unused_sm(pio, false); // false means don't panic + tft_pio = pio0; + pio_sm = pio_claim_unused_sm(tft_pio, false); // false means don't panic // Try pio1 if SM not found if (pio_sm < 0) { - pio = pio1; - pio_sm = pio_claim_unused_sm(pio, true); // panic this time if no SM is free + tft_pio = pio1; + pio_sm = pio_claim_unused_sm(tft_pio, true); // panic this time if no SM is free } +/* + // Find enough free space on one of the PIO's + tft_pio = pio0; + if (!pio_can_add_program(tft_pio, &tft_io_program) { + tft_pio = pio1; + if (!pio_can_add_program(tft_pio, &tft_io_program) { + Serial.println("No room for PIO program!"); + while(1) delay(100); + return; + } + } +*/ // Load the PIO program - program_offset = pio_add_program(pio, &tft_io_program); + program_offset = pio_add_program(tft_pio, &tft_io_program); // Associate pins with the PIO - pio_gpio_init(pio, TFT_DC); - pio_gpio_init(pio, TFT_WR); + pio_gpio_init(tft_pio, TFT_DC); + pio_gpio_init(tft_pio, TFT_WR); for (int i = 0; i < 8; i++) { - pio_gpio_init(pio, TFT_D0 + i); + pio_gpio_init(tft_pio, TFT_D0 + i); } // Configure the pins to be outputs - pio_sm_set_consecutive_pindirs(pio, pio_sm, TFT_DC, 1, true); - pio_sm_set_consecutive_pindirs(pio, pio_sm, TFT_WR, 1, true); - pio_sm_set_consecutive_pindirs(pio, pio_sm, TFT_D0, 8, true); + 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); // Configure the state machine pio_sm_config c = tft_io_program_get_default_config(program_offset); @@ -209,10 +236,10 @@ 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(pio, pio_sm, program_offset + tft_io_offset_start_16, &c); + pio_sm_init(tft_pio, pio_sm, program_offset + tft_io_offset_start_16, &c); // Start the state machine. - pio_sm_set_enabled(pio, pio_sm, true); + pio_sm_set_enabled(tft_pio, pio_sm, true); // Create the pull stall bit mask pull_stall_mask = 1u << (PIO_FDEBUG_TXSTALL_LSB + pio_sm); @@ -238,7 +265,7 @@ void TFT_eSPI::pushBlock(uint16_t color, uint32_t len) { if (len) { WAIT_FOR_STALL; - pio->sm[pio_sm].instr = pio_instr_fill; + tft_pio->sm[pio_sm].instr = pio_instr_fill; TX_FIFO = color; TX_FIFO = --len; // Decrement first as PIO sends n+1 @@ -564,7 +591,7 @@ void TFT_eSPI::pushPixelsDMA(uint16_t* image, uint32_t len) #if !defined (RP2040_PIO_INTERFACE) dma_channel_configure(dma_tx_channel, &dma_tx_config, &spi_get_hw(SPI_X)->dr, (uint16_t*)image, len, true); #else - dma_channel_configure(dma_tx_channel, &dma_tx_config, &pio->txf[pio_sm], (uint16_t*)image, len, true); + dma_channel_configure(dma_tx_channel, &dma_tx_config, &tft_pio->txf[pio_sm], (uint16_t*)image, len, true); #endif } @@ -617,7 +644,7 @@ void TFT_eSPI::pushImageDMA(int32_t x, int32_t y, int32_t w, int32_t h, uint16_t #if !defined (RP2040_PIO_INTERFACE) dma_channel_configure(dma_tx_channel, &dma_tx_config, &spi_get_hw(SPI_X)->dr, (uint16_t*)buffer, len, true); #else - dma_channel_configure(dma_tx_channel, &dma_tx_config, &pio->txf[pio_sm], (uint16_t*)buffer, len, true); + dma_channel_configure(dma_tx_channel, &dma_tx_config, &tft_pio->txf[pio_sm], (uint16_t*)buffer, len, true); #endif } @@ -631,14 +658,17 @@ bool TFT_eSPI::initDMA(bool ctrl_cs) ctrl_cs = ctrl_cs; // stop unused parameter warning - dma_tx_channel = dma_claim_unused_channel(true); + dma_tx_channel = dma_claim_unused_channel(false); + + if (dma_tx_channel < 0) return false; + dma_tx_config = dma_channel_get_default_config(dma_tx_channel); channel_config_set_transfer_data_size(&dma_tx_config, DMA_SIZE_16); #if !defined (RP2040_PIO_INTERFACE) channel_config_set_dreq(&dma_tx_config, spi_get_index(SPI_X) ? DREQ_SPI1_TX : DREQ_SPI0_TX); #else - channel_config_set_dreq(&dma_tx_config, pio_get_dreq(pio, pio_sm, true)); + channel_config_set_dreq(&dma_tx_config, pio_get_dreq(tft_pio, pio_sm, true)); #endif DMA_Enabled = true; diff --git a/Processors/TFT_eSPI_RP2040.h b/Processors/TFT_eSPI_RP2040.h index 5d12db0..dd769f4 100644 --- a/Processors/TFT_eSPI_RP2040.h +++ b/Processors/TFT_eSPI_RP2040.h @@ -101,7 +101,7 @@ // If smooth fonts are enabled the filing system may need to be loaded -#ifdef SMOOTH_FONT +#if defined (SMOOTH_FONT) && !defined (ARDUINO_ARCH_MBED) // Call up the filing system for the anti-aliased fonts //#define FS_NO_GLOBALS #include @@ -128,10 +128,10 @@ // PIO takes control of TFT_DC // Must wait for data to flush through before changing DC line #define DC_C WAIT_FOR_STALL; \ - pio->sm[pio_sm].instr = pio_instr_clr_dc + tft_pio->sm[pio_sm].instr = pio_instr_clr_dc // Flush has happened before this and mode changed back to 16 bit - #define DC_D pio->sm[pio_sm].instr = pio_instr_set_dc + #define DC_D tft_pio->sm[pio_sm].instr = pio_instr_set_dc #endif #endif @@ -315,22 +315,22 @@ // Wait for the PIO to stall (SM pull request finds no data in TX FIFO) // This is used to detect when the SM is idle and hence ready for a jump instruction - #define WAIT_FOR_STALL pio->fdebug = pull_stall_mask; while (!(pio->fdebug & pull_stall_mask)) + #define WAIT_FOR_STALL tft_pio->fdebug = pull_stall_mask; while (!(tft_pio->fdebug & pull_stall_mask)) // Wait until at least "S" locations free - #define WAIT_FOR_FIFO_FREE(S) while (((pio->flevel >> (pio_sm * 8)) & 0x000F) > (8-S)){} + #define WAIT_FOR_FIFO_FREE(S) while (((tft_pio->flevel >> (pio_sm * 8)) & 0x000F) > (8-S)){} // Wait until at least 5 locations free - #define WAIT_FOR_FIFO_5_FREE while ((pio->flevel) & (0x000c << (pio_sm * 8))){} + #define WAIT_FOR_FIFO_5_FREE while ((tft_pio->flevel) & (0x000c << (pio_sm * 8))){} // Wait until at least 1 location free - #define WAIT_FOR_FIFO_1_FREE while ((pio->flevel) & (0x0008 << (pio_sm * 8))){} + #define WAIT_FOR_FIFO_1_FREE while ((tft_pio->flevel) & (0x0008 << (pio_sm * 8))){} // Wait for FIFO to empty (use before swapping to 8 bits) - #define WAIT_FOR_FIFO_EMPTY while(!(pio->fstat & (1u << (PIO_FSTAT_TXEMPTY_LSB + pio_sm)))) + #define WAIT_FOR_FIFO_EMPTY while(!(tft_pio->fstat & (1u << (PIO_FSTAT_TXEMPTY_LSB + pio_sm)))) // The write register of the TX FIFO. - #define TX_FIFO pio->txf[pio_sm] + #define TX_FIFO tft_pio->txf[pio_sm] // Temporary - to be deleted #define dir_mask 0 @@ -339,7 +339,7 @@ // 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) pio->sm[pio_sm].instr = pio_instr_jmp8; \ + #define tft_Write_8(C) tft_pio->sm[pio_sm].instr = pio_instr_jmp8; \ TX_FIFO = (C); \ WAIT_FOR_STALL diff --git a/Processors/pio_SPI.pio b/Processors/pio_SPI.pio index fe7e399..95f6ef9 100644 --- a/Processors/pio_SPI.pio +++ b/Processors/pio_SPI.pio @@ -15,16 +15,11 @@ // 8 bit transfer public start_8: // Pull the next 32 bit value from the TX FIFO. - // Lose the top 24 bits pull side 0 + // Lose the top 24 bits out null, 24 -spi_out_8: - // Output the next 8 bits - out pins, 1 side 0 - // Set TFT_SCLK high and jump for next bit - jmp !osre, spi_out_8 side 1 - // Return to start - jmp start_16 side 0 + // Now send remaining bits + jmp spi_out side 0 public set_addr_window: // Loop count in x for caset, paset and ramwr @@ -34,7 +29,8 @@ pull_cmd: set pins, 0 // Fetch and output LS byte (caset, paset or ramwr), discarding top 24 bits, set WR low pull side 0 - out null, 24 + out pins, 25 + nop side 1 next_cmd_bit: out pins, 1 side 0 jmp !osre, next_cmd_bit side 1 @@ -79,13 +75,15 @@ next_bit: .wrap_target public start_16: // Pull the next 32 bit value from the TX FIFO. - // Write the top 16 bits + // Send the bottom 16 bits pull side 0 - out null, 16 -spi_out_16: - // Output the next 16 bits + // Drop the first 16 bits, write first bit + out pins, 17 side 0 + nop side 1 +spi_out: + // Output the next 15 bits out pins, 1 side 0 // Set TFT_SCLK high and jump for next bit - jmp !osre, spi_out_16 side 1 + jmp !osre, spi_out side 1 // Return to start .wrap diff --git a/Processors/pio_SPI.pio.h b/Processors/pio_SPI.pio.h index 0b1b6a9..a3d1199 100644 --- a/Processors/pio_SPI.pio.h +++ b/Processors/pio_SPI.pio.h @@ -12,46 +12,46 @@ // tft_io // // ------ // -#define tft_io_wrap_target 28 +#define tft_io_wrap_target 27 #define tft_io_wrap 31 #define tft_io_offset_start_8 0u -#define tft_io_offset_set_addr_window 5u -#define tft_io_offset_block_fill 18u -#define tft_io_offset_start_16 28u +#define tft_io_offset_set_addr_window 3u +#define tft_io_offset_block_fill 17u +#define tft_io_offset_start_16 27u static const uint16_t tft_io_program_instructions[] = { 0x90a0, // 0: pull block side 0 0x6078, // 1: out null, 24 - 0x7001, // 2: out pins, 1 side 0 - 0x18e2, // 3: jmp !osre, 2 side 1 - 0x101c, // 4: jmp 28 side 0 - 0xf022, // 5: set x, 2 side 0 - 0xe000, // 6: set pins, 0 - 0x90a0, // 7: pull block side 0 - 0x6078, // 8: out null, 24 - 0x7001, // 9: out pins, 1 side 0 - 0x18e9, // 10: jmp !osre, 9 side 1 - 0xf001, // 11: set pins, 1 side 0 - 0x003c, // 12: jmp !x, 28 - 0x80a0, // 13: pull block - 0x7001, // 14: out pins, 1 side 0 - 0x18ee, // 15: jmp !osre, 14 side 1 - 0x1046, // 16: jmp x--, 6 side 0 - 0x001c, // 17: jmp 28 - 0x90a0, // 18: pull block side 0 - 0xa027, // 19: mov x, osr - 0x80a0, // 20: pull block - 0xa047, // 21: mov y, osr - 0xb0e1, // 22: mov osr, x side 0 - 0x7011, // 23: out pins, 17 side 0 - 0xb842, // 24: nop side 1 - 0x7001, // 25: out pins, 1 side 0 - 0x18f9, // 26: jmp !osre, 25 side 1 - 0x1096, // 27: jmp y--, 22 side 0 + 0x101e, // 2: jmp 30 side 0 + 0xf022, // 3: set x, 2 side 0 + 0xe000, // 4: set pins, 0 + 0x90a0, // 5: pull block side 0 + 0x6019, // 6: out pins, 25 + 0xb842, // 7: nop side 1 + 0x7001, // 8: out pins, 1 side 0 + 0x18e8, // 9: jmp !osre, 8 side 1 + 0xf001, // 10: set pins, 1 side 0 + 0x003b, // 11: jmp !x, 27 + 0x80a0, // 12: pull block + 0x7001, // 13: out pins, 1 side 0 + 0x18ed, // 14: jmp !osre, 13 side 1 + 0x1044, // 15: jmp x--, 4 side 0 + 0x001b, // 16: jmp 27 + 0x90a0, // 17: pull block side 0 + 0xa027, // 18: mov x, osr + 0x80a0, // 19: pull block + 0xa047, // 20: mov y, osr + 0xb0e1, // 21: mov osr, x side 0 + 0x7011, // 22: out pins, 17 side 0 + 0xb842, // 23: nop side 1 + 0x7001, // 24: out pins, 1 side 0 + 0x18f8, // 25: jmp !osre, 24 side 1 + 0x1095, // 26: jmp y--, 21 side 0 // .wrap_target - 0x90a0, // 28: pull block side 0 - 0x6070, // 29: out null, 16 + 0x90a0, // 27: pull block side 0 + 0x7011, // 28: out pins, 17 side 0 + 0xb842, // 29: nop side 1 0x7001, // 30: out pins, 1 side 0 0x18fe, // 31: jmp !osre, 30 side 1 // .wrap diff --git a/TFT_eSPI.cpp b/TFT_eSPI.cpp index 1e64a8b..46d361f 100644 --- a/TFT_eSPI.cpp +++ b/TFT_eSPI.cpp @@ -3214,7 +3214,7 @@ void TFT_eSPI::setWindow(int32_t x0, int32_t y0, int32_t x1, int32_t y1) #else // This is for the RP2040 and PIO interface (SPI or parallel) WAIT_FOR_STALL; - pio->sm[pio_sm].instr = pio_instr_addr; + tft_pio->sm[pio_sm].instr = pio_instr_addr; TX_FIFO = TFT_CASET; TX_FIFO = (x0<<16) | x1; @@ -3441,14 +3441,15 @@ void TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color) #else // This is for the RP2040 and PIO interface (SPI or parallel) WAIT_FOR_STALL; - pio->sm[pio_sm].instr = pio_instr_addr; + tft_pio->sm[pio_sm].instr = pio_instr_addr; TX_FIFO = TFT_CASET; TX_FIFO = (x<<16) | x; TX_FIFO = TFT_PASET; TX_FIFO = (y<<16) | y; TX_FIFO = TFT_RAMWR; //DC set high by PIO - tft_Write_16((uint16_t)color); + TX_FIFO = color; + #endif #else @@ -3667,7 +3668,7 @@ void TFT_eSPI::drawLine(int32_t x0, int32_t y0, int32_t x1, int32_t y1, uint32_t ** Description: Constants for anti-aliased line drawing on TFT and in Sprites ***************************************************************************************/ constexpr float PixelAlphaGain = 255.0; -constexpr float LoAlphaTheshold = 1.0/31.0; +constexpr float LoAlphaTheshold = 1.0/32.0; constexpr float HiAlphaTheshold = 1.0 - LoAlphaTheshold; /*************************************************************************************** @@ -3677,9 +3678,9 @@ constexpr float HiAlphaTheshold = 1.0 - LoAlphaTheshold; uint16_t TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color, uint8_t alpha, uint32_t bg_color) { if (bg_color == 0x00FFFFFF) bg_color = readPixel(x, y); - bg_color = alphaBlend(alpha, color, bg_color); - drawPixel(x, y, bg_color); - return bg_color; + color = alphaBlend(alpha, color, bg_color); + drawPixel(x, y, color); + return color; } /*************************************************************************************** @@ -3688,27 +3689,45 @@ uint16_t TFT_eSPI::drawPixel(int32_t x, int32_t y, uint32_t color, uint8_t alpha ***************************************************************************************/ void TFT_eSPI::fillSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t color, uint32_t bg_color) { + if (r <= 0) return; + inTransaction = true; - int16_t xs = 0; - int16_t cx; + + drawFastHLine(x - r, y, 2 * r + 1, color); + int32_t xs = 1; + int32_t cx = 0; + + int32_t r1 = r * r; r++; - for (int16_t cy = r; cy > 0; cy--) + int32_t r2 = r * r; + + for (int32_t cy = r - 1; cy > 0; cy--) { - for (cx = xs; cx <= xs + 1 && cx < r; cx++) + int32_t dy2 = (r - cy) * (r - cy); + for (cx = xs; cx < r; cx++) { - float deltaX = r - cx; - float deltaY = r - cy; - float alphaf = r - sqrtf(deltaX * deltaX + deltaY * deltaY); - if (alphaf > 1.0) continue; + int32_t hyp2 = (r - cx) * (r - cx) + dy2; + if (hyp2 <= r1) break; + if (hyp2 >= r2) continue; + float alphaf = (float)r - sqrtf(hyp2); + if (alphaf > HiAlphaTheshold) break; xs = cx; if (alphaf < LoAlphaTheshold) continue; uint8_t alpha = alphaf * 255; - drawPixel(x + cx - r, y + cy - r, color, alpha, bg_color); - drawPixel(x - cx + r, y + cy - r, color, alpha, bg_color); - drawPixel(x - cx + r, y - cy + r, color, alpha, bg_color); - drawPixel(x + cx - r, y - cy + r, color, alpha, bg_color); + + if (bg_color == 0x00FFFFFF) { + drawPixel(x + cx - r, y + cy - r, color, alpha, bg_color); + drawPixel(x - cx + r, y + cy - r, color, alpha, bg_color); + drawPixel(x - cx + r, y - cy + r, color, alpha, bg_color); + drawPixel(x + cx - r, y - cy + r, color, alpha, bg_color); + } + else { + uint16_t pcol = drawPixel(x + cx - r, y + cy - r, color, alpha, bg_color); + drawPixel(x - cx + r, y + cy - r, pcol); + drawPixel(x - cx + r, y - cy + r, pcol); + drawPixel(x + cx - r, y - cy + r, pcol); + } } - cx--; drawFastHLine(x + cx - r, y + cy - r, 2 * (r - cx) + 1, color); drawFastHLine(x + cx - r, y - cy + r, 2 * (r - cx) + 1, color); } @@ -3716,40 +3735,45 @@ void TFT_eSPI::fillSmoothCircle(int32_t x, int32_t y, int32_t r, uint32_t color, end_tft_write(); } + /*************************************************************************************** -** Function name: fillSmoothCircle -** Description: Draw a filled anti-aliased circle +** Function name: fillSmoothRoundRect +** Description: Draw a filled anti-aliased rounded corner rectangle ***************************************************************************************/ void TFT_eSPI::fillSmoothRoundRect(int32_t x, int32_t y, int32_t w, int32_t h, int32_t r, uint32_t color, uint32_t bg_color) { inTransaction = true; - int16_t xs = 0; - int16_t cx; + int32_t xs = 0; + int32_t cx = 0; y += r; h -= 2*r; - fillRect(x, y, w, h, color); + fillRect(x, y, w, h + 1, color); x += r; w -= 2*r+1; + int32_t r1 = r * r; r++; + int32_t r2 = r * r; - for (int16_t cy = r; cy > 0; cy--) + for (int32_t cy = r - 1; cy > 0; cy--) { - for (cx = xs; cx <= xs + 1 && cx < r; cx++) + int32_t dy2 = (r - cy) * (r - cy); + for (cx = xs; cx < r; cx++) { - float deltaX = r - cx; - float deltaY = r - cy; - float weight = r - sqrtf(deltaX * deltaX + deltaY * deltaY); - if (weight > 1.0) continue; + int32_t hyp2 = (r - cx) * (r - cx) + dy2; + if (hyp2 <= r1) break; + if (hyp2 >= r2) continue; + float alphaf = (float)r - sqrtf(hyp2); + if (alphaf > HiAlphaTheshold) break; xs = cx; - if (weight < LoAlphaTheshold) continue; - uint8_t alpha = weight * 255; + if (alphaf < LoAlphaTheshold) continue; + uint8_t alpha = alphaf * 255; + drawPixel(x + cx - r, y + cy - r, color, alpha, bg_color); drawPixel(x - cx + r + w, y + cy - r, color, alpha, bg_color); drawPixel(x - cx + r + w, y - cy + r + h, color, alpha, bg_color); drawPixel(x + cx - r, y - cy + r + h, color, alpha, bg_color); } - cx--; drawFastHLine(x + cx - r, y + cy - r, 2 * (r - cx) + 1 + w, color); drawFastHLine(x + cx - r, y - cy + r + h, 2 * (r - cx) + 1 + w, color); } diff --git a/TFT_eSPI.h b/TFT_eSPI.h index e65eccb..e5c8e39 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.40" +#define TFT_ESPI_VERSION "2.4.41" // Bit level feature flags // Bit 0 set: viewport capability diff --git a/library.json b/library.json index 0894465..49cd36e 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "TFT_eSPI", - "version": "2.4.40", + "version": "2.4.41", "keywords": "Arduino, tft, ePaper, display, Pico, RP2040, STM32, ESP8266, NodeMCU, ESP32, M5Stack, ILI9341, ST7735, ILI9163, S6D02A1, ILI9481, ILI9486, ILI9488, ST7789, RM68140, SSD1351, SSD1963, ILI9225, HX8357D", "description": "A TFT and ePaper SPI graphics library with optimisation for Raspberry Pi Pico, ESP8266, ESP32 and STM32", "repository": diff --git a/library.properties b/library.properties index c05b80e..30deb7a 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=TFT_eSPI -version=2.4.40 +version=2.4.41 author=Bodmer maintainer=Bodmer sentence=TFT graphics library for Arduino processors with performance optimisation for RP2040, STM32, ESP8266 and ESP32