Das Terminal (PI5)
// // screen.S //
- include "config.h"
- include "base.h"
- include "mailbox.h"
- define maxZeichen 240
- define maxZeilen 108
/* Dimension */
- define FONT_WIDTH 8
- define FONT_HEIGHT 8
- define FONT_MAX 256
.section .text
// bolean Init_Screen (void) // .globl Init_Screen Init_Screen: stp x29, x30, [sp, -16]! mov x29, sp
ldr w0,=BCM_MAILBOX_PROP_OUT //Kanal ldr x1,=pScreen //ScreenStruktur 1: bl BcmMailBox_Write //Rufe die Mailbox auf
ldr x0,=m_nBufferPtr //lade die Speicheradresse ldr w0,[x0] cmp w0,#0 beq 1b
and w0,w0,#0x3FFFFFFF //Passe die Adresse an ldr x1,=graphicsAddress //und sichere sie str w0,[x1]
ldp x29, x30, [sp], 16 ret
// void DrawPixel(u32 x, u32 y) // Zeichne einen Pixel auf den Bildschirm .globl DrawPixel DrawPixel: stp x29, x30, [sp, -16]! stp x10, x11, [sp, -16]! mov x29, sp
//Überprüfe, ob der Pixel in den Screen passt
cmp w0,#SCREEN_X bge 1f cmp w1,#SCREEN_Y bge 1f
//Berechne Position des Pixels: graphicsAddress+(((SCREEN_X*y)+x)*4)
mov w10,SCREEN_X mul w10,w10,w1 add w10,w10,w0 lsl w10,w10,#2 ldr x11,=graphicsAddress ldr w11,[x11] add w10,w10,w11
//Schreibe die Farbe in die Position
ldr x11,=DrawColor ldr w11,[x11] str w11,[x10] 1: ldp x10, x11, [sp], 16 ldp x29, x30, [sp], 16 ret
//u32 GetPixel(u32 x, u32 y) //Abfrage, der Farbe des Pixels im Screen .globl GetPixel GetPixel: stp x29, x30, [sp, -16]! stp x10, x11, [sp, -16]! mov x29, sp
//Überprüfe, ob der Pixel im Screen ist
cmp w0,#SCREEN_X bge 1f cmp w1,#SCREEN_Y bge 1f
//Berechne Position des Pixels: graphicsAddress+(((SCREEN_X*y)+x)*4)
mov w10,SCREEN_X mul w10,w10,w1 add w10,w10,w0 lsl w10,w10,#2 ldr x11,=graphicsAddress ldr w11,[x11] add w10,w10,w11
//Lade die Farbe des Pixels nach w0
ldr w0,[x10] b 2f
1:
//Wenn Position des Pixel nicht im Screen ist, dann NULL zurück
mov w0,#0
2: ldp x10, x11, [sp], 16 ldp x29, x30, [sp], 16 ret
//void SetDrawColor(u8 r, u8 g, u8 b)
//definiert die Zeichenfarbe
.globl SetDrawColor
SetDrawColor:
stp x29, x30, [sp, -16]!
mov x29, sp
//Berechne die Farbe mit: (0xFF << 24) | (r << 16) | (g << 8) | b;
mov w3,#0xFF lsl w3,w3,#24 lsl w0,w0,#16 lsl w1,w1,#8 orr w3,w3,w0 orr w3,w3,w1 orr w3,w3,w2
//Und lege sie in der Variablen "DrawColor" ab
ldr x0,=DrawColor str w3,[x0]
ldp x29, x30, [sp], 16 ret
//void SetFrontColor(u8 r, u8 g, u8 b) //definiere die Vordergrundfarbe, für zum Beispiel des Chars .globl SetFrontColor SetFrontColor: stp x29, x30, [sp, -16]! mov x29, sp
//Berechne die Farbe mit: (0xFF << 24) | (r << 16) | (g << 8) | b;
mov w3,#0xFF lsl w3,w3,#24 lsl w0,w0,#16 lsl w1,w1,#8 orr w3,w3,w0 orr w3,w3,w1 orr w3,w3,w2
//Und lege sie in der Variablen "FrontColor" ab
ldr x0,=FrontColor str w3,[x0]
ldp x29, x30, [sp], 16 ret
//void SetBackColor(u8 r, u8 g, u8 b) //definiere die Hintergrundfarbe, für zum Beispiel des Chars .globl SetBackColor SetBackColor: stp x29, x30, [sp, -16]! mov x29, sp
//Berechne die Farbe mit: (0xFF << 24) | (r << 16) | (g << 8) | b;
mov w3,#0xFF lsl w3,w3,#24 lsl w0,w0,#16 lsl w1,w1,#8 orr w3,w3,w0 orr w3,w3,w1 orr w3,w3,w2
//Und lege sie in der Variablen "BackColor" ab
ldr x0,=BackColor str w3,[x0]
ldp x29, x30, [sp], 16 ret
//void DrawChar(char c, u32 x0, u32 y0) //Zeichnet einen Char an die Position x0, y0 auf den Screen .globl DrawChar DrawChar: stp x29, x30, [sp, -16]! stp x20, x21, [sp, -16]! stp x10, x11, [sp, -16]! stp x12, x13, [sp, -16]! stp x14, x15, [sp, -16]! mov x29, sp
Sichere zunächst die Position
mov w20,w1 // x0 mov w21,w2 // y0
//Berechne den Zeiger auf das richtige Zeichen
ldr x10,=font lsl w0,w0,#3 add x10,x10,x0
//for (w11 = 0; w11 < FONT_HEIGHT; w11++)
mov w11,#0 1: cmp w11,#FONT_HEIGHT bge 2f
//for (w12 = 0; w12 < FONT_WIDTH; w12++)
mov w12,#0 3: cmp w12,#FONT_WIDTH bge 4f
//Überprüfe das Bit nach folgender Formel: //(Zeile >> (7 - BitPos)) & 1;
ldrb w13,[x10,x11] mov w14,#7 sub w14,w14,w12 lsr w13,w13,w14 and w13,w13,#1
//Wenn Ergebniss 0 ist, dann Hintergrund zeichnen
cbz w13,5f
//Ansonsten in der Vordergrundfarbe
ldr x13,=FrontColor ldr w13,[x13] ldr x14,=DrawColor str w13,[x14] b 6f
5: ldr x13,=BackColor ldr w13,[x13] ldr x14,=DrawColor str w13,[x14]
6:
//Zeichne den Pixel an die Position
mov w0,w12 add w0,w0,w20 mov w1,w11 add w1,w1,w21 bl DrawPixel
//end_for w12
add w12,w12,#1 b 3b 4:
//end_for w11
add w11,w11,#1 b 1b 2: ldp x14, x15, [sp], 16 ldp x12, x13, [sp], 16 ldp x10, x11, [sp], 16 ldp x20, x21, [sp], 16 ldp x29, x30, [sp], 16 ret
//********************************************************** // Konsole //**********************************************************
// Dimensionen für die Konsole
- define CHAR_WIDTH 8
- define CHAR_HEIGHT 10
- define NUM_COLS (SCREEN_X / CHAR_WIDTH)
- define NUM_ROWS (SCREEN_Y / CHAR_HEIGHT)
//void ClearScreen() //Löscht den Inhalt des Screens in der Hintergrundfarbe .globl ClearScreen ClearScreen: stp x29, x30, [sp, -16]! stp x10, x11, [sp, -16]! mov x29, sp
//Setze die Zeichenfarbe auf die Hintergrundfarbe ldr x10,=BackColor
ldr w10,[x10] ldr x11,=DrawColor str w10,[x11]
//for (w11 = 0; w11 < SCREEN_Y; w11++)
mov w11,#0 1: cmp w11,#SCREEN_Y bge 2f
//for (w10 = 0; w10 < SCREEN_X; w10++)
mov w10,#0 3: cmp w10,#SCREEN_X bge 4f
//DrawPixel(x, y);
mov w0,w10 mov w1,w11 bl DrawPixel
//end_for w10
add w10,w10,#1 b 3b 4:
//end_for w11
add w11,w11,#1 b 1b 2:
//Setze cursor_x auf 0 mov x10,#0 ldr x11,=cursor_x str w10,[x11] //Setze cursor_y auf 0 ldr x11,=cursor_y str w10,[x11]
ldp x10, x11, [sp], 16 ldp x29, x30, [sp], 16 ret
//void MoveCursor(u32 x, u32 y) //Setze den Cursor auf eine neue Position .globl MoveCursor MoveCursor: stp x29, x30, [sp, -16]! stp x10, x11, [sp, -16]! mov x29, sp
//Setze cursor_x auf x
ldr x10,=cursor_x str w0,[x10]
//Setze cursor_y auf y
ldr x10,=cursor_y str w1,[x10]
ldp x10, x11, [sp], 16 ldp x29, x30, [sp], 16 ret
//void DrawCharAtCursor(char c) //Zeichne den Char an die aktuelle Position in der Konsole //Berücksichtige auch Sonderzeichen .globl DrawCharAtCursor DrawCharAtCursor: stp x29, x30, [sp, -16]! mov x29, sp
//Vergleiche auf Zeilenumbruch
cmp w0,#'\n'
//Wenn nicht, weitere Abfrage
bne 1f
//Setze den cursor_x auf 0
ldr x1,=cursor_x mov w2,#0 str w2,[x1]
//Und den cursor_y um eins höher, für die Zeile
ldr x1,=cursor_y ldr w2,[x1] add w2,w2,#1 str w2,[x1]
b 7f 1:
//Vergleiche auf Carriage Return
cmp w0,#'\r' bne 2f
//Setzt den Cursor an den Anfang der aktuellen Zeile.
ldr x1,=cursor_x mov w2,#0 str w2,[x1]
b 7f 2:
//Vergleiche, ob TAB angezeigt werden soll
cmp w0,#'\t' bne 3f
//Erhöht den cursor_x um 4 //DOTO: Fester Wert in allen Zeilen
ldr x1,=cursor_x ldr w2,[x1] add w2,w2,#4 str w2,[x1]
b 7f 3:
//Vergleich auf Backspace
cmp w0,#'\b' bne 4f
//Bewegt den Cursor um ein Zeichen nach links //nur wenn cursor_x > 0 ist
ldr x1,=cursor_x ldr w2,[x1] cmp w2,#0 ble 8f
// cursor_x -1
sub w2,w2,#1 str w2,[x1] 8: b 7f 4:
//Vergleich auf Form Feed)
cmp w0,#'\f' bne 5f
// Neue Seite
bl ClearScreen
b 7f 5:
//Vergleich auf ESC-Zeichen
cmp w0,#27 bne 6f
// ESC-Zeichen erkannt, muss aber zuvor Abgefangen werden.
b 7f 6:
//Wenn hier angelangt, müsste es sich um ein druckbares Zeichen handeln
// Char in w0
mov w0,w0
// Berechnung der x-Pos (cursor_x * CHAR_WIDTH)
ldr x1,=cursor_x ldr w1,[x1] mov w2,#CHAR_WIDTH mul w1,w1,w2
// Berechnung der y-Pos (cursor_y * CHAR_HEIGHT)
ldr x2,=cursor_y ldr w2,[x2] mov w3,#CHAR_HEIGHT mul w2,w2,w3 bl DrawChar
//Addiere cursor_x um 1
ldr x0,=cursor_x ldr w1,[x0] add w1,w1,#1 str w1,[x0]
// Wenn cursor_x >= NUM_COLS ist
cmp w1,NUM_COLS blt 9f
// dann cursor_x = 0
ldr x0,=cursor_x mov w1,#0 str w1,[x0]
// und neue Zeile (cursor_y + 1)
ldr x0,=cursor_y ldr w1,[x0] add w1,w1,#1 str w1,[x0] 9:
7: //Für alle:
//Wenn cursor_y >= max Anzahl Zeilen
ldr x0,=cursor_y ldr w1,[x0] cmp w1,NUM_ROWS blt 10f
//Dann Scrolle den Bildscirm
bl ScrollScreen
//Setze die Cursorposition auf Vorletzte Zeile (cursor_y = NUM_ROWS - 1)
mov w0,NUM_ROWS sub w0,w0,#1 ldr x1,=cursor_y str w0,[x1] 10: ldp x29, x30, [sp], 16 ret
// void ProcessEscSequence(const char* seq) // Bearbeite ESC-Funktionen .globl ProcessEscSequence ProcessEscSequence: stp x29, x30, [sp, -16]! mov x29, sp
// Beispiel: "\033[1m" -> Setzt die Vordergrundfarbe auf Rot
//DOTO: https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797 //Color Name Foreground Color Code Background Color Code //Black 30 40 //Red 31 41 //Green 32 42 //Yellow 33 43 //Blue 34 44 //Magenta 35 45 //Cyan 36 46 //White 37 47 //Default 39 49 //Reset 0 0 // //# Set style to bold, red foreground. //\033[1;31mHello //# Set style to dimmed white foreground with red background. //\033[2;37;41mWorld
// Unterstützung nur für Farben: ESC[xm -> x = Farbe
// Nur wenn seq[0] = '[' und seq[2] = 'm' entspricht
ldrb w1,[x0] cmp w1,'[' bne 1f ldrb w1,[x0,2] cmp w1,'m' bne 1f
//Werte seq[1] aus:
ldrb w1,[x0,1]
// Wenn 0
cmp w1,'0' bne 2f
//dann FrontColor = Schwarz
mov w0,#0 mov w1,#0 mov w2,#0 bl SetFrontColor b 1f 2:
// Wenn 1
cmp w1,'1' bne 3f
//dann FrontColor = Rot
mov w0,#0xFF mov w1,#0 mov w2,#0 bl SetFrontColor b 1f 3:
// Wenn 2
cmp w1,'2' bne 4f
//dann FrontColor = Grün
mov w0,#0 mov w1,#0xFF mov w2,#0 bl SetFrontColor b 1f 4:
// Wenn 3
cmp w1,'3' bne 5f
//dann FrontColor = Gelb
mov w0,#0xFF mov w1,#0xFF mov w2,#0 bl SetFrontColor b 1f 5:
// Wenn 4
cmp w1,'4' bne 6f
//dann FrontColor = Blau
mov w0,#0 mov w1,#0 mov w2,#0xFF bl SetFrontColor b 1f 6:
// Wenn 5
cmp w1,'5' bne 7f
//dann FrontColor = Magenta
mov w0,#0xFF mov w1,#0 mov w2,#0xFF bl SetFrontColor b 1f 7:
// Wenn 6
cmp w1,'6' bne 8f
//dann FrontColor = Cyan
mov w0,#0 mov w1,#0xFF mov w2,#0xFF bl SetFrontColor b 1f 8:
// Wenn 7
cmp w1,'7' bne 1f
//dann FrontColor = Weiß
mov w0,#0xFF mov w1,#0xFF mov w2,#0xFF bl SetFrontColor // b 1f
1: ldp x29, x30, [sp], 16 ret
//void ScrollScreen() // Schiebe den Inhalt des Screens um eine Zeichenzeile nach oben .globl ScrollScreen ScrollScreen: stp x29, x30, [sp, -16]! stp x10, x11, [sp, -16]! mov x29, sp //{ // for (u32 y = 1; y < NUM_ROWS; y++) mov x10,#1 1: cmp x10,#NUM_ROWS bge 2f // { // for (u32 x = 0; x < NUM_COLS; x++) mov x11,#0 3: cmp x11,#NUM_COLS bge 4f // { // DrawColor = GetPixel(x * CHAR_WIDTH, y * CHAR_HEIGHT); mov w0,w11 mov w2,#CHAR_WIDTH mul w0,w0,w2 mov w1,w10 mov w2,#CHAR_HEIGHT mul w1,w1,w2 bl GetPixel ldr x1,=DrawColor str w0,[x1] // DrawPixel(x * CHAR_WIDTH, (y - 1) * CHAR_HEIGHT); mov w0,w11 mov w2,#CHAR_WIDTH mul w0,w0,w2 mov w1,w10 sub w1,w1,#1 mov w2,#CHAR_HEIGHT mul w1,w1,w2 bl DrawPixel // } add x11,x11,#1 b 3b 4: // } add x10,x10,#1 b 1b 2: // // Clear the last line // for (u32 x = 0; x < NUM_COLS; x++) mov w10,#0 5: cmp w10,NUM_COLS bge 6f // { // DrawChar(' ', x * CHAR_WIDTH, (NUM_ROWS - 1) * CHAR_HEIGHT); mov w0,#' ' mov w1,w10 mov w3,#CHAR_WIDTH mul w1,w1,w3 mov w2,#NUM_ROWS sub w2,w2,#1 mov w3,#CHAR_HEIGHT mul w2,w2,w3 bl DrawChar // } add w10,w10,#1 b 5b 6: //} ldp x10, x11, [sp], 16 ldp x29, x30, [sp], 16 ret
//void DrawString(const char* str) { .globl DrawString DrawString: stp x29, x30, [sp, -16]! stp x10, x11, [sp, -16]! mov x29, sp
mov x10,x0 // while (*str) 2: ldrb w0,[x10] cmp w0,#0 beq 1f // { // if (*str == '\033') ToDo: Komplett nach DrawCharAtCursor verlegen (Flexibler) cmp w0,#27 bne 3f // { // ESC-Zeichen erkannt // const char* esc_seq = ++str; add x10,x10,#1 mov x0,x10 // ProcessEscSequence(esc_seq); bl ProcessEscSequence // str += 3; // Überspringen der ESC-Sequenz add x10,x10,#3 b 4f // } 3: // else // { // DrawCharAtCursor(*str++); //ldr w0,[x10] bl DrawCharAtCursor add x10,x10,#1 // } // } 4: b 2b //} 1: ldp x10, x11, [sp], 16 ldp x29, x30, [sp], 16 ret
//********************************************************** // Data //********************************************************** .section .data .align 16 pScreen: .int pScreen_end - pScreen .int CODE_REQUEST
.int PROPTAG_ALLOCATE_BUFFER .int 8 .int 4 m_nBufferPtr: .int 0 m_nBufferSize: .int 0
.int PROPTAG_END
pScreen_end:
.align 2 graphicsAddress: .int 0 DrawColor: .int 0xFFFFFFFF FrontColor: .int 0xFFFFFFFF BackColor: .int 0
// Terminal cursor_x: .int 0 cursor_y: .int 0
.ltorg font: .include "ms8x8font.fon"