Using LV_USE_THEME_MONO

Description

Trying to use a PMOLED in monochrome.

What MCU/Processor/Board and compiler are you using?

STM32F4

What LVGL version are you using?

7.0.1

What do you want to achieve?

Want to initialize LVGL with PMOLED background BLACK, text, symbols, and lines, etc in WHITE.

What have you tried so far?

In lv_conf.h, I have set the followings:

#define LV_USE_THEME_EMPTY       1
#define LV_USE_THEME_TEMPLATE    1
#define LV_USE_THEME_MATERIAL    1
#define LV_USE_THEME_MONO        1
#define LV_THEME_DEFAULT_COLOR_PRIMARY      LV_COLOR_WHITE
#define LV_THEME_DEFAULT_FLAG               LV_THEME_MATERIAL_FLAG_LIGHT

The OLED displays a picture and static text properly, but the whole screen changed to a white background somehow. I am using a bitwise frame-buffer similar to that of Sharp MIP:

#define DEV_BUFIDX(x, y)  ((x >> 3) + (y*(LV_HOR_RES_MAX >> 3)))
#define PIXIDX(x)     (1 << ((x) & 7)) 

In the callback function to set pixel, I use:

void mydisp_set_px_cb(lv_disp_drv_t * disp_drv, uint8_t * buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y, lv_color_t color, lv_opa_t opa) {
  (void) disp_drv;
  (void) buf_w;
  (void) opa;

  lv_coord_t _x,_y;

//also working on a runtime screen orientation change.
#if defined (LV_SCREEN_ROTATE_270)
  _x = y;
  _y = (LV_HOR_RES_MAX-1)-x;
#elif defined (LV_SCREEN_ROTATE_180)
  _x = (LV_HOR_RES_MAX-1)-x;
  _y = (LV_VER_RES_MAX-1)-y;
#elif defined (LV_SCREEN_ROTATE_90)
  _x = (LV_VER_RES_MAX-1)-y;
  _y = x;
#else
  _x = x;
  _y = y;
#endif

  if (lv_color_to1(color) == 1) {
    buf[DEV_BUFIDX(_x, _y)] |=  PIXIDX(_x);  //Set VDB pixel bit to 1 for other colors than BLACK
  } else {
    buf[DEV_BUFIDX(_x, _y)] &= ~PIXIDX(_x);  //Set VDB pixel bit to 0 for BLACK color
  }
}

I did an online debug and I was able to trace the actual function that sets the background white. It is located in lv_draw_rect.c::draw_bg(coords, clip, dsc) at line 97. After stepping through this function, the screen turns white, setting the whole frame buffer 0xff.

I am wondering if a style is required for MONOCHROME? I have not applied any style yet. The lv_hal_init() is short with snippet below:

void lv_hal_init(void)
{
	mydisp_init(); //a proven function to initialize the display will bg=BLACK, fg=WHITE, writing a bit 0=BLACK, 1=WHITE

	static lv_disp_buf_t lv_disp_buf;
	static lv_color_t lv_buf_array[LV_HOR_RES_MAX*LV_VER_RES_MAX];
	lv_disp_buf_init(&lv_disp_buf, lv_buf_array, NULL, LV_HOR_RES_MAX*LV_VER_RES_MAX);

	lv_disp_drv_t disp_drv;
	//disp_drv.rotated = 1;
	lv_disp_drv_init(&disp_drv);
	disp_drv.buffer = &lv_disp_buf;
	disp_drv.flush_cb = mydisp_flush_cb;
	disp_drv.set_px_cb = mydisp_set_px_cb;

	lv_disp_drv_register(&disp_drv);
}

Screenshot and/or video

The expected result is a black background with white text. But it is now inverted.

In 7.2 (not sure about earlier versions), there are two color defines:

I believe you want the primary color to be white and the secondary color to be black.

@embeddedt

primary color to be white and the secondary color to be black

I did set them in lv_conf.h. It looks like:

#define LV_THEME_DEFAULT_COLOR_PRIMARY      LV_COLOR_WHITE
#define LV_THEME_DEFAULT_COLOR_SECONDARY    LV_COLOR_BLACK

