Add font rendering
This commit is contained in:
parent
5f9b898e4f
commit
36a21f97c0
8
Makefile
8
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
|
DEBUG_FLAGS += -g -Og -DDEBUG -fno-omit-frame-pointer -fno-inline
|
||||||
LDSCRIPT=rpi3.ld
|
LDSCRIPT=rpi3.ld
|
||||||
|
|
||||||
OBJS=crt0.o uart.o hello.o
|
|
||||||
gasmsrc=$(wildcard *.S)
|
gasmsrc=$(wildcard *.S)
|
||||||
gasmobj=$(gasmsrc:%.S=%.o)
|
gasmobj=$(gasmsrc:%.S=%.o)
|
||||||
csrc=$(wildcard *.c)
|
csrc=$(wildcard *.c)
|
||||||
@ -18,12 +17,15 @@ KERNEL=kernel.bin
|
|||||||
|
|
||||||
all:$(KERNEL)
|
all:$(KERNEL)
|
||||||
|
|
||||||
kernel.elf: $(cobj) $(gasmobj) $(LDSCRIPT)
|
kernel.elf: $(cobj) $(gasmobj) font_psf.o $(LDSCRIPT)
|
||||||
$(LD) $(LDFLAGS) -o $@ $(gasmobj) $(cobj) -T$(LDSCRIPT) -Map kernel.map
|
$(LD) $(LDFLAGS) -o $@ $(gasmobj) $(cobj) font_psf.o -T$(LDSCRIPT) -Map kernel.map
|
||||||
|
|
||||||
$(KERNEL): kernel.elf
|
$(KERNEL): kernel.elf
|
||||||
$(CROSS)objcopy -O binary $< $@
|
$(CROSS)objcopy -O binary $< $@
|
||||||
|
|
||||||
|
font_psf.o: font.psf
|
||||||
|
$(LD) -r -b binary -o font_psf.o font.psf
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -rf $(cobj) $(gasmobj) $(deps) *.bin *.elf *.map
|
rm -rf $(cobj) $(gasmobj) $(deps) *.bin *.elf *.map
|
||||||
|
|
||||||
|
116
fb.c
116
fb.c
@ -12,38 +12,55 @@
|
|||||||
#define MBOX_TAG_FBSETPIXORD 0x48006
|
#define MBOX_TAG_FBSETPIXORD 0x48006
|
||||||
#define MBOX_TAG_FBSETOFF 0x48009
|
#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
|
// sending many tags at once
|
||||||
mbox[0] = 35 * 4;
|
mbox[0] = 35 * 4;
|
||||||
mbox[1] = MBOX_REQUEST;
|
mbox[1] = MBOX_REQUEST;
|
||||||
mbox[2] = MBOX_TAG_FBSETPHYS; // set phy wh
|
mbox[2] = MBOX_TAG_FBSETPHYS; // set phy wh
|
||||||
mbox[3] = 8;
|
mbox[3] = 8;
|
||||||
mbox[4] = 0;
|
mbox[4] = 0;
|
||||||
mbox[5] = 1920; // FrameBufferInfo.width
|
mbox[5] = 1920; // FrameBufferInfo.width
|
||||||
mbox[6] = 1080; // FrameBufferInfo.height
|
mbox[6] = 1080; // FrameBufferInfo.height
|
||||||
mbox[7] = MBOX_TAG_FBSETVIRT; // set virt wh
|
mbox[7] = MBOX_TAG_FBSETVIRT; // set virt wh
|
||||||
mbox[8] = 8;
|
mbox[8] = 8;
|
||||||
mbox[9] = 0;
|
mbox[9] = 0;
|
||||||
mbox[10] = 1920; // FrameBufferInfo.virtual_width
|
mbox[10] = 1920; // FrameBufferInfo.virtual_width
|
||||||
mbox[11] = 1080; // FrameBufferInfo.virtual_height
|
mbox[11] = 1080; // FrameBufferInfo.virtual_height
|
||||||
mbox[12] = MBOX_TAG_FBSETOFF; // set virt offset
|
mbox[12] = MBOX_TAG_FBSETOFF; // set virt offset
|
||||||
mbox[13] = 8;
|
mbox[13] = 8;
|
||||||
mbox[14] = 0;
|
mbox[14] = 0;
|
||||||
mbox[15] = 0; // FrameBufferInfo.x_offset
|
mbox[15] = 0; // FrameBufferInfo.x_offset
|
||||||
mbox[16] = 0; // FrameBufferInfo.y.offset
|
mbox[16] = 0; // FrameBufferInfo.y.offset
|
||||||
mbox[17] = MBOX_TAG_FBSETDEPTH; // set depth
|
mbox[17] = MBOX_TAG_FBSETDEPTH; // set depth
|
||||||
mbox[18] = 4;
|
mbox[18] = 4;
|
||||||
mbox[19] = 0;
|
mbox[19] = 0;
|
||||||
mbox[20] = 32; // FrameBufferInfo.depth
|
mbox[20] = 32; // FrameBufferInfo.depth
|
||||||
mbox[21] = MBOX_TAG_FBSETPIXORD; // set pixel order
|
mbox[21] = MBOX_TAG_FBSETPIXORD; // set pixel order
|
||||||
mbox[22] = 4;
|
mbox[22] = 4;
|
||||||
mbox[23] = 0;
|
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[25] = MBOX_TAG_FBALLOC; // get framebuffer, gets alignment on request
|
||||||
mbox[26] = 8;
|
mbox[26] = 8;
|
||||||
mbox[27] = 0;
|
mbox[27] = 0;
|
||||||
mbox[28] = 4096; // FrameBufferInfo.pointer
|
mbox[28] = 4096; // FrameBufferInfo.pointer
|
||||||
mbox[29] = 0; // FrameBufferInfo.size
|
mbox[29] = 0; // FrameBufferInfo.size
|
||||||
mbox[30] = MBOX_TAG_FBGETPITCH; // get pitch
|
mbox[30] = MBOX_TAG_FBGETPITCH; // get pitch
|
||||||
mbox[31] = 4;
|
mbox[31] = 4;
|
||||||
mbox[32] = 0;
|
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) {
|
if (mbox_call(MBOX_CH_PROP, mbox) == 0 && mbox[20] == 32 && mbox[28] != 0) {
|
||||||
mbox[28] &= 0x3FFFFFFF; // convert GPU address to ARM address
|
mbox[28] &= 0x3FFFFFFF; // convert GPU address to ARM address
|
||||||
fb->width = mbox[5]; // get actual physical width
|
fb.width = mbox[5]; // get actual physical width
|
||||||
fb->height = mbox[6]; // get actual physical height
|
fb.height = mbox[6]; // get actual physical height
|
||||||
fb->pitch = mbox[33]; // get number of bytes per line
|
fb.pitch = mbox[33]; // get number of bytes per line
|
||||||
fb->isrgb = mbox[24]; // get the actual channel order
|
fb.isrgb = mbox[24]; // get the actual channel order
|
||||||
fb->fbp = (void *)((unsigned long)mbox[28]);
|
fb.fbp = (void *)((unsigned long)mbox[28]);
|
||||||
} else {
|
} else {
|
||||||
puts("Unable to set framebuffer!\r\n");
|
puts("Unable to set framebuffer!\r\n");
|
||||||
return 0;
|
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++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
4
fb.h
4
fb.h
@ -8,4 +8,6 @@ struct fbst {
|
|||||||
unsigned int isrgb;
|
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);
|
||||||
|
17
hello.c
17
hello.c
@ -3,11 +3,13 @@
|
|||||||
#include "uart.h"
|
#include "uart.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
struct fbst fb;
|
|
||||||
int kernelmain(void)
|
int kernelmain(void)
|
||||||
{
|
{
|
||||||
init_uart();
|
struct fbst *fb;
|
||||||
if (init_fb(&fb) == 0) {
|
unsigned char *ptr;
|
||||||
|
|
||||||
|
uart_init();
|
||||||
|
if (fb_init() == 0) {
|
||||||
puts("Fail to init framebuffer");
|
puts("Fail to init framebuffer");
|
||||||
}
|
}
|
||||||
mbox[0] = 8 * 4;
|
mbox[0] = 8 * 4;
|
||||||
@ -32,10 +34,11 @@ int kernelmain(void)
|
|||||||
|
|
||||||
printclock();
|
printclock();
|
||||||
|
|
||||||
unsigned char *ptr = fb.fbp;
|
fb = fb_get();
|
||||||
|
ptr = fb->fbp;
|
||||||
|
|
||||||
for (unsigned int y = 0; y < fb.height; y++) {
|
for (unsigned int y = 0; y < fb->height; y++) {
|
||||||
for (unsigned int x = 0; x < fb.width; x++) {
|
for (unsigned int x = 0; x < fb->width; x++) {
|
||||||
if (y % 60 == 0)
|
if (y % 60 == 0)
|
||||||
*((unsigned int *)ptr) = 0x00FF0000;
|
*((unsigned int *)ptr) = 0x00FF0000;
|
||||||
else if (y % 40 == 0)
|
else if (y % 40 == 0)
|
||||||
@ -47,5 +50,7 @@ int kernelmain(void)
|
|||||||
ptr += 4;
|
ptr += 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fb_print(0, 0, "Hello Dude\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
2
uart.c
2
uart.c
@ -4,7 +4,7 @@
|
|||||||
#include "gpio.h"
|
#include "gpio.h"
|
||||||
|
|
||||||
|
|
||||||
void init_uart(void )
|
void uart_init(void )
|
||||||
{
|
{
|
||||||
//Active waiting
|
//Active waiting
|
||||||
while(UART0_FR & (1<<3)){}
|
while(UART0_FR & (1<<3)){}
|
||||||
|
2
uart.h
2
uart.h
@ -11,6 +11,6 @@
|
|||||||
#define UART0_IMSC (*(volatile unsigned *)(UART0_BASE + 0x38))
|
#define UART0_IMSC (*(volatile unsigned *)(UART0_BASE + 0x38))
|
||||||
#define UART0_ICR (*(volatile unsigned *)(UART0_BASE + 0x44))
|
#define UART0_ICR (*(volatile unsigned *)(UART0_BASE + 0x44))
|
||||||
|
|
||||||
void init_uart(void);
|
void uart_init(void);
|
||||||
void putc(char c);
|
void putc(char c);
|
||||||
void puts(const char *s);
|
void puts(const char *s);
|
||||||
|
Loading…
Reference in New Issue
Block a user