|
|
|
_How to define external stubs to implement your CommLCD engine and
|
|
|
|
Comm IAL engine outside MiniGUI Core._
|
|
|
|
|
|
|
|
## Introduction
|
|
|
|
|
|
|
|
Since MiniGUI 3.2.2, you can use MiniGUI's built-in CommLCD NEWGAL engine
|
|
|
|
and Comm IAL engine to support your video output device and input device.
|
|
|
|
|
|
|
|
By using these two engines, you do not need to change the source code of
|
|
|
|
MiniGUI core. Instead, you implement the engines outside the MiniGUI core
|
|
|
|
by defining some external functions.
|
|
|
|
|
|
|
|
In this document, we describe the usage and the interfaces about these
|
|
|
|
two engines.
|
|
|
|
|
|
|
|
## Key Points
|
|
|
|
|
|
|
|
* Use MiniGUI 3.2.2 or later.
|
|
|
|
* Enable the engines when configuring MiniGUI:
|
|
|
|
* `--enable-videocommlcd`: enable CommLCD NEWGAL engine.
|
|
|
|
* `--enable-commial`: enable Comm IAL engine.
|
|
|
|
* `--with-targetname=external`: define target name to be `external`.
|
|
|
|
* Implement the external stubs in your app side:
|
|
|
|
* `#include <minigui/exstubs.h>`
|
|
|
|
* Specify the following runtime configuration options:
|
|
|
|
* `gal_engine=commlcd`: use CommLCD NEWGAL engine.
|
|
|
|
* `ial_engine=comm`: use comm IAL engine.
|
|
|
|
* Sample code: [`commlcd` in `mg-samples`](https://github.com/VincentWei/mg-samples/tree/master/commlcd)
|
|
|
|
|
|
|
|
## Functions to be Implemented
|
|
|
|
|
|
|
|
In MiniGUI header file `<minigui/exstubs.h>`, we declare the function
|
|
|
|
prototypes you need to implement for these two engines. You must
|
|
|
|
include this header in your C source file(s), and implement all
|
|
|
|
of the functions correctly.
|
|
|
|
|
|
|
|
In the `commlcd` sample of `mg-samples` package, the file `commlcd_ops.c`
|
|
|
|
implements the functions for CommLCD NEWGAL engine, and the file `comminput_ops.c`
|
|
|
|
implements the functions for Comm IAL engine:
|
|
|
|
|
|
|
|
* [`commlcd_ops.c`](https://github.com/VincentWei/mg-samples/blob/master/commlcd/commlcd_ops.c)
|
|
|
|
* [`comminput_ops.c`](https://github.com/VincentWei/mg-samples/blob/master/commlcd/comminput_ops.c)
|
|
|
|
|
|
|
|
The former implementation does not connect to any real device; it creates
|
|
|
|
an anonymous memory map and returns the address of the memory map as
|
|
|
|
the frame buffer to MiniGUI. However, when there is a update, this engine
|
|
|
|
will save the whole frame buffer content to a Windows bitmap file. So you
|
|
|
|
can observe the behaviors of the engine.
|
|
|
|
|
|
|
|
The latter implementation gives you a sample which gets input events
|
|
|
|
from a touch screen on Linux, and passed the events to MiniGUI. If you
|
|
|
|
have no such device, the engine will fails to initialize.
|
|
|
|
|
|
|
|
### CommLCD NEWGAL engine
|
|
|
|
|
|
|
|
#### Initializing the engine
|
|
|
|
|
|
|
|
`__commlcd_drv_init` will be called when initializing your
|
|
|
|
CommLCD engine implementation. In the `commlcd` sample, it does nothing
|
|
|
|
and just returns zero:
|
|
|
|
|
|
|
|
int __commlcd_drv_init (void)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
Note that, all external methods for CommLCD engine should return zero for success.
|
|
|
|
|
|
|
|
#### Setting video mode
|
|
|
|
|
|
|
|
`__commlcd_drv_getinfo` will be called when MiniGUI trying to set the video
|
|
|
|
mode according to your settings in the MiniGUI runtime configuration, e.g.,
|
|
|
|
`defaultmode=240x320-32bpp`.
|
|
|
|
|
|
|
|
In our sample, it creates the anonymous memory map by calling `mmap` system
|
|
|
|
call and returns the video information via `struct commlcd_info* li`:
|
|
|
|
|
|
|
|
int __commlcd_drv_getinfo (struct commlcd_info *li, int width, int height, int depth)
|
|
|
|
{
|
|
|
|
sg_fb = (BYTE*) mmap (0, FB_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
|
|
|
if (sg_fb == MAP_FAILED) {
|
|
|
|
perror ("Failed calling __commlcd_drv_getinfo: ");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
li->type = COMMLCD_TRUE_ARGB8888;
|
|
|
|
li->height = SCREEN_HEIGHT;
|
|
|
|
li->width = SCREEN_WIDTH;
|
|
|
|
li->bpp = COLOR_DEPTH;
|
|
|
|
li->pitch = SCREEN_WIDTH * BYTES_PER_PIXEL;
|
|
|
|
li->update_method = COMMLCD_UPDATE_ASYNC;
|
|
|
|
li->fb = sg_fb;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
You need fill the all fields of `struct commlcd_info* li` by the correct
|
|
|
|
values:
|
|
|
|
|
|
|
|
* `type`: The video mode type. Currently, CommLCD supports the following modes:
|
|
|
|
- `COMMLCD_PSEUDO_RGB332`: 256-color video mode.
|
|
|
|
- `COMMLCD_TRUE_RGB555`: RGB555 15-bit video mode.
|
|
|
|
- `COMMLCD_TRUE_RGB565`: RGB565 16-bit video mode.
|
|
|
|
- `COMMLCD_TRUE_RGB888`: RGB888 24-bit video mode.
|
|
|
|
- `COMMLCD_TRUE_RGB0888`: RGB0888 32-bit video mode (without alpha component).
|
|
|
|
- `COMMLCD_TRUE_ARGB1555`: RGB1555 16-bit video mode (the alpha component use 1 bit only).
|
|
|
|
- `COMMLCD_TRUE_ARGB8888`: RGB8888 32-bit video mode (the alpha, red, green, blue components all use 8 bits).
|
|
|
|
* `height`: The vertical resolution in pixels.
|
|
|
|
* `width`: The horizontal resolution in pixels.
|
|
|
|
* `bpp`: The color depth in bits per pixels. Actually, this field is a redundancy,
|
|
|
|
because the type already contains the depth information.
|
|
|
|
* `pitch`: The length in bytes of one scan line. Generally, it should be a
|
|
|
|
times of 4, i.e., the address of each scan line should be 4-byte aligned.
|
|
|
|
* `update_method`: The update method when there is a dirty rectangle, can be
|
|
|
|
one of the following values:
|
|
|
|
- `COMMLCD_UPDATE_NONE`: do not call `__commlcd_drv_update` (see below).
|
|
|
|
- `COMMLCD_UPDATE_SYNC`: call `__commlcd_drv_update` synchronously.
|
|
|
|
- `COMMLCD_UPDATE_ASYNC`: call `__commlcd_drv_update` asynchronously.
|
|
|
|
* `fb`: The address of the frame buffer.
|
|
|
|
|
|
|
|
#### Setting palette
|
|
|
|
|
|
|
|
If the color depth of the video mode is less than 15 (`COMMLCD_PSEUDO_RGB332`),
|
|
|
|
`__commlcd_drv_setclut` function will be called to set the palette.
|
|
|
|
|
|
|
|
In our sample, this method does nothing and returns zero:
|
|
|
|
|
|
|
|
int __commlcd_drv_setclut (int firstcolor, int ncolors, GAL_Color *colors)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
In practice, you should set the hardware palette (color look up table) in this
|
|
|
|
method if the color depth of your video device is only 256-color.
|
|
|
|
|
|
|
|
The arguments of this function have the following meanings:
|
|
|
|
|
|
|
|
* `firstcolor`: The first color index (the palette entry index) should be set.
|
|
|
|
* `ncolors`: The number of palette entries should be set.
|
|
|
|
* `colors`: The array of `GAL_Color` which define the RGB triples for each
|
|
|
|
palette entries will be set.
|
|
|
|
|
|
|
|
`GAL_Color` is a structure defined in MiniGUI header:
|
|
|
|
|
|
|
|
typedef struct _GAL_Color
|
|
|
|
{
|
|
|
|
/**
|
|
|
|
* The red component of a RGBA quarter.
|
|
|
|
*/
|
|
|
|
gal_uint8 r;
|
|
|
|
/**
|
|
|
|
* The green component of a RGBA quarter.
|
|
|
|
*/
|
|
|
|
gal_uint8 g;
|
|
|
|
/**
|
|
|
|
* The blue component of a RGBA quarter.
|
|
|
|
*/
|
|
|
|
gal_uint8 b;
|
|
|
|
/**
|
|
|
|
* The alpha component of a RGBA quarter.
|
|
|
|
*/
|
|
|
|
gal_uint8 a;
|
|
|
|
} GAL_Color;
|
|
|
|
|
|
|
|
#### Update method
|
|
|
|
|
|
|
|
If you specify the `update_method` to be `COMMLCD_UPDATE_SYNC` or
|
|
|
|
`COMMLCD_UPDATE_ASYNC`, the update method `__commlcd_drv_update` will
|
|
|
|
be called frequently or periodically.
|
|
|
|
|
|
|
|
In our sample, this method save the whole frame buffer content to Windows
|
|
|
|
bitmap files by calling MiniGUI function:
|
|
|
|
|
|
|
|
int __commlcd_drv_update (const RECT* rc_dirty)
|
|
|
|
{
|
|
|
|
char filename [PATH_MAX + 1];
|
|
|
|
struct timeval tv;
|
|
|
|
|
|
|
|
MYBITMAP my_bmp = {
|
|
|
|
flags: MYBMP_TYPE_RGB | MYBMP_FLOW_DOWN,
|
|
|
|
frames: 1,
|
|
|
|
depth: 32,
|
|
|
|
w: SCREEN_WIDTH,
|
|
|
|
h: SCREEN_HEIGHT,
|
|
|
|
pitch: PITCH,
|
|
|
|
size: FB_SIZE,
|
|
|
|
bits: sg_fb
|
|
|
|
};
|
|
|
|
|
|
|
|
printf ("__commlcd_drv_update called (%d, %d, %d, %d)\n",
|
|
|
|
rc_dirty->left, rc_dirty->top,
|
|
|
|
rc_dirty->right, rc_dirty->bottom);
|
|
|
|
|
|
|
|
gettimeofday (&tv, NULL);
|
|
|
|
sprintf (filename, "screenshot-%d.%d.bmp", (int)tv.tv_sec, (int)tv.tv_usec);
|
|
|
|
SaveMyBitmapToFile (&my_bmp, NULL, filename);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Note that, you can not call MiniGUI GDI functions here to draw something to
|
|
|
|
screen.
|
|
|
|
|
|
|
|
In practice, you may need to send an `ioctl` command to your video device driver
|
|
|
|
to update the content in our frame buffer to the real LCD controller.
|
|
|
|
|
|
|
|
For example, if you use SPI
|
|
|
|
to connect a LCD screen, you may create an off-screen frame buffer in memory,
|
|
|
|
and transfer the pixels to the LCD controller via SPI.
|
|
|
|
|
|
|
|
The argument `rc_dirty` contains the dirty rectangle, i.e., the rectangle need
|
|
|
|
to be updated to the real frame buffer or LCD controller.
|
|
|
|
|
|
|
|
Generally, you should set `update_mothod` to be `COMMLCD_UPDATE_ASYNC` in
|
|
|
|
`__commlcd_drv_init` method, and the method will be called asynchronously
|
|
|
|
in a different thread, about 20 times per second.
|
|
|
|
|
|
|
|
If you set `update_mothod` to be `COMMLCD_UPDATE_SYNC`, this update method
|
|
|
|
will be called synchronously when there is any update of the frame buffer.
|
|
|
|
For example, you call the MiniGUI function `SetPixel` to draw just one pixel
|
|
|
|
on the screen. Therefore, this will reduce the refresh performance of the
|
|
|
|
entire system. However, if you use MiniGUI's
|
|
|
|
[Synchronous Update Mechanism](https://github.com/VincentWei/minigui/wiki/Sync-Update),
|
|
|
|
it will be better to set `update_mothod` to be `COMMLCD_UPDATE_SYNC`.
|
|
|
|
|
|
|
|
If you can access the LCD frame buffer directly, and your LCD screen
|
|
|
|
do not need a refresh/update operation, you do not need to implement
|
|
|
|
the update method, and the function can just return zero:
|
|
|
|
|
|
|
|
int __commlcd_drv_update (const RECT* rc_dirty)
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
If you specify the `update_mothod` to be `COMMLCD_UPDATE_NONE` in
|
|
|
|
`__commlcd_drv_init` method, this function will be never called.
|
|
|
|
|
|
|
|
#### Releasing the engine
|
|
|
|
|
|
|
|
When MiniGUI quits, it will call `__commlcd_drv_release` to release
|
|
|
|
the resource allocated or created by the engine.
|
|
|
|
|
|
|
|
In our sample, it destroys the anonymous memory map and returns zero:
|
|
|
|
|
|
|
|
int __commlcd_drv_release (void)
|
|
|
|
{
|
|
|
|
munmap (sg_fb, FB_SIZE);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
### Comm IAL engine
|
|
|
|
|
|
|
|
## Summary
|
|
|
|
|
|
|
|
## References
|
|
|
|
|
|
|
|
* [GAL and IAL Engines](http://wiki.minigui.com/twiki/bin/view/Products/MiniGUIPGV32Part5Chapter03) |