But the background is still in white. After running draw_bg(coords, clip, dsc) in lv_draw_rect.c (line 97), all buffer members changed to 0xff. That is the problem.

Even if I swap the definition above, to use COLOR_PRIMARY BLACK, COLOR_SECONARY WHITE, the background is not changed. It remains white, with text black.

Any style I need to initialize for the default?

No style should be necessary.

It might be worth cleaning and rebuilding the project to confirm that it picked up on the changes to lv_conf.h. When I try these settings (primary as white and secondary as black) I see a black background and white text.

@embeddedt

cleaning and rebuilding the project to confirm that it picked up on the changes to lv_conf.h

I did it, but it is the same result, unfortunately. One important clue is that, even when I swap BLACK and WHITE, the frame buffer remains initialized to 0xff after running draw_bg().

By the way, setting COLOR_PRIMARY and _SECONDARY to LV_COLOR_WHITE, or LV_COLOR_BLACK doesn’t make any difference in my environment. The display result is not dependent on the settings. Sometimes I make a stupid mistake with editing the wrong file with the name filename from other projects. This time I did a cross check to make sure with a slightly larger font (lv_font_montserrat_12 -> 14). It shows there is no stupid mistake of editing the wrong file.

There is something I have missed.

When I change LV_THEME_DEFAULT_FLAG to LV_THEME_MATERIAL_FLAG_DARK, the background is now in black with white text. Previously it was LV_THEME_MATERIAL_FLAG_LIGHT.
But now the top left icon is missing. There is something to change other than COLOR_PRIMARY and SECONDARY, I believe.

lv_conf.h extract:

 #define LV_USE_THEME_EMPTY       1
 #define LV_USE_THEME_TEMPLATE    1
 #define LV_USE_THEME_MATERIAL    1
 #define LV_USE_THEME_MONO        1

#define LV_THEME_DEFAULT_INCLUDE            <stdint.h>      /*Include a header for the init. function*/
#define LV_THEME_DEFAULT_INIT               lv_theme_material_init
#define LV_THEME_DEFAULT_COLOR_PRIMARY      LV_COLOR_WHITE
#define LV_THEME_DEFAULT_COLOR_SECONDARY    LV_COLOR_BLACK
#define LV_THEME_DEFAULT_FLAG               LV_THEME_MATERIAL_FLAG_DARK
#define LV_THEME_DEFAULT_FONT_SMALL         &lv_font_montserrat_14
#define LV_THEME_DEFAULT_FONT_NORMAL        &lv_font_montserrat_14
#define LV_THEME_DEFAULT_FONT_SUBTITLE      &lv_font_montserrat_14
#define LV_THEME_DEFAULT_FONT_TITLE         &lv_font_montserrat_14

LV_THEME_DEFAULT_INIT should be set to lv_theme_mono_init if you want the monochrome theme.

For black background and white text the LV_THEME_DEFAULT_COLOR_PRIMARY color should be set to LV_COLOR_BLACK and LV_THEME_DEFAULT_COLOR_SECONDARY should be set to LV_COLOR_WHITE, the MONO theme doesn’t have flags so LV_THEME_DEFAULT_FLAG should be set to 0, like this:

Now I have set lv_conf.h as follows:

#define LV_THEME_DEFAULT_INIT               lv_theme_mono_init 
#define LV_THEME_DEFAULT_COLOR_PRIMARY      LV_COLOR_WHITE
#define LV_THEME_DEFAULT_COLOR_SECONDARY    LV_COLOR_BLACK
#define LV_THEME_DEFAULT_FLAG               0 

The result is a black background and white text. But the image that’s supposed to show at the top left is missing

.

@embeddedt

LV_THEME_DEFAULT_INIT should be set to lv_theme_mono_init if you want the monochrome theme.

This is accurate. I needed to set LV_THEME_DEFAULT_INIT to lv_theme_mono_init to activate THEME_MONOCHROME.

Now I swap the primary and secondary color like:

