forked from Chadderz121/bakingpi-www
-
Notifications
You must be signed in to change notification settings - Fork 0
/
screen02.html
607 lines (607 loc) · 28.9 KB
/
screen02.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="https://www.w3.org/1999/xhtml">
<head>
<title>Lesson 7 Screen02</title>
<link href="stylesheet.css" rel="Stylesheet" type="text/css" />
<script language="javascript" type="text/javascript" src="script.js"></script>
</head>
<body>
<div id="contentAll">
<div id="courseHead">
<h1>
Lesson 7 Screen02</h1>
</div>
<div id="pageAll">
<div id="pageBody">
<p>
The Screen02 lesson builds on Screen01, by teaching how to draw lines and also
a small feature on generating pseudo random numbers. It is assumed you have the
code for the <a href="screen01.html">Lesson 6: Screen01</a> operating system as a
basis.</p>
<div class="ucampas-toc">
</div>
<h2 id="dots">
1 Dots</h2>
<p>
Now that we've got the screen working, it is only natural to start waiting to create
sensible images. It would be very nice indeed if we were able to actually draw something.
One of the most basic components in all drawings is a line. If we were able to draw
a line between any two points on the screen, we could start creating more complicated
drawings just using combinations of these lines.
</p>
<div class="informationBox"><p>To allow complex drawing, some systems use a colouring
function rather than just one colour to draw things. Each pixel calls the colouring function
to determine what colour to draw there.</p></div>
<p>
We will attempt to implement this in assembly code, but first we could really use
some other functions to help. We need a function I will call SetPixel that changes
the colour of a particular pixel, supplied as inputs in r0 and r1. It will be helpful
for future if we write code that could draw to any memory, not just the screen,
so first of all, we need some system to control where we are actually going to draw
to. I think that the best way to do this would be to have a piece of memory which
stores where we are going to draw to. What we should end up with is a stored
address which normally points to the frame buffer structure from last time. We will
use this at all times in our drawing method. That way, if we want to draw to a different
image in another part of our operating system, we could make this value the address
of a different structure, and use the exact same code. For simplicity we will use
another piece of data to control the colour of our drawings.</p>
<p>
Copy the following code to a new file called 'drawing.s'.</p>
<div class="armCodeBlock"><p>
.section .data<br />
.align 1<br />
foreColour:<br />
.hword 0xFFFF<br />
<br />
.align 2<br />
graphicsAddress:<br />
.int 0<br />
<br />
.section .text<br />
.globl SetForeColour<br />
SetForeColour:<br />
cmp r0,#0x10000<br />
movhs pc,lr<br />
ldr r1,=foreColour<br />
strh r0,[r1]<br />
mov pc,lr<br />
<br />
.globl SetGraphicsAddress<br />
SetGraphicsAddress:<br />
ldr r1,=graphicsAddress<br />
str r0,[r1]<br />
mov pc,lr<br />
</div>
<p>
This is just the pair of functions that I described above, along with their data.
We will use them in 'main.s' before drawing anything to control where and what we
are drawing.
</p>
<div class="informationBox">
<p>Building generic methods like SetPixel which we can build other methods on top of is
a useful idea. We have to make sure the method is fast though, since we will use it a lot.</p></div>
<p>
Our next task is to implement a SetPixel method. This needs to take two parameters,
the x and y co-ordinate of a pixel, and it should use the graphicsAddress and foreColour
we have just defined to control exactly what and where it is drawing. If you think
you can implement this immediately, do, if not I shall outline the steps to be taken,
and then give an example implementation.</p>
<ol>
<li>Load in the graphicsAddress.</li>
<li>Check that the x and y co-ordinates of the pixel are less than the width and height.</li>
<li>Compute the address of the pixel to write. (hint: frameBufferAddress + (x + y * width)
* pixel size)</li>
<li>Load in the foreColour.</li>
<li>Store it at the address.</li>
</ol>
<p>
An implementation of the above follows.</p>
<ol>
<li>
<div class="armCodeBlock"><p>
.globl DrawPixel<br />
DrawPixel:<br />
px .req r0<br />
py .req r1<br />
addr .req r2<br />
ldr addr,=graphicsAddress<br />
ldr addr,[addr]<br />
</div>
</li>
<li>
<div class="armCodeBlock"><p>
height .req r3<br />
ldr height,[addr,#4]<br />
sub height,#1<br />
cmp py,height<br />
movhi pc,lr<br />
.unreq height<br />
<br />
width .req r3<br />
ldr width,[addr,#0]<br />
sub width,#1<br />
cmp px,width<br />
movhi pc,lr<br />
</div>
<p>
Remember that the width and height are stored at offsets of 0 and 4 into the frame
buffer description respectively. You can refer back to 'frameBuffer.s' if necessary.</p>
</li>
<li>
<div class="armCodeBlock"><p>
ldr addr,[addr,#32]<br />
add width,#1<br />
mla px,py,width,px<br />
.unreq width<br />
.unreq py<br />
add addr, px,lsl #1<br />
.unreq px<br />
</div>
<div class="commandBox"><p>
<span class="armCodeInline">mla dst,reg1,reg2,reg3</span> multiplies the values
from <span class="armCodeInline">reg1</span> and <span class="armCodeInline">reg2</span>,
adds the value from <span class="armCodeInline">reg3</span> and places
the least significant 32 bits of the result in
<span class="armCodeInline">dst</span>.</p></div>
<p>
Admittedly, this code is specific to high colour frame buffers, as I use a bit shift
directly to compute this address. You may wish to code a version of this function
without the specific requirement to use high colour frame buffers, remembering to
update the SetForeColour code. It may be significantly more complicated to implement.</p>
</li>
<li>
<div class="armCodeBlock"><p>
fore .req r3<br />
ldr fore,=foreColour<br />
ldrh fore,[fore]<br />
</div>
<p>
As above, this is high colour specific.</p>
</li>
<li>
<div class="armCodeBlock"><p>
strh fore,[addr]<br />
.unreq fore<br />
.unreq addr<br />
mov pc,lr<br />
</div>
<p>
As above, this is high colour specific.</p>
</li>
</ol>
<h2 id="lines">
2 Lines</h2>
<p>
The trouble is, line drawing isn't quite as simple as you may expect. By now you
must realise that when making operating system, we have to do almost everything
ourselves, and line drawing is no exception. I suggest for a few minutes you have
a think about how you would draw a line between any two points.</p>
<div class="informationBox">
<p>
When programming normally, we tend to be lazy with things like division. Operating
Systems must be incredibly efficient, and so we must focus on doing things as best
as possible.</p>
</div>
<p>
I expect the central idea of most strategies will involve computing the gradient
of the line, and stepping along it. This sounds perfectly reasonable, but is actually
a terrible idea. The problem with it is it involves division, which is something
that we know can't easily be done in assembly, and also keeping track of decimal
numbers, which is again difficult. There is, in fact, an algorithm called Bresenham's
Algorithm, which is perfect for assembly code because it only involves addition,
subtraction and bit shifts.
</p>
<div class="expandableHeader" onclick="return ExpandToggle('derivation')">
<p>
<a class="icon-more">Algorithm derivation</a></p>
</div>
<div id="derivation" class="expandable">
<p>
Let's start off by defining a reasonably straightforward line drawing algorithm
as follows:
</p>
<div class="pseudoCodeBlock"><p>
<span class="comment">/* We wish to draw a line from (x0,y0) to (x1,y1), using only
a function setPixel(x,y) which draws a dot in the pixel given by (x,y). */</span><br />
<span class="keyword">if </span>x1 > x0 <span class="keyword">then</span>
<div class="indent"><p>
<span class="keyword">set </span>deltax <span class="keyword">to </span>x1 - x0<br />
<span class="keyword">set </span>stepx <span class="keyword">to </span>+1<br />
</div><p>
<span class="keyword">otherwise</span><br />
<div class="indent"><p>
<span class="keyword">set </span>deltax <span class="keyword">to </span>x0 - x1<br />
<span class="keyword">set </span>stepx <span class="keyword">to </span>-1<br />
</div><p>
<span class="keyword">end if</span><br />
<br />
<span class="keyword">if </span>y1 > y0 <span class="keyword">then</span>
<div class="indent"><p>
<span class="keyword">set </span>deltay <span class="keyword">to </span>y1 - y0<br />
<span class="keyword">set </span>stepy <span class="keyword">to </span>+1<br />
</div><p>
<span class="keyword">otherwise</span><br />
<div class="indent"><p>
<span class="keyword">set </span>deltay <span class="keyword">to </span>y0 - y1<br />
<span class="keyword">set </span>stepy <span class="keyword">to </span>-1<br />
</div><p>
<span class="keyword">end if</span><br />
<br />
<span class="keyword">if</span> deltax > deltay <span class="keyword">then </span>
<div class="indent"><p>
<span class="keyword">set </span>error <span class="keyword">to </span>0<br />
<span class="keyword">until </span>x0 = x1 + stepx<br />
<div class="indent"><p>
<span class="keyword">setPixel</span>(x0, y0)<br />
<span class="keyword">set </span>error <span class="keyword">to </span>error + deltax
÷ deltay<br />
<span class="keyword">if </span>error ≥ 0.5 <span class="keyword">then </span>
<br />
<div class="indent"><p>
<span class="keyword">set </span>y0 <span class="keyword">to </span>y0 + stepy<br />
<span class="keyword">set </span>error <span class="keyword">to </span>error - 1<br />
</div><p>
<span class="keyword">end if</span><br />
<span class="keyword">set </span>x0 <span class="keyword">to </span>x0 + stepx<br />
</div><p>
<span class="keyword">repeat</span><br />
</div><p>
<span class="keyword">otherwise</span>
<div class="indent"><p>
<span class="comment">/* As above but swap x and y */</span></div><p>
<span class="keyword">end if</span><br />
</div>
<p>
This algorithm is a representation of the sort of thing you may have imagined. The
variable error keeps track of how far away from the actual line we are. Every step
we take along the x axis increases this error, and every time we move down the y
axis, the error decreases by 1 unit again. The error is measured as a distance along
the y axis.
</p>
<p>
While this algorithm works, it suffers a major problem in that we clearly have to
use decimal numbers to store error, and also we have to do a division. An immediate
optimisation would therefore be to change the units of error. There is no need to
store it in any particular units, as long as we scale every use of it by the same
amount. Therefore, we could rewrite the algorithm simply by multiplying all equations
involving error by deltay, and simplifying the result. Just showing the main loop:</p>
<div class="pseudoCodeBlock"><p>
<span class="keyword">set </span>error <span class="keyword">to </span>0 ×
deltay<br />
<span class="keyword">until </span>x0 = x1 + stepx<br />
<div class="indent"><p>
<span class="keyword">setPixel</span>(x0, y0)<br />
<span class="keyword">set </span>error <span class="keyword">to </span>error + deltax
÷ deltay × deltay<br />
<span class="keyword">if </span>error ≥ 0.5 × deltay <span class="keyword">
then </span>
<br />
<div class="indent"><p>
<span class="keyword">set </span>y0 <span class="keyword">to </span>y0 + stepy<br />
<span class="keyword">set </span>error <span class="keyword">to </span>error - 1
× deltay<br />
</div><p>
<span class="keyword">end if</span><br />
<span class="keyword">set </span>x0 <span class="keyword">to </span>x0 + stepx<br />
</div><p>
<span class="keyword">repeat</span><br />
</div>
<p>
Which simplifies to:</p>
<div class="pseudoCodeBlock"><p>
<span class="keyword">set </span>error <span class="keyword">to </span>0<br />
<span class="keyword">until </span>x0 = x1 + stepx<br />
<div class="indent"><p>
<span class="keyword">setPixel</span>(x0, y0)<br />
<span class="keyword">set </span>error <span class="keyword">to </span>error + deltax<br />
<span class="keyword">if </span>error × 2 ≥ deltay <span class="keyword">then
</span>
<br />
<div class="indent"><p>
<span class="keyword">set </span>y0 <span class="keyword">to </span>y0 + stepy<br />
<span class="keyword">set </span>error <span class="keyword">to </span>error - deltay<br />
</div><p>
<span class="keyword">end if</span><br />
<span class="keyword">set </span>x0 <span class="keyword">to </span>x0 + stepx<br />
</div><p>
<span class="keyword">repeat</span><br />
</div>
<p>
Suddenly we have a much better algorithm. We see now that we've eliminated the need
for division altogether. Better still, the only multiplication is by 2, which we
know is just a bit shift left by 1! This is now very close to Bresenham's Algorithm,
but one further optimisation can be made. At the moment, we have an if statement
which leads to two very similar blocks of code, one for lines with larger x differences,
and one for lines with larger y differences. It is worth checking if the code could
be converted to a single statement for both types of line.</p>
<p>
The difficulty arises somewhat in that in the first case, error is to do with y,
and in the second case error is to do with x. The solution is to track the error
in both variables simultaneously, using negative error to represent an error in
x, and positive error in y.
</p>
<div class="pseudoCodeBlock"><p>
<span class="keyword">set </span>error <span class="keyword">to </span>deltax -
deltay<br />
<span class="keyword">until </span>x0 = x1 + stepx <span class="keyword">or </span>
y0 = y1 + stepy<br />
<div class="indent"><p>
<span class="keyword">setPixel</span>(x0, y0)<br />
<span class="keyword">if </span>error × 2 > -deltay <span class="keyword">then
</span>
<br />
<div class="indent"><p>
<span class="keyword">set </span>x0 <span class="keyword">to </span>x0 + stepx<br />
<span class="keyword">set </span>error <span class="keyword">to </span>error - deltay<br />
</div><p>
<span class="keyword">end if</span><br />
<span class="keyword">if </span>error × 2 < deltax <span class="keyword">then
</span>
<br />
<div class="indent"><p>
<span class="keyword">set </span>y0 <span class="keyword">to </span>y0 + stepy<br />
<span class="keyword">set </span>error <span class="keyword">to </span>error + deltax<br />
</div><p>
<span class="keyword">end if</span><br />
</div><p>
<span class="keyword">repeat</span><br />
</div>
<p>
It may take some time to convince yourself that this actually works. At each step,
we consider if it would be correct to move in x or y. We do this by checking if
the magnitude of the error would be lower if we moved in the x or y co-ordinates,
and then moving if so.</p>
</div>
<div class="informationBox">
<p>
Bresenham's Line Algorithm was developed in 1962 by Jack Elton Bresenham, 24 at
the time, whilst studying for a PhD.</p>
</div>
<p>
Bresenham's Algorithm for drawing a line can be described by the following pseudo
code. Pseudo code is just text which looks like computer instructions, but is actually
intended for programmers to understand algorithms, rather than being machine readable.</p>
<div class="pseudoCodeBlock"><p>
<span class="comment">/* We wish to draw a line from (x0,y0) to (x1,y1), using only
a function setPixel(x,y) which draws a dot in the pixel given by (x,y). */</span><br />
<span class="keyword">if </span>x1 > x0 <span class="keyword">then</span>
<div class="indent"><p>
<span class="keyword">set </span>deltax <span class="keyword">to </span>x1 - x0<br />
<span class="keyword">set </span>stepx <span class="keyword">to </span>+1<br />
</div><p>
<span class="keyword">otherwise</span><br />
<div class="indent"><p>
<span class="keyword">set </span>deltax <span class="keyword">to </span>x0 - x1<br />
<span class="keyword">set </span>stepx <span class="keyword">to </span>-1<br />
</div><p>
<span class="keyword">end if</span><br />
<br />
<span class="keyword">set </span>error <span class="keyword">to </span>deltax -
deltay<br />
<span class="keyword">until </span>x0 = x1 + stepx <span class="keyword">or </span>
y0 = y1 + stepy<br />
<div class="indent"><p>
<span class="keyword">setPixel</span>(x0, y0)<br />
<span class="keyword">if </span>error × 2 ≥ -deltay <span class="keyword">then
</span>
<br />
<div class="indent"><p>
<span class="keyword">set </span>x0 <span class="keyword">to </span>x0 + stepx<br />
<span class="keyword">set </span>error <span class="keyword">to </span>error - deltay<br />
</div><p>
<span class="keyword">end if</span><br />
<span class="keyword">if </span>error × 2 ≤ deltax <span class="keyword">then
</span>
<br />
<div class="indent"><p>
<span class="keyword">set </span>y0 <span class="keyword">to </span>y0 + stepy<br />
<span class="keyword">set </span>error <span class="keyword">to </span>error + deltax<br />
</div><p>
<span class="keyword">end if</span><br />
</div><p>
<span class="keyword">repeat</span><br />
</div>
<p>
Rather than numbered lists as I have used so far, this representation of an algorithm
is far more common. See if you can implement this yourself. For reference, I have
provided my implementation below.</p>
<div class="armCodeBlock"><p>
.globl DrawLine<br />
DrawLine:<br />
push {r4,r5,r6,r7,r8,r9,r10,r11,r12,lr}<br />
x0 .req r9<br />
x1 .req r10<br />
y0 .req r11<br />
y1 .req r12<br />
<br />
mov x0,r0<br />
mov x1,r2<br />
mov y0,r1<br />
mov y1,r3<br />
<br />
dx .req r4<br />
dyn .req r5 <span class="comment">/* Note that we only ever use -deltay, so I store
its negative for speed. (hence dy<strong>n</strong>) */</span><br />
sx .req r6<br />
sy .req r7<br />
err .req r8<br />
<br />
cmp x0,x1<br />
subgt dx,x0,x1<br />
movgt sx,#-1<br />
suble dx,x1,x0<br />
movle sx,#1<br />
<br />
cmp y0,y1<br />
subgt dyn,y1,y0<br />
movgt sy,#-1<br />
suble dyn,y0,y1<br />
movle sy,#1<br />
<br />
add err,dx,dyn<br />
add x1,sx<br />
add y1,sy<br />
<br />
pixelLoop$:<br />
<div class="indent"><p>
teq x0,x1<br />
teqne y0,y1<br />
popeq {r4,r5,r6,r7,r8,r9,r10,r11,r12,pc}<br />
<br />
mov r0,x0<br />
mov r1,y0<br />
bl DrawPixel<br />
<br />
cmp dyn, err,lsl #1<br />
addle err,dyn<br />
addle x0,sx<br />
<br />
cmp dx, err,lsl #1<br />
addge err,dx<br />
addge y0,sy<br />
<br />
b pixelLoop$<br />
</div><p>
<br />
.unreq x0<br />
.unreq x1<br />
.unreq y0<br />
.unreq y1<br />
.unreq dx<br />
.unreq dyn<br />
.unreq sx<br />
.unreq sy<br />
.unreq err<br />
</div>
<h2 id="randomness">
3 Randomness</h2>
<p>
So, now we can draw lines. Although we could use this to draw pictures and whatnot
(feel free to do so!), I thought I would take the opportunity to introduce the idea
of computer randomness. What we will do is select a pair of random co-ordinates,
and then draw a line from the last pair to that point in steadily incrementing colours.
I do this purely because it looks quite pretty.</p>
<div class="informationBox">
<p>
Hardware random number generators are occasionally used in security, where the predictability
sequence of random numbers may affect the security of some encryption.</p>
</div>
<p>
So, now it comes down to it, how do we be random? Unfortunately for us there isn't
some device which generates random numbers (such devices are very rare). So somehow
using only the operations we've learned so far we need to invent 'random numbers'.
It shouldn't take you long to realise this is impossible. The operations always
have well defined results, executing the same sequence of instructions with the
same registers yields the same answer. What we instead do is deduce a sequence that
is pseudo random. This means numbers that, to the outside observer, look random,
but in fact were completely determined. So, we need a formula to generate random
numbers. One might be tempted to just spam mathematical operators out for example:
4x<sup>2</sup>! / 64, but in actuality this generally produces low quality random
numbers. In this case for example, if x were 0, the answer would be 0. Stupid though
it sounds, we need a very careful choice of equation to produce high quality random
numbers.
</p>
<div class="informationBox"><p>This sort of discussion often begs the question what do we
mean by a random number? We generally mean statistical randomness: A sequence of numbers
that has no obvious patterns or properties that could be used to generalise it.</p></div>
<p>
The method I'm going to teach you is called the quadratic congruence generator.
This is a good choice because it can be implemented in 5 instructions, and yet generates
a seemingly random order of the numbers from 0 to 2<sup>32</sup>-1.
</p>
<p>
The reason why the generator can create such long sequence with so few instructions
is unfortunately a little beyond the scope of this course, but I encourage the interested
to research it. It all centralises on the following quadratic formula, where <span
class="equationInline">x<sub>n</sub></span> is the nth random number generated.</p>
<div class="equation"><p>
x<sub>n+1</sub> = ax<sub>n</sub><sup>2</sup> + bx<sub>n</sub> + c mod 2<sup>32</sup></div>
<p>
Subject to the following constraints:</p>
<ol>
<li><span class="equationInline">a</span> is even</li>
<li><span class="equationInline">b = a + 1 mod 4</span></li>
<li><span class="equationInline">c</span> is odd</li></ol>
<p>
If you've not seen mod before, it means the remainder of a division by the number
after it. For example <span class="equationInline">b = a + 1 mod 4</span> means
that b is the remainder of dividing <span class="equationInline">a + 1</span> by
4, so if <span class="equationInline">a</span> were 12 say, <span class="equationInline">
b</span> would be 1 as <span class="equationInline">a + 1</span> is 13, and
13 divided by 4 is 3 remainder 1.</p>
<p>
Copy the following code into a file called 'random.s'.</p>
<div class="armCodeBlock"><p>
.globl Random<br />
Random:<br />
xnm .req r0<br />
a .req r1<br />
<br />
mov a,#0xef00<br />
mul a,xnm<br />
mul a,xnm<br />
add a,xnm<br />
.unreq xnm<br />
add r0,a,#73<br />
<br />
.unreq a<br />
mov pc,lr<br />
</div>
<p>
This is an implementation of the random function, with an input of the last value
generated in <span class="armCodeInline">r0</span>, and an output of the next number.
In my case, I've used a = EF00<sub>16</sub>, b = 1, c = 73. This choice was arbitrary
but meets the requirements above. Feel free to use any numbers you wish instead,
as long as they obey the rules.</p>
<h2 id="picasso">
4 Pi-casso</h2>
<p>
OK, now we have all the functions we're going to need, let's try it out. Alter main
to do the following, after getting the frame buffer info address:</p>
<ol>
<li>Call SetGraphicsAddress with r0 containing the frame buffer info address.</li>
<li>Set four registers to 0. One will be the last random number, one will be the colour,
one will be the last x co-ordinate and one will be the last y co-ordinate.</li>
<li>Call random to generate the next x-coordinate, using the last random number as the
input.</li>
<li>Call random again to generate the next y-coordinate, using the x-coordinate you
generated as an input.</li>
<li>Update the last random number to contain the y-coordinate.</li>
<li>Call SetForeColour with the colour, then increment the colour. If it goes above
FFFF<sub>16</sub>, make sure it goes back to 0.</li>
<li>The x and y coordinates we have generated are between 0 and FFFFFFFF<sub>16</sub>.
Convert them to a number between 0 and 1023<sub>10</sub> by using a logical shift
right of 22.</li>
<li>Check the y coordinate is on the screen. Valid y coordinates are between 0 and 767<sub>10</sub>.
If not, go back to 3.</li>
<li>Draw a line from the last x and y coordinates to the current x and y coordinates.</li>
<li>Update the last x and y coordinates to contain the current ones.</li>
<li>Go back to 3.</li>
</ol>
<p>
As always, a solution for this can be found on the downloads page.</p>
<p>
Once you've finished, test it on the Raspberry Pi. You should see a very fast sequence
of random lines being drawn on the screen, in steadily incrementing colours. This
should never stop. If it doesn't work, please see our troubleshooting page.
</p>
<p>
When you have it working, congratulations! We've now learned about meaningful graphics,
and also about random numbers. I encourage you to play with line drawing, as it
can be used to render almost anything you want. You may also want to explore more
complicated shapes. Most can be made out of lines, but is this necessarily the best
strategy? If you like the line program, try experimenting with the SetPixel function.
What happens if instead of just setting the value of the pixel, you increase it
by a small amount? What other patterns can you make? In the next lesson, <a href="screen03.html">
Lesson 8: Screen 03</a>, we will look at the invaluable skill of drawing text.</p>
</div>
<div id="pageFooter">
<hr />
<p>Spot a mistake? You can help improve this tutorial on <a href="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/chadderz121/bakingpi-www">GitHub</a>.</p>
<p><a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/deed.en_GB"><img alt="Creative Commons Licence" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/3.0/88x31.png" /></a><br /><span xmlns:dct="https://purl.org/dc/terms/" property="dct:title">Baking Pi: Operating Systems Development</span> by <span xmlns:cc="https://creativecommons.org/ns#" property="cc:attributionName">Alex Chadwick</span> is licensed under a <a rel="license" href="https://creativecommons.org/licenses/by-sa/3.0/deed.en_GB">Creative Commons Attribution-ShareAlike 3.0 Unported License</a>.</p>
<p>Based on contributions at <a href="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/chadderz121/bakingpi-www">https://github.com/chadderz121/bakingpi-www</a>.</p>
</div>
</div>
</div>
</body>
</html>