-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
10 changed files
with
571 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
# SCREEN03 - How to draw text to the screen | ||
|
||
The SCREEN03 lesson builds on top of SCREEN02 teaching how to draw text. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
@; | ||
@; Counter functions to be used by this exercise | ||
@; | ||
|
||
.section .text | ||
.global delay | ||
delay: | ||
ldr r1, =0x3F000000 @; pi peripheral address | ||
orr r1, r1, #0x3000 @; r1 = r1 | 0x3000 = 0x3F003000 timer base address | ||
ldr r2, [r1, #0x4] @; time in microseconds given by the timer | ||
delay1$: | ||
ldr r3, [r1, #0x4] @; get timer in microseconds in each iteration | ||
sub r3, r3, r2 @; current timer - initial timer | ||
cmp r3, r0 @; compare time elapsed with desired timer | ||
blt delay1$ @; if elapsed time < desired time repeat the loop | ||
mov pc, lr @; return |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,251 @@ | ||
@; | ||
@; Functions to draw on the screen | ||
@; | ||
|
||
.section .text | ||
.global DrawPixel | ||
DrawPixel: | ||
px .req r0 | ||
py .req r1 | ||
addr .req r2 | ||
|
||
ldr addr, =graphicsAddress @; load address into r2 | ||
ldr addr, [addr] @; load the value into r2 | ||
|
||
height .req r3 | ||
ldr height, [addr, #4] @; load the height into r3 | ||
sub height, #1 @; subtract 1 from height | ||
cmp py, height @; cmp py with the actual height | ||
movhi pc, lr @; return if higher | ||
.unreq height | ||
|
||
width .req r3 | ||
ldr width, [addr, #0] @; load the width into r3 | ||
sub width, #1 @; subtract 1 from width | ||
cmp px, width @; cmp py with the actual width | ||
movhi pc, lr @; return if higher | ||
|
||
ldr addr, [addr, #32] @; get the gpu pointer for the framebuffer response | ||
and addr, #0x3FFFFFFF @; convert bus address to physical address used by the ARM CPU | ||
|
||
add width, #1 @; add 1 to r3 | ||
mla px, py, width, px @; multiply px with width, adds px and store the least significant 32 bits into px | ||
.unreq width | ||
.unreq py | ||
add addr, px, lsl #1 @; adds px and addr and left shift by 1 | ||
.unreq px | ||
fore .req r3 | ||
ldr fore, =foreColor @; load forecolor address into r3 | ||
ldrh fore, [fore] @; load half word from fore into r3 | ||
|
||
strh fore, [addr] @; store half word from fore into gpu framebuffer pointer | ||
.unreq fore | ||
.unreq addr | ||
mov pc, lr @; return | ||
|
||
.global DrawLine | ||
DrawLine: | ||
push {r4,r5,r6,r7,r8,r9,r10,r11,r12,lr} @; push caller-saved registers and lr | ||
x0 .req r9 | ||
x1 .req r10 | ||
y0 .req r11 | ||
y1 .req r12 | ||
|
||
mov x0, r0 @; move function args into registers | ||
mov x1, r2 | ||
mov y0, r1 | ||
mov y1, r3 | ||
|
||
dx .req r4 | ||
dyn .req r5 @; delta y negative stored for speed | ||
sx .req r6 | ||
sy .req r7 | ||
err .req r8 | ||
|
||
cmp x0, x1 @; compare x0 and x1 | ||
subgt dx, x0, x1 @; if x0 greater than x1 subtract and store into dx | ||
movgt sx, #-1 @; if x0 greater than x1 move -1 to step x | ||
suble dx, x1, x0 @; if x0 less than or equal x1 subtract and store into dx | ||
movle sx, #1 @; if x0 less than or equal x1 move 1 into step x | ||
|
||
cmp y0, y1 | ||
subgt dyn, y1, y0 | ||
movgt sy, #-1 | ||
suble dyn, y0, y1 | ||
movle sy, #1 | ||
|
||
add err, dx, dyn | ||
add x1, sx | ||
add y1, sy | ||
|
||
pixelLoop$: | ||
teq x0, x1 | ||
teqne y0, y1 | ||
popeq {r4,r5,r6,r7,r8,r9,r10,r11,r12,pc} | ||
|
||
mov r0, x0 | ||
mov r1, y0 | ||
bl DrawPixel | ||
|
||
cmp dyn, err, lsl #1 | ||
addle err, dyn | ||
addle x0, sx | ||
|
||
cmp dx, err, lsl #1 | ||
addge err, dx | ||
addge y0, sy | ||
|
||
b pixelLoop$ | ||
|
||
.unreq x0 | ||
.unreq x1 | ||
.unreq y0 | ||
.unreq y1 | ||
.unreq dx | ||
.unreq dyn | ||
.unreq sx | ||
.unreq sy | ||
.unreq err | ||
|
||
.global DrawCharacter | ||
DrawCharacter: | ||
cmp r0, #127 @; check if is a valid ascII code | ||
movhi r0, #0 | ||
movhi pc, lr | ||
|
||
push {r4, r5, r6, r7, r8, lr} | ||
x .req r4 | ||
y .req r5 | ||
addr .req r6 | ||
mov x, r1 | ||
mov y, r2 | ||
ldr addr, =font | ||
add addr, r0, lsl #4 | ||
|
||
lineLoop$: | ||
bits .req r7 | ||
bit .req r8 | ||
ldrb bits, [addr] | ||
mov bit, #8 | ||
|
||
charPixelLoop$: | ||
subs bit, #1 | ||
blt charPixelLoopEnd$ | ||
lsl bits, #1 | ||
tst bits, #0x100 | ||
beq charPixelLoop$ | ||
|
||
add r0, x, bit | ||
mov r1, y | ||
bl DrawPixel | ||
|
||
teq bit, #0 | ||
bne charPixelLoop$ | ||
charPixelLoopEnd$: | ||
.unreq bit | ||
.unreq bits | ||
add y, #1 | ||
add addr, #1 | ||
tst addr, #0b1111 | ||
bne lineLoop$ | ||
|
||
.unreq x | ||
.unreq y | ||
.unreq addr | ||
|
||
width .req r0 | ||
height .req r1 | ||
mov width, #8 | ||
mov height, #16 | ||
|
||
pop {r4,r5,r6,r7,r8,pc} | ||
.unreq width | ||
.unreq height | ||
|
||
.global DrawString | ||
DrawString: | ||
x .req r4 | ||
y .req r5 | ||
x0 .req r6 | ||
string .req r7 | ||
length .req r8 | ||
char .req r9 | ||
push {r4, r5, r6, r7, r8, r9, lr} | ||
|
||
mov string, r0 | ||
mov x, r2 | ||
mov x0, x | ||
mov y, r3 | ||
mov length, r1 | ||
|
||
stringLoop$: | ||
subs length, #1 | ||
blt stringLoopEnd$ | ||
|
||
ldrb char, [string] | ||
add string, #1 | ||
|
||
mov r0, char | ||
mov r1, x | ||
mov r2, y | ||
bl DrawCharacter | ||
cwidth .req r0 | ||
cheight .req r1 | ||
|
||
teq char, #'\n' | ||
moveq x, x0 | ||
addeq y, cheight | ||
beq stringLoop$ | ||
|
||
teq char, #'\t' | ||
addne x, cwidth | ||
bne stringLoop$ | ||
|
||
add cwidth, cwidth, lsl #2 | ||
x1 .req r1 | ||
mov x1, x0 | ||
|
||
stringLoopTab$: | ||
add x1, cwidth | ||
cmp x, x1 | ||
bge stringLoopTab$ | ||
mov x, x1 | ||
.unreq x1 | ||
b stringLoop$ | ||
stringLoopEnd$: | ||
.unreq cwidth | ||
.unreq cheight | ||
|
||
pop {r4, r5, r6, r7, r8, r9, pc} | ||
.unreq x | ||
.unreq y | ||
.unreq x0 | ||
.unreq string | ||
.unreq length | ||
|
||
.global SetForeColor | ||
SetForeColor: | ||
cmp r0, #0x10000 @; compare color to max integer | ||
movhs pc, lr @; return according to cmp flags (higher or same) | ||
ldr r1, =foreColor @; load forecolor into register r1 | ||
strh r0, [r1] @; store half word from r0 into r1 | ||
mov pc, lr @; return | ||
|
||
.global SetGraphicsAddress | ||
SetGraphicsAddress: | ||
ldr r1, =graphicsAddress @; load graphics address into r1 | ||
str r0, [r1] @; store r0 into r1 | ||
mov pc, lr @; return | ||
|
||
.section .data | ||
.align 1 | ||
foreColor: | ||
.hword 0xFFFF @; half word with the forecolor (white) | ||
|
||
.align 2 | ||
graphicsAddress: | ||
.int 0 @; graphics address (default 0) | ||
|
||
.align 4 | ||
font: | ||
.incbin "font.bin" @; the bitmap font to use |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
@; | ||
@; Functions to define framebuffers to interact with the GPU | ||
@; | ||
|
||
.section .text | ||
.global InitializeFrameBuffer | ||
InitializeFrameBuffer: | ||
width .req r0 @; set up alias | ||
height .req r1 | ||
bitDepth .req r2 | ||
|
||
cmp width, #4096 @; compare width with 4096 | ||
cmpls height, #4096 @; compare height with 4096 if width is less or equal to 4096 | ||
cmpls bitDepth, #32 @; compare bitDepth with 32 if height is less or equal to 4096 | ||
result .req r0 | ||
movhi result, #0 @; mov 0 to result if last cmp C and Z flag are clear (higher) | ||
movhi pc, lr @; return if last cmp C and Z flag are clear (higher) | ||
|
||
push {r4, lr} @; save the address the function should return to | ||
|
||
fbInfoAddr .req r4 | ||
ldr fbInfoAddr, =FrameBufferInfo @; load frame buffer addr into register | ||
str width, [fbInfoAddr] @; store width into fbInfoAddr offset 0 | ||
str height, [fbInfoAddr, #4] @; store height into fbInfoAddr offset 4 | ||
str width, [fbInfoAddr, #8] @; store width into fbInfoAddr offset 8 | ||
str height, [fbInfoAddr, #12] @; store height into fbInfoAddr offset 12 | ||
str bitDepth, [fbInfoAddr, #20] @; store bitDepth into fbInfoAddr offset 20 | ||
.unreq width @; unset alias | ||
.unreq height | ||
.unreq bitDepth | ||
|
||
mov r1, #0 | ||
str r1, [fbInfoAddr, #16] @; reset framebuffer | ||
str r1, [fbInfoAddr, #24] | ||
str r1, [fbInfoAddr, #28] | ||
str r1, [fbInfoAddr, #32] | ||
str r1, [fbInfoAddr, #36] | ||
|
||
mov r0, fbInfoAddr | ||
bl FrameBufferWrite @; write message to mailbox | ||
teq result, #0 @; check if last function succeed | ||
movne result, #0 @; if result not equal to 0, set result to 0 | ||
popne {r4, pc} @; return if result not equal to 0 | ||
|
||
mov result, fbInfoAddr @; mov frame buffer info address to r0 | ||
.unreq result | ||
.unreq fbInfoAddr | ||
pop {r4, pc} @; return | ||
|
||
.global FrameBufferWrite | ||
FrameBufferWrite: | ||
push {lr} | ||
orr r0, #0xC0000000 @; signal the GPU to not flush its cache | ||
mov r1, #1 @; channel for mailbox write | ||
bl MailboxWrite @; write message to mailbox channel 1 | ||
|
||
mov r0, #1 @; channel for mailbox read | ||
bl MailboxRead @; read the response from mailbox channel 1 | ||
pop {pc} | ||
|
||
.section .data | ||
.align 4 | ||
.global FrameBufferInfo | ||
FrameBufferInfo: | ||
.int 1024 @; #0 Physical Width | ||
.int 768 @; #4 Physical Height | ||
.int 1024 @; #8 Virtual Width | ||
.int 768 @; #12 Virtual Height | ||
.int 0 @; #16 GPU - Pitch | ||
.int 16 @; #20 Bit Depth | ||
.int 0 @; #24 X | ||
.int 0 @; #28 Y | ||
.int 0 @; #32 GPU - Pointer | ||
.int 0 @; #36 GPU - Size |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
@; | ||
@; Functions to interact with the leds | ||
@; | ||
|
||
.section .text | ||
.global SetACTLedState | ||
SetACTLedState: | ||
push {lr} @; save address the function should return to | ||
mov r1, r0 @; move the led state to r1 | ||
ldr r0, =message @; load the message into r0 | ||
mov r2, #0 | ||
str r2, [r0, #4] @; reset request code | ||
str r2, [r0, #16] @; reset request/response size | ||
mov r2, #130 | ||
str r2, [r0, #20] @; reset pin number | ||
|
||
str r1, [r0, #24] @; overwrite the led state | ||
|
||
mov r1, #8 @; set mailbox channel | ||
bl MailboxWrite @; write the message | ||
mov r0, #8 @; the channel to read the message from | ||
bl MailboxRead @; read the message to prevent the FIFO queue to get full | ||
pop {pc} @; return | ||
|
||
.section .data | ||
.align 4 @; last 4 bits of the next label set to 0 (16-byte alligned) | ||
message: | ||
.int size @; #0 message header contains the size of the message | ||
.int 0 @; #4 request code 0 | ||
|
||
.int 0x00038041 @; #8 header tag ID | ||
.int 8 @; #12 size of tag data | ||
.int 0 @; #16 request/response size | ||
|
||
.int 130 @; #20 pin number | ||
.int 1 @; #24 pin state | ||
.int 0 @; #28 signal the GPU that the message is over | ||
size: | ||
.int . - message @; size of the message |
Oops, something went wrong.