Pascal on the Raspberry Pi first created
01/07/16 - last modified
24/07/16 Page Author: Ty Harness
Using Free Pascal on the Raspberry Pi(running Raspbian) I've created a fractal voyager program. The program is written in plain old Pascal and an X11 window to visualise the fractals.
sudo apt-get update
sudo apt-get upgrade
sudo apt-get install fpc
sudo apt-get install lazarus
Although you can use a text editor to write your source and use fpc to compile and link the program it's far easier to install the Lazarus-ide.
Here's some general notes:
missing link
./x11_demo_fp_raspberry_pi_ver_11
C = 0.3+ 0i elephant valley
./x11_demo_fp_raspberry_pi_ver_11 0.3 0.0 0.05 512
C = -0.75+0.1i sea horse valley
./x11_demo_fp_raspberry_pi_ver_11 -0.75 0.1 0.01 512
To grab images I've used the xwd (X window dump) command. To use the feature you'll need to install the
X11 utilites:
sudo apt-get install x11-utils
To view the images you can use the xwud command or The Gimp now opens xwd files.
If you then want to make an animated gif with all the saved frames them imagemagick convert application. http://www.imagemagick.org/
Press s to grab screen shots using x11 utils and use imagemagik to convert to an animated gif.
Download the source code tarball below and extract the 4 pas files. You need all 4 files in the same directory.
tar zxvf fractal_voyage-11.tar.gz
fractal_voyage-11.tar.gz
Start the lazarus-ide and open x11_demo_fp_raspberry_pi_ver_11.pas (make a simple program if asked.) Either run in the program in the ide or press Build. Once built you can execute from the command line:
./x11_demo_fp_raspberry_pi_ver_11
program x11_demo_fp_raspberry_pi_ver_11;
{$mode objfpc}{$H+}
(*
Version 1.1
This is a example to help pascal programmers on the raspberry pi get started with Xlib
Please improve this example as you see fit - Ty Harness.
The easiest way to compile the code is to install fpc and lazarus-ide on the Raspberry pi
and use the Lazarus-ide to compile,link and build the program. You know all the units for xlib
are installed correctly. You'll be pleasently surprised how quick it is. The source will compile
for other X11 linux distros, but wont cross compile for the windows gdi.
Source files needed to compile:
x11_demo_fp_raspberry_pi_ver_1.pas
unitmandelbrot.pas
unitnewton.pas
commonDataTypes.pas
to compile via the command line:
fpc x11_demo_fp_raspberry_pi_ver_1.pas
and execute with
./x11_demo_fp_raspberry_pi_ver_1 <parameters>
<parameters can be left blank or use specify a complex number and region of interest
Re img Re+/-ROI Max. Iterations e.g.>
C = -0.75+0.1i sea horse valley
./x11_demo_fp_raspberry_pi_ver_11 -0.75 0.1 0.01 512
C = 0.3+0i elephant valley
./x11_demo_fp_raspberry_pi_ver_11 0.3 0.0 0.05 512
if you want to use xwd on the raspberry pi you'll need the x11-utils
sudo apt-get install x11-utils
xwd -out frame0000.xwd
xwud -in frame0000.xwd
Using imagemagik to make an animated gif out of the frames saved.
convert -delay 100 frame*xwd fractalvoyage.gif
uses
xlib, x, ctypes, unitmandelbrot, unitnewton, commonDataTypes,unix,sysutils;
const
Height = 480;
Width = 600;
procedure zoomer(factor:double);
var
d : double;
begin
d := (URZ.Re - LLZ.Re)*factor*0.01;
LLZ.Re := LLZ.Re - d;
LLZ.i := LLZ.i - d*aspect;
URZ.Re := URZ.Re + d;
URZ.i := URZ.i + d*aspect;
end;
procedure pan(panRe,pani:double);
var
x,y : double;
begin
x := (URZ.Re - LLZ.Re)*panRe*0.01;
y := (URZ.i - LLZ.i)*pani*0.01;
LLZ.Re := LLZ.Re + x;
URZ.Re := URZ.Re + x;
LLZ.i := LLZ.i + y;
URZ.i := URZ.i + y;
end;
procedure InitGCarray(d: PDisplay; w: TWindow;s: cint);
begin
//set up a colour pallette for Xwindow -gotter be a better way than this
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:00/00/00', @color, @dummy);
xgv10.foreground := color.pixel;
xgc10[0] := XCreateGC(d,w,GCForeground, @xgv10);
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:ff/00/00', @color, @dummy); xgv10.foreground := color.pixel;
xgc10[1] := XCreateGC(d,w,GCForeground, @xgv10);
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:ff/80/00', @color, @dummy); xgv10.foreground := color.pixel;
xgc10[2] := XCreateGC(d,w,GCForeground, @xgv10);
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:ff/ff/00', @color, @dummy); xgv10.foreground := color.pixel;
xgc10[3] := XCreateGC(d,w,GCForeground, @xgv10);
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:80/ff/00', @color, @dummy); xgv10.foreground := color.pixel;
xgc10[4] := XCreateGC(d,w,GCForeground, @xgv10);
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:00/ff/80', @color, @dummy); xgv10.foreground := color.pixel;
xgc10[5] := XCreateGC(d,w,GCForeground, @xgv10);
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:00/ff/ff', @color, @dummy); xgv10.foreground := color.pixel;
xgc10[6] := XCreateGC(d,w,GCForeground, @xgv10);
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:00/80/ff', @color, @dummy); xgv10.foreground := color.pixel;
xgc10[7] := XCreateGC(d,w,GCForeground, @xgv10);
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:00/00/ff', @color, @dummy); xgv10.foreground := color.pixel;
xgc10[8] := XCreateGC(d,w,GCForeground, @xgv10);
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:80/00/ff', @color, @dummy); xgv10.foreground := color.pixel;
xgc10[9] := XCreateGC(d,w,GCForeground, @xgv10);
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:ff/00/ff', @color, @dummy); xgv10.foreground := color.pixel;
xgc10[10] := XCreateGC(d,w,GCForeground, @xgv10);
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:ff/00/80', @color, @dummy); xgv10.foreground := color.pixel;
xgc10[11] := XCreateGC(d,w,GCForeground, @xgv10);
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:ff/00/80', @color, @dummy); xgv10.foreground := color.pixel;
xgc10[12] := XCreateGC(d,w,GCForeground, @xgv10);
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:ff/ff/ff', @color, @dummy); xgv10.foreground := color.pixel;
xgc10[13] := XCreateGC(d,w,GCForeground, @xgv10); //white
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:10/10/10', @color, @dummy); xgv10.foreground := color.pixel;
xgc10[14] := XCreateGC(d,w,GCForeground, @xgv10);
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:40/40/40', @color, @dummy); xgv10.foreground := color.pixel;
xgc10[15] := XCreateGC(d,w,GCForeground, @xgv10);
XAllocNamedColor(d, DefaultColormap(d, s),'rgb:90/90/90', @color, @dummy); xgv10.foreground := color.pixel;
xgc10[16] := XCreateGC(d,w,GCForeground, @xgv10);
end;
procedure OpenX11Window(Amsg: string;choice: integer);
var
d: PDisplay;
w: TWindow;
e: TXEvent;
msg: PChar;
s: cint;
Xattributes : TXSetWindowAttributes;
skeysym : TKeysym ; skeycode : TkeyCode;
mkeysym : TKeysym ; mkeycode : TkeyCode;
nkeysym : TKeysym ; nkeycode : TkeyCode;
Upkeysym : TKeysym ; upkeycode : TkeyCode;
Downkeysym : TKeysym ; downkeycode : TkeyCode;
Leftkeysym : TKeysym ; leftkeycode : TkeyCode;
Rightkeysym : TKeysym ; rightkeycode : TkeyCode;
pluskeysym : TKeysym ; pluskeycode : TkeyCode;
minuskeysym : TKeysym ; minuskeycode : TkeyCode;
ikeysym : TKeysym ; ikeycode : TkeyCode;
keycode : TKeyCode;
draw_once : boolean;
frame : integer;
begin
msg := PChar(Amsg);
draw_once := true;
frame := 0;
//xserver connection
d := XOpenDisplay(nil);
if (d = nil) then
begin
WriteLn('Cannot open display');
exit;
end;
s := DefaultScreen(d);
Xattributes.background_pixel := WhitePixel(d, s);
w := XCreateWindow(d, RootWindow(d, s), 0, 0, Width, Height, 0, DefaultDepth(d,s),
InputOutput, DefaultVisual(d,s), CWBackPixel, @Xattributes);
InitGCarray(d,w,s);
Xstorename(d,w,msg); //caption
// Xstorename(d,w,Displaystring(d)); //caption
{ select kind of events we are interested in }
XSelectInput(d, w, ExposureMask or KeyPressMask or KeyReleaseMask);
{ map (show) the window }
XMapWindow(d, w);
Xflush(d);
{set up keys}
sKeySym := XStringToKeysym ('s');
sKeycode := XKeysymToKeycode (d, sKeySym);
mKeySym := XStringToKeysym ('m');
mKeycode := XKeysymToKeycode (d, mKeySym);
nKeySym := XStringToKeysym ('n');
nKeycode := XKeysymToKeycode (d, nKeySym);
iKeySym := XStringToKeysym ('i');
iKeycode := XKeysymToKeycode (d, iKeySym);
upKeySym := XStringToKeysym ('Up');
upKeycode := XKeysymToKeycode (d, upKeySym);
rightKeySym := XStringToKeysym ('Right');
rightKeycode := XKeysymToKeycode (d, rightKeySym);
leftKeySym := XStringToKeysym ('Left');
leftKeycode := XKeysymToKeycode (d, leftKeySym);
downKeySym := XStringToKeysym ('Down');
downKeycode := XKeysymToKeycode (d, downKeySym);
plusKeySym := XStringToKeysym ('KP_Add');
plusKeycode := XKeysymToKeycode (d, plusKeySym);
minusKeySym := XStringToKeysym ('KP_Subtract');
minusKeycode := XKeysymToKeycode (d, minusKeySym);
{ event loop }
while (True) do
begin
XNextEvent(d, @e);
if draw_once = true then
begin
if choice = 1 then DrawMandelbrotSet(d,w,s,Width,Height); //Plot the Mandelbrot set.
if choice = 2 then DrawNewtonSet(d,w,s,Width,Height);
draw_once := false;
end;
//keep checking the events for a key press
if (e._type = KeyPress) then
begin
// xmodmap -pk to display keycodes and keysym
if e.xkey.keycode = 9 then break; //break on escape keycode
Keycode := XKeysymToKeycode (d, XStringToKeysym ('1'));
if e.xkey.keycode = Keycode then
begin
Maxiter := 48;
choice := 1;
end;
Keycode := XKeysymToKeycode (d, XStringToKeysym ('2'));
if e.xkey.keycode = Keycode then
begin
Maxiter := 15;
choice := 2;
end;
if e.xkey.keycode = sKeycode then
begin
//fpSystem('xwd -out tydump.xwd -name "' + Displaystring(d) + '"' );
fpSystem('xwd -out frame' + Format('%.4d',[frame]) + '.xwd -name "X11 Example"' );
frame := frame + 1;
end;
if e.xkey.keycode = mkeycode then
begin
maxiter := maxiter + 12;
end;
if e.xkey.keycode = nKeycode then
begin
maxiter := maxiter - 12;
if maxiter < 2 then maxiter := 2;
end;
;
if e.xkey.keycode = plusKeycode then
begin
zoomer(-20);
end;
if e.xkey.keycode = minusKeycode then
begin
zoomer(20);
end;
if e.xkey.keycode = UpKeycode then
begin
Pan(0,15);
end;
if e.xkey.keycode = downKeycode then
begin
Pan(0,-15);
end;
if e.xkey.keycode = rightKeycode then
begin
Pan(15,0);
end;
if e.xkey.keycode = leftKeycode then
begin
Pan(-15,0);
end;
if e.xkey.keycode = iKeycode then
begin
writeinformation;
end;
XclearWindow(d,w); //you may prefer to paint on a blank canvas
draw_once := true;
Xflush(d);
end;
end;
{ close connection to server }
XCloseDisplay(d);
end;
var
c : integer;
begin {Main}
writedestructions; //general instructions on program use
c := 1; //kick off with the Mandelbrot Plot
if c = 1 then Init_MandelBrot_variables(Width,Height,ParamCount,Paramstr(1),Paramstr(2),Paramstr(3),Paramstr(4));
if c = 2 then Newton_Init_globals(Width,Height);
OpenX11Window('X11 Example',c);
end.