The PowerView embedded GUI system in the Examples\PowerView directory is derived from several years work with industrial displays. The code is designed to be a reasonable compromise between code space, RAM space and facilities. It is not intended as a replacement for a desktop windowing system.
Drivers are provided for several CPU and LCD panel combinations:
The supplied example code in this manual is for the MPE ARM Development Kit, which uses a Sharp LH77790B ARM with an on-chip LCD controller. To compile the code, set up the text macro GuiDir to point to the PowerView folder, and compile the following files:
include %GuiDir%\FontDefs \ font structs and data
include %GuiDir%\Font\Font12x8x2 \ 12x8 font
include %GuiDir%\Font\Font16x12x2 \ 16x12 font
include %GuiDir%\Font\Font16x16x2 \ 16x16 font
include %GuiDir%\Drivers\LcdQvgaMono5 \ hardware specific driver
include %GuiDir%\GUI \ GUI kernel
include %GuiDir%\DemoMono2 \ GUI demo
The configuration equates below are only used if they have not already been defined, e.g. in your control file.
1 equ GUIdiags? \ -- n
Set this non-zero to compile some diagnostics.
: c+! \ n c-addr --
Add n to the byte at c-addr.
: addchar \ char string --
Add the character to the end of the counted string.
: append \ c-addr u $dest --
Add the string described by C-ADDR U to the counted string at
$DEST. The strings must not overlap.
: -leading \ caddr len -- caddr' len'
Ignore leading spaces.
: split \ addr len char -- laddr llen raddr rlen
Extract a substring at the start of addr/len, returning
the string remaining after char and the substring addr/sslen
which does not include char. If the string does not contain the
character, raddr is addr+len and rlen=0.
In the GUI system, much use is made of rectangles stored
in /Rect
structures.
struct /Rect \ -- size
Rectangle structure.
int r.x \ x,y position int r.y int r.w \ width int r.h \ height end-struct
: r>coords \ rect -- x y w h
Return the coordinates of the given rectangle.
: centred \ rect len -- xleft ytop
Given the length of a string and a rectangle in which to
display it, form the x/y start point at which the string
should be displayed.
: button \ caddr len rect --
Display a button - a rectangle with centred text.
: 3D-Button \ caddr len rect --
Display a 3D effect button. This is achieved by varying the
colour of the borders, and so is specific to the display
hardware.
: nInter \ c-addr u -- n
Gets number of interword spaces in a string by counting the
number of spaces in the string.
#40 buffer: jText \ -- addr
Temporary buffer that holds justified text.
: AddNext \ caddr len -- caddr' len'
Extract the leftmost string (delimited by a space), and
add it to the justified text buffer, returning the string
to the right of the first space.
: AddSpaces \ n --
Add n spaces to the justified text buffer.
: FindLine \ caddr1 len1 n -- caddr2 len2
Return a line of maximum length n containing complete words
of text.
: BuildJustified \ caddr len w -- caddr' w
Build a justified line of text of size w in a buffer, and
return the buffer address and length.
: ShowJLines \ x y caddr len w --
Display a block of justified text starting at pixel position
x,y in a width of w pixels. The text must contain
single spaces as word separators. N.B. No word may be longer
than w/fontwidth-1 characters, otherwise the display may
hang.
The drawing routines for the GUI are all given the item's data structure.
struct /GUIdef \ -- len
All elements of the GUI are controlled by this data structure
which is usually built at compile time.
\ -- Chains int pNext \ points to next child int pParent \ points to parent int pChild \ points to first child \ -- Processing int idSel \ user specified identifier int xtDraw \ holds xt of routine that draws this int xtAction \ holds xt of associated action, e.g. when pressed \ -- Rectangle, text and font /Rect field Grect \ holds X Y W H int ppFont \ points to a pointer to the required font int pText \ Points to counted string text for buttons etc \ -- Type specific data 0 field Gprivate \ Item specific data follows. \ MENU only int ppMenuFont \ points to pointer to the font for the MENU 4 - end-struct
The following two words are compiled if the equate
GUIdiags?
is non-zero.
: .GuiItem \ item --
Display the data structure for a GUI element.
: .GuiChain \ item --
Display the chain of data structures for a compund GUI
structure such as a menu.
: SetItemFont \ item -- font
Return the current font and set the font for this item.
: DrawButton \ item --
Draw a 3D button with centred text.
: DrawCtext \ item --
Draw text centred in the rectangle.
: DrawLtext \ item --
Draw text left justified in the rectangle.
: DrawRtext \ item --
Draw text right justified in the rectangle.
: DrawJText \ item --
Draw justified text in the rectangular area.
: DrawBox \ item --
Draw a box (rectangle).
: DrawTextBox \ item --
Draw a box filled with justified text.
: DrawImage \ item --
Display an image. The image data follows the item.
: DrawPicture \ item --
Display an image. The address of the image data follows
the item.
: DrawMenuFrame \ item --
Draw the menu frame and caption.
: DrawMenu \ item --
Draw a menu and its first level children.
Defer ActOnMenu \ id item --
Perform the action specified by ID (usually a GUI item
structure or an x,y pair from a touch screen) for the
given menu. The default action is 2DROP
.
Define your own action for this word. It should walk the
menu chain, select which item if any that ID refers to,
and execute the selected action word in the item data
structure.
variable LastItem \ -- addr
Holds the address of the last item defined
variable CurrItem \ -- addr
Holds the address of the item being defined
variable ParentItem \ -- addr
Holds the address of the item's parent
create Null$ 0 , \ -- addr
A null string which may be used as a counted
string or a zero-terminated string.
Please note that the following words are only available
during cross-compilation. If you need them on the target,
just make copies outside the INTERPRETER ... TARGET
structure.
: pNext, \ -- ; lay next pointer
INTERPRETER: lay the pointer to the next item. The list is
anchored at the parent's pChild
field.
: parent, \ -- ; lay pointer to parent
INTERPRETER: Lay the pointer to the parent item.
: child, \ -- ; lay pointer to children
INTERPRETER: Lay a pointer to any children.
: +ParX \ x -- x'
INTERPRETER: Add the parent's x offset.
: +ParY \ y -- y'
INTERPRETER: Add the parent's Y offset.
: ident, \ --
Lay default user identifier.
: Rect, \ x y w h -- ; lay rectangle
INTERPRETER: Add the parent's x offset.
: GuiDef, \ x y w h xt --
INTERPRETER: Lay down the basic /GuiDef
structure
using the given rectangle data and the xt of the word that
draws the item.
: text", \ -- ; followed by delimited text
INTERPRETER: Lay down the following text string and set
the pText
field in the current item being defined.
These words are used to generate menus which can contain
buttons, text, boxes and graphics. The menu is displayed
by the word DrawMenu ( menu -- )
and actions can be
performed by the user-defined action of
ActOnMenu ( x menu -- )
.
With the exception of MENU
the application words
construct data structures without names. If you want to
refer to a specific item, use
create <name>
before the item. The data structures are held in linked lists, so having additional code and data between items is permitted.
: MENU \ x y w h "<name>" -- par last ; -- addr
INTERPRETER: Use in the form:
x y w h MENU <name>
to start a MENU ... END-MENU
definition. When
data structure.
The positions of the internal elements are relative to
the top left hand corner of the menu. A title bar is
generated only if a caption is defined (see below).
: CAPTION" \ -- ; followed by delimited text
INTERPRETER: Use in the form:
CAPTION" <text>"
to add a caption and title bar to a menu.
: MENUFONT \ fonttable --
INTERPRETER: Use in the form:
<fonttable> MENUFONT
to define the default font used by all items within a menu. If no font is set, the current font will be used.
: FONT \ fonttable --
INTERPRETER: Use in the form:
<fonttable> FONT
to define the font used by an item. The defined font will only apply to that item. If no font is set, the current font will be used.
INTERPRETER: Ends a MENU ... END-MENU
definition.
: SetID \ x --
Give the current item an identifier that can be used to select
the item. This may be a character or any other unique identifier
for this menu.
: BUTTON" \ x y w h <"text"> --
INTERPRETER: Use in the form below to create a button:
x y w h BUTTON" <text>"
: RUNS \ -- ; name follows inline
INTERPRETER: Use in the form:
RUNS <name>
to set the xtAction
field of the item being defined.
: CTEXT" \ x y w h <"text"> --
INTERPRETER: Use in the form:
x y w h CTEXT" <text>"
to produce text centred in the given rectangle.
: LTEXT" \ x y w h <"text"> --
INTERPRETER: Use in the form:
x y w h LTEXT" <text>"
to produce text left justified in the given rectangle.
: RTEXT" \ x y w h <"text"> --
INTERPRETER: Use in the form:
x y w h RTEXT" <text>"
to produce text right justified in the given rectangle.
: BOX \ x y w h --
INTERPRETER: Use in the form:
x y w h BOX
to produce a rectangular outline.
: JTEXT" \ x y w h <"text"> --
INTERPRETER: Use in the form:
x y w h JTEXT" <lots of text on one source line>"
to produce fully justfied text that may spread over several lines. Note that there should be only one space between each word for best results.
: JTEXTBOX" \ x y w h <"text"> --
INTERPRETER: Use in the form:
x y w h JTEXTBOX" <lots of text on one source line>"
to produce a rectangular outline filled with justfied text.
Like JTEXT"
but with a box around it.
: GRAPHIC \ x y w h --
INTERPRETER: Use in the form:
x y w h GRAPHIC <filename>
to produce an image loaded with the top left hand corner at x,y. The width and height are at present unused. The image file is loaded into the dictionary at compile time.
: PICTURE \ x y w h --
INTERPRETER: Use in the form:
x y w h addr PICTURE
to produce an image loaded with the top left hand corner at x,y. The width and height are at present unused. The image data is at addr.
: Image: \ -- ; -- addr
INTERPRETER: Create a dictionary entry and load a graphics
file to the current section, e.g.
Image: demo1 %GuiDir%\Pics\demo1.bin
The image can be displayed using code of the for:
x y demo1 load-image
Before use, images created on a PC must be converted to the format required by the particular LCD panel. The The conversion tools are now part of the AIDE compiler front-end.
Although it is possible to convert standard graphics formats "on the fly" for display, it usually requires considerably more image storage space, is usually slower, and requires a more complicated (larger and slower) image display routine. If your display system is running at 8 or 16 bits per pixel, and/or images are frequently changed, it may well be worthwhile to consider this approach.
The tool in the AIDE front end is the current version. Source code for AIDE is available on request. In AIDE, select Utilities -> BMP to LCD converter. There are options to flip the image vertically, generate little or big-endian data, and to add the header needed by PowerView to display the image.
The older tool for the QVGA 2-bit mono is in the folder Examples\PowerView\BMPcnv folder, together with full source code to compile on VFX Forth for Windows.
When generating images for use with a 2 bit LCD panel, ensure that the image width is a multiple of four bits. Save the image as 4 bits per pixel grayscale if this is available, or as a 16-colour image, e.g. in MS Paint (file mspaint.exe} the selection of output file type is "16 Colour Bitmap".
BMPcnv.exe is a Windows-32 tool for converting 16 colour (4-bit) images to the four-level (2-bit) grayscale format required by the GiantPlus GPG3224TWE3 and equivalent panels for which we have provided a driver. It is assumed that the bitmap being converted is a .BMP file with a 4 bit Windows standard pallette (preferably grayscale) and has been flipped vertically prior to conversion. To convert a file:
If you are not using a panel with the same RAM layout as one of the supplied example drivers, or you are not using one of the example LCD controllers, you will have to modify the files:
Fontxxxx.fth |
contains the font used for text display. |
LCDxxxx.fth |
contains the LCD driver and graphics primitives. |
GUI.fth |
contains the high level code. |
If your hardware requires an LCD layout that is not currently
supported, you will need to add a new output format to AIDE's
BmpCnv utility. Source code for AIDE is available on request.
If the panel
operates at 8 or 16 bits per pixel, you may find it more
convenient to modify LOAD-IMAGE
in the video driver
to operate with BMP file images.
The example code in PowerView\GUIdemo.fth may be compiled as an example or to test changes you may have made.
2 equ GUIexamples? \ -- n
Set this non-zero to compile some examples. If set greater
than one, an example with several graphics images will be
compiled. The full set of graphics requires 100+ kb of memory
in the current CDATA
section.
This equate is only used if it has not already been defined,
e.g. in your control file.
The following examples define two menus and their actions. The menu position is given in absolute pixel coordinates. The positions of the internal elements are relative to the top left hand corner of the menu. A title bar is generated only if a caption is defined.
: test1 ( -- ) cr ." ONE" ; : test2 ( -- ) cr ." TWO" ; : test3 ( -- ) cr ." THREE" ; : test4 ( -- ) cr ." FOUR" ; 40 0 240 230 MENU MainMenu Font16x12x2 MENUFONT CAPTION" MPE PowerView" Font16x16x2 FONT 40 36 160 32 BUTTON" Button 1" RUNS test1 40 76 160 32 BUTTON" Button 2" RUNS test2 40 116 160 32 BUTTON" Button 3" RUNS test3 40 156 160 32 BUTTON" Button 4" RUNS test4 0 196 240 32 CTEXT" Try me!" Font16x16x2 FONT END-MENU 0 0 320 240 MENU JustMenu CAPTION" MPE Embedded GUI" Font16x12x2 FONT 0 16 80 32 LTEXT" TLHC" RUNS test1 240 16 80 32 RTEXT" TRHC" RUNS test2 0 208 80 32 LTEXT" BLHC" RUNS test3 240 208 80 32 RTEXT" BRHC" RUNS test4 create mpe 88 24 160 80 GRAPHIC %GuiDir%\Pics\mpe.bin 48 128 224 80 JTEXTBOX" This box is filled and justified with several lines of text" END-MENU
: tt \ --
Draw the menu MainMenu
.
: uu \ --
Draw the menu JustMenu
.
The next example is of a slide presentation run as a separate task.
: Image: \ -- ; -- addr
INTERPRETER: Create a dictionary entry and load a graphics
file to the current section, e.g.
Image: demo1 %GuiDir%\Pics\demo1.bin
: demo \ -- ; graphics demo
The action of the demonstration task.
task DemoTask \ -- addr
Task that runs the demonstration.
: StartDemo \ --
Start the demonstration task.
: StopDemo \ --
Stop the demonstration task.
The file LcdQvgaMono5.fth is a driver for a 320*240*2 bits monochrome QVGA panel for the Sharp LH77790B CPU with an on-chip LCD controller.
variable Fcolor \ -- addr
Holds the colour used for display - the foreground colour.
variable Bcolor \ -- addr
Holds the colour used for the background.
variable TColor \ -- addr
Holds the colour used for text. For displays that have more
than one pixel per byte, TColor
holds a cell-width
colour mask.
: setFColor \ colour --
Set the foreground colour.
: SetBColor \ colour --
Set the background colour.
: setTColor \ colour --
Set the text drawing colour.
: clear-lcd \ --
Clear the LCD screen.
: init-lcd \ --
Initialise the LCD hardware. Performed at power-up.
: PutPixel \ x y --
Set the pixel to the current drawing (line) colour.
: PutByte \ x y --
Set a byte (4 pixels) to the current drawing (line) colour.
: PutCell \ x y --
Set a cell (16 pixels) to the current drawing (line) colour.
: h-line \ x y len --
Draw a horizontal line of length len pixels starting
at x,y.
: v-line \ x y len --
Draw a vertical line of length len pixels starting
at x,y.
: absRect \ x y w h --
Draw a rectangle at x,y with width and height w,h.
: absFilledRect \ x y w h --
Draw a filled rectangle at x,y with width and height
w,h.
: DrawChar \ char vbuff bytes/row --
Draw the character at the given video buffer address or offset.
The number of bytes or pixels per video row is also given. Note
that DrawChar
just calls the routine given in the
current font table.
: .fchar \ px py char --
Write a character at the given pixel address, which is
stepped to the nearest byte boundary.
: sout \ px py caddr len --
Write a string at the given pixel address, which is
stepped to the nearest byte boundary.
Before use, images created on a PC must be converted to the format required by the particular LCD panel. There are tools to do this in the Tools\BMPcnv folder.
: load-image \ x y imageaddr --
Display a graphics image in memory at imageaddr at pixel
position x,y. If part of the image is off the screen, the
displayed image is clipped to the screen size.
Each font requires a word that draws a character from the font.
[defined] Font12x8x2 [if]
Words for a 12x8 font.
: v@ \ addr -- 24bit
COMPILER: Unaligned 16 bit fetch.
: v! \ 24bit addr --
COMPILER: Unaligned 16 bit store.
: !fontrow \ 32b vaddr --
Write one row/line of the font map into video memory
: Draw12x8x2 \ char vbuff bytes/row --
Write a character at the given video address, given the
number of bytes per video row.
[defined] Font16x12x2 [if]
Words for a 16x12 font.
: v@ \ addr -- 24bit
COMPILER: Unaligned 24 bit fetch.
: v! \ 24bit addr --
COMPILER: Unaligned 24 bit store.
: !fontrow \ 32b vaddr --
Write one row/line of the font map into video memory
: Draw16x12x2 \ char vbuff bytes/row --
Write a character at the given video address, given the
number of bytes per video row.
[defined] Font16x16x2 [if]
Words for a 16x16 font.
: v@ \ addr -- 32bit
COMPILER: Unaligned 32 bit fetch.
: v! \ 32bit addr --
COMPILER: Unaligned 32 bit store.
: !fontrow \ 32b vaddr --
Write one row/line of the font map into video memory
: Draw16x16x2 \ char vbuff bytes/row --
Write a character at the given video address, given the
number of bytes per video row.
The file %GuiDir%\FontDefs.fth contains the structure definition for font tables. It must be compiled before any font tables are compiled. Six example font table files are provided:
Font12x8x1.fth |
12x8 font, 1 bit per pixel |
Font16x12x1.fth |
16x12 font, 1 bit per pixel |
Font16x16x1.fth |
16x16 font, 1 bit per pixel |
Font12x8x2.fth |
12x8 font, 2 bit gray scale |
Font16x12x2.fth |
16x12 font, 2 bit gray scale |
Font16x16x2.fth |
16x16 font, 2 bit gray scale |
Each font table structure includes the xt of the word that draws a character into video RAM. In the example fonts, this word is in the font file after the table. The word must have the stack effect:
char vbuff bytes/row --
where char is the ASCII code of the character to be displayed, vbuff is the address of the first location in the video buffer and bytes/row is the number of bytes in each row of pixels in the video buffer. It is assumed that the rows are contiguous in video memory, that video RAM is byte addressable and that video rows are displayed horizontally. Characters are always set on byte boundaries. This means that for displays with more than one pixel per byte, character placement will be restricted in the X (horizontal) axis.
struct /Font \ -- len
The font table data structure
int f.link \ link to previous font int f.height \ height of character in pixels int f.width \ width of character in pixels int f.mwidth \ width of character in bytes/row int f.first \ ASCII code of first character int f.end \ ASCII code of last+1 character int f.charsize \ size of character in bytes int f.xtDrawChar \ xt of character drawing routine \ char vbuff bytes/row -- 0 field f.map \ start of character table end-struct
variable CurrFont \ -- addr
Holds the current font.
variable FontLink \ -- addr
Anchor for list of fonts.
: char>map \ char font -- map
Convert a character number into the address of the bitmap in
the current font table.
: drawChar \ char sys --
Draw the character at the given video buffer address or offset.
The sys parameter(s) are implementation dependent. Note
that DrawChar
just calls the routine given in the
current font table. See the hardware driver for the parameter
details.
: /fwidth \ -- pw
Return the current character width in pixels.
: /fheight \ -- ph
Return the current character height in pixels.
The file Fonts/Font16x12x2 contains a simple 16x12 font for
use with 2 bit grayscale panels. It supports the standard
ASCII characters with codes from 32 to 126. Each font
requires a drawing word as defined by the /Font
structure
in FontDefs.fth.
struct /Font \ -- len
The font table data structure from FontDefs.fth
int f.link \ link to previous font int f.height \ height of character in pixels int f.width \ width of character in pixels int f.mwidth \ width of character in bytes/row int f.first \ ASCII code of first character int f.end \ ASCII code of last+1 character int f.charsize \ size of character in bytes int f.xtDrawChar \ xt of character drawing routine \ char vbuff bytes/row -- 0 field f.map \ start of character table end-struct
create Font16x12x2 \ -- addr
Font table starting at char 32. Each character is defined as
16 24-bit items, each defining 12 bits as 2 bits per pixel
for a 16x12 character.