LCD Text and Graphics demo forARM's mbed application board
Posted: Thu Apr 18, 2013 1:29 pm
These files are the complete source code for an application which shows:
v4.4.2 or later of Astrobe for Cortex-M3 is required to successfully compile and run the example.
DisplayDemo is the main program. Delays are used as the update of the display is so fast that you would not have time to see what is going on.
Display.mod is used to write consecutive lines of text as on a terminal. The display is refreshed after the last character of a row, or a line feed character is written. If the last line is at the bottom of the display, the next line written causes the existing lines to scroll up.
LCDST756R.mod is the display driver. Two bitmap array variables are used. bitMap0 represents the pixels that can currently be seen on the screen. When characters, lines or pixels are drawn, they just update the second array, bitMap, in memory. When the Refresh function is called corresponding 8-bit columns of pixels in each bitmap array are compared. The data is only sent to the screen whenever the two do not match. Characters are drawn using 6x8 pixel font data stored in the resource file, accessed using the Astrobe library module ResData.
- the set of characters contained in the 6x8 font
- high speed scrolling text
- random display of pixels
- random display of filled squares
- a filled square in motion
v4.4.2 or later of Astrobe for Cortex-M3 is required to successfully compile and run the example.
DisplayDemo is the main program. Delays are used as the update of the display is so fast that you would not have time to see what is going on.
Code: Select all
MODULE DisplayDemo;
(* =========================================================================
Example Cortex-M3 Oberon Program
Description:
Demonstrate text and graphics capabilities of an LCD display.
Target:
Dependent on the imported modules: Display -> LCDST756R
Tested on:
ARM mbed Application Board with a Newhaven C12832A1Z 128 x 32 LCD display
(c) 2013 CFB Software
http://www.astrobe.com
========================================================================= *)
IMPORT Display, LCD := LCDST756R, Main, Out, Random, Timer;
PROCEDURE DisplayChars;
(* Display all the printable characters in the character set
implemented in the font used *)
VAR
i: INTEGER;
BEGIN
FOR i := ORD(" ") TO ORD("~") DO
Out.Char(CHR(i));
(* Pause for a second at the start of a
new line to allow time to read it
before the screen scrolls *)
IF Display.colNo = 0 THEN
Timer.MSecDelay(1000)
END;
END;
Out.Ln();
Timer.MSecDelay(1000)
END DisplayChars;
PROCEDURE DisplayText;
(* Display 500 scrolling lines of text *)
VAR
count: INTEGER;
BEGIN
FOR count := 1 TO 500 DO
Out.String("Line ");
Out.Int(count, 0);
Out.Ln()
END
END DisplayText;
PROCEDURE DisplayDots;
(* Randomly display / clear pixels *)
VAR
i, x, y: INTEGER;
black: BOOLEAN;
BEGIN
LCD.ClearScreen(LCD.White);
black := TRUE;
FOR i := 0 TO 100000 DO
x := Random.Next(LCD.MaxX);
y := Random.Next(LCD.MaxY);
IF black THEN
LCD.DrawDot(LCD.Black, x, y)
ELSE
LCD.DrawDot(LCD.White, x, y)
END;
black := ~black;
IF i MOD 32 = 0 THEN
LCD.Refresh()
END
END
END DisplayDots;
PROCEDURE MoveBox(x, y, delay: INTEGER);
(* Display a black square for 1/10th second
and then erase it *)
BEGIN
LCD.FillRectangle(LCD.Black, x, y, x + 7, y + 7);
LCD.Refresh();
Timer.MSecDelay(delay);
LCD.FillRectangle(LCD.White, x, y, x + 7, y + 7)
END MoveBox;
PROCEDURE DisplayBoxes;
(* Display a black square at random positions *)
VAR
i, x, y: INTEGER;
BEGIN
LCD.ClearScreen(LCD.White);
FOR i := 0 TO 50 DO
x := Random.Next(LCD.MaxX - 7);
y := Random.Next(LCD.MaxY - 7);
MoveBox(x, y, 100)
END
END DisplayBoxes;
PROCEDURE DisplayMovingBox;
(* Move a box from left to right along a row and
then return in the opposite direction on the
next row, continuing until all rows
is reached *)
CONST
delay = 40;
VAR
pageNo, xLimit, yLimit, pageLimit, x, y: INTEGER;
BEGIN
pageLimit := LCD.Pages - 1;
xLimit := LCD.MaxX - 7;
FOR pageNo := 0 TO pageLimit DO
y := pageNo * 8;
yLimit := y + 7;
IF ODD(pageNo) THEN
FOR x := xLimit TO 0 BY - 1 DO MoveBox(x, y, delay) END;
IF pageNo < pageLimit THEN
FOR y := y TO yLimit DO MoveBox(0, y, delay) END
END
ELSE
FOR x := 0 TO xLimit DO MoveBox(x, y, delay) END;
FOR y := y TO yLimit DO MoveBox(xLimit, y, delay) END
END
END
END DisplayMovingBox;
PROCEDURE Run;
CONST
Delay = 4000; (* 4 secs *)
BEGIN
(* Redirect all output to the display *)
Out.Init(Display.Char);
Display.Init();
DisplayChars();
Timer.MSecDelay(Delay);
DisplayText();
Timer.MSecDelay(Delay);
DisplayDots();
Timer.MSecDelay(Delay);
DisplayBoxes();
Timer.MSecDelay(Delay);
DisplayMovingBox();
END Run;
BEGIN
Run
END DisplayDemo.
Code: Select all
MODULE Display;
(* =========================================================================
Example Cortex-M3 Oberon Module
Description:
Write line-oriented output to an LCD display
Target:
Dependent on the imported module: LCD
Tested on:
ARM mbed Application Board with a Newhaven C12832A1Z 128 x 32 LCD display
(c) 2011-2013 CFB Software
http://www.astrobe.com
========================================================================= *)
IMPORT LCD := LCDST756R, Fonts := Fonts6x8;
CONST
LF = 0AX;
Cols* = LCD.Cols;
Rows* = LCD.Rows;
TYPE
Row = ARRAY Cols OF CHAR;
Screen = ARRAY Rows + 1 OF Row;
VAR
rowNo*, colNo*: INTEGER;
screen: Screen;
blankRow: Row;
Refresh*: PROCEDURE;
PROCEDURE WriteChar(ch: CHAR; r, c: INTEGER);
BEGIN
LCD.DrawChar(LCD.Black, ch, c, r)
END WriteChar;
PROCEDURE WriteRow(row: Row);
VAR
c: INTEGER;
BEGIN
FOR c := 0 TO Cols - 1 DO
WriteChar(row[c], rowNo, c)
END;
Refresh()
END WriteRow;
PROCEDURE* NewRow();
BEGIN
INC(rowNo);
colNo := 0;
screen[rowNo] := blankRow
END NewRow;
PROCEDURE ScrollUp;
VAR
r: INTEGER;
BEGIN
(* Move rows up *)
FOR r := 1 TO Rows DO
rowNo := r - 1;
screen[rowNo] := screen[r];
WriteRow(screen[rowNo])
END;
NewRow()
END ScrollUp;
PROCEDURE Ln*();
BEGIN
IF rowNo < Rows THEN
WriteRow(screen[rowNo]);
NewRow()
ELSE
ScrollUp
END
END Ln;
PROCEDURE Char*(ch: CHAR);
BEGIN
IF ch = LF THEN
Ln
ELSIF ch >= " " THEN
screen[rowNo, colNo] := ch;
INC(colNo);
IF colNo = Cols THEN Ln END
END
END Char;
PROCEDURE String*(s: ARRAY OF CHAR);
VAR
i: INTEGER;
BEGIN
i := 0;
WHILE (i < LEN(s)) & (s[i] # 0X) DO Char(s[i]); INC(i) END
END String;
PROCEDURE Init*();
BEGIN
LCD.Init();
ASSERT(LCD.LoadFont("Fonts6x8"), 100);
END Init;
BEGIN
(* Initialise the memory representation of the screen *)
FOR colNo := 0 TO Cols - 1 DO blankRow[colNo] := " " END;
FOR rowNo := 0 TO Rows - 1 DO screen[rowNo] := blankRow END;
rowNo := 0;
colNo := 0;
Refresh := LCD.Refresh;
END Display.
Code: Select all
MODULE LCDST756R;
(* =========================================================================
Example Cortex-M3 Oberon Module
Description:
Sitronix ST756R LCD Controller Driver
Target:
mbed systems
Tested on:
ARM mbed Application Board with a Newhaven C12832A1Z 128 x 32 LCD display
Reference:
Sitronix ST756R DataSheet Ver 1.5 (10 Mar 2006).
(c) 2013 CFB Software
http://www.astrobe.com
========================================================================= *)
IMPORT Timer, MCU, ResData, SPI, SYSTEM;
CONST
Black* = 0;
White* = 1;
MaxX* = 127;
MaxY* = 31;
FontWidth = 6;
FontHeight = 8;
Cols* = (MaxX + 1) DIV FontWidth;
Rows* = (MaxY + 1) DIV FontHeight;
Pages* = (MaxY + 1) DIV 8;
A0 = {6}; (* P0.6 = mbed P8 *)
CS = {18}; (* P0.18 = mbed P11 *)
Reset = {8}; (* P0.8 = mbed P6 *)
TYPE
(* Each bit represents a pixel on the screen *)
(* Each page can be refreshed invidually *)
BitMap = ARRAY MaxX + 1 OF SET;
(* 6 x 8 pixels *)
FontPattern = ARRAY FontWidth OF BYTE;
DoubleWord = ARRAY 2 OF INTEGER;
VAR
font: ResData.Resource;
fontPattern: FontPattern;
(* In-memory representation of the screen *)
bitMap0, bitMap: BitMap;
PROCEDURE LoadFont*(name: ARRAY OF CHAR): BOOLEAN;
BEGIN
ResData.Open(font, name);
RETURN ResData.Size(font) > 0
END LoadFont;
PROCEDURE* DoubleWordToFontPattern(data: ARRAY OF BYTE; VAR fontPattern: FontPattern);
VAR
i: INTEGER;
BEGIN
FOR i := 0 TO FontWidth - 1 DO
fontPattern[i] := data[i]
END
END DoubleWordToFontPattern;
PROCEDURE CharToFontPattern(ch: CHAR; VAR fontPattern: FontPattern);
(* Store the font data for a character in a 2-D 6 x 8 pixel array *)
VAR
i, index: INTEGER;
data: DoubleWord;
BEGIN
IF (ORD(ch) < ORD(" ")) OR (ORD(ch) > ORD("~")) THEN ch := "." END;
index := (ORD(ch) - ORD(" ")) * 2;
ResData.GetInt(font, index, data[0]);
ResData.GetInt(font, index + 1, data[1]);
DoubleWordToFontPattern(data, fontPattern)
END CharToFontPattern;
PROCEDURE SendData(data: INTEGER);
BEGIN
SYSTEM.PUT(MCU.FIO0SET, A0);
SYSTEM.PUT(MCU.FIO0CLR, CS);
SPI.SendData(data);
SYSTEM.PUT(MCU.FIO0SET, CS);
END SendData;
PROCEDURE SendCommand(data: INTEGER);
BEGIN
SYSTEM.PUT(MCU.FIO0CLR, A0);
SYSTEM.PUT(MCU.FIO0CLR, CS);
SPI.SendData(data);
SYSTEM.PUT(MCU.FIO0SET, CS)
END SendCommand;
PROCEDURE SetColumnAddr(x: INTEGER);
CONST
ColumnAddrLo = 000H;
ColumnAddrHi = 010H;
BEGIN
SendCommand(ColumnAddrLo + x MOD 16);
SendCommand(ColumnAddrHi + x DIV 16)
END SetColumnAddr;
PROCEDURE SetPageAddr(n: INTEGER);
CONST
PageAddrSet = 0B0H;
BEGIN
SendCommand(PageAddrSet + n)
END SetPageAddr;
PROCEDURE* DrawDot*(colour, x, y: INTEGER);
BEGIN
ASSERT((x <= MaxX) & (y <= MaxY) & (x >= 0) & (y >= 0), 100);
IF colour = Black THEN
bitMap[x] := bitMap[x] + {y}
ELSE
bitMap[x] := bitMap[x] - {y}
END
END DrawDot;
PROCEDURE* DrawVerticalLine*(colour: INTEGER; x, y1, y2: INTEGER);
VAR
yBits: SET;
BEGIN
ASSERT((x >= 0) & (y1 >= 0) & (y2 >= y1) & (y2 <= MaxY), 100);
yBits := {y1..y2};
IF colour = Black THEN
bitMap[x] := bitMap[x] + yBits
ELSE
bitMap[x] := bitMap[x] - yBits
END
END DrawVerticalLine;
PROCEDURE* FillRectangle*(colour, x1, y1, x2, y2: INTEGER);
VAR
x: INTEGER;
yBits: SET;
BEGIN
ASSERT((x >= 0) & (x2 > x1) & (x2 <= MaxX) & (y1 >= 0) & (y2 >= y1) & (y2 <= MaxY), 100);
yBits := {y1..y2};
IF colour = Black THEN
FOR x := x1 TO x2 DO bitMap[x] := bitMap[x] + yBits END
ELSE
FOR x := x1 TO x2 DO bitMap[x] := bitMap[x] - yBits END
END
END FillRectangle;
PROCEDURE* UpdateSegment(VAR segment: ARRAY OF BYTE; pageNo: INTEGER; fontPattern: BYTE);
BEGIN
segment[pageNo] := fontPattern
END UpdateSegment;
PROCEDURE DrawChar*(colour: INTEGER; ch: CHAR; col, row: INTEGER);
VAR
i, x: INTEGER;
fontPattern: FontPattern;
BEGIN
CharToFontPattern(ch, fontPattern);
ASSERT((col >= 0) & (col < Cols) & (row >= 0) & (row < Rows), 100);
x := (col * FontWidth);
FOR i := 0 TO FontWidth - 1 DO
UpdateSegment(bitMap[x + i], row, fontPattern[i]);
END
END DrawChar;
PROCEDURE* PixelColumn(columns: ARRAY OF BYTE; pageNo: INTEGER): BYTE;
(* Returns a column of eight pixels in a page. A 6x8 character consists
of six of these columns. Each SendCommand sends a single column
to the display *)
BEGIN
RETURN columns[pageNo]
END PixelColumn;
PROCEDURE Refresh*();
(* Only write the pixel columns that have changed since the last refresh *)
VAR
pageNo, x: INTEGER;
data0, data: BYTE;
col: INTEGER;
BEGIN
FOR pageNo := 0 TO Pages - 1 DO
SetPageAddr(pageNo);
col := -1;
FOR x := 0 TO MaxX DO
data0 := PixelColumn(bitMap0[x], pageNo);
data := PixelColumn(bitMap[x], pageNo);
IF data # data0 THEN
IF col # x THEN
SetColumnAddr(x);
col := x
END;
SendData(data);
INC(col)
END
END
END;
bitMap0 := bitMap
END Refresh;
PROCEDURE* ClearScreen*(colour: INTEGER);
VAR
x: INTEGER;
BEGIN
IF colour = White THEN
FOR x := 0 TO MaxX DO
bitMap[x] := {}
END
ELSE
FOR x := 0 TO MaxX DO
bitMap[x] := {0..31}
END
END
END ClearScreen;
PROCEDURE* ConfigurePins;
VAR
s: SET;
BEGIN
(* P0.6, P0.8 are GPIO ports *)
SYSTEM.GET(MCU.PINSEL0, s);
s := s - {12, 13, 16, 17};
SYSTEM.PUT(MCU.PINSEL0, s);
(* P0.18 is GPIO port *)
SYSTEM.GET(MCU.PINSEL1, s);
s := s - {4, 5};
SYSTEM.PUT(MCU.PINSEL1, s);
(* P0.6, 0.8 and 0.18 are outputs *)
SYSTEM.GET(MCU.FIO0DIR, s);
SYSTEM.PUT(MCU.FIO0DIR, s + A0 + CS + Reset)
END ConfigurePins;
PROCEDURE Init*;
CONST
SPIBus = 1;
nBits = 8;
useSSEL = FALSE;
VAR
i: INTEGER;
BEGIN
SPI.Init(SPIBus, nBits, useSSEL);
ConfigurePins();
SYSTEM.PUT(MCU.FIO0CLR, A0);
SYSTEM.PUT(MCU.FIO0SET, CS);
SYSTEM.PUT(MCU.FIO0CLR, Reset);
Timer.uSecDelay(100);
SYSTEM.PUT(MCU.FIO0SET, Reset);
Timer.uSecDelay(100);
SendCommand(0AEH); (* Display off *)
SendCommand(0A2H); (* Bias voltage *)
SendCommand(0A0H); (* ADC Normal *)
SendCommand(0C8H); (* COM Scan normal *)
SendCommand(022H); (* Resistor ratio *)
SendCommand(02FH); (* Power on *)
SendCommand(040H); (* Display start line 0 *)
SendCommand(081H); (* Set contrast *)
SendCommand(017H);
SendCommand(0A6H); (* Display normal *)
ClearScreen(Black);
bitMap0 := bitMap;
ClearScreen(White);
Refresh();
SendCommand(0AFH); (* DisplayOn *);
END Init;
END LCDST756R.