JohnLKW
Members-
Posts
16 -
Joined
-
Last visited
Recent Profile Visitors
The recent visitors block is disabled and is not being shown to other users.
-
Yes, the speed won't be high for a SPI bus. The plan is to copy all assets required from a SDcard to SDRAM during initialization. Once an asset in .c array is stored in SDRAM, pictures can be copied to main window via blit. Will see... Thank you.
-
Over the weekend I have studied virtmem which is an Arduino library that maps external memory sources to extend the (limited) amount of available MCU's RAM. This library supports several memory resources including SPI ram & SD card hence it is possible to extend this library for a SPI-based gfx controller like ra8876. The library is made in such a way that managing and using this virtual memory closely resembles working with data from 'normal' memory. I think this will solve the problem of an external SDRAM previously "not addressable." Actual virtmem implementation can be found in https://github.com/rhelmus/virtmem. A diagram below shows the idea. Because dereferencing data from the external SDRAM still needs to copy the whole data structure to the main memory of MCU, a virtual pointer VPtr is used here to point to framebuffer1 reside in SDRAM. In this case only a virtual pointer is stored that the structure Surface can now fit in MCU memory! After allocation we will be able to fill up the framebuffer1 with a certain color (yellow) like addressable ram. Not sure if this can be implemented in Pixmap?
-
Found an interesting library that may solve the problem. https://github.com/rhelmus/virtmem Extract "virtmem is an Arduino library that allows your project to easily use an external memory source to extend the (limited) amount of available RAM. This library supports several memory resources, for instance, SPI ram (e.g. the 23LC1024 chip from Microchip), an SD card or even a computer connected via a serial connection." SDRAM connected to the gfx connector is just like a SPI RAM. With virtmem this SDRAM extends memory of a Teensy for framebuffer.
-
Does it mean that it is an internal routine not released in current uGFX version? Where to find more information about the "special gdispControl commands"? If there is an apparent tearing I will try to use Vsync as the time gate to update any blit command. Hope this will solve tearing. But even though vsync is not used I think it would be better than showing pixel-by-pixel raster from Flash or SD card to display directly. Teensy is selected for its friendly audio library.
-
Yes, the concept of Pixmap is puzzling me especially when it doesn't fit for my case. Attached is a block diagram for your reference. The current problem is that, it is not possible to map the external SDRAM to a pixmap surface as it is not an addressable RAM space for the MCU. Small systems like a Teensy doesn't have sufficient RAM space for 1024x768 frame buffer. Since Pixmap doesn't work for me, I am now considering gdispGBlit(). Although it is possible to copy an array of pixels from the sd card as the source to display, the performance is very slow. One will see pixel raster across the screen like snail walking. An alternative is to copy the array from sd card to a buffer allocated in those unused 10pages external SDRAM (say page 2). Some mechanism to notify the system that copy is complete then a single instruction can be used to copy from page 2 to page 1 which is the physical display to solve tearing effect. a 2D blit function is available in the gfx controller for this, but I still have to decide where to declare a framebuffer in uGFX. Similar topic by crteensy above have tackled this problem with a slight modification to GDisplay structure. I am wondering if there is any native location in uGFX for this purpose instead of a change to GDisplay structure?
-
I am thinking where to accommodate a framebuffer that is located in external graphic controller (like SSD1963) so that I call gdispGBlitArea(... const pixel_t *buffer) with *buffer point to that framebuffer. There is a relevant post about this topic at But I am not sure if there is some other way that does not need to change GDisplay structure... I was considering Pixmap but it doesn't work for my controller because it is a SPI-based external controller that cannot map to addressable memory space for Pixmap. This is what puzzling me...
-
Hi All Is there any example on how to use gdispGBlitArea(GDisplay *g, coord_t x, ...) and where is it? Is use Pixmap a precondition to use gdispGBlitArea()? John
-
Functions tested with basic primitive draw, font printing, solid area fill by hardware, line draw & pixel draw and confirmed the system is now stable. Going further I am going to port PIXMAP for RA8876 now. Searching over uGFX library there are two files gdisp_pixmap.h & gdisp_pixmap.c. Inside there is GDisplay *gdispPixmapCreate(coord_t width, coord_t height) calling void *gfxAlloc(size_t sz) from main memory of the MCU but this doesn't work for low resource system. Because an external SDRAM is bonded with RA8876 and there is 2D blit function built-in the chip, a preference is to make use of off-screen area from the SDRAM to allocate a whole page for assets storage. Simply say I would need to change the *gdispPixmapCreate(coord_t width, coord_t height) function to use an off-chip memory from the MCU for a virtual screen. There is no gdisp_lld_xxx function related to Pixmap as far as I see, right? Is it a nice approach to do this? John
-
Guru Yes, gdisp_fill_area routine got fixed just now. I had mixed up the fact that in gdisp_fill_area function, arguments are (x,y) and (width,height). In RA887x it should be translated to coordinates. And the pixel draw should be a cursor based routine as well. Extract of the lld_driver look like this: #if GDISP_HARDWARE_STREAM_WRITE LLDSPEC void gdisp_lld_write_start(GDisplay *g) { } LLDSPEC void gdisp_lld_write_color(GDisplay *g) { LLDCOLOR_TYPE c; c = gdispColor2Native(g->p.color); hal_lcdDataWrite16bbp(c); } LLDSPEC void gdisp_lld_write_stop(GDisplay *g) { } #endif //cursor based streaming for RA8876 #if GDISP_HARDWARE_STREAM_POS LLDSPEC void gdisp_lld_write_pos(GDisplay *g){ ra8876SetPixelCursor(g->p.x, g->p.y); hal_lcdRegWrite(RA8876_MRWDP); } #endif #if GDISP_HARDWARE_FILLS LLDSPEC void gdisp_lld_fill_area(GDisplay *g) { drawSquare(g->p.x, g->p.y, g->p.x+g->p.cx-1, g->p.y+g->p.cy-1, gdispColor2Native(g->p.color), 1); } #endif // GDISP_HARDWARE_FILLS
-
In this case do you mean that I have to call my specific string draw function like hal_drawString(args) instead of gdispDrawString(args)? I cannot find any directive to bypass uGFX font rendering like GDISP_HARDWARE_xxx. Where to find more documentation on GDISP control interface?
-
Thanks a lot. GDISP_HARDWARE_FILLS turned off leaving GDISP_HARDWARE_DRAWPIXEL alone. A video is better to show this. Please download it from a dropbox link here. I have tuned it to 720x480P @60Hz for faster rendering. A monitor is connected to RA8876 via HDMI transmitter. The host is an Arduino Due with SPI interface. https://www.dropbox.com/s/oft4zu8vmvc3rt9/with_GDISP_HARDWARE_DRAWPIXEL.mp4?dl=0 Again, thank you. Putting GDISP_STARTUP_LOGO macro to gfxconf.h with GDISP_HARDWARE_DRAWPIXEL does draw the LOGO OK. Another video is seen in this link. Does it restrict to gfxconf.h for GDISP_STARTUP_LOGO macro ? https://www.dropbox.com/s/akhtfz3mwia2cpm/Logo_render_w_pixel_streaming.mp4?dl=0 Yes it seems there is a bug. When GDISP_HARDWARE_FILLS turned on together with GDISP_HARDWARE_DRAWPIXEL defined TRUE, no string can be drawn and the logo vanished too. Function gdispDrawBox(0,0, 300, 300, random(0,65535)) became a solid fill. Still looking into it. However, as you can see from this video, the performance with 2D acceleration is very acceptable, even with 1280x720P@60Hz. https://www.dropbox.com/s/m2mewza8xzgv0le/with_GDISP_HARDWARE_FILLS.mp4?dl=0 Code for the main is extracted here: void loop() { //Hot plug detect for a new monitor edidHandler(); gdispDrawBox(0,0, 300, 300, random(0,65535)); delay(1000); gdispFillString(10,10,"Hello World Hello World Hello World Hello World", font_DejaVuSans24, White, Black); delay(1000); gdispFillArea(0, 0, width-1, height-1, random(0,65535)); delay(500); gdispFillArea(random(0,300), random(0,300), random(300,900), random(300,900), random(0,65535)); delay(500); uint16_t i; for(i=0; i<10000; i++){ gdispDrawPixel(random(10,width-10), random(10,height-10), random(0,65535)); } delay(500); for(i=0; i<10; i++){ gdispDrawLine(random(0,width-1), random(0,height-1), random(0,width-1), random(0,height-1), random(0,65535)); } delay(500); } Best Regards John
-
Besides the startup logo is it the hidden screen clear operation to black color causing the delay? No startup logo has been enabled before. I have found that when screen resolution is set to 320x240 delay is very short. However when resolution changed to 1280x720 delay spans as long as 10 seconds. This is because I didn't implement a hardware screen clear few days ago. Now I have implemented screen clear by 2D acceleration and the problem of delay startup has been solved. So I believe the delay was caused by a stream write iteration hidden in the init function somewhere. But I am not sure since no relevant code for screen flush can be found yet. This is exactly what I am asking in this post. On top, string draw is also a problem now.
-
Hi Some progress has been made to port uGFX to RA8876 which is an advanced display driver for high resolution TFT (up to 1366x768x24-bit). Up to now, basic operations like gfxInit(), gdispDrawBox(), gdispFillArea(), gdispDrawPixel(), gdispClear(), and gdispDrawLine() are working. But I have difficulty in getting gdispFillString() to work. Running function gdispFillString(10,10,"Hello World", font_DejaVuSans24, White, Black) only print a solid black color bar with white bar of the same size sweeping across it with no character can be seen. My questions are: 1. What else macro(s) should I put in to use gdispFillString()? 2. There is a font rendering feature by hardware on RA8876. Any where I implement this in uGFX? 3. Although Startup Logo has been enabled but there is no logo shown. What interface functions should I do for this? File gfxconf.h looks like: #ifndef _GFXCONF_H #define _GFXCONF_H #define GFX_USE_OS_ARDUINO TRUE #define GFX_USE_GDISP TRUE #define GDISP_NEED_TEXT TRUE #define GDISP_INCLUDE_FONT_DEJAVUSAN24_AA TRUE #endif From gdisp_lld_RA8876.c, I have three interface functions implemented: LLDSPEC bool_t gdisp_lld_init(GDisplay *g), LLDSPEC void gdisp_lld_draw_pixel(GDisplay *g) LLDSPEC void gdisp_lld_fill_area(GDisplay *g) The following options enabled in gdisp_lld_config.h for hardware pixel draw, hardware fill, and startup logo. #define GDISP_HARDWARE_DRAWPIXEL TRUE #define GDISP_HARDWARE_FILLS TRUE #define GDISP_NEED_STARTUP_LOGO TRUE #define GDISP_LLD_PIXELFORMAT GDISP_PIXELFORMAT_RGB565 Remarks: There are many nice features with this controller like: 2D blit operation. Accelerated graphic operation incl. square draw, circle draw, line draw, etc. Internal Font and external font stored in font chip support. That means we may print characters by hardware instead of rendering pixel-by-pixel. Graphic assets can be stored in external SPI Flash in bin format and transfer to display by DMA. External SDRAM (up to 512Mbit) is used for frame buffer that contains more than 10 pages of graphical contents in 1366x768. This implies that we may store graphic assets in non-visible window to wait until a slow rendering operation finished in that frame and then copy it to the main window by a single instruction. This is what I am going to port with Pixmap, and this is the key for slow MCU like Arduino to use a large TFT screen. SPI write in 4MHz clock is used in my setup. A whole page clear screen is done in no time by 2D operation. No pixel by pixel raster is seen. Any help is appreciated. John Leung
-
@Joel Bodenmann :That's all that gdispCreatePixmap() is doing in order to support setting a resolution during run-time. @John : Sorry that I still cannot get this point. I do understand virtual display and gdispCreatePixmap() can create a surface of an arbitrary size in memory. But this surface needs to be copied to the physical display at the end. The problem is that we have different physical display size ranging from 640x480 to 1920x1080. @inmarket : What is important is the setting of the g->g.Width and g->g.Height members in the gdisp_lld_init routine. @John : That is what I am trying to set. Code snippets below is working. When a monitor of 1920x1080 is connected, gdispGetWidth() & gdispGetHeight() returns 1920 & 1080, respectively. //... #ifdef GFX_USE_HDMI struct MonitorInfo *monitor; /* monitor is a structure defined to describe an edid array fetched from a monitor */ #endif //... LLDSPEC bool_t gdisp_lld_init(GDisplay *g) { // Initialise the board interface incl. hardware reset etc. hal_begin(); /* Initialise the GDISP structure */ #ifdef GFX_USE_HDMI g->g.Width = GDISP_SCREEN_WIDTH = monitor->detailed_timings[0].h_addr; g->g.Height = GDISP_SCREEN_HEIGHT = monitor->detailed_timings[0].v_addr; #else g->g.Width = GDISP_SCREEN_WIDTH; g->g.Height = GDISP_SCREEN_HEIGHT; #endif g->g.Orientation = GDISP_ROTATE_0; g->g.Powermode = powerOn; g->g.Backlight = GDISP_INITIAL_BACKLIGHT; g->g.Contrast = GDISP_INITIAL_CONTRAST; return TRUE; } In main I wrote: while(1){ //... some more init code gfxInit(); coord_t width, height; coord_t i, j; // Get the screen size width = gdispGetWidth(); height = gdispGetHeight(); Serial.println(width, DEC); //is able to print 1920 Serial.println(height, DEC); //is able to print 1080 } This code is working! But there is another problem. The time to run gfxInit() takes an incredible amount of time to finish (around 10sec). I need to wait such time to see 1920 and 1080 from the serial monitor. My question is: what functions are involved in gfxInit() besides getting LLDSPEC bool_t gdisp_lld_init(GDisplay *g) called? I am tracing it down to the line gdriverRegister(&GDISPVMT_OnlyOne->d, 0) in file gdisp.c but can't understand what it is. John
-
Hi Joel I've took a second thought on my problem and find my system may not strictly require resolution change in run-time. The scenario is like a PC connecting to monitors of different resolution. Monitor A has 1920x1080 preferred resolution but monitor B may have a 1280x1024 resolution. Fortunately my target system allows a system reboot when monitor is changed. That means it is only required to substitute the right resolution inside gdisp_lld_init(GDisplay *g) in the startup sequence. Therefore it is not strictly a change in run-time. It is just a startup parameter to be changed. Thanks for the gdispPixmapCreate() suggestion and it is definitely useful for my work. Best Regards John