Jump to content

Recommended Posts

Posted

Hello,

I attached the project hoping it could be useful. I used STM32CubeMX and Atollic True Studio. I have a 128x128 custom display with UC1610 via I2C.
The display shows the uGFX logduring gfxInit(), but then nothing else.

  /* Initialize and clear the display */
  gfxInit();

  // Get the screen size
  width = gdispGetWidth();
  height = gdispGetHeight();

  gdispDrawBox(10, 10, width/2, height/2, Black);
  gdispFillArea(width/2, height/2, width/2-10, height/2-10, Black);
  gdispDrawLine(5, 30, width-50, height-40, Black);

  for(i = 5, j = 0; i < width && j < height; i += 7, j += i/20)
   	gdispDrawPixel(i, j, White);

   /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
	  gfxSleepMilliseconds(500);
  }


What could be the problem ?

How can I debug correctly ?

 

Thanks

bye

K150_uGFX.zip

Posted

Hello @quipu and welcome to the µGFX community!

As @aeroman already mentioned the problem is that the changes are not being flushed to the real display. The UC1610 GDISP driver needs to maintain an internal framebuffer as the display controller doesn't provide one that allows addressing each pixel individually. Therefore, when rendering you always modify the framebuffer inside your microcontroller's RAM. The framebuffer contents need to be actively pushed to the UC1610 display controller. This is done by what's called "flushing" in the GDISP module.
There are multiple ways to flush:

  • Manually call gdispFlush()
  • Use auto flushing (can be enabled in the configuration file)
  • Use a flush timer (can be enabled in the configuration file)

I hope that helps.

Posted (edited)

Hello @aeroman and  @Joel Bodenmann.

Thanks for support. I followed your directions and now I see something :)

I noticed stange behavior with this code:

gdispDrawBox(10, 10, 64, 64, White);	/* First box without base*/
gfxSleepMillisecond(1000);
gdispDrawBox(0, 0, 128, 128, White);	/* Second box: drawn also base of first box ! */

The first box does not have the base. When the second box is drawn, also the base of first box is drawn!

You can watch the video at this link.

Also how colors are mapped? It is correct that the White is visualized and the Black no. What are Light Gray and Dark Gray?

Edited by quipu
Posted

Other question.

My display is custom, as shown in the attached image (pixels are rectangular).
At this link you see the problem.
How can I solve?
@aeroman, is it possible to configure UC1610 to limit COM number (from 160 to 128 - registers CEN, DST, DEN)?
Can the "Window" function help (registers WCP0, WPP0, WCP1, WPP1)?

RCustom_UC1610_128x128.jpg.b0664470ba210d8849b080f7792930eb.jpgegards

Posted

hi @quipu,

for the "colors", i use 0, 1, 2, 3 (gray0 .. gray4) when calling gdisp drawing functions.

the COM number is limited to GDISP_SCREEN_HEIGHT - 1 by the UC1610_SET_COM_END (CEN register) command in the init sequence.

for the rotation problem, the way used by the driver is to mirror the ram to seg mapping for X axis (datasheet pages 36..38) and on your screen this produces some ram mapped with not connected seg (128 seg < 160).

A workaroud might be to adapt the window function in gdisp_lld_flush() :

        // set window to fill
        cmdBuffer[0] = UC1610_SET_WINDOW_PROGRAM_ENABLE | 0;    // before changing boundaries
        cmdBuffer[1] = UC1610_SET_WP_STARTING_CA;
        cmdBuffer[3] = UC1610_SET_WP_ENDING_CA;
        cmdBuffer[5] = UC1610_SET_WP_STARTING_PA;
        cmdBuffer[6] = y1 >> 2;
        cmdBuffer[7] = UC1610_SET_WP_ENDING_PA;
        cmdBuffer[8] = y2 >> 2;
        cmdBuffer[9] = UC1610_SET_WINDOW_PROGRAM_ENABLE | 1;    // entering window programming
        switch (g->g.Orientation) {
            default :
                cmdBuffer[2] = x1;
                cmdBuffer[4] = x2;
                break;
            case GDISP_ROTATE_90 :
                cmdBuffer[2] = x1 + UC1610_SEG_NUMBER - UC1610_SCREEN_WIDTH;
                cmdBuffer[4] = x2 + UC1610_SEG_NUMBER - UC1610_SCREEN_WIDTH;
                break;
            case GDISP_ROTATE_180 :
                cmdBuffer[2] = x1 + UC1610_SEG_NUMBER - UC1610_SCREEN_WIDTH;
                cmdBuffer[4] = x2 + UC1610_SEG_NUMBER - UC1610_SCREEN_WIDTH;
                break;
        }

where UC1610_SEG_NUMBER == 160 and UC1610_SCREEN_WIDTH == 128

I suppose there is a better way to process rotation ...

  • 2 weeks later...
Posted

Hi,

i reproduced this bug and it seems related to the gdisp_lld_flush() function when writing pages segments from RAM(g) to display ram :

with the actual  y1 <= y2 in the "for" loop, when y2 is not a multiple of UC1610_PAGE_HEIGHT, the last segment is not writed to display ram.

I found this solution : for loop condition based on the end address of the flush window :

		// write each page segment from RAM(g) to display RAM
		for (c = RAM(g) + xyaddr(x1, y1) ; c < RAM(g) + xyaddr(x2, y2) ; c += GDISP_SCREEN_WIDTH) {
			write_data(g, c, cx);
		}

it seems to work correcly.

Posted
4 hours ago, aeroman said:

Hi,

i reproduced this bug and it seems related to the gdisp_lld_flush() function when writing pages segments from RAM(g) to display ram :

with the actual  y1 <= y2 in the "for" loop, when y2 is not a multiple of UC1610_PAGE_HEIGHT, the last segment is not writed to display ram.

I found this solution : for loop condition based on the end address of the flush window :


		// write each page segment from RAM(g) to display RAM
		for (c = RAM(g) + xyaddr(x1, y1) ; c < RAM(g) + xyaddr(x2, y2) ; c += GDISP_SCREEN_WIDTH) {
			write_data(g, c, cx);
		}

it seems to work correcly.

Hi @aeroman, great work. I will Apple your patch and i will let YouTube know asap. 

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...