#define LV_THEME_DEFAULT_COLOR_PRIMARY      LV_COLOR_BLACK
#define LV_THEME_DEFAULT_COLOR_SECONDARY    LV_COLOR_WHITE

The result is:


Ignore the black vertical line. It is just the sync problem with my digital camera. The background is white with black text “LittlevGL”. You can see that the image at the top left is now visible.

I can conclude that COLOR_PRIMARY= LV_COLOR_WHITE and COLOR_SECONDARY = LV_COLOR_BLACK is the way to go. The last issue is to fix the lv_img_create() issue.

No style applied to image creation at all. Code snippet to display the image is very simple:

/*Create a title label*/
  lv_obj_t * label = lv_label_create(lv_scr_act(), NULL);
  lv_label_set_text(label, "LittlevGL");
  lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, 0);
/*Create an image at top left*/
  lv_obj_t* logo = lv_img_create(lv_scr_act(), NULL);
  lv_img_set_src(logo, &SSL_logo);
  lv_obj_align(logo, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);

The C array of SSL_logo was exported from the online imageconverter tool with Indexed 2 color. File content matches exactly the image layout with code listed below:

const LV_ATTRIBUTE_MEM_ALIGN LV_ATTRIBUTE_IMG_SSL_LOGO uint8_t SSL_logo_map[] = {
  0x00, 0x00, 0x00, 0xff, 	/*Color of index 0*/
  0xff, 0xff, 0xff, 0xff, 	/*Color of index 1*/

  0x3f, 0x38, 0x3d, 
  0x3f, 0xbc, 0x3d, 
  0x7f, 0xbc, 0x7d, 
  0x73, 0xbc, 0x7d, 
  0x73, 0xbe, 0x7d, 
  0x7b, 0x3e, 0x7d, 
  0x38, 0x3e, 0x7d, 
  0x3c, 0x3e, 0xfd, 
  0x1e, 0x3e, 0xfd, 
  0x1e, 0x3f, 0xfd, 
  0x0f, 0x3f, 0xfd, 
  0x07, 0xbf, 0xfd, 
  0x07, 0xbb, 0xdd, 
  0x73, 0xbb, 0xdd, 
};

const lv_img_dsc_t SSL_logo = {
  .header.always_zero = 0,
  .header.w = 24,
  .header.h = 14,
  .data_size = 50,
  .header.cf = LV_IMG_CF_INDEXED_1BIT,
  .data = SSL_logo_map,
};

Look closely into the original image by correlating with the byte count shows:

Everything seems in order, but somehow, the image is missing when primary color is white.

Why?

@techtoys could you tell, what you use to annotate images?

@puzrin

what to use to annotate images?

The tool is Screenpresso Free.

1 Like

To avoid making silly mistakes from my custom hardware, I am switching to the Simulator lv_sim_visual_studio_sdl project to do the same test for this monochrome issue.

The main code is to display the same image that I use on my hardware (OLED + STM32) together with a static text and SYMBOL with the snippet below:

void lv_my_test(void)
{
	lv_obj_t* label = lv_label_create(lv_scr_act(), NULL);
	lv_label_set_text(label, "LittlevGL");
	lv_obj_align(label, NULL, LV_ALIGN_CENTER, 0, 0);

	lv_obj_t* img1 = lv_img_create(lv_scr_act(), NULL);
	lv_img_set_src(img1, &SSL_logo);
	lv_obj_align(img1, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);

	lv_obj_t* img2 = lv_img_create(lv_scr_act(), NULL);
	lv_img_set_src(img2, LV_SYMBOL_OK "Pass");
	lv_obj_align(img2, NULL, LV_ALIGN_IN_BOTTOM_RIGHT, 0, 0);
}

In lv_conf.h, the following configurations are used with corresponding result in simulator window:

 #define LV_USE_THEME_MONO        1

