From 36a21f97c018a3693ac1b69c4bc9d18c0f058745 Mon Sep 17 00:00:00 2001 From: Mathieu Maret Date: Fri, 18 Mar 2022 00:30:59 +0100 Subject: [PATCH] Add font rendering --- Makefile | 8 ++-- fb.c | 116 +++++++++++++++++++++++++++++++++++++++++++------------ fb.h | 4 +- font.psf | Bin 0 -> 2080 bytes hello.c | 17 +++++--- uart.c | 2 +- uart.h | 2 +- 7 files changed, 112 insertions(+), 37 deletions(-) create mode 100644 font.psf diff --git a/Makefile b/Makefile index 056d7a2..042ab99 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,6 @@ CFLAGS=-Wall -Wextra -ffreestanding -march=armv8-a+crc -mcpu=cortex-a53 DEBUG_FLAGS += -g -Og -DDEBUG -fno-omit-frame-pointer -fno-inline LDSCRIPT=rpi3.ld -OBJS=crt0.o uart.o hello.o gasmsrc=$(wildcard *.S) gasmobj=$(gasmsrc:%.S=%.o) csrc=$(wildcard *.c) @@ -18,12 +17,15 @@ KERNEL=kernel.bin all:$(KERNEL) -kernel.elf: $(cobj) $(gasmobj) $(LDSCRIPT) - $(LD) $(LDFLAGS) -o $@ $(gasmobj) $(cobj) -T$(LDSCRIPT) -Map kernel.map +kernel.elf: $(cobj) $(gasmobj) font_psf.o $(LDSCRIPT) + $(LD) $(LDFLAGS) -o $@ $(gasmobj) $(cobj) font_psf.o -T$(LDSCRIPT) -Map kernel.map $(KERNEL): kernel.elf $(CROSS)objcopy -O binary $< $@ +font_psf.o: font.psf + $(LD) -r -b binary -o font_psf.o font.psf + clean: rm -rf $(cobj) $(gasmobj) $(deps) *.bin *.elf *.map diff --git a/fb.c b/fb.c index 3cd0aec..3af3682 100644 --- a/fb.c +++ b/fb.c @@ -12,38 +12,55 @@ #define MBOX_TAG_FBSETPIXORD 0x48006 #define MBOX_TAG_FBSETOFF 0x48009 -unsigned char *init_fb(struct fbst *fb) { +/* PC Screen Font as used by Linux Console */ +typedef struct { + unsigned int magic; + unsigned int version; + unsigned int headersize; + unsigned int flags; + unsigned int numglyph; + unsigned int bytesperglyph; + unsigned int height; + unsigned int width; + unsigned char glyphs; +} __attribute__((packed)) psf_t; +extern volatile unsigned char _binary_font_psf_start; + +static struct fbst fb; + +unsigned char *fb_init() +{ // sending many tags at once - mbox[0] = 35 * 4; - mbox[1] = MBOX_REQUEST; - mbox[2] = MBOX_TAG_FBSETPHYS; // set phy wh - mbox[3] = 8; - mbox[4] = 0; - mbox[5] = 1920; // FrameBufferInfo.width - mbox[6] = 1080; // FrameBufferInfo.height - mbox[7] = MBOX_TAG_FBSETVIRT; // set virt wh - mbox[8] = 8; - mbox[9] = 0; - mbox[10] = 1920; // FrameBufferInfo.virtual_width - mbox[11] = 1080; // FrameBufferInfo.virtual_height + mbox[0] = 35 * 4; + mbox[1] = MBOX_REQUEST; + mbox[2] = MBOX_TAG_FBSETPHYS; // set phy wh + mbox[3] = 8; + mbox[4] = 0; + mbox[5] = 1920; // FrameBufferInfo.width + mbox[6] = 1080; // FrameBufferInfo.height + mbox[7] = MBOX_TAG_FBSETVIRT; // set virt wh + mbox[8] = 8; + mbox[9] = 0; + mbox[10] = 1920; // FrameBufferInfo.virtual_width + mbox[11] = 1080; // FrameBufferInfo.virtual_height mbox[12] = MBOX_TAG_FBSETOFF; // set virt offset mbox[13] = 8; mbox[14] = 0; - mbox[15] = 0; // FrameBufferInfo.x_offset - mbox[16] = 0; // FrameBufferInfo.y.offset + mbox[15] = 0; // FrameBufferInfo.x_offset + mbox[16] = 0; // FrameBufferInfo.y.offset mbox[17] = MBOX_TAG_FBSETDEPTH; // set depth mbox[18] = 4; mbox[19] = 0; - mbox[20] = 32; // FrameBufferInfo.depth + mbox[20] = 32; // FrameBufferInfo.depth mbox[21] = MBOX_TAG_FBSETPIXORD; // set pixel order mbox[22] = 4; mbox[23] = 0; - mbox[24] = 1; // RGB, not BGR preferably + mbox[24] = 1; // RGB, not BGR preferably mbox[25] = MBOX_TAG_FBALLOC; // get framebuffer, gets alignment on request mbox[26] = 8; mbox[27] = 0; - mbox[28] = 4096; // FrameBufferInfo.pointer - mbox[29] = 0; // FrameBufferInfo.size + mbox[28] = 4096; // FrameBufferInfo.pointer + mbox[29] = 0; // FrameBufferInfo.size mbox[30] = MBOX_TAG_FBGETPITCH; // get pitch mbox[31] = 4; mbox[32] = 0; @@ -52,15 +69,64 @@ unsigned char *init_fb(struct fbst *fb) { if (mbox_call(MBOX_CH_PROP, mbox) == 0 && mbox[20] == 32 && mbox[28] != 0) { mbox[28] &= 0x3FFFFFFF; // convert GPU address to ARM address - fb->width = mbox[5]; // get actual physical width - fb->height = mbox[6]; // get actual physical height - fb->pitch = mbox[33]; // get number of bytes per line - fb->isrgb = mbox[24]; // get the actual channel order - fb->fbp = (void *)((unsigned long)mbox[28]); + fb.width = mbox[5]; // get actual physical width + fb.height = mbox[6]; // get actual physical height + fb.pitch = mbox[33]; // get number of bytes per line + fb.isrgb = mbox[24]; // get the actual channel order + fb.fbp = (void *)((unsigned long)mbox[28]); } else { puts("Unable to set framebuffer!\r\n"); return 0; } - return fb->fbp; + return fb.fbp; +} + +struct fbst * fb_get(){ + return &fb; +} + +void fb_print(int x, int y, char *s) +{ + // get our font + psf_t *font = (psf_t *)&_binary_font_psf_start; + // draw next character if it's not zero + while (*s) { + // get the offset of the glyph. Need to adjust this to support unicode table + unsigned char *glyph = + (unsigned char *)&_binary_font_psf_start + font->headersize + + (*((unsigned char *)s) < font->numglyph ? *s : 0) * font->bytesperglyph; + // calculate the offset on screen + int offs = (y * fb.pitch) + (x * 4); + // variables + int line, mask, bytesperline = (font->width + 7) / 8; + // handle carrige return + if (*s == '\r') { + x = 0; + } else + // new line + if (*s == '\n') { + x = 0; + y += font->height; + } else { + // display a character + for (unsigned int j = 0; j < font->height; j++) { + // display one row + line = offs; + mask = 1 << (font->width - 1); + for (unsigned int i = 0; i < font->width; i++) { + // if bit set, we use white color, otherwise black + *((unsigned int *)(fb.fbp + line)) = ((int)*glyph) & mask ? 0xFFFFFF : 0; + mask >>= 1; + line += 4; + } + // adjust to next line + glyph += bytesperline; + offs += fb.pitch; + } + x += (font->width + 1); + } + // next character + s++; + } } diff --git a/fb.h b/fb.h index 27216c8..a04a65b 100644 --- a/fb.h +++ b/fb.h @@ -8,4 +8,6 @@ struct fbst { unsigned int isrgb; }; -unsigned char *init_fb(struct fbst *fb); +unsigned char *fb_init(); +struct fbst * fb_get(); +void fb_print(int x, int y, char *s); diff --git a/font.psf b/font.psf new file mode 100644 index 0000000000000000000000000000000000000000..3e67693f59d769c6453826ed9012a09818a9b9af GIT binary patch literal 2080 zcmZuyJ!>0D7#>_KR}4bsa4{l9ij>P897`AyNSU9IYDvN-#T4cWA-F-duJC{G54fL@ zbcRKSsZ2^0kr1w|CInT73$wcC{TS^A?#0^Ocb@nAWBljmHB10uHuk&-tTrh=e)ws&!OD& zIEIK5^uV;cAqPZ!>YLZE8&T)Oo2%>Vs~g29qhEiU-GXLf!8ai9;6V6SzrQL$XZt(h z&)=WF2YuY#w{qaz+VA{Y-GAtCq&H0R97LTP}vkkfS*({VNnjTr}Y#bM;bqUfqI81m+h>gY@@8Zx*QlcZQH7K zK7Ag#@Vv*zRTX1)k7G11R(<<=LH8K`*G8P>6EwU3UbcBQLcDrdc zzA+V~qku&I5fcz;;va?g%@P^5OI=X&5D09V@E~~Cy!$l!RKIJqUdq??exScisd*th zd180!kA{!Q3qIj#==c2|u4Xehy%&66Gadb4RA`6UDj_MD1UD@KOKcBz-DPA(or1q5ydEtm(tybNSpz)=EZHy?o@Kj5#f#%<( zOKRRS&!3ldDNDr-Zm_fJ^mt!+Ss!Z|r*4Yf|9RrJEz9A>qB1iZkNaxw>YA#JAvjuy z2?LPpcM4Ad;=11?6cd&p<5l=jbC0yXz^5dB8!cbqupg#mU+as}tcLwB3NykwfKV4G zLtX|zfbp; - for (unsigned int y = 0; y < fb.height; y++) { - for (unsigned int x = 0; x < fb.width; x++) { + for (unsigned int y = 0; y < fb->height; y++) { + for (unsigned int x = 0; x < fb->width; x++) { if (y % 60 == 0) *((unsigned int *)ptr) = 0x00FF0000; else if (y % 40 == 0) @@ -47,5 +50,7 @@ int kernelmain(void) ptr += 4; } } + + fb_print(0, 0, "Hello Dude\n"); return 0; } diff --git a/uart.c b/uart.c index 794dc5b..4df3466 100644 --- a/uart.c +++ b/uart.c @@ -4,7 +4,7 @@ #include "gpio.h" -void init_uart(void ) +void uart_init(void ) { //Active waiting while(UART0_FR & (1<<3)){} diff --git a/uart.h b/uart.h index 2fa910e..c6bbf1e 100644 --- a/uart.h +++ b/uart.h @@ -11,6 +11,6 @@ #define UART0_IMSC (*(volatile unsigned *)(UART0_BASE + 0x38)) #define UART0_ICR (*(volatile unsigned *)(UART0_BASE + 0x44)) -void init_uart(void); +void uart_init(void); void putc(char c); void puts(const char *s);