diff --git a/main/main.c b/main/main.c index 28d6c63c..3dc64f23 100644 --- a/main/main.c +++ b/main/main.c @@ -19,6 +19,10 @@ #define INTERVAL 400 #define WAIT vTaskDelay(INTERVAL) +//#define SVG_LOGGING +#ifdef SVG_LOGGING +static char *svg_cut_line = "cut-cut-cut-cut"; +#endif static const char *TAG = "ST7789"; @@ -102,7 +106,7 @@ TickType_t ArrowTest(TFT_t * dev, FontxFile *fx, int width, int height) { uint8_t fontHeight; GetFontx(fx, 0, buffer, &fontWidth, &fontHeight); //ESP_LOGI(__FUNCTION__,"fontWidth=%d fontHeight=%d",fontWidth,fontHeight); - + uint16_t xpos; uint16_t ypos; int stlen; @@ -840,7 +844,7 @@ void ST7789(void *pvParameters) InitFontx(fx16M,"/spiffs/ILMH16XB.FNT",""); // 8x16Dot Mincyo InitFontx(fx24M,"/spiffs/ILMH24XB.FNT",""); // 12x24Dot Mincyo InitFontx(fx32M,"/spiffs/ILMH32XB.FNT",""); // 16x32Dot Mincyo - + TFT_t dev; spi_master_init(&dev, CONFIG_MOSI_GPIO, CONFIG_SCLK_GPIO, CONFIG_CS_GPIO, CONFIG_DC_GPIO, CONFIG_RESET_GPIO, CONFIG_BL_GPIO); lcdInit(&dev, CONFIG_WIDTH, CONFIG_HEIGHT, CONFIG_OFFSETX, CONFIG_OFFSETY); @@ -882,80 +886,208 @@ void ST7789(void *pvParameters) lcdDrawFillRect(&dev, 20, 20, 30, 30, BLUE); #endif + // give plenty of time to enable the serial monitor +#ifdef SVG_LOGGING + WAIT; + WAIT; + WAIT; + WAIT; + WAIT; + WAIT; + WAIT; + WAIT; + WAIT; + WAIT; + WAIT; + WAIT; + WAIT; + WAIT; + WAIT; + WAIT; + WAIT; + WAIT; +#endif + while(1) { +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "FillTest-SVG"); +#endif FillTest(&dev, CONFIG_WIDTH, CONFIG_HEIGHT); +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "ColorBarTest-SVG"); +#endif ColorBarTest(&dev, CONFIG_WIDTH, CONFIG_HEIGHT); +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; - +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "ArrowTest-SVG"); +#endif ArrowTest(&dev, fx16G, CONFIG_WIDTH, CONFIG_HEIGHT); +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "LineTest-SVG"); +#endif LineTest(&dev, CONFIG_WIDTH, CONFIG_HEIGHT); +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "CircleTest-SVG"); +#endif CircleTest(&dev, CONFIG_WIDTH, CONFIG_HEIGHT); +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "RoundRectTest-SVG"); +#endif RoundRectTest(&dev, CONFIG_WIDTH, CONFIG_HEIGHT); +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "RectAngleTest-SVG"); +#endif RectAngleTest(&dev, CONFIG_WIDTH, CONFIG_HEIGHT); +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "TriangleTest-SVG"); +#endif TriangleTest(&dev, CONFIG_WIDTH, CONFIG_HEIGHT); +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "DirectionTest-SVG"); +#endif if (CONFIG_WIDTH >= 240) { DirectionTest(&dev, fx24G, CONFIG_WIDTH, CONFIG_HEIGHT); } else { DirectionTest(&dev, fx16G, CONFIG_WIDTH, CONFIG_HEIGHT); } +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "HorizontalTest-SVG"); +#endif if (CONFIG_WIDTH >= 240) { HorizontalTest(&dev, fx24G, CONFIG_WIDTH, CONFIG_HEIGHT); } else { HorizontalTest(&dev, fx16G, CONFIG_WIDTH, CONFIG_HEIGHT); } +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "VerticalTest-SVG"); +#endif if (CONFIG_WIDTH >= 240) { VerticalTest(&dev, fx24G, CONFIG_WIDTH, CONFIG_HEIGHT); } else { VerticalTest(&dev, fx16G, CONFIG_WIDTH, CONFIG_HEIGHT); } +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "FillRectTest-SVG"); +#endif FillRectTest(&dev, CONFIG_WIDTH, CONFIG_HEIGHT); +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "ColorTest-SVG"); +#endif ColorTest(&dev, CONFIG_WIDTH, CONFIG_HEIGHT); WAIT; +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "CodeTestfx32G-SVG"); +#endif CodeTest(&dev, fx32G, CONFIG_WIDTH, CONFIG_HEIGHT); +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "CodeTestfx32L-SVG"); +#endif CodeTest(&dev, fx32L, CONFIG_WIDTH, CONFIG_HEIGHT); +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "BMPTest-SVG"); +#endif char file[32]; strcpy(file, "/spiffs/image.bmp"); BMPTest(&dev, file, CONFIG_WIDTH, CONFIG_HEIGHT); +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; #ifndef CONFIG_IDF_TARGET_ESP32S2 +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "JPEGTest-SVG"); +#endif strcpy(file, "/spiffs/esp32.jpeg"); JPEGTest(&dev, file, CONFIG_WIDTH, CONFIG_HEIGHT); +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; #endif +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "PNGTest-SVG"); +#endif strcpy(file, "/spiffs/esp_logo.png"); PNGTest(&dev, file, CONFIG_WIDTH, CONFIG_HEIGHT); +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; - +#ifdef SVG_LOGGING + lcdSvgLoggingStart(&dev, ESP_LOG_INFO, "MultiFontTest-SVG"); +#endif // Multi Font Test uint16_t color; uint8_t ascii[40]; @@ -1008,7 +1140,13 @@ void ST7789(void *pvParameters) lcdDrawString(&dev, fx32M, xpos, ypos, ascii, color); } lcdSetFontDirection(&dev, 0); +#ifdef SVG_LOGGING + lcdSvgLoggingEnd(&dev, svg_cut_line); +#endif WAIT; +#ifdef SVG_LOGGING + break; +#endif } // end while @@ -1019,9 +1157,10 @@ void ST7789(void *pvParameters) } + void app_main(void) { - ESP_LOGI(TAG, "Initializing SPIFFS"); + ESP_LOGI(TAG, "Initializing SPIFFS"); esp_vfs_spiffs_conf_t conf = { .base_path = "/spiffs", diff --git a/main/st7789.c b/main/st7789.c index c09a2e29..663cca78 100644 --- a/main/st7789.c +++ b/main/st7789.c @@ -98,7 +98,7 @@ void spi_master_init(TFT_t * dev, int16_t GPIO_MOSI, int16_t GPIO_SCLK, int16_t } else { devcfg.spics_io_num = -1; } - + spi_device_handle_t handle; ret = spi_bus_add_device( LCD_HOST, &devcfg, &handle); ESP_LOGD(TAG, "spi_bus_add_device=%d",ret); @@ -123,7 +123,7 @@ bool spi_master_write_byte(spi_device_handle_t SPIHandle, const uint8_t* Data, s #else ret = spi_device_polling_transmit( SPIHandle, &SPITransaction ); #endif - assert(ret==ESP_OK); + assert(ret==ESP_OK); } return true; @@ -208,17 +208,17 @@ void lcdInit(TFT_t * dev, int width, int height, int offsetx, int offsety) dev->_font_direction = DIRECTION0; dev->_font_fill = false; dev->_font_underline = false; - + dev->_svg_log_level = ESP_LOG_NONE; //SVG logging off by default spi_master_write_command(dev, 0x01); //Software Reset delayMS(150); spi_master_write_command(dev, 0x11); //Sleep Out delayMS(255); - + spi_master_write_command(dev, 0x3A); //Interface Pixel Format spi_master_write_data_byte(dev, 0x55); delayMS(10); - + spi_master_write_command(dev, 0x36); //Memory Data Access Control spi_master_write_data_byte(dev, 0x00); @@ -257,6 +257,12 @@ void lcdDrawPixel(TFT_t * dev, uint16_t x, uint16_t y, uint16_t color){ if (x >= dev->_width) return; if (y >= dev->_height) return; + if (dev->_svg_log_level != ESP_LOG_NONE) { + ESP_LOG_LEVEL(dev->_svg_log_level, dev->_svg_log_tag, "", + __FUNCTION__, rgb565_to_rgb(color), x, y); + vTaskDelay(1); + } + uint16_t _x = x + dev->_offsetx; uint16_t _y = y + dev->_offsety; @@ -278,6 +284,33 @@ void lcdDrawMultiPixels(TFT_t * dev, uint16_t x, uint16_t y, uint16_t size, uint if (x+size > dev->_width) return; if (y >= dev->_height) return; + if (dev->_svg_log_level != ESP_LOG_NONE) { + uint16_t color = colors[0]; + int run_length = 0; + // These are horizontal renderings of colored pixels. We could just draw them like + // individual pixels, but in practical cases there are likely to be significant + // runs of pixels of the same color. Detect those and emit a single SVG line for + // each such run. The degenerate case is randomly colored pixels with no two + // consecutive pixels of the same color. For that case, we haven't lost anything + // (in the emitted SVG) by looking for the runs. + // + // The library's sample app only uses lcdDrawMultiPixels() for the BMP/JPEG/PNG tests. + for (int ii=0; ii_svg_log_level, dev->_svg_log_tag, "", + __FUNCTION__, rgb565_to_rgb(color), (x+ii)-run_length, y, run_length); + run_length = 1; + color = colors[ii]; + vTaskDelay(1); + } + } + } + uint16_t _x1 = x + dev->_offsetx; uint16_t _x2 = _x1 + size; uint16_t _y1 = y + dev->_offsety; @@ -303,6 +336,18 @@ void lcdDrawFillRect(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_ if (y1 >= dev->_height) return; if (y2 >= dev->_height) y2=dev->_height-1; + if (dev->_svg_log_level != ESP_LOG_NONE) { + uint16_t minx = x1>x2 ? x2 : x1; + uint16_t miny = y1>y2 ? y2 : y1; + uint16_t maxx = x1>x2 ? x1 : x2; + uint16_t maxy = x1>x2 ? y1 : y2; + char *color_name = rgb565_to_rgb(color); + ESP_LOG_LEVEL(dev->_svg_log_level, dev->_svg_log_tag, + "", + __FUNCTION__, color_name, color_name, minx, miny, maxx-minx, maxy-miny); + vTaskDelay(1); + } + ESP_LOGD(TAG,"offset(x)=%d offset(y)=%d",dev->_offsetx,dev->_offsety); uint16_t _x1 = x1 + dev->_offsetx; uint16_t _x2 = x2 + dev->_offsetx; @@ -330,7 +375,7 @@ void lcdDrawFillRect(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_ void lcdDisplayOff(TFT_t * dev) { spi_master_write_command(dev, 0x28); //Display off } - + // Display ON void lcdDisplayOn(TFT_t * dev) { spi_master_write_command(dev, 0x29); //Display on @@ -347,7 +392,7 @@ void lcdFillScreen(TFT_t * dev, uint16_t color) { // y1:Start Y coordinate // x2:End X coordinate // y2:End Y coordinate -// color:color +// color:color void lcdDrawLine(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { int i; int dx,dy; @@ -358,6 +403,17 @@ void lcdDrawLine(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2 dx = ( x2 > x1 ) ? x2 - x1 : x1 - x2; dy = ( y2 > y1 ) ? y2 - y1 : y1 - y2; + esp_log_level_t old_level = ESP_LOG_NONE; + if (dev->_svg_log_level != ESP_LOG_NONE) { + char *color_name = rgb565_to_rgb(color); + ESP_LOG_LEVEL(dev->_svg_log_level, dev->_svg_log_tag, + "", + __FUNCTION__, color_name, x1, y1, x2, y2); + vTaskDelay(1); + old_level = dev->_svg_log_level; + dev->_svg_log_level = ESP_LOG_NONE; // to skip the draw pixel stuff + } + /* direction of two point */ sx = ( x2 > x1 ) ? 1 : -1; sy = ( y2 > y1 ) ? 1 : -1; @@ -388,6 +444,7 @@ void lcdDrawLine(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2 } } } + dev->_svg_log_level = old_level; } // Draw rectangle @@ -397,10 +454,25 @@ void lcdDrawLine(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2 // y2:End Y coordinate // color:color void lcdDrawRect(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2, uint16_t color) { + esp_log_level_t old_level = ESP_LOG_NONE; + if (dev->_svg_log_level != ESP_LOG_NONE) { + uint16_t minx = x1>x2 ? x2 : x1; + uint16_t miny = y1>y2 ? y2 : y1; + uint16_t maxx = x1>x2 ? x1 : x2; + uint16_t maxy = x1>x2 ? y1 : y2; + char *color_name = rgb565_to_rgb(color); + ESP_LOG_LEVEL(dev->_svg_log_level, dev->_svg_log_tag, + "", + __FUNCTION__, color_name, minx, miny, (maxx-minx)+1, (maxy-miny)+1); + vTaskDelay(1); + old_level = dev->_svg_log_level; + dev->_svg_log_level = ESP_LOG_NONE; // to skip the draw pixel stuff + } lcdDrawLine(dev, x1, y1, x2, y1, color); lcdDrawLine(dev, x2, y1, x2, y2, color); lcdDrawLine(dev, x2, y2, x1, y2, color); lcdDrawLine(dev, x1, y2, x1, y1, color); + dev->_svg_log_level = old_level; } // Draw rectangle with angle @@ -439,10 +511,20 @@ void lcdDrawRectAngle(TFT_t * dev, uint16_t xc, uint16_t yc, uint16_t w, uint16_ x4 = (int)(xd * cos(rd) - yd * sin(rd) + xc); y4 = (int)(xd * sin(rd) + yd * cos(rd) + yc); + esp_log_level_t old_level = ESP_LOG_NONE; + if (dev->_svg_log_level != ESP_LOG_NONE) { + ESP_LOG_LEVEL(dev->_svg_log_level, dev->_svg_log_tag, "", + __FUNCTION__, rgb565_to_rgb(color), x1, y1, x2, y2, x4, y4, x3, y3); + vTaskDelay(1); + old_level = dev->_svg_log_level; + dev->_svg_log_level = ESP_LOG_NONE; // to skip the draw pixel stuff + } + lcdDrawLine(dev, x1, y1, x2, y2, color); lcdDrawLine(dev, x1, y1, x3, y3, color); lcdDrawLine(dev, x2, y2, x4, y4, color); lcdDrawLine(dev, x3, y3, x4, y4, color); + dev->_svg_log_level = old_level; } // Draw triangle @@ -476,9 +558,20 @@ void lcdDrawTriangle(TFT_t * dev, uint16_t xc, uint16_t yc, uint16_t w, uint16_t x3 = (int)(xd * cos(rd) - yd * sin(rd) + xc); y3 = (int)(xd * sin(rd) + yd * cos(rd) + yc); + esp_log_level_t old_level = ESP_LOG_NONE; + if (dev->_svg_log_level != ESP_LOG_NONE) { + ESP_LOG_LEVEL(dev->_svg_log_level, dev->_svg_log_tag, + "", + __FUNCTION__, rgb565_to_rgb(color), x1, y1, x2, y2, x3, y3); + vTaskDelay(1); + old_level = dev->_svg_log_level; + dev->_svg_log_level = ESP_LOG_NONE; // to skip the draw pixel stuff + } + lcdDrawLine(dev, x1, y1, x2, y2, color); lcdDrawLine(dev, x1, y1, x3, y3, color); lcdDrawLine(dev, x2, y2, x3, y3, color); + dev->_svg_log_level = old_level; } // Draw circle @@ -492,17 +585,28 @@ void lcdDrawCircle(TFT_t * dev, uint16_t x0, uint16_t y0, uint16_t r, uint16_t c int err; int old_err; + esp_log_level_t old_level = ESP_LOG_NONE; + if (dev->_svg_log_level != ESP_LOG_NONE) { + ESP_LOG_LEVEL(dev->_svg_log_level, dev->_svg_log_tag, + "", + __FUNCTION__, rgb565_to_rgb(color), x0, y0, r); + vTaskDelay(1); + old_level = dev->_svg_log_level; + dev->_svg_log_level = ESP_LOG_NONE; // to skip the draw pixel stuff + } + x=0; y=-r; err=2-2*r; do{ - lcdDrawPixel(dev, x0-x, y0+y, color); - lcdDrawPixel(dev, x0-y, y0-x, color); - lcdDrawPixel(dev, x0+x, y0-y, color); - lcdDrawPixel(dev, x0+y, y0+x, color); + lcdDrawPixel(dev, x0-x, y0+y, color); + lcdDrawPixel(dev, x0-y, y0-x, color); + lcdDrawPixel(dev, x0+x, y0-y, color); + lcdDrawPixel(dev, x0+y, y0+x, color); if ((old_err=err)<=x) err+=++x*2+1; - if (old_err>y || err>x) err+=++y*2+1; + if (old_err>y || err>x) err+=++y*2+1; } while(y<0); + dev->_svg_log_level = old_level; } // Draw circle of filling @@ -517,6 +621,17 @@ void lcdDrawFillCircle(TFT_t * dev, uint16_t x0, uint16_t y0, uint16_t r, uint16 int old_err; int ChangeX; + esp_log_level_t old_level = ESP_LOG_NONE; + if (dev->_svg_log_level != ESP_LOG_NONE) { + char *color_name = rgb565_to_rgb(color); + ESP_LOG_LEVEL(dev->_svg_log_level, dev->_svg_log_tag, + "", + __FUNCTION__, color_name, color_name, x0, y0, r); + vTaskDelay(1); + old_level = dev->_svg_log_level; + dev->_svg_log_level = ESP_LOG_NONE; // to skip the draw pixel stuff + } + x=0; y=-r; err=2-2*r; @@ -530,7 +645,8 @@ void lcdDrawFillCircle(TFT_t * dev, uint16_t x0, uint16_t y0, uint16_t r, uint16 if (ChangeX) err+=++x*2+1; if (old_err>y || err>x) err+=++y*2+1; } while(y<=0); -} + dev->_svg_log_level = old_level; +} // Draw rectangle with round corner // x1:Start X coordinate @@ -549,7 +665,7 @@ void lcdDrawRoundRect(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16 if(x1>x2) { temp=x1; x1=x2; x2=temp; } // endif - + if(y1>y2) { temp=y1; y1=y2; y2=temp; } // endif @@ -563,15 +679,29 @@ void lcdDrawRoundRect(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16 y=-r; err=2-2*r; + esp_log_level_t old_level = ESP_LOG_NONE; + if (dev->_svg_log_level != ESP_LOG_NONE) { + uint16_t minx = x1>x2 ? x2 : x1; + uint16_t miny = y1>y2 ? y2 : y1; + uint16_t maxx = x1>x2 ? x1 : x2; + uint16_t maxy = x1>x2 ? y1 : y2; + char *color_name = rgb565_to_rgb(color); + ESP_LOG_LEVEL(dev->_svg_log_level, dev->_svg_log_tag, + "", + __FUNCTION__, color_name, minx, miny, (maxx-minx)+1, (maxy-miny)+1, r); + old_level = dev->_svg_log_level; + dev->_svg_log_level = ESP_LOG_NONE; // to skip the draw pixel stuff + } + do{ if(x) { - lcdDrawPixel(dev, x1+r-x, y1+r+y, color); - lcdDrawPixel(dev, x2-r+x, y1+r+y, color); - lcdDrawPixel(dev, x1+r-x, y2-r-y, color); + lcdDrawPixel(dev, x1+r-x, y1+r+y, color); + lcdDrawPixel(dev, x2-r+x, y1+r+y, color); + lcdDrawPixel(dev, x1+r-x, y2-r-y, color); lcdDrawPixel(dev, x2-r+x, y2-r-y, color); - } // endif + } // endif if ((old_err=err)<=x) err+=++x*2+1; - if (old_err>y || err>x) err+=++y*2+1; + if (old_err>y || err>x) err+=++y*2+1; } while(y<0); ESP_LOGD(TAG, "x1+r=%d x2-r=%d",x1+r, x2-r); @@ -579,8 +709,10 @@ void lcdDrawRoundRect(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16 lcdDrawLine(dev, x1+r,y2 ,x2-r,y2 ,color); ESP_LOGD(TAG, "y1+r=%d y2-r=%d",y1+r, y2-r); lcdDrawLine(dev, x1 ,y1+r,x1 ,y2-r,color); - lcdDrawLine(dev, x2 ,y1+r,x2 ,y2-r,color); -} + lcdDrawLine(dev, x2 ,y1+r,x2 ,y2-r,color); + + dev->_svg_log_level = old_level; +} // Draw arrow // x1:Start X coordinate @@ -659,6 +791,18 @@ uint16_t rgb565_conv(uint16_t r,uint16_t g,uint16_t b) { return (((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)); } +static char color_name_buf[20]; +static size_t color_name_buf_len = sizeof(color_name_buf); +// Don't make overlapped calls to this function because +// the returned string might change when you're not expecting it. +char * rgb565_to_rgb(uint16_t color) { + uint16_t r = (color >> 8) & 0xF8; + uint16_t g = (color >> 3) & 0xFC; + uint16_t b = (color << 3) & 0xF8; + snprintf(color_name_buf, color_name_buf_len, "rgb(%d,%d,%d)", r, g, b); + return color_name_buf; +} + // Draw ASCII character // x:X coordinate // y:Y coordinate @@ -935,3 +1079,44 @@ void lcdInversionOff(TFT_t * dev) { void lcdInversionOn(TFT_t * dev) { spi_master_write_command(dev, 0x21); //Display Inversion On } + +// SVG logging sends equivalent SVG directives to the ESP log (usually uart0). +// It logs at the logging level and with the logging tag specified. That +// should make it straightforward to use text tools to carve the actual SVG +// out of the log. There is an optional "cut line" argument to the lcdSvgLoggingEnd. +// If provided, it is logged as-is and could be used to automatically separate +// multiple chunks from the overall output. +// +// There is no inherent overall background color. If you want one, you +// should start with lcdFillScreen() within the SVG logging. +// +// SVG output can be quite verbose (especially for things like text that are +// drawn a pixel at a time). It also slows things down a huge amount. In fact, +// it makes things so slow that there are task delays of 1 tick sprinked +// throughout to avoid tripping the task watchdog timer. +// +// If you normally view the log output inside an IDE or other tool, SVG +// logging might overflow whatever buffer it uses. A more reliable way +// would be to use "idf.py monitor" and send or tee the output to a file. +// For simplicity, you probably also want to turn off the ANSI color +// coding of log output in your ESP-IDF project config settings. +void lcdSvgLoggingStart(TFT_t * dev, esp_log_level_t level, const char *tag) { + dev->_svg_log_level = level; + dev->_svg_log_tag = tag; + if (dev->_svg_log_level != ESP_LOG_NONE) { + ESP_LOG_LEVEL(dev->_svg_log_level, dev->_svg_log_tag, + "", + dev->_width, dev->_height, dev->_width, dev->_height); + } +} + +// You must call this to properly end SVG logging. +void lcdSvgLoggingEnd(TFT_t * dev, char *cut_line) { + if (dev->_svg_log_level != ESP_LOG_NONE) { + ESP_LOG_LEVEL(dev->_svg_log_level, dev->_svg_log_tag, ""); + if (cut_line != NULL) { + ESP_LOG_LEVEL(dev->_svg_log_level, dev->_svg_log_tag, "%s", cut_line); + } + } + dev->_svg_log_level = ESP_LOG_NONE; +} diff --git a/main/st7789.h b/main/st7789.h index c2c5c1ae..52006b1a 100644 --- a/main/st7789.h +++ b/main/st7789.h @@ -1,6 +1,7 @@ #ifndef MAIN_ST7789_H_ #define MAIN_ST7789_H_ +#include "esp_log.h" #include "driver/spi_master.h" #include "fontx.h" @@ -34,6 +35,8 @@ typedef struct { int16_t _dc; int16_t _bl; spi_device_handle_t _SPIHandle; + esp_log_level_t _svg_log_level; + const char * _svg_log_tag; } TFT_t; void spi_master_init(TFT_t * dev, int16_t GPIO_MOSI, int16_t GPIO_SCLK, int16_t GPIO_CS, int16_t GPIO_DC, int16_t GPIO_RESET, int16_t GPIO_BL); @@ -63,6 +66,7 @@ void lcdDrawRoundRect(TFT_t * dev, uint16_t x1, uint16_t y1, uint16_t x2, uint16 void lcdDrawArrow(TFT_t * dev, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t w, uint16_t color); void lcdDrawFillArrow(TFT_t * dev, uint16_t x0, uint16_t y0, uint16_t x1, uint16_t y1, uint16_t w, uint16_t color); uint16_t rgb565_conv(uint16_t r, uint16_t g, uint16_t b); +char * rgb565_to_rgb(uint16_t color); // static result buffer int lcdDrawChar(TFT_t * dev, FontxFile *fx, uint16_t x, uint16_t y, uint8_t ascii, uint16_t color); int lcdDrawString(TFT_t * dev, FontxFile *fx, uint16_t x, uint16_t y, uint8_t * ascii, uint16_t color); int lcdDrawCode(TFT_t * dev, FontxFile *fx, uint16_t x,uint16_t y,uint8_t code,uint16_t color); @@ -77,5 +81,8 @@ void lcdBacklightOff(TFT_t * dev); void lcdBacklightOn(TFT_t * dev); void lcdInversionOff(TFT_t * dev); void lcdInversionOn(TFT_t * dev); + +void lcdSvgLoggingStart(TFT_t * dev, esp_log_level_t level, const char *tag); +void lcdSvgLoggingEnd(TFT_t * dev, char * cut_line); #endif /* MAIN_ST7789_H_ */