diff --git a/.gitignore b/.gitignore index ae9acc0..adf74d0 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -_archived/ \ No newline at end of file +*.zip +exclude/ +compare/ \ No newline at end of file diff --git a/README.md b/README.md index 8d7dd34..17f9dc0 100644 --- a/README.md +++ b/README.md @@ -4,8 +4,11 @@ The GFX4dESP32 library is provided by 4D Systems for use with gen4-ESP32-XX prod Note however that some functionalities might not be supported by a certain product types, depending on its specifications. For instance, non-touch variants have no access to all touch-related functions. For more information on the specifications of a product, refer to its datasheet. -To install the library, please refer to the instructions in **Workshop4 ESP32 Development Manual** +To install the library, please refer to the instructions in [Workshop4 ESP32 Development Manual](https://resources.4dsystems.com.au/manuals/workshop4/esp32/#install-via-library-manager) It is recommended to use Workshop4 IDE to get the most of out the library functions. -**Note**: Workshop4 is a **Windows-only** application. +### Notes + +1. Workshop4 is a **Windows-only** application. +2. This is tested against Arduino ESP32 Core version 2.0.13. It might also work with 2.0.14 or higher but if any issues occur, it is recommend to try to set the boards package version to 2.0.13. If the issue persists, please don't hesitate to [write an issue](https://github.com/4dsystems/GFX4dESP32/issues/new) or contact us directly. diff --git a/extras/gfx4dESP32.fnc b/extras/gfx4dESP32.fnc index f6f6c81..075da94 100644 --- a/extras/gfx4dESP32.fnc +++ b/extras/gfx4dESP32.fnc @@ -114,6 +114,22 @@ void gfx.PutPixel(x, y, colour), void; // Write 1 pixel at co-ordinates x, y and // Notes : Write 1 pixel at co-ordinates x, y and colour. // +void gfx.PutPixelAlpha(x, y, colour, alpha), void; // Draws a pixel to the current frame buffer with color parameter switch +// Syntax : gfx.PutPixelAlpha(x, y, colour); +// Usage : gfx.PutPixelAlpha(10, 10, GCI_IMAGE + 3, 255); +// : gfx.PutPixelAlpha(10, 10, FRAMEBUFFER_IMAGE + 3, 127); +// : gfx.PutPixelAlpha(10, 10, RED, 127); +// Notes : Draws a pixel to the current frame buffer with color parameter switch. +// : 'colour' can be a 16bit color or a GCI image or a FrameBuffer +// : ex. gfx.PutPixelAlpha(10, 10, GCI_IMAGE + 3, 255) draws a pixel at 10, 10 +// : from GCI image index 3 and full alpha level. x and y are relative to objects x and y. +// : ex. gfx.PutPixelAlpha(10, 10, FRAMEBUFFER_IMAGE + 3, 127) draws a pixel at 10, 100 +// : from GCI image index 3 with half alpha at the same x and y position. +// : ex. gfx.PutPixelAlpha(10, 10, RED, 127) draws a RED pixel at 10, 10 +// : with half alpha at the same x and y position. +// + + int16_t gfx.getHeight(), word; // Returns the height of the display in pixels. // Syntax : gfx.getHeight(); // Usage : gfx.getHeight(); @@ -255,7 +271,16 @@ void gfx.Cls([colour]), void; // Clears the screen with the specified colour or void gfx.begin(), void; // Initialize the screen // Syntax : gfx.begin(); // Usage : gfx.begin(); -// Notes : Initialize the screen +// Notes : Initialize global variables, orientation and clears the screen +// : uSD is mounted at this stage and called separately. +// : begin(); // start with default settings +// : begin(IPS_DISPLAY); // use ips display +// : begin(18); // set display clock to 18Mhz +// : begin(false); // start without backlight on +// : begin(IPS_DISPLAY, 18); // start with ips at 18Mhz +// : begin(IPS_DISPLAY, true); // start with ips and backlight on +// : begin(20, false); // start at 20Mhz and backlight off +// : begin(IPS_DISPLAY, 40, false); // start with ips at 40Mhz and backlight off // void gfx.ScrollEnable(mode), void; // Enable or disable auto scrolling @@ -321,6 +346,18 @@ void gfx.Arc(x, y, r, quadrants, colour), void; // Draw a 90-degree Arc with cen // : Support function for outline rounded rectangles and circles // +void gfx.RectangleFilledX(x1, y1, x2, y2, colour), void; // Draws a rectangle to the current frame buffer with color parameter switch +// Syntax : gfx.RectangleFilledX(x1, y1, x2, y2, colour); +// Usage : gfx.RectangleFilledX(10, 10, 100, 100, GCI_IMAGE + 3); +// : gfx.RectangleFilledX(10, 10, 100, 100, FRAMEBUFFER_IMAGE + 3); +// Notes : Draws a filled rectangle having a diagonal with endpoints at (x1, y1) and (x2, y2) with colour 'colour'. +// : 'colour' can be a 16bit color or a GCI image or a FrameBuffer +// : ex. gfx.RectangleFilledX(10, 10, 100, 100, GCI_IMAGE + 3) draws a rectangle at 10, 10 +// : from GCI image index 3. x and y are relative to objects x and y. +// : ex. gfx.RectangleFilledX(10, 10, 100, 100, FRAMEBUFFER_IMAGE + 3) draws a rectangle at 10, 10 +// : from framebuffer 3 at the same x and y position. +// + void gfx.RectangleFilled(x1, y1, x2, y2, colour), void; // Draws a filled rectangle having a diagonal with endpoints at (x1, y1) and (x2, y2) with colour 'colour'. // Syntax : gfx.RectangleFilled(x1, y1, x2, y2, colour); // Usage : gfx.RectangleFilled(10, 20, 110, 170, RED); @@ -624,12 +661,36 @@ void gfx.HlineD(y, x1, x2, colour), void; // Draw fast horizontal line from (x1, // Notes : Draw fast horizontal line from (x1, y) to (x2, y) - 4DGL compatible function // +void gfx.HlineX(x, y, w, colour), void; // Draws a horizontal line to the current frame buffer with color parameter switch. +// Syntax : gfx.HlineX(x, y, h, colour); +// Usage : gfx.HlineX(10, 10, 100, GCI_IMAGE + 3); +// : gfx.HlineX(10, 10, 100, FRAMEBUFFER_IMAGE + 3); +// Notes : Draws a horizontal line to the current frame buffer with color parameter switch. +// : 'colour' can be a 16bit color or a GCI image or a FrameBuffer +// : ex. gfx.HlineX(10, 10, 100, GCI_IMAGE + 3) draws a horizontal line at 10, 10 and a length of 100 pixels +// : from GCI image index 3. x and y are relative to objects x and y. +// : ex. gfx.HlineX(10, 10, 100, FRAMEBUFFER_IMAGE + 3) draws a horizontal line at 10, 10 and a length of 100 pixels +// : from GCI image index 3 at the same x and y position. +// + void gfx.VlineD(x, y1, y2, colour), void; // Draw fast vertical line from (x1, y) to (x2, y) // Syntax : gfx.VlineD(x, y1, y2, colour); // Usage : gfx.VlineD(x, y1, y2, colour); // Notes : Draw fast vertical line from (x, y1) to (x, y1) - 4DGL compatible function // +void gfx.VlineX(x, y, w, colour), void; // Draws a vertical line to the current frame buffer with color parameter switch. +// Syntax : gfx.VlineX(x, y, w, colour); +// Usage : gfx.VlineX(10, 10, 100, GCI_IMAGE + 3); +// : gfx.VlineX(10, 10, 100, FRAMEBUFFER_IMAGE + 3); +// Notes : Draws a vertical line to the current frame buffer with color parameter switch. +// : 'colour' can be a 16bit color or a GCI image or a FrameBuffer +// : ex. gfx.VlineX(10, 10, 100, GCI_IMAGE + 3) draws a vertical line at 10, 10 and a length of 100 pixels +// : from GCI image index 3. x and y are relative to objects x and y. +// : ex. gfx.VlineX(10, 10, 100, FRAMEBUFFER_IMAGE + 3) draws a vertical line at 10, 10 and a length of 100 pixels +// : from GCI image index 3 at the same x and y position. +// + void gfx.gradientShape(vert, ow, xPos, yPos, w, h, r1, r2, r3, r4, darken, colour, sr1, gl1, colorD, sr3, gl3, gtb), void; // Draw a shaped color gradient using the supplied parameters // Syntax : gfx.gradientShape(vert, ow, xPos, yPos, w, h, r1, r2, r3, r4, darken, colour, sr1, gl1, colorD, sr3, gl3, gtb); // Usage : gfx.gradientShape(vert, ow, xPos, yPos, w, h, r1, r2, r3, r4, darken, colour, sr1, gl1, colorD, sr3, gl3, gtb); @@ -847,6 +908,12 @@ void gfx.DrawToframebuffer(fbnum), void; // Set the frame buffer for drawing fun // : If frame buffer 0 is set (default) all drawing functions will appear immediately on the display. // +void gfx.GetFrameBuffer(), uint8_t; // Get the number of the current frame buffer in use. +// Syntax : gfx.GetFrameBuffer(); +// Usage : gfx.GetFrameBuffer(); +// Notes : Returns current frame buffer number. +// + void gfx.SpriteAreaSet(x, y, x1, y1), void; // Sets the area of the screen that sprites will be displayed in. // Syntax : gfx.SpriteAreaSet(x, y, x1, y1); // Usage : gfx.SpriteAreaSet(x, y, x1, y1); @@ -1021,7 +1088,7 @@ int gfx.imageGetWord(img, controlIndex), 1; // Queries the current selected para // Syntax : gfx.imageGetWord(img, controlIndex); // Usage : gfx.imageGetWord(img, controlIndex); // Notes : Queries the current selected parameter of the GCI widget -// : Parameters can be IMAGE_XPOS, IMAGE_YPOS, IMAGE_WIDTH or IMAGE_HEIGHT +// : Parameters can be IMAGE_XPOS, IMAGE_YPOS, IMAGE_WIDTH, IMAGE_HEIGHT or IMAGE_INDEX // void gfx.imageSetWord(img, controlIndex, val1 [, val2]), void; // Sets the selected parameter(s) of the GCI widget @@ -1030,8 +1097,8 @@ void gfx.imageSetWord(img, controlIndex, val1 [, val2]), void; // Sets the selec // Usage : gfx.imageSetWord(img, IMAGE_XYPOS, val1, val2); // : gfx.imageSetWord(img, controlIndex, val1); // Notes : Sets the selected parameter(s) of the GCI widget -// : Parameters can be IMAGE_XPOS, IMAGE_YPOS, or IMAGE_XYPOS -// : WHen using IMAGE_XYPOS, two values are required +// : Parameters can be IMAGE_XPOS, IMAGE_YPOS, IMAGE_XYPOS or IMAGE_INDEX +// : When using IMAGE_XYPOS, two values are required // int16_t gfx.getImageValue(ui), 1; // Returns the current value of a GCI widget diff --git a/keywords.txt b/keywords.txt index 649bb87..460ea56 100644 --- a/keywords.txt +++ b/keywords.txt @@ -64,11 +64,14 @@ Clipping KEYWORD2 ClipWindow KEYWORD2 Cls KEYWORD2 Contrast KEYWORD2 +CopyFrameBufferLine KEYWORD2 +CopyImageLine KEYWORD2 DecodeKeypad KEYWORD2 DeleteButton KEYWORD2 DeleteButtonBG KEYWORD2 DigitalRead KEYWORD2 DigitalWrite KEYWORD2 +DisplayControl KEYWORD2 Download KEYWORD2 DownloadFile KEYWORD2 drawBitmap KEYWORD2 @@ -85,6 +88,7 @@ FontHeight KEYWORD2 FontStyle KEYWORD2 GetCommand KEYWORD2 getFontData KEYWORD2 +GetFrameBuffer KEYWORD2 getHeight KEYWORD2 getImageValue KEYWORD2 getNumberofObjects KEYWORD2 @@ -102,6 +106,7 @@ getY KEYWORD2 gradientShape KEYWORD2 GradTriangleFilled KEYWORD2 Hline KEYWORD2 +HlineX KEYWORD2 Grad KEYWORD2 touch_GetInvertMode KEYWORD2 imageAutoKnob KEYWORD2 @@ -135,13 +140,17 @@ putch KEYWORD2 putchXY KEYWORD2 PutColor KEYWORD2 PutPixel KEYWORD2 +PutPixelAlpha KEYWORD2 putstr KEYWORD2 putstrXY KEYWORD2 ReadCommand KEYWORD2 +ReadImagePixel KEYWORD2 ReadLine KEYWORD2 ReadPixel KEYWORD2 +ReadPixelFromFrameBuffer KEYWORD2 Rectangle KEYWORD2 RectangleFilled KEYWORD2 +RectangleFilledX KEYWORD2 ResetKeypad KEYWORD2 RGBto565 KEYWORD2 RoundRect KEYWORD2 @@ -221,6 +230,7 @@ UserImageHideBG KEYWORD2 UserImages KEYWORD2 UserImagesDR KEYWORD2 Vline KEYWORD2 +VlineX KEYWORD2 WrGRAMs KEYWORD2 write KEYWORD2 WriteLine KEYWORD2 @@ -477,4 +487,27 @@ DISPLAY_TOUCH_TYPE LITERAL1 DISP_TOUCH_NONE LITERAL1 DISP_TOUCH_CTP LITERAL1 DISP_TOUCH_RTP LITERAL1 -NO_TRANSPARENCY LITERAL1 \ No newline at end of file +NO_TRANSPARENCY LITERAL1 +GEN4_I2C_SDA LITERAL1 +GEN4_I2C_SCL LITERAL1 +GEN4_SPI_DISPLAY LITERAL1 +GEN4_RGB_DISPLAY LITERAL1 +DISP_CTRL_RE_INIT LITERAL1 +DISP_CTRL_RESET LITERAL1 +DISP_CTRL_NEW LITERAL1 +DISP_CTRL_INIT LITERAL1 +DISP_CTRL_STOP LITERAL1 +DISP_CTRL_START_TX LITERAL1 +DISP_CTRL_DEL LITERAL1 +DISP_CTRL_START LITERAL1 +DISP_CTRL_FLUSH LITERAL1 +DISP_CTRL_RESTART_TX LITERAL1 +DISP_CTRL_RESET_ON_VSYNC LITERAL1 +DISP_CTRL_SET_CLOCK LITERAL1 +DISP_CTRL_FILL_BOUNCE_BUFFER LITERAL1 +GCI_IMAGE LITERAL1 +FRAMEBUFFER_IMAGE LITERAL1 +BEGIN_WITH_BACKLIGHT_ON LITERAL1 +BEGIN_WITH_BACKLIGHT_OFF LITERAL1 + + diff --git a/library.properties b/library.properties index 52c74fd..65f9205 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=GFX4dESP32 -version=1.0.0 +version=1.0.1 author=4D Systems Pty Ltd maintainer=4D Systems Pty Ltd sentence=Graphics Library for the gen4-ESP32 displays by 4D Systems diff --git a/src/gfx4desp32.cpp b/src/gfx4desp32.cpp index ff101e0..63176d0 100644 --- a/src/gfx4desp32.cpp +++ b/src/gfx4desp32.cpp @@ -7,26 +7,74 @@ b = tab; \ } +#define calcAlpha(a, b, c) \ + { \ + __alphatemp = c >> 3; \ + uint32_t fgu = a; \ + uint32_t bgu = b; \ + uint32_t fg = (fgu | (fgu << 16)) & 0x07e0f81f; \ + uint32_t bg = (bgu | (bgu << 16)) & 0x07e0f81f; \ + bg += (fg - bg) * __alphatemp >> 5; bg &= 0x07e0f81f; \ + __colour = (uint16_t)(bg | bg >> 16); \ + } + gfx4desp32::gfx4desp32() {} gfx4desp32::~gfx4desp32() {} +#ifndef USE_LITTLEFS_FILE_SYSTEM +#ifndef USE_SDMMC_FILE_SYSTEM SdFat gfx4desp32::uSD; SdFat& gfx4desp32::getSdFatInstance() { return uSD; } +#else +#include "SD_MMC.h" +#endif +#endif + +/****************************************************************************/ +/*! + @brief Begin gfx4desp32. + @param ips - sets if ips display is being used IPS_DISPLAY or TN_DISPLAY if not ips + Default is TN_DISPLAY + pval - sets the value of display clock in Mhz eg 13 = 13000000 + backLightStartOn, true or false. sets startup behaviour of backlight. + @note sets global variables, orientation and clears the screen. + uSD is mounted at this stage and called seperately. + begin(); start with default settings + begin(IPS_DISPLAY); // use ips display + begin(18); // set display clock to 18Mhz + begin(false); // start without backlight on + begin(IPS_DISPLAY, 18); // start with ips at 18Mhz + begin(IPS_DISPLAY, true); // start with ips and backlight on + begin(20, false); // start at 20Mhz and backlight off + begin(IPS_DISPLAY, 40, false); // start with ips at 40Mhz and backlight off +*/ +/****************************************************************************/ +void gfx4desp32::begin(String ips) { begin(ips, 0, true); } +void gfx4desp32::begin(int pval) { begin(DEFAULT_DISPLAY, pval, true); } +void gfx4desp32::begin(bool backLightStartOn) { begin(DEFAULT_DISPLAY, 0, backLightStartOn); } +void gfx4desp32::begin(String ips, int pval) { begin(ips, pval, true); } +void gfx4desp32::begin(String ips, bool backLightStartOn) { begin(ips, 0, backLightStartOn); } +void gfx4desp32::begin(int pval, bool backLightStartOn) { begin(DEFAULT_DISPLAY, pval, backLightStartOn); } /****************************************************************************/ /*! @brief Begin gfx4desp32. - @note sets global variables, orientation and clears the screen. - uSD is mounted at this stage and called seperately. + @note sets global variables, orientation and clears the screen. + uSD is mounted at this stage and called seperately. */ /****************************************************************************/ -void gfx4desp32::begin(String ips) { +void gfx4desp32::begin(String ips, int pval, bool backLightStartOn) { + if (pval >= 13) { + changePCLK = true; + PCLKval = pval * 1000 * 1000; + } if (ips == IPS_DISPLAY) IPS_Display = true; if (ips == TN_DISPLAY) IPS_Display = false; + if (backLightStartOn) bkStartOn = true; GCItype = GCI_SYSTEM_USD; __begin(); // start panel panelOrientation(0); // set default orientation @@ -46,13 +94,13 @@ void gfx4desp32::begin(String ips) { wrap = true; // turn on wrap fno = 1; // set system font 1 fsh = 8; // set font height - lastfsh = 8; // match last font height - used by sutoscroll if font changes + lastfsh = 8; // match last font height - used by autoscroll if font changes // and scroll is needed fsw = 5; // set font width scrolled = false; // legacy variable used for hardware scroll sEnable = false; // disable auto scroll nl = false; // set newline needed flag to false - ssSpeed = 5; // set default smooth scroll to 5 - maybe we should default to 0, + ssSpeed = 0; // set default smooth scroll to 5 - maybe we should default to 0, // smooth scroll off twcolnum = 13; // set default text window column number tchen = true; @@ -66,6 +114,24 @@ void gfx4desp32::begin(String ips) { else { sdok = false; } +#else +#ifdef USE_SDMMC_FILE_SYSTEM +#ifndef SDMMC_4BIT + pinMode(sd_cs, OUTPUT); + digitalWrite(sd_cs, HIGH); + SD_MMC.setPins(sd_sck, sd_mosi, sd_miso); + if (SD_MMC.begin("/sdcard", true, 50000)) +#else + if (displayBus == DISPLAY_BUS_SPI) SD_MMC.setPins(SPI_SDMMC_4BIT_CLK, SPI_SDMMC_4BIT_CMD, SPI_SDMMC_4BIT_DATA0, SPI_SDMMC_4BIT_DATA1, SPI_SDMMC_4BIT_DATA2, SPI_SDMMC_4BIT_DATA3); + if (displayBus == DISPLAY_BUS_QSPI) SD_MMC.setPins(QSPI_SDMMC_4BIT_CLK, QSPI_SDMMC_4BIT_CMD, QSPI_SDMMC_4BIT_DATA0, QSPI_SDMMC_4BIT_DATA1, QSPI_SDMMC_4BIT_DATA2, QSPI_SDMMC_4BIT_DATA3); + if (SD_MMC.begin("/sdcard", false, 50000)) +#endif + { + sdok |= true; + } + else { + sdok |= false; + } #else SPI.begin(sd_sck, sd_miso, sd_mosi); @@ -77,7 +143,12 @@ void gfx4desp32::begin(String ips) { sdok |= false; } #endif - psRAMbuffer1 = (uint8_t*)ps_malloc(1024000); +#endif + AllocateFB(0); + //psRAMbuffer1 = (uint8_t*)ps_malloc(1024000); + if (bkStartOn) { + Contrast(BK_LIGHT_STARTUP_LEVEL); + } } /****************************************************************************/ @@ -591,14 +662,16 @@ void gfx4desp32::drawChar4Dcmp(int16_t x, int16_t y, unsigned char c, void gfx4desp32::MoveTo(int16_t x, int16_t y) { cursor_x = x; cursor_y = y; - if (cursor_y > (height - 1)) - cursor_y = (height - 1); - if (cursor_y < 0) - cursor_y = 0; - if (cursor_x < 0) - cursor_x = 0; - if (cursor_x > (width - 1)) - cursor_x = width - 1; + if (wrap == true) { + if (cursor_y > (height - 1)) + cursor_y = height - 1; + if (cursor_y < 0) + cursor_y = 0; + if (cursor_x < 0) + cursor_x = 0; + if (cursor_x > (width - 1)) + cursor_x = width - 1; + } nl = false; } @@ -1424,7 +1497,11 @@ void gfx4desp32::_Open4dGFX(String file4d, bool scan) { } #else if (GCItype == GCI_SYSTEM_USD) { +#ifdef USE_SDMMC_FILE_SYSTEM + userDat = SD_MMC.open(dat4d); +#else userDat = uSD.open(dat4d); +#endif } if (GCItype == GCI_SYSTEM_PROGMEM) { datArrayPos = 0; @@ -1471,7 +1548,7 @@ void gfx4desp32::_Open4dGFX(String file4d, bool scan) { } if (GCItype == GCI_SYSTEM_PROGMEM) { while (datArrayPos < datArraySize) { - c = (char) DATarray[datArrayPos++]; + c = (char)DATarray[datArrayPos++]; if (c != 13 && c != 10) { strpos++; if (c == 34) { @@ -1518,7 +1595,11 @@ void gfx4desp32::_Open4dGFX(String file4d, bool scan) { } #else if (GCItype == GCI_SYSTEM_USD) { +#ifdef USE_SDMMC_FILE_SYSTEM + userImag = SD_MMC.open((char*)gci4d.c_str()); +#else userImag = uSD.open((char*)gci4d.c_str()); +#endif } if (GCItype == GCI_SYSTEM_PROGMEM) { gciArrayPos = 0; @@ -1548,9 +1629,13 @@ gfx4d_font gfx4desp32::Open4dFont(String font4d) { #ifdef USE_LITTLEFS_FILE_SYSTEM String tstring = "/" + font4d; return LittleFS.open((char*)tstring.c_str(), "r"); +#else +#ifdef USE_SDMMC_FILE_SYSTEM + return SD_MMC.open(font4d); #else return uSD.open(font4d); #endif +#endif } /****************************************************************************/ @@ -1685,8 +1770,9 @@ void gfx4desp32::DrawWidget(uint32_t Index, int16_t uix, int16_t uiy, (!transalpha) && (!WriteFBonly) && (frame_buffer == 0); SetGRAM(uix, uiy, x1, y1); pos = (isize * frame); - GCIreadToBuff(Index + ofst + pos, isize); + //GCIreadToBuff(Index + ofst + pos, isize); if (GCItype == GCI_SYSTEM_USD) { + GCIreadToBuff(Index + ofst + pos, isize); if (usePushColors && frame_buffer == 0) { pushColors(psRAMbuffer1, isize >> 1); } @@ -1881,7 +1967,11 @@ int16_t gfx4desp32::getLastPointerPos() { return LastLinearPointerPosition; } /****************************************************************************/ void gfx4desp32::DrawImageFile(String Fname) { #ifndef USE_LITTLEFS_FILE_SYSTEM +#ifdef USE_SDMMC_FILE_SYSTEM + dataFile = SD_MMC.open((char*)Fname.c_str()); +#else dataFile = uSD.open((char*)Fname.c_str()); +#endif #else Fname = "/" + Fname; dataFile = LittleFS.open((char*)Fname.c_str(), "r"); @@ -1910,7 +2000,11 @@ void gfx4desp32::DrawImageFile(String Fname) { /****************************************************************************/ void gfx4desp32::DrawImageFile(const char* Fname) { #ifndef USE_LITTLEFS_FILE_SYSTEM +#ifdef USE_SDMMC_FILE_SYSTEM + dataFile = SD_MMC.open(Fname); +#else dataFile = uSD.open(Fname); +#endif #else String temp = "/" + String(Fname); dataFile = LittleFS.open((char*)temp.c_str(), "r"); @@ -2472,8 +2566,9 @@ void gfx4desp32::UserImageDRcache(uint16_t ui, int16_t uxpos, int16_t uypos, (GCItype == GCI_SYSTEM_PROGMEM && (!gcidatArray))) return; if (!cache_Enabled) { - psRAMbuffer2 = (uint8_t*)ps_malloc(DRcache); - cache_Enabled = true; + AllocateDRcache(DRcache); + //psRAMbuffer2 = (uint8_t*)ps_malloc(DRcache); + //cache_Enabled = true; } int32_t bwidth = tuiw[ui] << 1; uint32_t slen; @@ -2560,6 +2655,23 @@ void gfx4desp32::Orbit(int angle, int lngth, int* oxy) { oxy[1] = (int)(sy * lngth + cursor_y); } +/****************************************************************************/ +/*! + @brief calculate float x & y co-ordinate using given angle and length using current + x - y origin (MoveTo) + @param angle - Degrees + @param length - Pixels from x - y origin + @param oxy - prefined 2 float array containing x at location 0 and y at + location 1 +*/ +/****************************************************************************/ +void gfx4desp32::Orbit(float angle, float lngth, float* oxy) { + float sx = cos((angle - 90) * 0.0174532925); + float sy = sin((angle - 90) * 0.0174532925); + oxy[0] = (sx * lngth + cursor_x); + oxy[1] = (sy * lngth + cursor_y); +} + /****************************************************************************/ /*! @brief convert R, G, B to RGB565 @@ -3716,9 +3828,9 @@ void gfx4desp32::GradTriangleFilled(int x0, int y0, int x1, int y1, int x2, uint16_t gfx4desp32::Grad(int GraisSunk, int Gstate, int Gglev, int Gh1, int Gpos, uint16_t colToAdj) { // **** Modified gradients for vertical again **** *new* - uint32_t __alpha; - uint32_t __alphatemp; - uint16_t __colour; + //uint32_t __alpha; + //uint32_t __alphatemp; + //uint16_t __colour; int tgcol = colToAdj; int CTAr, CTAg, CTAb; int CTALevel; @@ -4502,10 +4614,18 @@ bool gfx4desp32::ScreenCapture(int16_t x, int16_t y, int16_t w, int16_t h, } if ((y + h) > height) h = height - y; + +#ifdef USE_SDMMC_FILE_SYSTEM + File tempfile; + if (SD_MMC.exists(fname)) + return false; + tempfile = SD_MMC.open(fname, FILE_WRITE); +#else FsFile tempfile; if (uSD.exists(fname)) return false; tempfile = uSD.open(fname, FILE_WRITE); +#endif int n, o, wline; uint16_t sline[w]; for (n = 0; n < h; n++) { @@ -4538,11 +4658,255 @@ bool gfx4desp32::ScreenCapture(int16_t x, int16_t y, int16_t w, int16_t h, /****************************************************************************/ void gfx4desp32::FontStyle(uint8_t ctyp) { fstyle = ctyp % 6; } +/****************************************************************************/ +/*! + @brief Get the number of the current frame buffer in use. + @note returns current frame buffer number. +*/ +/****************************************************************************/ +uint8_t gfx4desp32::GetFrameBuffer() { + return frame_buffer; +} + +/****************************************************************************/ +/*! + @brief Read the colour value of a pixel within a GCI object. + @param inum - GCI object index. + @param x - The X position that the pixel would be at if the image was drawn on-screen + @param y - The Y position that the pixel would be at if the image was drawn on-screen + @note returns 16bit colour value. +*/ +/****************************************************************************/ +uint16_t gfx4desp32::ReadImagePixel(int inum, int x, int y) { + if ((GCItype == GCI_SYSTEM_USD && (!userImag)) || + (GCItype == GCI_SYSTEM_PROGMEM && (!gcidatArray))) + return 0; + int yc = y - tuiy[inum]; + int xc = x - tuix[inum]; + if (y < tuiy[inum] || x < tuix[inum]) return 0; + if (y > tuiy[inum] + tuih[inum] - 1 || x > tuix[inum] + tuiw[inum] - 1) return 0; + uint32_t ofst = 6; + ofst += ((gciobjframes[inum] > 0) << 1); + uint32_t pos = ((yc * tuiw[inum]) << 1) + (xc << 1); + if (ofst == 8) ofst += (((tuiw[inum] * tuih[inum]) * tuiImageIndex[inum]) << 1); + GCIreadToBuff(tuiIndex[inum] + ofst + pos, 2); + return psRAMbuffer1[1] + (psRAMbuffer1[0] << 8); +} + +/****************************************************************************/ +/*! + @brief Copies a horizontal line from GCI object to the current frame buffer. + @param inum - GCI object index. + @param x - The X position that the line would start if the image was drawn on-screen + @param y - The Y position that the line would start if the image was drawn on-screen + @param w - The length of the line to be copied + @note returns nothing. +*/ +/****************************************************************************/ +void gfx4desp32::CopyImageLine(int inum, int x, int y, int w) { + if (y > tuiy[inum] + tuih[inum] - 1 || y < 0) + return; + if (x > tuix[inum] + tuiw[inum] - 1 || (x + w - 1) < 0) + return; + if (w < 0) { + x += w; + //w *= -1; + w = abs(w); + } + if (x < tuix[inum]) { + w += x; + x = 0; + } + //if ((x + w - 1) >= tuix[inum] + tuiw[inum] - 1) + // w = tuiw[inum] - x; + int yc = y - tuiy[inum]; + int xc = x - tuix[inum]; + if ((GCItype == GCI_SYSTEM_USD && (!userImag)) || + (GCItype == GCI_SYSTEM_PROGMEM && (!gcidatArray))) + return; + uint32_t ofst = 6; + ofst += ((gciobjframes[inum] > 0) << 1); + uint32_t pos = ((yc * tuiw[inum]) << 1) + (xc << 1); + if (ofst == 8) ofst += (((tuiw[inum] * tuih[inum]) * tuiImageIndex[inum]) << 1); + GCIreadToBuff(tuiIndex[inum] + ofst + pos, w << 1); + usePushColors = (DisplayType == DISP_INTERFACE_RGB) && (x >= clipx1) && + (y >= clipy1) && (x + w <= clipx2) && (y <= clipy2) && + (!transalpha) && (!WriteFBonly) && (frame_buffer == 0); + SetGRAM(x, y, x + w - 1, y); + // if (GCItype == GCI_SYSTEM_USD) { + if (usePushColors && frame_buffer == 0) { + pushColors(psRAMbuffer1, w); + } + else { + WrGRAMs(psRAMbuffer1, w); + } +} + +/****************************************************************************/ +/*! + @brief draws a horizontal line to the current frame buffer with color parameter switch. + @param x - The X position of the start of the line + @param y - The Y position of the start of the line + @param w - The length of the line to be drawn + @param color - can be a 16bit color or a GCI image or a FrameBuffer + HlineX(10, 10, 100, GCI_IMAGE + 3) draws a line at 10, 10 and a length of + 100 pixels from GCI image index 3. x and y are relative to objects x and y + position. + HlineX(10, 10, 100, FRAMEBUFFER_IMAGE + 3) draws a line at 10, 10 and a length of + 100 pixels from frame buffer 3 at the same x and y position. + @note returns nothing. +*/ +/****************************************************************************/ +void gfx4desp32::HlineX(int x, int y, int w, int32_t color) { + if (w < 1) return; + uint8_t fB = 0; + int16_t imageNum = -1; + int gpos = 7 * (gradON == 2); + if ((color & 0xffff0000) == 0xf00000) fB = color & 0x000f; + if ((color & 0xffff0000) == 0xf0000) imageNum = color & 0xffff; + uint16_t fgcol = color; + if (fB) { + CopyFrameBufferLine(x, y, w, fB); + } + else if (imageNum != -1) { + CopyImageLine(imageNum, x, y, w); + } + else { + if (gradON) { + Hline(x, y, w, Grad(grad1[0 + gpos], grad1[1 + gpos], grad1[2 + gpos], grad1[3 + gpos], y - grad1[6 + gpos], fgcol)); + } + else { + Hline(x, y, w, fgcol); + } + } +} + +/****************************************************************************/ +/*! + @brief draws a vertical line to the current frame buffer with color parameter switch. + @param x - The X position of the start of the line + @param y - The Y position of the start of the line + @param w - The length of the line to be drawn + @param color - can be a 16bit color or a GCI image or a FrameBuffer + VlineX(10, 10, 100, GCI_IMAGE + 3) draws a line at 10, 10 and a length of + 100 pixels from GCI image index 3. x and y are relative to objects x and y + position. + VlineX(10, 10, 100, FRAMEBUFFER_IMAGE + 3) draws a line at 10, 10 and a length of + 100 pixels from frame buffer 3 at the same x and y position. + @note returns nothing. +*/ +/****************************************************************************/ +void gfx4desp32::VlineX(int x, int y, int w, int32_t color) { + if (w < 1) return; + uint8_t fB = 0; + int16_t imageNum = -1; + int gpos = 7 * (gradON == 2); + if ((color & 0xffff0000) == 0xf00000) fB = color & 0x000f; + if ((color & 0xffff0000) == 0xf0000) imageNum = color & 0xffff; + uint16_t fgcol = color; + if (fB || imageNum != -1 || (gradON && !gradientVert)) { + for (int n = 0; n < w; n++) { + if (fB) { + fgcol = ReadPixelFromFrameBuffer(x, y + n, fB); + } + else { + fgcol = ReadImagePixel(imageNum, x, y + n); + } + if (gradON) fgcol = Grad(grad1[0 + gpos], grad1[1 + gpos], grad1[2 + gpos], grad1[3 + gpos], (y + n) - grad1[6 + gpos], color); + PutPixel(x, y + n, fgcol); + } + } + else { + if (gradientVert) fgcol = Grad(grad1[0 + gpos], grad1[1 + gpos], grad1[2 + gpos], grad1[3 + gpos], x - grad1[6 + gpos], color); + Vline(x, y, w, fgcol); + } +} + +/****************************************************************************/ +/*! + @brief draws a rectangle to the current frame buffer with color parameter switch. + @param x0 - The X position of the top left corner of the rectangle + @param y0 - The Y position of the top left corner of the rectangle + @param x1 - The X position of the bottom right corner of the rectangle + @param y1 - The Y position of the bottom right corner of the rectangle + @param color - can be a 16bit color or a GCI image or a FrameBuffer + RectangleFilledX(10, 10, 100, 100, GCI_IMAGE + 3) draws a rectangle at 10, 10 + from GCI image index 3. x and y are relative to objects x and y. + RectangleFilledX(10, 10, 100, 100, FRAMEBUFFER_IMAGE + 3) draws a rectangle at 10, 10 + from framebuffer 3 at the same x and y position. + @note returns nothing. +*/ +/****************************************************************************/ +void gfx4desp32::RectangleFilledX(int x0, int y0, int x1, int y1, int32_t color) { + uint8_t fB = 0; + int16_t imageNum = -1; + int w = x1 - x0 + 1; + int h = y1 - y0 + 1; + if ((color & 0xffff0000) == 0xf00000) fB = color & 0x000f; + if ((color & 0xffff0000) == 0xf0000) imageNum = color & 0xffff; + uint16_t fgcol = color; + if (fB) { + DrawFrameBufferArea(fB, x0, y0, x1, y1); + } + else if (imageNum != -1) { + UserImageDR(imageNum, x0, y0, w, h, x0, y0); + } + else { + RectangleFilled(x0, y0, x1, y1, color); + } +} + +/****************************************************************************/ +/*! + @brief draws a pixel to the current frame buffer with color parameter switch. + @param x - The X position of the pixel + @param y - The Y position of the pixel + @param color - can be a 16bit color or a GCI image or a FrameBuffer + PutPixelAlpha(10, 10, GCI_IMAGE + 3, 255) draws a pixel at 10, 10 + from GCI image index 3 and full alpha level. x and y are relative to objects x and y. + PutPixelAlpha(10, 10, FRAMEBUFFER_IMAGE + 3, 127) draws a pixel at 10, 100 + from GCI image index 3 with half alpha at the same x and y position. + PutPixelAlpha(10, 10, RED, 127) draws a RED pixel at 10, 10 + with half alpha at the same x and y position. + @param alpha - the level of alpha that the pixel is drawn. + @note returns nothing. +*/ +/****************************************************************************/ +void gfx4desp32::PutPixelAlpha(int x, int y, int32_t color, uint8_t alpha) { + uint8_t FB = 0; + int16_t imageNum = -1; + uint16_t bg; + int gpos = 7 * (gradON == 2); + if ((color & 0xffff0000) == 0xf00000) FB = color & 0x07; + if ((color & 0xffff0000) == 0xf0000) imageNum = color & 0xffff; + uint16_t fgcol; + if (FB) { + fgcol = ReadPixelFromFrameBuffer(x, y, FB); + } + else if (imageNum != -1) { + fgcol = ReadImagePixel(imageNum, x, y); + } + else { + fgcol = color & 0xffff; + } + bg = ReadPixel(x, y); //swin = true; + if (gradON) { + if (gradientVert) { + fgcol = Grad(grad1[0 + gpos], grad1[1 + gpos], grad1[2 + gpos], grad1[3 + gpos], x - grad1[6 + gpos], fgcol); + } + else { + fgcol = Grad(grad1[0 + gpos], grad1[1 + gpos], grad1[2 + gpos], grad1[3 + gpos], y - grad1[6 + gpos], fgcol); + } + } + calcAlpha(fgcol, bg, (uint8_t)alpha); + PutPixel(x, y, __colour); +} + /****************************************************************************/ /*! @brief Set the frame buffer for drawing functions. @param fbnum - frame buffer number 0 is main 1 to 3 are additional buffers - @note once set, all drawing functions will be sent tio specified frame + @note once set, all drawing functions will be sent to specified frame buffer. If frame buffer 0 is set (default) all drawing functions will appear immediately on the display. */ @@ -4555,26 +4919,22 @@ void gfx4desp32::DrawToframebuffer(uint8_t fbnum) { case 1: frame_buffer = 1; if (!framebufferInit1) - psRAMbuffer3 = (uint8_t*)ps_malloc(screenArea); - framebufferInit1 = true; + AllocateFB(1); break; case 2: frame_buffer = 2; if (!framebufferInit2) - psRAMbuffer4 = (uint8_t*)ps_malloc(screenArea); - framebufferInit2 = true; + AllocateFB(2); break; case 3: frame_buffer = 3; if (!framebufferInit3) - psRAMbuffer5 = (uint8_t*)ps_malloc(screenArea); - framebufferInit3 = true; + AllocateFB(3); break; case 4: frame_buffer = 4; if (!framebufferInit4) - psRAMbuffer6 = (uint8_t*)ps_malloc(screenArea); - framebufferInit4 = true; + AllocateFB(4); break; } } @@ -5014,34 +5374,40 @@ int gfx4desp32::strWidth(char* ts) { void gfx4desp32::imageSetWord(uint16_t img, byte controlIndex, int val1, int val2) { switch (controlIndex) { - case 1: + case IMAGE_XPOS: tuix[img] = val1; break; - case 2: + case IMAGE_YPOS: tuiy[img] = val1; break; case IMAGE_XYPOS: tuix[img] = val1; tuiy[img] = val2; break; + case IMAGE_INDEX: + tuiImageIndex[img] = val1; + break; } } int gfx4desp32::imageGetWord(uint16_t img, byte controlIndex) { int retval = -1; switch (controlIndex) { - case 1: + case IMAGE_XPOS: retval = tuix[img]; break; - case 2: + case IMAGE_YPOS: retval = tuiy[img]; break; - case 4: + case IMAGE_WIDTH: retval = tuiw[img]; break; - case 8: + case IMAGE_HEIGHT: retval = tuih[img]; break; + case IMAGE_INDEX: + retval = tuiImageIndex[img]; + break; } return retval; } @@ -5070,7 +5436,11 @@ void gfx4desp32::Download(String Address, uint16_t port, String hfile, dlok = false; int32_t lens; uint8_t buffDL[512] = { 0 }; +#ifdef USE_SDMMC_FILE_SYSTEM + File Dwnload; +#else FsFile Dwnload; +#endif HTTPClient http; WiFiClient client; WiFiClientSecure clientS; @@ -5105,10 +5475,17 @@ void gfx4desp32::Download(String Address, uint16_t port, String hfile, error = true; goto skipDownload; } +#ifdef USE_SDMMC_FILE_SYSTEM + if (SD_MMC.exists((char*)Fname.c_str())) { + SD_MMC.remove((char*)Fname.c_str()); + } + Dwnload = SD_MMC.open((char*)Fname.c_str(), FILE_WRITE); +#else if (uSD.exists((char*)Fname.c_str())) { uSD.remove((char*)Fname.c_str()); } Dwnload = uSD.open((char*)Fname.c_str(), FILE_WRITE); +#endif stream = http.getStreamPtr(); while (http.connected() && (lens > 0 || lens == -1)) { size_t size = stream->available(); @@ -5156,9 +5533,15 @@ void gfx4desp32::Download(String Address, uint16_t port, String hfile, println("0 Bytes Rec Error"); } Dwnload.close(); +#ifdef USE_SDMMC_FILE_SYSTEM + if (SD_MMC.exists((char*)Fname.c_str())) { + SD_MMC.remove((char*)Fname.c_str()); + } +#else if (uSD.exists((char*)Fname.c_str())) { uSD.remove((char*)Fname.c_str()); } +#endif delay(500); dlok = false; } @@ -5183,7 +5566,11 @@ void gfx4desp32::PrintImageFile(String ifile) { if (cursor_y > (height - 1) && (sEnable == false)) return; #ifndef USE_LITTLEFS_FILE_SYSTEM +#ifdef USE_SDMMC_FILE_SYSTEM + dataFile = SD_MMC.open(ifile); +#else dataFile = uSD.open(ifile); +#endif #else ifile = "/" + ifile; dataFile = LittleFS.open((char*)ifile.c_str(), "r"); diff --git a/src/gfx4desp32.h b/src/gfx4desp32.h index b183932..35af75a 100644 --- a/src/gfx4desp32.h +++ b/src/gfx4desp32.h @@ -33,24 +33,52 @@ //**** Uncomment below if LittleFS File sysem is used instead of uSD **** // #define USE_LITTLEFS_FILE_SYSTEM +//**** Uncomment below if SD_MMC File sysem is used instead of SdFat. Note, SPI is not available to user on RGB displays when SDMMC is enabled **** +//#define USE_SDMMC_FILE_SYSTEM + +//**** Uncomment below if external SDMMC slot is used instead of on-board slot, Note, not available on RGB displays **** +//#define SDMMC_4BIT + #include "gfx4desp32_types.h" #ifdef USE_LITTLEFS_FILE_SYSTEM #include #else +#ifdef USE_SDMMC_FILE_SYSTEM +#include "SD_MMC.h" +#include +#else #include #endif +#endif + +#define QSPI_SDMMC_4BIT_CLK 14 +#define QSPI_SDMMC_4BIT_DATA2 15 +#define QSPI_SDMMC_4BIT_DATA0 16 +#define QSPI_SDMMC_4BIT_DATA1 21 +#define QSPI_SDMMC_4BIT_DATA3 38 +#define QSPI_SDMMC_4BIT_CMD 39 + +#define SPI_SDMMC_4BIT_CLK 15 +#define SPI_SDMMC_4BIT_DATA2 48 +#define SPI_SDMMC_4BIT_DATA0 47 +#define SPI_SDMMC_4BIT_DATA1 38 +#define SPI_SDMMC_4BIT_DATA3 39 +#define SPI_SDMMC_4BIT_CMD 40 #define gfx4d_font File -#define SD_BUFF_SIZE 16 * 1024 // 102400 +#define SD_BUFF_SIZE 8 * 1024 // 102400 #define ON true #define OFF false #define ALL -1 +#define BK_LIGHT_STARTUP_LEVEL 15 #define DEFAULT_BK_LIGHT_ON_LEVEL 1 #define DEFAULT_BK_LIGHT_OFF_LEVEL !DEFAULT_BK_LIGHT_ON_LEVEL +#define BEGIN_WITH_BACKLIGHT_OFF false +#define BEGIN_WITH_BACKLIGHT_ON true #define DEFAULT_PIN_NUM_BK_LIGHT 2 @@ -223,6 +251,7 @@ #define IMAGE_HEIGHT 8 #define IMAGE_VALUE 16 #define IMAGE_XYPOS 32 +#define IMAGE_INDEX 64 #define SOLID 0 #define DOTMATRIXROUND 1 @@ -337,6 +366,18 @@ #define DISP_CTRL_DEL 0x06 #define DISP_CTRL_START 0x07 #define DISP_CTRL_FLUSH 0x08 +#define DISP_CTRL_RESTART_TX 0x09 +#define DISP_CTRL_RESET_ON_VSYNC 0x0a +#define DISP_CTRL_SET_CLOCK 0x0b +#define DISP_CTRL_RESTART_DISPLAY 0x0c +#define DISP_CTRL_FILL_BOUNCE_BUFFER 0x0d + +#define DISPLAY_BUS_SPI 0x01 +#define DISPLAY_BUS_QSPI 0x02 +#define DISPLAY_BUS_RGB 0x03 + +#define GCI_IMAGE 0xf0000UL +#define FRAMEBUFFER_IMAGE 0xf00000UL #define SetGRAM setGRAM #define startWrite StartWrite @@ -429,7 +470,11 @@ class gfx4desp32 : public Print { int8_t fnoBkup; protected: +#ifndef USE_LITTLEFS_FILE_SYSTEM +#ifndef USE_SDMMC_FILE_SYSTEM static SdFat uSD; +#endif +#endif esp_lcd_panel_handle_t panel_handle = NULL; gfx4desp32_backlight_config bk_config = { .pin = DEFAULT_PIN_NUM_BK_LIGHT, @@ -566,7 +611,11 @@ class gfx4desp32 : public Print { gfx4desp32(); ~gfx4desp32(); +#ifndef USE_LITTLEFS_FILE_SYSTEM +#ifndef USE_SDMMC_FILE_SYSTEM static SdFat& getSdFatInstance(); +#endif +#endif virtual esp_lcd_panel_handle_t __begin() = 0; virtual void DisplayControl(uint8_t cmd) = 0; virtual void RectangleFilled(int x1, int y1, int x2, int y2, @@ -604,26 +653,39 @@ class gfx4desp32 : public Print { virtual void AlphaBlend(bool alphablend) = 0; virtual void AlphaBlendLevel(uint32_t alphaLevel) = 0; virtual uint16_t ReadPixel(uint16_t xrp, uint16_t yrp) = 0; + virtual uint16_t ReadPixelFromFrameBuffer(uint16_t xrp, uint16_t yrp, uint8_t fb) = 0; virtual uint16_t ReadLine(int16_t x, int16_t y, int16_t w, uint16_t* data) = 0; virtual void WriteLine(int16_t x, int16_t y, int16_t w, uint16_t* data) = 0; virtual void DrawFrameBuffer(uint8_t fbnum) = 0; virtual void DrawFrameBufferArea(uint8_t fbnum, int16_t ui) = 0; - virtual void DrawFrameBufferArea(uint8_t fbnum, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) = 0; + virtual void DrawFrameBufferArea(uint8_t fbnum, int16_t x1, int16_t y1, int16_t x2, int16_t y2) = 0; virtual void MergeFrameBuffers(uint8_t fbto, uint8_t fbfrom1, uint8_t fbfrom2, uint16_t transColor) = 0; virtual void MergeFrameBuffers(uint8_t fbto, uint8_t fbfrom1, uint8_t fbfrom2, uint8_t fbfrom3, uint16_t transColor, uint16_t transColor1) = 0; // virtual void drawBitmap(int x1, int y1, int x2, int y2, uint16_t* c_data) = 0; + virtual void CopyFrameBuffer(uint8_t fbto, uint8_t fbfrom1) = 0; + virtual void CopyFrameBufferLine(int16_t x, int16_t y, int16_t w, int fb) = 0; + void CopyImageLine(int inum, int x, int y, int w); virtual void PinMode(byte pin, uint8_t mode) = 0; virtual void DigitalWrite(byte pin, bool state) = 0; virtual int DigitalRead(byte pin) = 0; virtual void FlushArea(int x1, int x2, int y1, int y2, int xpos) = 0; virtual void WriteToFrameBuffer(uint32_t offset, uint8_t* data, uint32_t len) = 0; virtual void WriteToFrameBuffer(uint32_t offset, uint16_t* data, uint32_t len) = 0; + virtual void AllocateFB(uint8_t sel) = 0; + virtual void AllocateDRcache(uint32_t cacheSize) = 0; void Cls(); void Cls(uint16_t color); - void begin(String ips = DEFAULT_DISPLAY); + void begin(String ips = DEFAULT_DISPLAY, int pval = 0, bool backightStartOn = true); + void begin(String ips); + void begin(int pval); + void begin(bool backLightStartOn); + void begin(String ips, int pval); + void begin(String ips, bool backLightStartOn); + void begin(int pval, bool backLightStartOn); void ScrollEnable(bool sEn); int16_t getX(void); int16_t getY(void); + void PutPixelAlpha(int x, int y, int32_t color, uint8_t alpha); void CircleFilled(int16_t xc, int16_t yc, int16_t r, uint16_t color); void Circle(int16_t xc, int16_t yc, int16_t r, uint16_t color); void Ellipse(int16_t xe, int16_t ye, int16_t radx, int16_t rady, uint16_t color); @@ -790,6 +852,7 @@ class gfx4desp32 : public Print { void DeleteButtonBG(int hndl, int objBG); void setAddrWindow(int16_t x1, int16_t y1, int16_t w, int16_t h); void Orbit(int angle, int lngth, int* oxy); + void Orbit(float angle, float lngth, float* oxy); void UserImageHide(int hndl); virtual void UserImageHide(int hndl, uint16_t color); virtual void UserImageHideBG(int hndl, int objBG); @@ -872,6 +935,11 @@ class gfx4desp32 : public Print { uint32_t DATAsize(); void setCacheSize(uint32_t cs); int16_t getLastPointerPos(); + uint8_t GetFrameBuffer(); + uint16_t ReadImagePixel(int inum, int x, int y); + void HlineX(int x, int y, int w, int32_t color); + void VlineX(int x, int y, int w, int32_t color); + void RectangleFilledX(int x0, int y0, int x1, int y1, int32_t color); uint8_t GFX4dESP32_RED; uint8_t GFX4dESP32_BLUE; @@ -924,12 +992,14 @@ class gfx4desp32 : public Print { int inx[MAX_ARCSIZE]; uint16_t oldgTX, oldgTY, oldgPEN; uint16_t gTX, gTY, gPEN; + uint8_t* fb; uint8_t* psRAMbuffer1; uint8_t* psRAMbuffer2; uint8_t* psRAMbuffer3; uint8_t* psRAMbuffer4; uint8_t* psRAMbuffer5; uint8_t* psRAMbuffer6; + uint8_t* workbuffer; uint32_t screenArea; bool cache_Enabled; uint32_t cache_Start; @@ -942,6 +1012,7 @@ class gfx4desp32 : public Print { bool framebufferInit2; bool framebufferInit3; bool framebufferInit4; + bool workbufferInit; bool IPS_Display = false; const uint8_t* DATarray = NULL; const uint8_t* GCIarray = NULL; @@ -955,6 +1026,18 @@ class gfx4desp32 : public Print { bool usePushColors; bool WriteFBonly; int16_t LastLinearPointerPosition; + bool changePCLK; + uint32_t PCLKval; + uint8_t displayBus; + bool bkStartOn; + uint32_t __alpha; + uint32_t __alphatemp; + uint16_t __colour; + uint16_t lbuff[800]; + int grad1[21]; + int grad2[7]; + uint8_t gradON; + bool gradientVert; }; #endif diff --git a/src/gfx4desp32_rgb_panel.cpp b/src/gfx4desp32_rgb_panel.cpp index 19ab074..8bc1d82 100644 --- a/src/gfx4desp32_rgb_panel.cpp +++ b/src/gfx4desp32_rgb_panel.cpp @@ -18,6 +18,18 @@ __colour = (uint16_t)(bg | bg >> 16); \ } +#include "esp_lcd_panel_ops.h" +#include "esp_lcd_panel_rgb.h" +#include "esp_lcd_types.h" +#include "esp_err.h" +#include "esp_log.h" +// #include "esp_psram.h" +#include "soc/lcd_periph.h" +#include "hal/lcd_hal.h" +#include "hal/lcd_ll.h" +#include "rom/cache.h" +#include "esp_rom_gpio.h" + gfx4desp32_rgb_panel::gfx4desp32_rgb_panel( esp_lcd_rgb_panel_config_t* panel_config, int bk_pin, int bk_on_level, int bk_off_level, int sd_gpio_sck, int sd_gpio_miso, int sd_gpio_mosi, @@ -25,14 +37,14 @@ gfx4desp32_rgb_panel::gfx4desp32_rgb_panel( : gfx4desp32() { this->panel_config = panel_config; - // this->bk_config.pin = bk_pin; + this->bk_config.pin = bk_pin; this->bk_config.on_level = bk_on_level; this->bk_config.off_level = bk_off_level; sd_sck = sd_gpio_sck; sd_miso = sd_gpio_miso; sd_mosi = sd_gpio_mosi; sd_cs = sd_gpio_cs; - backlight = bk_pin; + // backlight = bk_pin; __TImode = touchYinvert; } @@ -40,7 +52,7 @@ gfx4desp32_rgb_panel::~gfx4desp32_rgb_panel() {} void gfx4desp32_rgb_panel::DisplayControl(uint8_t cmd) { switch (cmd) { - case 0: + case DISP_CTRL_RE_INIT: esp_lcd_panel_reset(panel_handle); digitalWrite(40, LOW); delay(400); @@ -52,32 +64,32 @@ void gfx4desp32_rgb_panel::DisplayControl(uint8_t cmd) { digitalWrite(40, HIGH); rgb_panel = __containerof(panel_handle, esp_rgb_panel_t, base);; break; - case 1: + case DISP_CTRL_RESET: esp_lcd_panel_reset(panel_handle); break; - case 2: + case DISP_CTRL_NEW: ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(panel_config, &panel_handle)); break; - case 3: + case DISP_CTRL_INIT: esp_lcd_panel_init(panel_handle); break; - case 4: + case DISP_CTRL_STOP: gdma_reset(rgb_panel->dma_chan); lcd_ll_stop(rgb_panel->hal.dev); lcd_ll_fifo_reset(rgb_panel->hal.dev); break; - case 5: + case DISP_CTRL_START_TX: __start_transmission(); break; - case 6: + case DISP_CTRL_DEL: esp_lcd_panel_del(panel_handle); break; - case 7: + case DISP_CTRL_START: gdma_start(rgb_panel->dma_chan, (intptr_t)rgb_panel->dma_nodes); esp_rom_delay_us(1); lcd_ll_start(rgb_panel->hal.dev); break; - case 8: + case DISP_CTRL_FLUSH: FlushArea(0, __scrHeight - 1, -1); break; } @@ -87,8 +99,10 @@ void gfx4desp32_rgb_panel::DisplayControl(uint8_t cmd) { esp_lcd_panel_handle_t gfx4desp32_rgb_panel::__begin() { ESP_LOGI(TAG, "Turn off LCD Backlight"); - gpio_config_t bk_gpio_config = { .pin_bit_mask = 1ULL << bk_config.pin, - .mode = GPIO_MODE_OUTPUT }; + gpio_config_t bk_gpio_config = { + .pin_bit_mask = 1ULL << bk_config.pin, + .mode = GPIO_MODE_OUTPUT + }; ESP_ERROR_CHECK(gpio_config(&bk_gpio_config)); ESP_LOGI(TAG, "Install RGB LCD panel driver"); @@ -135,8 +149,9 @@ esp_lcd_panel_handle_t gfx4desp32_rgb_panel::__begin() { scroll_Y1 = 0; scroll_X2 = __width - 1; scroll_Y2 = __height - 1; - ledcSetup(1, 25000, 10); - ledcAttachPin(backlight, 1); + + ledcSetup(backlight, 25000, 10); + ledcAttachPin(bk_config.pin, backlight); Contrast(15); if (I2CInit == false) { @@ -165,52 +180,52 @@ void gfx4desp32_rgb_panel::Contrast(int ctrst) { ctrst = 0; switch (ctrst) { case 15: - ledcWrite(1, 1023); + ledcWrite(backlight, 1023); break; case 14: - ledcWrite(1, 820); + ledcWrite(backlight, 820); break; case 13: - ledcWrite(1, 608); + ledcWrite(backlight, 608); break; case 12: - ledcWrite(1, 460); + ledcWrite(backlight, 460); break; case 11: - ledcWrite(1, 352); + ledcWrite(backlight, 352); break; case 10: - ledcWrite(1, 276); + ledcWrite(backlight, 276); break; case 9: - ledcWrite(1, 224); + ledcWrite(backlight, 224); break; case 8: - ledcWrite(1, 188); + ledcWrite(backlight, 188); break; case 7: - ledcWrite(1, 140); + ledcWrite(backlight, 140); break; case 6: - ledcWrite(1, 105); + ledcWrite(backlight, 105); break; case 5: - ledcWrite(1, 78); + ledcWrite(backlight, 78); break; case 4: - ledcWrite(1, 62); + ledcWrite(backlight, 62); break; case 3: - ledcWrite(1, 47); + ledcWrite(backlight, 47); break; case 2: - ledcWrite(1, 35); + ledcWrite(backlight, 35); break; case 1: - ledcWrite(1, 28); + ledcWrite(backlight, 28); break; case 0: - ledcWrite(1, 0); + ledcWrite(backlight, 0); break; } } @@ -224,10 +239,10 @@ void gfx4desp32_rgb_panel::Contrast(int ctrst) { /****************************************************************************/ void gfx4desp32_rgb_panel::BacklightOn(bool blight) { if (blight) { - ledcWrite(1, 1023); + ledcWrite(backlight, 1023); } else { - ledcWrite(1, 0); + ledcWrite(backlight, 0); } } @@ -300,7 +315,7 @@ uint8_t gfx4desp32_rgb_panel::getPanelOrientation(void) { return rotation; } /*! @brief Set Invert mode @param Inv true / false - @note Needs coding. Not sure how to deal with this on RGB displays +@note Needs coding. Not sure how to deal with this on RGB displays */ /****************************************************************************/ void gfx4desp32_rgb_panel::Invert(bool Inv) { @@ -504,9 +519,9 @@ void gfx4desp32_rgb_panel::DrawFrameBufferArea(uint8_t fbnum, int16_t ui) { y2 - bottom co-ordinate */ /****************************************************************************/ -void gfx4desp32_rgb_panel::DrawFrameBufferArea(uint8_t fbnum, uint16_t x1, - uint16_t y1, uint16_t x2, - uint16_t y2) { +void gfx4desp32_rgb_panel::DrawFrameBufferArea(uint8_t fbnum, int16_t x1, + int16_t y1, int16_t x2, + int16_t y2) { uint8_t* tfrom = SelectFB(fbnum); uint8_t* to = SelectFB(frame_buffer); int32_t x_start = 0; @@ -529,18 +544,20 @@ void gfx4desp32_rgb_panel::DrawFrameBufferArea(uint8_t fbnum, uint16_t x1, y_start = rgb_panel->timings.v_res - 2 - y2; y_end = rgb_panel->timings.v_res - 2 - y1; break; - case PORTRAIT: + case PORTRAIT_R: x_start = rgb_panel->timings.h_res - 1 - y2; x_end = rgb_panel->timings.h_res - 1 - y1; y_start = x1; y_end = x2; break; - case PORTRAIT_R: + case PORTRAIT: x_start = y1; x_end = y2; y_start = rgb_panel->timings.v_res - 2 - x2; y_end = rgb_panel->timings.v_res - 2 - x1; } + if (x_start >= rgb_panel->timings.h_res || x_end < 0 || y_start >= (rgb_panel->timings.v_res - 2) || y_end < 0) + return; if (x_start < 0) x_start = 0; if (y_start < 0) @@ -686,7 +703,7 @@ void gfx4desp32_rgb_panel::WrGRAMs(uint8_t* color_data, uint32_t len) { pixelPos++; } } - if (rotation == PORTRAIT) { + if (rotation == PORTRAIT_R) { pto = tpto + (__scrWidth - (GRAMypos << 1) - 2) + (GRAMxpos * __scrWidth); while (len--) { if (GRAMxpos >= clipX1 && GRAMxpos <= clipX2 && GRAMypos >= clipY1 && @@ -725,7 +742,7 @@ void gfx4desp32_rgb_panel::WrGRAMs(uint8_t* color_data, uint32_t len) { pixelPos++; } } - if (rotation == PORTRAIT_R) { + if (rotation == PORTRAIT) { pto = tpto + (GRAMypos << 1) + ((__scrHeight - GRAMxpos - 1) * __scrWidth); while (len--) { if (GRAMxpos >= clipX1 && GRAMxpos <= clipX2 && GRAMypos >= clipY1 && @@ -769,13 +786,13 @@ void gfx4desp32_rgb_panel::WrGRAMs(uint8_t* color_data, uint32_t len) { wrGRAM = false; // CPU writes data to PSRAM through DCache, data in PSRAM might not get // updated, so write back - if (rotation == 0) + if (rotation == LANDSCAPE) FlushArea(GRAMy1, GRAMy2, -1); - if (rotation == 1) + if (rotation == LANDSCAPE_R) FlushArea(__scrHeight - GRAMy2 - 1, __scrHeight - GRAMy1 - 1, -1); - if (rotation == 2) + if (rotation == PORTRAIT_R) FlushArea(GRAMx1, GRAMx2, -1); - if (rotation == 3) + if (rotation == PORTRAIT) FlushArea(__scrHeight - GRAMx2 - 1, __scrHeight - GRAMx1 - 1, -1); } } @@ -877,7 +894,7 @@ void gfx4desp32_rgb_panel::WrGRAMs(const uint8_t* color_data, uint32_t len) { } } } - if (rotation == PORTRAIT) { + if (rotation == PORTRAIT_R) { pto = tpto + (__scrWidth - (GRAMypos << 1) - 2) + (GRAMxpos * __scrWidth); while (len--) { if (GRAMxpos >= clipX1 && GRAMxpos <= clipX2 && GRAMypos >= clipY1 && @@ -915,7 +932,7 @@ void gfx4desp32_rgb_panel::WrGRAMs(const uint8_t* color_data, uint32_t len) { } } } - if (rotation == PORTRAIT_R) { + if (rotation == PORTRAIT) { pto = tpto + (GRAMypos << 1) + ((__scrHeight - GRAMxpos - 1) * __scrWidth); while (len--) { if (GRAMxpos >= clipX1 && GRAMxpos <= clipX2 && GRAMypos >= clipY1 && @@ -956,13 +973,13 @@ void gfx4desp32_rgb_panel::WrGRAMs(const uint8_t* color_data, uint32_t len) { if (GRAMypos > GRAMy2 && frame_buffer == 0) { // CPU writes data to PSRAM through DCache, data in PSRAM might not get // updated, so write back - if (rotation == 0) + if (rotation == LANDSCAPE) FlushArea(GRAMy1, GRAMy2, -1); - if (rotation == 1) + if (rotation == LANDSCAPE_R) FlushArea(__scrHeight - GRAMy2 - 1, __scrHeight - GRAMy1 - 1, -1); - if (rotation == 2) + if (rotation == PORTRAIT_R) FlushArea(GRAMx1, GRAMx2, -1); - if (rotation == 3) + if (rotation == PORTRAIT) FlushArea(__scrHeight - GRAMx2 - 1, __scrHeight - GRAMx1 - 1, -1); } } @@ -1172,7 +1189,7 @@ void gfx4desp32_rgb_panel::WrGRAMs(uint16_t* color_data, uint32_t len) { pixelPos++; } } - if (rotation == PORTRAIT) { + if (rotation == PORTRAIT_R) { pto = tpto + (__scrWidth - (GRAMypos << 1) - 2) + (GRAMxpos * __scrWidth); while (len--) { tcol = color_data[pc++]; @@ -1209,7 +1226,7 @@ void gfx4desp32_rgb_panel::WrGRAMs(uint16_t* color_data, uint32_t len) { pixelPos++; } } - if (rotation == PORTRAIT_R) { + if (rotation == PORTRAIT) { pto = tpto + (GRAMypos << 1) + ((__scrHeight - GRAMxpos - 1) * __scrWidth); while (len--) { tcol = color_data[pc++]; @@ -1249,13 +1266,13 @@ void gfx4desp32_rgb_panel::WrGRAMs(uint16_t* color_data, uint32_t len) { if (pixelPos >= pixelCount && frame_buffer == 0) { // if GRAM area is written to flush the area. wrGRAM = false; - if (rotation == 0) + if (rotation == LANDSCAPE) FlushArea(GRAMy1, GRAMy2, -1); - if (rotation == 1) + if (rotation == LANDSCAPE_R) FlushArea(__scrHeight - GRAMy2 - 1, __scrHeight - GRAMy1 - 1, -1); - if (rotation == 2) + if (rotation == PORTRAIT_R) FlushArea(GRAMx1, GRAMx2, -1); - if (rotation == 3) + if (rotation == PORTRAIT) FlushArea(__scrHeight - GRAMx2 - 1, __scrHeight - GRAMx1 - 1, -1); } } @@ -1365,7 +1382,7 @@ void gfx4desp32_rgb_panel::WrGRAMs(uint32_t* color_data, uint16_t len) { } } } - if (rotation == PORTRAIT) { + if (rotation == PORTRAIT_R) { pto = tpto + (__scrWidth - (GRAMypos << 1) - 2) + (GRAMxpos * __scrWidth); while (len--) { innerloop = 2; @@ -1406,7 +1423,7 @@ void gfx4desp32_rgb_panel::WrGRAMs(uint32_t* color_data, uint16_t len) { } } } - if (rotation == PORTRAIT_R) { + if (rotation == PORTRAIT) { pto = tpto + (GRAMypos << 1) + ((__scrHeight - GRAMxpos - 1) * __scrWidth); while (len--) { innerloop = 2; @@ -1450,13 +1467,13 @@ void gfx4desp32_rgb_panel::WrGRAMs(uint32_t* color_data, uint16_t len) { if (pixelPos >= pixelCount && frame_buffer == 0) { // if GRAM area is written to flush the area. wrGRAM = false; - if (rotation == 0) + if (rotation == LANDSCAPE) FlushArea(GRAMy1, GRAMy2, -1); - if (rotation == 1) + if (rotation == LANDSCAPE_R) FlushArea(__scrHeight - GRAMy2 - 1, __scrHeight - GRAMy1 - 1, -1); - if (rotation == 2) + if (rotation == PORTRAIT_R) FlushArea(GRAMx1, GRAMx2, -1); - if (rotation == 3) + if (rotation == PORTRAIT) FlushArea(__scrHeight - GRAMx2 - 1, __scrHeight - GRAMx1 - 1, -1); } } @@ -1513,7 +1530,7 @@ void gfx4desp32_rgb_panel::pushColors(uint16_t* color_data, uint32_t len) { pixelPos++; } } - if (rotation == PORTRAIT) { + if (rotation == PORTRAIT_R) { pto = tpto + (__scrWidth - (GRAMypos << 1) - 2) + (GRAMxpos * __scrWidth); while (len--) { tcol = color_data[pc++]; @@ -1530,7 +1547,7 @@ void gfx4desp32_rgb_panel::pushColors(uint16_t* color_data, uint32_t len) { pixelPos++; } } - if (rotation == PORTRAIT_R) { + if (rotation == PORTRAIT) { pto = tpto + (GRAMypos << 1) + ((__scrHeight - GRAMxpos - 1) * __scrWidth); while (len--) { tcol = color_data[pc++]; @@ -1550,13 +1567,13 @@ void gfx4desp32_rgb_panel::pushColors(uint16_t* color_data, uint32_t len) { if (pixelPos >= pixelCount && frame_buffer == 0) { // if GRAM area fully written to, flush area wrGRAM = false; - if (rotation == 0) + if (rotation == LANDSCAPE) FlushArea(GRAMy1, GRAMy2, -1); - if (rotation == 1) + if (rotation == LANDSCAPE_R) FlushArea(__scrHeight - GRAMy2 - 1, __scrHeight - GRAMy1 - 1, -1); - if (rotation == 2) + if (rotation == PORTRAIT_R) FlushArea(GRAMx1, GRAMx2, -1); - if (rotation == 3) + if (rotation == PORTRAIT) FlushArea(__scrHeight - GRAMx2 - 1, __scrHeight - GRAMx1 - 1, -1); } } @@ -1614,7 +1631,7 @@ void gfx4desp32_rgb_panel::pushColors(uint8_t* color_data, uint32_t len) { pixelPos++; } } - if (rotation == PORTRAIT) { + if (rotation == PORTRAIT_R) { pto = tpto + (__scrWidth - (GRAMypos << 1) - 2) + (GRAMxpos * __scrWidth); while (len--) { pto[1] = color_data[pc++]; @@ -1630,7 +1647,7 @@ void gfx4desp32_rgb_panel::pushColors(uint8_t* color_data, uint32_t len) { pixelPos++; } } - if (rotation == PORTRAIT_R) { + if (rotation == PORTRAIT) { pto = tpto + (GRAMypos << 1) + ((__scrHeight - GRAMxpos - 1) * __scrWidth); while (len--) { pto[1] = color_data[pc++]; @@ -1649,13 +1666,13 @@ void gfx4desp32_rgb_panel::pushColors(uint8_t* color_data, uint32_t len) { if (pixelPos >= pixelCount && frame_buffer == 0) { // if GRAM area fully written to, flush area wrGRAM = false; - if (rotation == 0) + if (rotation == LANDSCAPE) FlushArea(GRAMy1, GRAMy2, -1); - if (rotation == 1) + if (rotation == LANDSCAPE_R) FlushArea(__scrHeight - GRAMy2 - 1, __scrHeight - GRAMy1 - 1, -1); - if (rotation == 2) + if (rotation == PORTRAIT_R) FlushArea(GRAMx1, GRAMx2, -1); - if (rotation == 3) + if (rotation == PORTRAIT) FlushArea(__scrHeight - GRAMx2 - 1, __scrHeight - GRAMx1 - 1, -1); } } @@ -1699,7 +1716,7 @@ void gfx4desp32_rgb_panel::pushColors(const uint8_t* color_data, uint32_t len) { } } } - if (rotation == PORTRAIT) { + if (rotation == PORTRAIT_R) { pto = tpto + (__scrWidth - (GRAMypos << 1) - 2) + (GRAMxpos * __scrWidth); while (len--) { pto[1] = color_data[pc++]; @@ -1714,7 +1731,7 @@ void gfx4desp32_rgb_panel::pushColors(const uint8_t* color_data, uint32_t len) { } } } - if (rotation == PORTRAIT_R) { + if (rotation == PORTRAIT) { pto = tpto + (GRAMypos << 1) + ((__scrHeight - GRAMxpos - 1) * __scrWidth); while (len--) { pto[1] = color_data[pc++]; @@ -1731,13 +1748,13 @@ void gfx4desp32_rgb_panel::pushColors(const uint8_t* color_data, uint32_t len) { } if (GRAMypos > GRAMy2 && frame_buffer == 0) { wrGRAM = false; - if (rotation == 0) + if (rotation == LANDSCAPE) FlushArea(GRAMy1, GRAMy2, -1); - if (rotation == 1) + if (rotation == LANDSCAPE_R) FlushArea(__scrHeight - GRAMy2 - 1, __scrHeight - GRAMy1 - 1, -1); - if (rotation == 2) + if (rotation == PORTRAIT_R) FlushArea(GRAMx1, GRAMx2, -1); - if (rotation == 3) + if (rotation == PORTRAIT) FlushArea(__scrHeight - GRAMx2 - 1, __scrHeight - GRAMx1 - 1, -1); } } @@ -1803,7 +1820,7 @@ void gfx4desp32_rgb_panel::WrGRAM(uint16_t color) { } pixelPos++; } - if (rotation == PORTRAIT) { + if (rotation == PORTRAIT_R) { pto = tpto + (__scrWidth - (GRAMypos << 1) - 2) + (GRAMxpos * __scrWidth); if (GRAMxpos >= clipX1 && GRAMxpos <= clipX2 && GRAMypos >= clipY1 && GRAMypos <= clipY2) { @@ -1819,7 +1836,7 @@ void gfx4desp32_rgb_panel::WrGRAM(uint16_t color) { } pixelPos++; } - if (rotation == PORTRAIT_R) { + if (rotation == PORTRAIT) { pto = tpto + (GRAMypos << 1) + ((__scrHeight - GRAMxpos - 1) * __scrWidth); if (GRAMxpos >= clipX1 && GRAMxpos <= clipX2 && GRAMypos >= clipY1 && GRAMypos <= clipY2) { @@ -1839,13 +1856,13 @@ void gfx4desp32_rgb_panel::WrGRAM(uint16_t color) { if (pixelPos >= pixelCount && frame_buffer == 0) { // if GRAM area is written to flush the area. wrGRAM = false; - if (rotation == 0) + if (rotation == LANDSCAPE) FlushArea(GRAMy1, GRAMy2, -1); - if (rotation == 1) + if (rotation == LANDSCAPE_R) FlushArea(__scrHeight - GRAMy2 - 1, __scrHeight - GRAMy1 - 1, -1); - if (rotation == 2) + if (rotation == PORTRAIT_R) FlushArea(GRAMx1, GRAMx2, -1); - if (rotation == 3) + if (rotation == PORTRAIT) FlushArea(__scrHeight - GRAMx2 - 1, __scrHeight - GRAMx1 - 1, -1); } } @@ -1870,13 +1887,36 @@ uint16_t gfx4desp32_rgb_panel::ReadPixel(uint16_t xrp, uint16_t yrp) { if (rotation == LANDSCAPE_R) pto = tpto + ((__scrHeight - yrp - 1) * __scrWidth) + (__scrWidth - ((xrp + 1) << 1)); - if (rotation == PORTRAIT) { + if (rotation == PORTRAIT_R) { int32_t temp = (__scrWidth - ((yrp + 1) << 1)) + (__scrWidth * xrp); if (temp < 0 || temp > __fbSize) return 0; pto = tpto + temp; } - if (rotation == PORTRAIT_R) + if (rotation == PORTRAIT) + pto = tpto + (yrp << 1) + ((__scrHeight - xrp - 1) * __scrWidth); + return pto[0] + (pto[1] << 8); +} + +uint16_t gfx4desp32_rgb_panel::ReadPixelFromFrameBuffer(uint16_t xrp, uint16_t yrp, uint8_t fB) { + if (yrp > clipY2 || yrp < clipY1) + return 0; + if (xrp > clipX2 || yrp < clipX1) + return 0; + uint8_t* tpto = SelectFB(fB); + uint8_t* pto; + if (rotation == LANDSCAPE) + pto = tpto + (yrp * __scrWidth) + (xrp << 1); + if (rotation == LANDSCAPE_R) + pto = tpto + ((__scrHeight - yrp - 1) * __scrWidth) + + (__scrWidth - ((xrp + 1) << 1)); + if (rotation == PORTRAIT_R) { + int32_t temp = (__scrWidth - ((yrp + 1) << 1)) + (__scrWidth * xrp); + if (temp < 0 || temp > __fbSize) + return 0; + pto = tpto + temp; + } + if (rotation == PORTRAIT) pto = tpto + (yrp << 1) + ((__scrHeight - xrp - 1) * __scrWidth); return pto[0] + (pto[1] << 8); } @@ -1907,14 +1947,14 @@ uint16_t gfx4desp32_rgb_panel::ReadLine(int16_t x, int16_t y, int16_t w, uint8_t* pto; int pc = 0; int readw = w; - if (rotation == 0) { + if (rotation == LANDSCAPE) { pto = tpto + (y * __scrWidth) + (x << 1); while (w--) { data[pc++] = pto[0] + (pto[1] << 8); pto += 2; } } - if (rotation == 1) { + if (rotation == LANDSCAPE_R) { pto = tpto + ((__scrHeight - y - 1) * __scrWidth) + (__scrWidth - ((x + 1) << 1)); while (w--) { @@ -1922,14 +1962,14 @@ uint16_t gfx4desp32_rgb_panel::ReadLine(int16_t x, int16_t y, int16_t w, pto -= 2; } } - if (rotation == 2) { + if (rotation == PORTRAIT_R) { pto = tpto + (__scrWidth - ((y + 1) << 1)) + (x * __scrWidth); while (w--) { data[pc++] = pto[0] + (pto[1] << 8); pto += __scrWidth; } } - if (rotation == 3) { + if (rotation == PORTRAIT) { pto = tpto + (y << 1) + ((__scrHeight - x - 1) * __scrWidth); while (w--) { data[pc++] = pto[0] + (pto[1] << 8); @@ -1939,6 +1979,39 @@ uint16_t gfx4desp32_rgb_panel::ReadLine(int16_t x, int16_t y, int16_t w, return readw; } +/****************************************************************************/ +/*! + @brief Copy a line of pixels from selected frame buffer to current frame buffer. + @param x left X position in pixels + @param y top Y position in pixels + @param w width of line + @param fb source frame buffer number +*/ +/****************************************************************************/ +void gfx4desp32_rgb_panel::CopyFrameBufferLine(int16_t x, int16_t y, int16_t w, + int Fb) { + if (y > clipY2 || y < clipY1) + return; + if (x > clipX2 || (x + w - 1) < clipX1) + return; + if (w < 0) { + x += w; + w = abs(w); + } + if (x < clipX1) { + w -= clipX1 - x; + x = clipX1; + } + if ((x + w - 1) >= clipX2) + w = clipX2 - x; + uint8_t cb = GetFrameBuffer(); + DrawToframebuffer(Fb); + ReadLine(x, y, w, lbuff); + DrawToframebuffer(cb); + WriteLine(x, y, w, lbuff); +} + + /****************************************************************************/ /*! @brief Write a line of pixels. @@ -1962,52 +2035,115 @@ void gfx4desp32_rgb_panel::WriteLine(int16_t x, int16_t y, int16_t w, w = clipX2 - x; uint8_t* tpto = SelectFB(frame_buffer); uint8_t* pto; + uint8_t colM, colL; + uint16_t tcol; int pc = 0; int flushw = w; - if (rotation == 0) { + if (rotation == LANDSCAPE) { pto = tpto + (y * __scrWidth) + (x << 1); while (w--) { - pto[0] = data[pc]; - pto[1] = data[pc] >> 8; + tcol = data[pc++]; + colM = tcol >> 8; + colL = tcol & 0xff; + if (!transalpha) { + pto[1] = colM; + pto[0] = colL; + } + else { + if (!(transparency && (colM == _transMSB && colL == _transLSB))) { + if (alpha) { + calcAlpha(colL + (colM << 8), pto[0] | (pto[1] << 8), __alpha); + pto[0] = __colour; + pto[1] = __colour >> 8; + } + else { + pto[1] = colM; + pto[0] = colL; + } + } + } + pto += 2; - pc++; } - if (frame_buffer == 0) - FlushArea(y, y, -1); } - if (rotation == 1) { + if (rotation == LANDSCAPE_R) { pto = tpto + ((__scrHeight - y - 1) * __scrWidth) + (__scrWidth - ((x + 1) << 1)); while (w--) { - pto[0] = data[pc]; - pto[1] = data[pc] >> 8; + tcol = data[pc++]; + colM = tcol >> 8; + colL = tcol & 0xff; + if (!transalpha) { + pto[1] = colM; + pto[0] = colL; + } + else { + if (!(transparency && (colM == _transMSB && colL == _transLSB))) { + if (alpha) { + calcAlpha(colL + (colM << 8), pto[0] | (pto[1] << 8), __alpha); + pto[0] = __colour; + pto[1] = __colour >> 8; + } + else { + pto[1] = colM; + pto[0] = colL; + } + } + } pto -= 2; - pc++; } - if (frame_buffer == 0) - FlushArea(__scrHeight - y - 1, __scrHeight - y - 1, -1); } - if (rotation == 2) { + if (rotation == PORTRAIT_R) { pto = tpto + (__scrWidth - ((y + 1) << 1)) + (x * __scrWidth); while (w--) { - pto[0] = data[pc]; - pto[1] = data[pc] >> 8; + tcol = data[pc++]; + colM = tcol >> 8; + colL = tcol & 0xff; + if (!transalpha) { + pto[1] = colM; + pto[0] = colL; + } + else { + if (!(transparency && (colM == _transMSB && colL == _transLSB))) { + if (alpha) { + calcAlpha(colL + (colM << 8), pto[0] | (pto[1] << 8), __alpha); + pto[0] = __colour; + pto[1] = __colour >> 8; + } + else { + pto[1] = colM; + pto[0] = colL; + } + } + } pto += __scrWidth; - pc++; } - if (frame_buffer == 0) - FlushArea(x, x + flushw, -1); } - if (rotation == 3) { + if (rotation == PORTRAIT) { pto = tpto + (y << 1) + ((__scrHeight - x - 1) * __scrWidth); while (w--) { - pto[0] = data[pc]; - pto[1] = data[pc] >> 8; + tcol = data[pc++]; + colM = tcol >> 8; + colL = tcol & 0xff; + if (!transalpha) { + pto[1] = colM; + pto[0] = colL; + } + else { + if (!(transparency && (colM == _transMSB && colL == _transLSB))) { + if (alpha) { + calcAlpha(colL + (colM << 8), pto[0] | (pto[1] << 8), __alpha); + pto[0] = __colour; + pto[1] = __colour >> 8; + } + else { + pto[1] = colM; + pto[0] = colL; + } + } + } pto -= __scrWidth; - pc++; } - if (frame_buffer == 0) - FlushArea(__scrHeight - x - 1 - flushw, __scrHeight - x - 1, -1); } } @@ -2191,13 +2327,13 @@ void gfx4desp32_rgb_panel::Scroll(int steps) { y_start = rgb_panel->timings.v_res - 2 - scroll_Y2; y_end = rgb_panel->timings.v_res - 2 - scroll_Y1; } - if (rotation == PORTRAIT) { + if (rotation == PORTRAIT_R) { x_start = rgb_panel->timings.h_res - 1 - scroll_Y2; x_end = rgb_panel->timings.h_res - 1 - scroll_Y1; y_start = scroll_X1; y_end = scroll_X2; } - if (rotation == PORTRAIT_R) { + if (rotation == PORTRAIT) { x_start = scroll_Y1; x_end = scroll_Y2; y_start = rgb_panel->timings.v_res - 2 - scroll_X2; @@ -2276,7 +2412,7 @@ void gfx4desp32_rgb_panel::Scroll(int steps) { } to += 2; } - to -= (__scrWidth + (s_width << 1)); + to -= (__scrWidth + (s_width << 1)); } } FlushArea(y_start, y_end, -1); @@ -2418,7 +2554,7 @@ void gfx4desp32_rgb_panel::RectangleFilled(int x1, int y1, int x2, int y2, if (frame_buffer == 0) FlushArea(__scrHeight - y2 - 1, __scrHeight - y1 - 1, -1); } - if (rotation == PORTRAIT) { + if (rotation == PORTRAIT_R) { pto = tpto + (__scrWidth - ((ypos + 1) << 1)) + (xpos * __scrWidth); while (pixels--) { @@ -2446,7 +2582,7 @@ void gfx4desp32_rgb_panel::RectangleFilled(int x1, int y1, int x2, int y2, if (frame_buffer == 0) FlushArea(x1, x2, -1); } - if (rotation == PORTRAIT_R) { + if (rotation == PORTRAIT) { pto = tpto + (ypos << 1) + ((__scrHeight - xpos - 1) * __scrWidth); while (pixels--) { @@ -2505,6 +2641,41 @@ uint8_t* gfx4desp32_rgb_panel::SelectFB(uint8_t sel) { return rgb_panel->fb; } +void gfx4desp32_rgb_panel::AllocateDRcache(uint32_t cacheSize) { + size_t psram_trans_align = rgb_panel->psram_trans_align; + psRAMbuffer2 = (uint8_t*)heap_caps_aligned_calloc(psram_trans_align, 1, cacheSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + cache_Enabled = true; +} + +void gfx4desp32_rgb_panel::AllocateFB(uint8_t sel) { + size_t psram_trans_align = rgb_panel->psram_trans_align; + if (sel == 0) { + psRAMbuffer1 = (uint8_t*)heap_caps_aligned_calloc(psram_trans_align, 1, 1024000, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + } + if (sel == 1) { + psRAMbuffer3 = (uint8_t*)heap_caps_aligned_calloc(psram_trans_align, 1, __fbSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + framebufferInit1 = true; + } + if (sel == 2) { + psRAMbuffer4 = (uint8_t*)heap_caps_aligned_calloc(psram_trans_align, 1, __fbSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + framebufferInit2 = true; + } + if (sel == 3) { + psRAMbuffer5 = (uint8_t*)heap_caps_aligned_calloc(psram_trans_align, 1, __fbSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + framebufferInit3 = true; + } + if (sel == 4) { + psRAMbuffer6 = (uint8_t*)heap_caps_aligned_calloc(psram_trans_align, 1, __fbSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + framebufferInit4 = true; + } +} + +void gfx4desp32_rgb_panel::CopyFrameBuffer(uint8_t fbto, uint8_t fbfrom1) { + uint8_t* to = SelectFB(fbto); + uint8_t* from1 = SelectFB(fbfrom1); + memcpy(to, from1, __fbSize); +} + /****************************************************************************/ /*! @brief Merge 2 frame buffers and send to specified frame buffer. @@ -2632,7 +2803,7 @@ void gfx4desp32_rgb_panel::PutPixel(int16_t x, int16_t y, uint16_t color) { if (frame_buffer == 0) FlushArea(__scrHeight - y - 1, __scrHeight - y - 1, (__scrWidth - x + 1)); } - if (rotation == PORTRAIT) { + if (rotation == PORTRAIT_R) { int32_t temp = (__scrWidth - ((y + 1) << 1)) + (__scrWidth * x); if (temp < 0 || temp > __fbSize) return; @@ -2649,7 +2820,7 @@ void gfx4desp32_rgb_panel::PutPixel(int16_t x, int16_t y, uint16_t color) { if (frame_buffer == 0) FlushArea(x, x, __scrWidth - y + 1); } - if (rotation == PORTRAIT_R) { + if (rotation == PORTRAIT) { pto = tpto + (y << 1) + ((__scrHeight - x - 1) * __scrWidth); if (!alpha) { pto[0] = color; @@ -2686,18 +2857,19 @@ void gfx4desp32_rgb_panel::Hline(int16_t x, int16_t y, int16_t w, } if (w < 0) { x += w; - w *= -1; + //w *= -1; + w = abs(w); } if (x < clipX1) { w -= clipX1 - x; x = clipX1; } - if ((x + w - 1) >= clipX2) - w = clipX2 - x; + if ((x + w) > clipX2 - 1) + w = clipX2 - x + 1; uint8_t* tpto = SelectFB(frame_buffer); uint8_t* pto; int flushw = w; - if (rotation == 0) { + if (rotation == LANDSCAPE) { pto = tpto + (y * __scrWidth) + (x << 1); while (w--) { if (!alpha) { @@ -2714,7 +2886,7 @@ void gfx4desp32_rgb_panel::Hline(int16_t x, int16_t y, int16_t w, if (frame_buffer == 0) FlushArea(y, y, -1); } - if (rotation == 1) { + if (rotation == LANDSCAPE_R) { pto = tpto + ((__scrHeight - y - 1) * __scrWidth) + (__scrWidth - ((x + 1) << 1)); while (w--) { @@ -2732,7 +2904,7 @@ void gfx4desp32_rgb_panel::Hline(int16_t x, int16_t y, int16_t w, if (frame_buffer == 0) FlushArea(__scrHeight - y - 1, __scrHeight - y - 1, -1); } - if (rotation == 2) { + if (rotation == PORTRAIT_R) { pto = tpto + (__scrWidth - ((y + 1) << 1)) + (x * __scrWidth); while (w--) { @@ -2750,7 +2922,7 @@ void gfx4desp32_rgb_panel::Hline(int16_t x, int16_t y, int16_t w, if (frame_buffer == 0) FlushArea(x, x + flushw, -1); } - if (rotation == 3) { + if (rotation == PORTRAIT) { pto = tpto + (y << 1) + ((__scrHeight - x - 1) * __scrWidth); while (w--) { @@ -2797,12 +2969,12 @@ void gfx4desp32_rgb_panel::Vline(int16_t x, int16_t y, int16_t w, w -= clipY1 - y; y = clipY1; } - if ((y + w - 1) >= clipY2) - w = clipY2 - y; + if ((y + w) > clipY2 - 1) + w = clipY2 - y + 1; uint8_t* tpto = SelectFB(frame_buffer); uint8_t* pto; int flushw = w; - if (rotation == 0) { + if (rotation == LANDSCAPE) { pto = tpto + (y * __scrWidth) + (x << 1); while (w--) { if (!alpha) { @@ -2819,7 +2991,7 @@ void gfx4desp32_rgb_panel::Vline(int16_t x, int16_t y, int16_t w, if (frame_buffer == 0) FlushArea(y, y + flushw, -1); } - if (rotation == 1) { + if (rotation == LANDSCAPE_R) { pto = tpto + ((__scrHeight - y - 1) * __scrWidth) + (__scrWidth - ((x + 1) << 1)); while (w--) { @@ -2837,7 +3009,7 @@ void gfx4desp32_rgb_panel::Vline(int16_t x, int16_t y, int16_t w, if (frame_buffer == 0) FlushArea(__scrHeight - y - 1 - flushw, __scrHeight - y - 1, -1); } - if (rotation == 2) { + if (rotation == PORTRAIT_R) { pto = tpto + (__scrWidth - ((y + 1) << 1)) + (x * __scrWidth); while (w--) { @@ -2855,7 +3027,7 @@ void gfx4desp32_rgb_panel::Vline(int16_t x, int16_t y, int16_t w, if (frame_buffer == 0) FlushArea(x, x, -1); } - if (rotation == 3) { + if (rotation == PORTRAIT) { pto = tpto + (y << 1) + ((__scrHeight - x - 1) * __scrWidth); while (w--) { diff --git a/src/gfx4desp32_rgb_panel.h b/src/gfx4desp32_rgb_panel.h index 352937f..b5850e4 100644 --- a/src/gfx4desp32_rgb_panel.h +++ b/src/gfx4desp32_rgb_panel.h @@ -6,6 +6,10 @@ #include "gfx4desp32.h" #include "Wire.h" +#define RGB_LCD_PANEL_MAX_FB_NUM 1 // maximum supported frame buffer number +#define RGB_LCD_PANEL_BOUNCE_BUF_NUM 2 // bounce buffer number +#define RGB_LCD_PANEL_DMA_LINKS_REPLICA 2 + #define DISPLAY_INTERFACE DISP_INTERFACE_RGB #define GFX4d_IO_EXPANDER_ADDR 0x39 @@ -16,6 +20,11 @@ #define GFX4d_TOUCH_RESET 0x07 #define GFX4d_TOUCH_INT 0x06 +#define GEN4_RGB_DISPLAY +#define GEN4_I2C_SDA 17 +#define GEN4_I2C_SCL 18 + + struct esp_rgb_panel_t { esp_lcd_panel_t base; // Base class of generic lcd panel int panel_id; // LCD panel ID @@ -30,7 +39,7 @@ struct esp_rgb_panel_t { uint8_t* fb; // Frame buffer size_t fb_size; // Size of frame buffer int data_gpio_nums[SOC_LCD_RGB_DATA_WIDTH]; // GPIOs used for data lines, we keep these GPIOs for action like "invert_color" - uint32_t src_clk_hz; // Peripheral source clock resolution + uint32_t src_clk_hz; // Peripheral source clock resolution esp_lcd_rgb_timing_t timings; // RGB timing parameters (e.g. pclk, sync pulse, porch width) gdma_channel_handle_t dma_chan; // DMA channel handle esp_lcd_rgb_panel_frame_trans_done_cb_t on_frame_trans_done; // Callback, invoked after frame trans done @@ -70,9 +79,12 @@ enum { class gfx4desp32_rgb_panel : virtual public gfx4desp32 { private: + + int RGB_InvertFix[16] = { 8, 3, 46, 9, 1, 5, 6, 7, 15, 16, 4, 45, 48, 47, 21, 14 }; const char* TAG = "gfx4desp32_rgb_panel"; esp_lcd_rgb_panel_config_t* panel_config = NULL; esp_rgb_panel_t* rgb_panel = NULL; + int currFB; int32_t GRAMx1; int32_t GRAMy1; int32_t GRAMx2; @@ -107,7 +119,7 @@ class gfx4desp32_rgb_panel : virtual public gfx4desp32 { int32_t scroll_blanking; uint8_t scroll_speed; bool flush_pending; - int backlight; + int backlight = 1; uint16_t _transparentColor; uint8_t _transMSB, _transLSB; uint8_t m_inp; @@ -120,13 +132,13 @@ class gfx4desp32_rgb_panel : virtual public gfx4desp32 { uint8_t pinNum2bitNum[8] = { 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 }; - uint8_t scroll_Directions[16] = { 0x00, 0x01, 0x02, 0x03, - 0x01, 0x00, 0x03, 0x02, - 0x02, 0x03, 0x01, 0x00, - 0x03, 0x02, 0x00, 0x01 }; + uint8_t scroll_Directions[16] = { 0x00, 0x01, 0x03, 0x03, + 0x01, 0x00, 0x02, 0x03, + 0x03, 0x02, 0x01, 0x00, + 0x02, 0x03, 0x00, 0x01 }; void __start_transmission(); - + void FlushArea(int y1, int y2, int xpos); uint8_t RTCread(uint8_t address); // read one byte from selected register void RTCwrite(uint8_t address, uint8_t data); // write one byte of data to the register @@ -205,17 +217,22 @@ class gfx4desp32_rgb_panel : virtual public gfx4desp32 { virtual void AlphaBlend(bool alphablend) override; virtual void AlphaBlendLevel(uint32_t alphaLevel) override; virtual uint16_t ReadPixel(uint16_t xrp, uint16_t yrp) override; + virtual uint16_t ReadPixelFromFrameBuffer(uint16_t xrp, uint16_t yrp, uint8_t fb) override; virtual uint16_t ReadLine(int16_t x, int16_t y, int16_t w, uint16_t* data) override; virtual void WriteLine(int16_t x, int16_t y, int16_t w, uint16_t* data) override; virtual void DrawFrameBuffer(uint8_t fbnum) override; virtual void DrawFrameBufferArea(uint8_t fbnum, int16_t ui) override; - virtual void DrawFrameBufferArea(uint8_t fbnum, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) override; + virtual void DrawFrameBufferArea(uint8_t fbnum, int16_t x1, int16_t y1, int16_t x2, int16_t y2) override; virtual void MergeFrameBuffers(uint8_t fbto, uint8_t fbfrom1, uint8_t fbfrom2, uint16_t transColor) override; virtual void MergeFrameBuffers(uint8_t fbto, uint8_t fbfrom1, uint8_t fbfrom2, uint8_t fbfrom3, uint16_t transColor, uint16_t transColor1) override; // virtual void drawBitmap(int x1, int y1, int x2, int y2, uint16_t* c_data) override; + virtual void CopyFrameBuffer(uint8_t fbto, uint8_t fbfrom1) override; + virtual void CopyFrameBufferLine(int16_t x, int16_t y, int16_t w, int fb) override; virtual void PinMode(byte pin, uint8_t mode) override; virtual void DigitalWrite(byte pin, bool state) override; virtual int DigitalRead(byte pin) override; + virtual void AllocateFB(uint8_t sel) override; + virtual void AllocateDRcache(uint32_t cacheSize) override; int rotation; void* wb = NULL; int32_t __scrWidth; @@ -247,9 +264,9 @@ class gfx4desp32_rgb_panel : virtual public gfx4desp32 { bool RTCcheckClockIntegrity(); // check clock integrity const char* RTCformatDateTime(uint8_t sytle); int calx1, calx2, caly1, caly2; - uint32_t __alpha; - uint32_t __alphatemp; - uint16_t __colour; + //uint32_t __alpha; + //uint32_t __alphatemp; + //uint16_t __colour; }; #endif // __GFX4D_RGB_PANEL__ \ No newline at end of file diff --git a/src/gfx4desp32_spi_panel.cpp b/src/gfx4desp32_spi_panel.cpp index adb23b2..c4b7283 100644 --- a/src/gfx4desp32_spi_panel.cpp +++ b/src/gfx4desp32_spi_panel.cpp @@ -33,6 +33,8 @@ #include "hal/gpio_hal.h" #include "hal/lcd_hal.h" #include "hal/lcd_ll.h" +#include "Wire.h" + @@ -51,13 +53,14 @@ gfx4desp32_spi_panel::gfx4desp32_spi_panel( panel_VRES = vres; panelPin_RST = panel_Pin_RST; + this->bk_config.pin = bk_pin; this->bk_config.on_level = bk_on_level; this->bk_config.off_level = bk_off_level; sd_sck = sd_gpio_SCK; sd_miso = sd_gpio_MISO; sd_mosi = sd_gpio_MOSI; sd_cs = sd_gpio_CS; - backlight = bk_pin; + // backlight = bk_pin; v_res = vres; h_res = hres; __TImode = touchXinvert; @@ -79,8 +82,10 @@ void gfx4desp32_spi_panel::DisplayControl(uint8_t cmd) { esp_lcd_panel_handle_t gfx4desp32_spi_panel::__begin() { ESP_LOGI(TAG, "Turn off LCD Backlight"); - gpio_config_t bk_gpio_config = { .pin_bit_mask = 1ULL << bk_config.pin, - .mode = GPIO_MODE_OUTPUT }; + gpio_config_t bk_gpio_config = { + .pin_bit_mask = 1ULL << bk_config.pin, + .mode = GPIO_MODE_OUTPUT + }; ESP_ERROR_CHECK(gpio_config(&bk_gpio_config)); ESP_LOGI(TAG, "Install SPI LCD panel driver"); @@ -103,11 +108,17 @@ esp_lcd_panel_handle_t gfx4desp32_spi_panel::__begin() { esp_lcd_panel_io_spi_config_t io_config = {}; io_config.dc_gpio_num = panelPin_DC; io_config.cs_gpio_num = panelPin_CS; - io_config.pclk_hz = 40 * 1000 * 1000; // maximum spi dislay clock speed + if (changePCLK) { + io_config.pclk_hz = PCLKval; + changePCLK = false; + } + else { + io_config.pclk_hz = 40 * 1000 * 1000; // maximum spi dislay clock speed + } io_config.lcd_cmd_bits = 8; io_config.lcd_param_bits = 8; io_config.spi_mode = 0; - io_config.trans_queue_depth = 6; + io_config.trans_queue_depth = 7; esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)GEN4_35CT_SPI_HOST, &io_config, &io_handle); @@ -152,7 +163,7 @@ esp_lcd_panel_handle_t gfx4desp32_spi_panel::__begin() { while (len != 0xff) { command = InitCommands[ic + 1]; if (len == 0xfe) { - delay(command); + delay(command * 10); ic += 2; } else { @@ -211,10 +222,11 @@ esp_lcd_panel_handle_t gfx4desp32_spi_panel::__begin() { scroll_Y1 = 0; scroll_X2 = __width - 1; scroll_Y2 = __height - 1; - ledcSetup(1, 20000, 10); - ledcAttachPin(backlight, 1); - Contrast(15); + ledcSetup(backlight, 20000, 10); + ledcAttachPin(bk_config.pin, 1); + + //Contrast(15); /*** Initiaize main frame buffer ***/ fb = (uint8_t*)ps_malloc(__fbSize); @@ -241,52 +253,52 @@ void gfx4desp32_spi_panel::Contrast(int ctrst) { ctrst = 0; switch (ctrst) { case 15: - ledcWrite(1, 1023); + ledcWrite(backlight, 1023); break; case 14: - ledcWrite(1, 820); + ledcWrite(backlight, 820); break; case 13: - ledcWrite(1, 608); + ledcWrite(backlight, 608); break; case 12: - ledcWrite(1, 460); + ledcWrite(backlight, 460); break; case 11: - ledcWrite(1, 352); + ledcWrite(backlight, 352); break; case 10: - ledcWrite(1, 276); + ledcWrite(backlight, 276); break; case 9: - ledcWrite(1, 224); + ledcWrite(backlight, 224); break; case 8: - ledcWrite(1, 188); + ledcWrite(backlight, 188); break; case 7: - ledcWrite(1, 140); + ledcWrite(backlight, 140); break; case 6: - ledcWrite(1, 105); + ledcWrite(backlight, 105); break; case 5: - ledcWrite(1, 78); + ledcWrite(backlight, 78); break; case 4: - ledcWrite(1, 62); + ledcWrite(backlight, 62); break; case 3: - ledcWrite(1, 47); + ledcWrite(backlight, 47); break; case 2: - ledcWrite(1, 31); + ledcWrite(backlight, 35); break; case 1: - ledcWrite(1, 15); + ledcWrite(backlight, 28); break; case 0: - ledcWrite(1, 0); + ledcWrite(backlight, 0); break; } } @@ -301,10 +313,10 @@ void gfx4desp32_spi_panel::Contrast(int ctrst) { /****************************************************************************/ void gfx4desp32_spi_panel::BacklightOn(bool blight) { if (blight) { - ledcWrite(1, 1023); + ledcWrite(backlight, 1023); } else { - ledcWrite(1, 0); + ledcWrite(backlight, 0); } } @@ -398,7 +410,32 @@ uint8_t gfx4desp32_spi_panel::getPanelOrientation(void) { return rotation; } */ /****************************************************************************/ void gfx4desp32_spi_panel::Invert(bool Inv) { - /*** Not sure how to deal with this on RGB displays ***/ + if (DisplayModel == GFX4d_DISPLAY_ILI9488) { + if (Inv) { + esp_lcd_panel_io_tx_param(io_handle, ILI9488_CMD_DISP_INVERSION_OFF, NULL, 0); + } + else { + esp_lcd_panel_io_tx_param(io_handle, ILI9488_CMD_DISP_INVERSION_ON, NULL, 0); + } + } + else { + if (IPS_Display) { + if (Inv) { + esp_lcd_panel_invert_color(panel_handle, false); + } + else { + esp_lcd_panel_invert_color(panel_handle, true); + } + } + else { + if (Inv) { + esp_lcd_panel_invert_color(panel_handle, true); + } + else { + esp_lcd_panel_invert_color(panel_handle, false); + } + } + } } /****************************************************************************/ @@ -571,9 +608,9 @@ void gfx4desp32_spi_panel::DrawFrameBufferArea(uint8_t fbnum, int16_t ui) { y2 - bottom co-ordinate */ /****************************************************************************/ -void gfx4desp32_spi_panel::DrawFrameBufferArea(uint8_t fbnum, uint16_t x1, - uint16_t y1, uint16_t x2, - uint16_t y2) { +void gfx4desp32_spi_panel::DrawFrameBufferArea(uint8_t fbnum, int16_t x1, + int16_t y1, int16_t x2, + int16_t y2) { uint8_t* tfrom = SelectFB(fbnum); uint8_t* to = SelectFB(frame_buffer); int32_t x_start; @@ -585,10 +622,12 @@ void gfx4desp32_spi_panel::DrawFrameBufferArea(uint8_t fbnum, uint16_t x1, y_start = y1; x_end = x2; y_end = y2; - if (x_end >= h_res) - x_end = h_res - 1; - if (y_end >= v_res) - y_end = v_res - 1; + if (x_start >= __width || x_end < 0 || y_start >= __height || y_end < 0) + return; + if (x_end >= __width) + x_end = __width - 1; + if (y_end >= __height) + y_end = __height - 1; uint32_t s_width = x_end - x_start + 1; uint32_t s_height = y_end - y_start + 1; uint32_t pc = (y_start * __scrWidth) + (x_start << 1); @@ -923,8 +962,8 @@ void gfx4desp32_spi_panel::FlushArea(int y1, int y2, int xpos) { /****************************************************************************/ /*! @brief Flush frame buffer area recently written to - @param x1 left start position in pixels - @param x2 right end position in pixels + @param x1 left start position in pixels + @param x2 right end position in pixels @param y1 top start position in pixels @param y2 bottom position in pixels @param xpos x position in line @@ -1576,7 +1615,18 @@ uint16_t gfx4desp32_spi_panel::ReadPixel(uint16_t xrp, uint16_t yrp) { uint8_t* tpto = SelectFB(frame_buffer); uint8_t* pto; pto = tpto + (yrp * __scrWidth) + (xrp << 1); - return pto[0] + (pto[1] << 8); + return pto[1] + (pto[0] << 8); +} + +uint16_t gfx4desp32_spi_panel::ReadPixelFromFrameBuffer(uint16_t xrp, uint16_t yrp, uint8_t fb) { + if (yrp > clipY2 || yrp < clipY1) + return 0; + if (xrp > clipX2 || yrp < clipX1) + return 0; + uint8_t* tpto = SelectFB(fb); + uint8_t* pto; + pto = tpto + (yrp * __scrWidth) + (xrp << 1); + return pto[1] + (pto[0] << 8); } /****************************************************************************/ @@ -1613,6 +1663,41 @@ uint16_t gfx4desp32_spi_panel::ReadLine(int16_t x, int16_t y, int16_t w, return readw; } +/****************************************************************************/ +/*! + @brief Write a line of pixels. + @param x left X position in pixels + @param y top Y position in pixels + @param w width of line + @param data - 16 bit user array +*/ +/****************************************************************************/ +void gfx4desp32_spi_panel::CopyFrameBufferLine(int16_t x, int16_t y, int16_t w, + int fb) { + if (y > clipY2 || y < clipY1) + return; + if (x > clipX2 || (x + w - 1) < clipX1) + return; + if (w < 0) { + x += w; + w = abs(w); + } + if (x < clipX1) { + w -= clipX1 - x; + x = clipX1; + } + if ((x + w - 1) >= clipX2) + w = clipX2 - x; + uint8_t* tpfrom = SelectFB(fb); + uint8_t* pfrom; + int flushw = w; + SetGRAM(x, y, x + w - 1, y); + pfrom = tpfrom + (y * __scrWidth) + (x << 1); + WrGRAMs(pfrom, w); + if (frame_buffer == 0) + FlushArea(x, x + w, y, y, -1); +} + /****************************************************************************/ /*! @brief Write a line of pixels. @@ -1720,11 +1805,11 @@ void gfx4desp32_spi_panel::setScrollArea(int x1, int y1, int x2, int y2) { scroll_Y2 = y2; if (scroll_X1 < 0) scroll_X1 = 0; - if (scroll_X2 > __width - 1) + if (scroll_X2 >= __width) scroll_X2 = __width - 1; if (scroll_Y1 < 0) scroll_Y1 = 0; - if (scroll_Y2 > __height - 1) + if (scroll_Y2 >= __height) scroll_Y2 = __height - 1; } @@ -1820,7 +1905,7 @@ void gfx4desp32_spi_panel::Scroll(int steps) { y_start = scroll_Y1; x_end = scroll_X2; y_end = scroll_Y2; - + if (x_start >= __width || x_end < 0 || y_start >= __height || y_end < 0) return; uint32_t s_width = x_end - x_start + 1; uint32_t s_height = y_end - y_start + 1; scrdir = @@ -1866,7 +1951,8 @@ void gfx4desp32_spi_panel::Scroll(int steps) { to += (__scrWidth - (s_width << 1)); } } - FlushArea(y_start, y_end, -1); + FlushArea(scroll_X1, scroll_X2, scroll_Y1, scroll_Y2, -1); + //FlushArea(y_start, y_end, -1); delay(scroll_speed); } } @@ -1897,7 +1983,8 @@ void gfx4desp32_spi_panel::Scroll(int steps) { to -= (__scrWidth + (s_width << 1)); } } - FlushArea(y_start, y_end, -1); + FlushArea(scroll_X1, scroll_X2, scroll_Y1, scroll_Y2, -1); + //FlushArea(y_start, y_end, -1); delay(scroll_speed); } } @@ -1919,7 +2006,8 @@ void gfx4desp32_spi_panel::Scroll(int steps) { from += __scrWidth; to += __scrWidth; } - FlushArea(y_start, y_end, -1); + FlushArea(scroll_X1, scroll_X2, scroll_Y1, scroll_Y2, -1); + //FlushArea(y_start, y_end, -1); delay(scroll_speed); } } @@ -1941,7 +2029,8 @@ void gfx4desp32_spi_panel::Scroll(int steps) { from += __scrWidth; to += __scrWidth; } - FlushArea(y_start, y_end, -1); + FlushArea(scroll_X1, scroll_X2, scroll_Y1, scroll_Y2, -1); + //FlushArea(y_start, y_end, -1); delay(scroll_speed); } } @@ -2029,12 +2118,45 @@ uint8_t* gfx4desp32_spi_panel::SelectFB(uint8_t sel) { return psRAMbuffer5; break; case 4: - return psRAMbuffer5; + return psRAMbuffer6; break; } return fb; } +void gfx4desp32_spi_panel::AllocateDRcache(uint32_t cacheSize) { + psRAMbuffer2 = (uint8_t*)ps_malloc(cacheSize); + cache_Enabled = true; +} + +void gfx4desp32_spi_panel::AllocateFB(uint8_t sel) { + if (sel == 0) { + psRAMbuffer1 = (uint8_t*)ps_malloc(1024000); + } + if (sel == 1) { + psRAMbuffer3 = (uint8_t*)ps_malloc(__fbSize); + framebufferInit1 = true; + } + if (sel == 2) { + psRAMbuffer4 = (uint8_t*)ps_malloc(__fbSize); + framebufferInit2 = true; + } + if (sel == 3) { + psRAMbuffer5 = (uint8_t*)ps_malloc(__fbSize); + framebufferInit3 = true; + } + if (sel == 4) { + psRAMbuffer6 = (uint8_t*)ps_malloc(__fbSize); + framebufferInit4 = true; + } +} + +void gfx4desp32_spi_panel::CopyFrameBuffer(uint8_t fbto, uint8_t fbfrom1) { + uint8_t* to = SelectFB(fbto); + uint8_t* from1 = SelectFB(fbfrom1); + memcpy(to, from1, __fbSize); +} + /****************************************************************************/ /*! @brief Merge 2 frame buffers and send to specified frame buffer. @@ -2175,8 +2297,8 @@ void gfx4desp32_spi_panel::Hline(int16_t x, int16_t y, int16_t w, w -= clipX1 - x; x = clipX1; } - if ((x + w - 1) >= clipX2) - w = clipX2 - x; + if ((x + w) > clipX2 - 1) + w = clipX2 - x + 1; uint8_t* tpto = SelectFB(frame_buffer); uint8_t* pto; int flushw = w; @@ -2225,8 +2347,8 @@ void gfx4desp32_spi_panel::Vline(int16_t x, int16_t y, int16_t w, w -= clipY1 - y; y = clipY1; } - if ((y + w - 1) >= clipY2) - w = clipY2 - y; + if ((y + w) > clipY2 - 1) + w = clipY2 - y + 1; uint8_t* tpto = SelectFB(frame_buffer); uint8_t* pto; int flushw = w; diff --git a/src/gfx4desp32_spi_panel.h b/src/gfx4desp32_spi_panel.h index 3201101..474c01f 100644 --- a/src/gfx4desp32_spi_panel.h +++ b/src/gfx4desp32_spi_panel.h @@ -78,6 +78,11 @@ #define GFX4d_DISPLAY_ILI9341_ST7789 0x00 #define GFX4d_DISPLAY_ILI9488 0x01 +#define GEN4_SPI_DISPLAY +#define GEN4_I2C_SDA 10 +#define GEN4_I2C_SCL 9 + + class gfx4desp32_spi_panel : virtual public gfx4desp32 { private: @@ -137,7 +142,7 @@ class gfx4desp32_spi_panel : virtual public gfx4desp32 { uint8_t scroll_speed; bool flush_pending; - int backlight; + int backlight = 1; uint16_t _transparentColor; uint8_t _transMSB, _transLSB; uint8_t* fb = NULL; @@ -204,20 +209,26 @@ class gfx4desp32_spi_panel : virtual public gfx4desp32 { virtual void AlphaBlend(bool alphablend) override; virtual void AlphaBlendLevel(uint32_t alphaLevel) override; virtual uint16_t ReadPixel(uint16_t xrp, uint16_t yrp) override; + virtual uint16_t ReadPixelFromFrameBuffer(uint16_t xrp, uint16_t yrp, uint8_t fb) override; virtual uint16_t ReadLine(int16_t x, int16_t y, int16_t w, uint16_t* data) override; virtual void WriteLine(int16_t x, int16_t y, int16_t w, uint16_t* data) override; virtual void DrawFrameBuffer(uint8_t fbnum) override; virtual void DrawFrameBufferArea(uint8_t fbnum, int16_t ui) override; - virtual void DrawFrameBufferArea(uint8_t fbnum, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2) override; + virtual void DrawFrameBufferArea(uint8_t fbnum, int16_t x1, int16_t y1, int16_t x2, int16_t y2) override; virtual void MergeFrameBuffers(uint8_t fbto, uint8_t fbfrom1, uint8_t fbfrom2, uint16_t transColor) override; virtual void MergeFrameBuffers(uint8_t fbto, uint8_t fbfrom1, uint8_t fbfrom2, uint8_t fbfrom3, uint16_t transColor, uint16_t transColor1) override; // virtual void drawBitmap(int x1, int y1, int x2, int y2, uint16_t* c_data) override; + virtual void CopyFrameBuffer(uint8_t fbto, uint8_t fbfrom1) override; + virtual void CopyFrameBufferLine(int16_t x, int16_t y, int16_t w, int fb) override; void drawBitmap(int x1, int y1, int x2, int y2, uint16_t* c_data); + void draw_bitmap(int x1, int y1, int x2, int y2, uint16_t* c_data); virtual void PinMode(byte pin, uint8_t mode) override; virtual void DigitalWrite(byte pin, bool state) override; virtual int DigitalRead(byte pin) override; virtual void WriteToFrameBuffer(uint32_t offset, uint8_t* data, uint32_t len) override; virtual void WriteToFrameBuffer(uint32_t offset, uint16_t* data, uint32_t len) override; + virtual void AllocateFB(uint8_t sel) override; + virtual void AllocateDRcache(uint32_t cacheSize) override; int rotation; void* wb = NULL; int32_t __scrWidth; @@ -242,9 +253,9 @@ class gfx4desp32_spi_panel : virtual public gfx4desp32 { uint8_t InitCommandsili[160]; uint8_t InitCommands9488[160]; uint8_t DisplayModel; - uint32_t __alpha; - uint32_t __alphatemp; - uint16_t __colour; + //uint32_t __alpha; + //uint32_t __alphatemp; + //uint16_t __colour; }; #endif // __GFX4D_SPI_PANEL__ \ No newline at end of file