#define LV_THEME_DEFAULT_INCLUDE            <stdint.h>      /*Include a header for the init. function*/
#define LV_THEME_DEFAULT_INIT               lv_theme_mono_init //lv_theme_material_init
#define LV_THEME_DEFAULT_COLOR_PRIMARY      LV_COLOR_BLACK //lv_color_hex(0x01a2b1)
#define LV_THEME_DEFAULT_COLOR_SECONDARY    LV_COLOR_WHITE //lv_color_hex(0x44d1b6)
#define LV_THEME_DEFAULT_FLAG               0 //LV_THEME_MATERIAL_FLAG_LIGHT
#define LV_THEME_DEFAULT_FONT_SMALL         &lv_font_montserrat_12
#define LV_THEME_DEFAULT_FONT_NORMAL        &lv_font_montserrat_16
#define LV_THEME_DEFAULT_FONT_SUBTITLE      &lv_font_montserrat_20
#define LV_THEME_DEFAULT_FONT_TITLE         &lv_font_montserrat_24

When PRIMARY_COLOR=LV_COLOR_BLACK, all three objects displayed properly with a white background and black text.
Primary_color_black

Now I swap the primary and secondary color. Surprising, only the text is displayed. The top left image and the lower right SYMBOL now missing. They are supposed to display with color inverted, right?
Code snippets:

 #define LV_USE_THEME_MONO        1

#define LV_THEME_DEFAULT_INCLUDE            <stdint.h>      /*Include a header for the init. function*/
#define LV_THEME_DEFAULT_INIT               lv_theme_mono_init //lv_theme_material_init
#define LV_THEME_DEFAULT_COLOR_PRIMARY      LV_COLOR_WHITE //lv_color_hex(0x01a2b1)
#define LV_THEME_DEFAULT_COLOR_SECONDARY    LV_COLOR_BLACK //lv_color_hex(0x44d1b6)
#define LV_THEME_DEFAULT_FLAG               0 //LV_THEME_MATERIAL_FLAG_LIGHT
#define LV_THEME_DEFAULT_FONT_SMALL         &lv_font_montserrat_12
#define LV_THEME_DEFAULT_FONT_NORMAL        &lv_font_montserrat_16
#define LV_THEME_DEFAULT_FONT_SUBTITLE      &lv_font_montserrat_20
#define LV_THEME_DEFAULT_FONT_TITLE         &lv_font_montserrat_24

The result with primary and secondary color swapped:
Primary_color_white

Images are never inverted. Symbols follow the font color of the label they’re inside, so you should check that the label’s text color is set to white.

@ embeddedt

Images are never inverted

Yes, images are never inverted. Bit ‘1’ should be white, and ‘0’ black.
This is what I have expected to see:
Expected_result
But now the simulator window shows all black. This is what I don’t understand.

Maybe the SM part is transparent instead of white, so it shows as black against a black background. Check the palette (it should be at the beginning of the image data if it’s indexed).

1 Like

@embeddedt

the SM part is transparent instead of white

Thank you. Finally, I have got it working by a cheat somehow. Instead of an LV_COLOR_LIME, I just set
#define LV_COLOR_TRANSP LV_COLOR_BLACK

The complete lv_conf.h is like:

#define LV_COLOR_TRANSP    LV_COLOR_BLACK
//...
#define LV_USE_THEME_MONO        1

#define LV_THEME_DEFAULT_INCLUDE            <stdint.h>      /*Include a header for the init. function*/
#define LV_THEME_DEFAULT_INIT               lv_theme_mono_init 
#define LV_THEME_DEFAULT_COLOR_PRIMARY      LV_COLOR_WHITE
#define LV_THEME_DEFAULT_COLOR_SECONDARY    LV_COLOR_BLACK
#define LV_THEME_DEFAULT_FLAG               0 
#define LV_THEME_DEFAULT_FONT_SMALL         &lv_font_montserrat_12
#define LV_THEME_DEFAULT_FONT_NORMAL        &lv_font_montserrat_16
#define LV_THEME_DEFAULT_FONT_SUBTITLE      &lv_font_montserrat_20
#define LV_THEME_DEFAULT_FONT_TITLE         &lv_font_montserrat_24

Now the simulator and actual hw both show corrected results.
Primary_color_white_OK

The OLED display shows the expected result:

Is chroma key mandatory in LVGL? Can I not using it? There are only two colors BLACK/WHITE so I need to avoid an 1 treated as transparent.