Add time measure to SPI display

This commit is contained in:
Stephan Hadinger 2021-04-25 21:40:01 +02:00
parent b39b57e695
commit b03756a24a
2 changed files with 107 additions and 61 deletions

View File

@ -3,6 +3,8 @@
// ARCHITECTURE-SPECIFIC TIMER STUFF --------------------------------------- // ARCHITECTURE-SPECIFIC TIMER STUFF ---------------------------------------
extern void lv_flush_callback(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p);
// Tick interval for LittlevGL internal timekeeping; 1 to 10 ms recommended // Tick interval for LittlevGL internal timekeeping; 1 to 10 ms recommended
static const int lv_tick_interval_ms = 10; static const int lv_tick_interval_ms = 10;
@ -51,63 +53,63 @@ static bool touchscreen_read(struct _lv_indev_drv_t *indev_drv, lv_indev_data_t
#define LV_BUFFER_ROWS 60 // Most others have a bit more space #define LV_BUFFER_ROWS 60 // Most others have a bit more space
// This is the flush function required for LittlevGL screen updates. // // This is the flush function required for LittlevGL screen updates.
// It receives a bounding rect and an array of pixel data (conveniently // // It receives a bounding rect and an array of pixel data (conveniently
// already in 565 format, so the Earth was lucky there). // // already in 565 format, so the Earth was lucky there).
static void lv_flush_callback(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) { // static void lv_flush_callback(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
// Get pointer to glue object from indev user data // // Get pointer to glue object from indev user data
Adafruit_LvGL_Glue *glue = (Adafruit_LvGL_Glue *)disp->user_data; // Adafruit_LvGL_Glue *glue = (Adafruit_LvGL_Glue *)disp->user_data;
uint16_t width = (area->x2 - area->x1 + 1); // uint16_t width = (area->x2 - area->x1 + 1);
uint16_t height = (area->y2 - area->y1 + 1); // uint16_t height = (area->y2 - area->y1 + 1);
if (glue->getScreenshotFile() != nullptr) { // // check if we are currently doing a screenshot
// save pixels to file // if (glue->getScreenshotFile() != nullptr) {
int32_t btw = (width * height * LV_COLOR_DEPTH + 7) / 8; // // save pixels to file
while (btw > 0) { // int32_t btw = (width * height * LV_COLOR_DEPTH + 7) / 8;
int32_t ret = glue->getScreenshotFile()->write((const uint8_t*) color_p, btw); // while (btw > 0) {
//Serial.printf(">>> btw %d, written %d\n", btw, ret); // int32_t ret = glue->getScreenshotFile()->write((const uint8_t*) color_p, btw);
if (ret >= 0) { // if (ret >= 0) {
btw -= ret; // btw -= ret;
} else { // } else {
btw = 0; // abort // btw = 0; // abort
} // }
} // }
lv_disp_flush_ready(disp); // lv_disp_flush_ready(disp);
return; // ok // return; // ok
} // // }
Renderer *display = glue->display; // Renderer *display = glue->display;
if (!glue->first_frame) { // if (!glue->first_frame) {
//display->dmaWait(); // Wait for prior DMA transfer to complete // //display->dmaWait(); // Wait for prior DMA transfer to complete
//display->endWrite(); // End transaction from any prior call // //display->endWrite(); // End transaction from any prior call
} else { // } else {
glue->first_frame = false; // glue->first_frame = false;
} // }
display->setAddrWindow(area->x1, area->y1, area->x1+width, area->y1+height); // display->setAddrWindow(area->x1, area->y1, area->x1+width, area->y1+height);
display->pushColors((uint16_t *)color_p, width * height, true); // display->pushColors((uint16_t *)color_p, width * height, true);
display->setAddrWindow(0,0,0,0); // display->setAddrWindow(0,0,0,0);
lv_disp_flush_ready(disp); // lv_disp_flush_ready(disp);
} // }
#if (LV_USE_LOG) // #if (LV_USE_LOG)
// Optional LittlevGL debug print function, writes to Serial if debug is // // Optional LittlevGL debug print function, writes to Serial if debug is
// enabled when calling glue begin() function. // // enabled when calling glue begin() function.
static void lv_debug(lv_log_level_t level, const char *file, uint32_t line, const char *fname, // static void lv_debug(lv_log_level_t level, const char *file, uint32_t line, const char *fname,
const char *dsc) { // const char *dsc) {
Serial.print(file); // Serial.print(file);
Serial.write('@'); // Serial.write('@');
Serial.print(line); // Serial.print(line);
Serial.print(":"); // Serial.print(":");
Serial.print(fname); // Serial.print(fname);
Serial.write("->"); // Serial.write("->");
Serial.println(dsc); // Serial.println(dsc);
} // }
#endif // #endif
// GLUE LIB FUNCTIONS ------------------------------------------------------ // GLUE LIB FUNCTIONS ------------------------------------------------------
@ -120,9 +122,6 @@ static void lv_debug(lv_log_level_t level, const char *file, uint32_t line, cons
*/ */
Adafruit_LvGL_Glue::Adafruit_LvGL_Glue(void) Adafruit_LvGL_Glue::Adafruit_LvGL_Glue(void)
: first_frame(true), lv_pixel_buf(NULL) { : first_frame(true), lv_pixel_buf(NULL) {
#if defined(ARDUINO_ARCH_SAMD)
zerotimer = NULL;
#endif
} }
// Destructor // Destructor
@ -133,9 +132,6 @@ Adafruit_LvGL_Glue::Adafruit_LvGL_Glue(void)
*/ */
Adafruit_LvGL_Glue::~Adafruit_LvGL_Glue(void) { Adafruit_LvGL_Glue::~Adafruit_LvGL_Glue(void) {
delete[] lv_pixel_buf; delete[] lv_pixel_buf;
#if defined(ARDUINO_ARCH_SAMD)
delete zerotimer;
#endif
// Probably other stuff that could be deallocated here // Probably other stuff that could be deallocated here
} }
@ -207,11 +203,6 @@ LvGLStatus Adafruit_LvGL_Glue::begin(Renderer *tft, void *touch, bool debug) {
lv_init(); lv_init();
// #if (LV_USE_LOG)
// if (debug) {
// lv_log_register_print_cb(lv_debug); // Register debug print function
// }
// #endif
// Allocate LvGL display buffer (x2 because DMA double buffering) // Allocate LvGL display buffer (x2 because DMA double buffering)
LvGLStatus status = LVGL_ERR_ALLOC; LvGLStatus status = LVGL_ERR_ALLOC;

View File

@ -119,6 +119,61 @@ static void guiTask(void *pvParameter) {
vTaskDelete(NULL); vTaskDelete(NULL);
} }
/************************************************************
* Main screen refresh function
************************************************************/
// This is the flush function required for LittlevGL screen updates.
// It receives a bounding rect and an array of pixel data (conveniently
// already in 565 format, so the Earth was lucky there).
void lv_flush_callback(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p);
void lv_flush_callback(lv_disp_drv_t *disp, const lv_area_t *area, lv_color_t *color_p) {
// Get pointer to glue object from indev user data
Adafruit_LvGL_Glue *glue = (Adafruit_LvGL_Glue *)disp->user_data;
uint16_t width = (area->x2 - area->x1 + 1);
uint16_t height = (area->y2 - area->y1 + 1);
// check if we are currently doing a screenshot
if (glue->getScreenshotFile() != nullptr) {
// save pixels to file
int32_t btw = (width * height * LV_COLOR_DEPTH + 7) / 8;
while (btw > 0) {
int32_t ret = glue->getScreenshotFile()->write((const uint8_t*) color_p, btw);
if (ret >= 0) {
btw -= ret;
} else {
btw = 0; // abort
}
}
lv_disp_flush_ready(disp);
return; // ok
}
Renderer *display = glue->display;
if (!glue->first_frame) {
//display->dmaWait(); // Wait for prior DMA transfer to complete
//display->endWrite(); // End transaction from any prior call
} else {
glue->first_frame = false;
}
uint32_t pixels_len = width * height;
uint32_t chrono_start = millis();
display->setAddrWindow(area->x1, area->y1, area->x1+width, area->y1+height);
display->pushColors((uint16_t *)color_p, pixels_len, true);
display->setAddrWindow(0,0,0,0);
uint32_t chrono_time = millis() - chrono_start;
lv_disp_flush_ready(disp);
if (pixels_len >= 10000) {
AddLog(LOG_LEVEL_DEBUG, D_LOG_LVGL "Refreshed %d pixels in %d ms (%i pix/ms)", pixels_len, chrono_time,
chrono_time > 0 ? pixels_len / chrono_time : -1);
}
}
/************************************************************ /************************************************************
* Callbacks for file system access from LVGL * Callbacks for file system access from LVGL
* *
@ -255,7 +310,7 @@ void start_lvgl(const char * uconfig) {
} }
if (uconfig && !renderer) { if (uconfig && !renderer) {
#ifdef USE_UNIVERSAL_DISPLAY #ifdef USE_UNIVERSAL_DISPLAY // TODO - we will probably support only UNIV_DISPLAY
renderer = Init_uDisplay((char*)uconfig, -1); renderer = Init_uDisplay((char*)uconfig, -1);
if (!renderer) return; if (!renderer) return;
#else #else