Important: posts that do not use this template will be ignored or closed.
Description
I am trying to use LittlevGL on OLED(SSD1306) using Nordic’s nRF52840.
I am not getting the desired output. It is noise which seems random but is the same every time you power on the OLED.
What MCU/Processor/Board and compiler are you using?
MCU - nRF52840
What do you experience?
Screen is showing random noise. Actually the pattern made by this noise is always same.
I am guessing there is some problem with the generated buffer.
Any idea how can I debug ? Or is there some problem with my code.
Code to reproduce
main.c
lv_init();
lv_port_disp_init();
lv_obj_t * scr = lv_disp_get_scr_act(NULL);
lv_theme_t * th = lv_theme_mono_init(0, NULL);
/* Set the mono system theme */
lv_theme_set_current(th);
/*Create a Label on the currently active screen*/
lv_obj_t *label1;
label1 = lv_label_create(scr, NULL);
lv_label_set_text(label1, "Hello World");
lv_obj_set_pos(label1,30, 30);// position, position);
NRF_LOG_INFO("Towards end of main"); NRF_LOG_FLUSH();
while (1) {
lv_task_handler();
lv_tick_inc(1);
nrf_delay_ms(1);
}
disp_flush function
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
int16_t x;
int16_t y;
uint8_t *buf = (uint8_t*) color_p;
for(y = area->y1; y <= area->y2; y++) {
for(x = area->x1; x <= area->x2; x++) {
/* Put a pixel to the display. For example: */
/* put_px(x, y, *color_p)*/
Adafruit_GFX_drawPixel(x, y, *buf);
buf++;
}
}
NRF_LOG_INFO("Written to screen"); NRF_LOG_FLUSH();
/* IMPORTANT!!!
* Inform the graphics library that you are ready with the flushing*/
lv_disp_flush_ready(disp_drv);
}
void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
int16_t x;
int16_t y;
uint8_t *buf = (uint8_t*) color_p;
//copyToBuffer(buf);
NRF_LOG_INFO("X1 Value %d | X2 Value %d | Y1 Value %d | Y2 Value %d", area->x1, area->x2, area->y1, area->y2); NRF_LOG_FLUSH();
for(y = area->y1; y <= area->y2; y++) {
for(x = area->x1; x <= area->x2; x++) {
SSD1306_drawPixel(x, y, *buf);
buf++;
}
}
SSD1306_display();
NRF_LOG_INFO("Written to screen"); NRF_LOG_FLUSH();
/* IMPORTANT!!!
* Inform the graphics library that you are ready with the flushing*/
lv_disp_flush_ready(disp_drv);
}
What color depth are you using? You should use lv_color_toX(*color_p) (where X is the display’s color depth) instead of casting color_p to a uint8_t directly.
For example, if you want a 16-bit RGB color value, you should call lv_color_to16 and use the value it returns instead of casting lv_color_t * to uint16_t *.
I was using a callback function set_px_cb which was taken from this blog.
uint16_t byte_index = x + (( y>>3 ) * buf_w);
uint8_t bit_index = y & 0x7;
// == 0 inverts, so we get blue on black
if ( color.full == 0 ) {
BIT_SET( buf[ byte_index ] , bit_index );
}
else {
BIT_CLEAR( buf[ byte_index ] , bit_index );
}
Removing this function and printing each pixel from buffer using this callback function solved my problem.
int16_t x;
int16_t y;
for(y = area->y1; y <= area->y2; y++) {
for(x = area->x1; x <= area->x2; x++) {
SSD1306_drawPixel(x, y, lv_color_to1(*color_p));
color_p++;
}
}
SSD1306_display();
/* IMPORTANT!!!
* Inform the graphics library that you are ready with the flushing*/
lv_disp_flush_ready(disp_drv);
I think one of the uses of this function was there to invert pixels. If this function is interfering with printing of pixels then how can I correct this function to invert my display ?
Another problem I am facing is that content is being displayed in segments.
I analysed the function calls and found that the disp_flush function is called around 8 times with different area segments segments.
For eg the first call to disp_flush is with area segments X1 = 0, X2=64 and Y1=0, Y2=8
the second call to disp_flush is with area segments X1 = 0, X2=64 and Y1=8, Y2=16
and so on…
**How can I increase speed of display process ? **
You can increase your display buffer size. That will reduce the number of calls to disp_flush.
To increase the speed further you’ll have to optimize the loop. For example, on other SSD display controllers, you can avoid setting the X and Y window before every pixel and just set it once. That has proved to be a huge speedup in my experience.