#include "fb.h" #include "mbox.h" #include "uart.h" #include "utils.h" #include #define MBOX_TAG_FBALLOC 0x40001 #define MBOX_TAG_FBGETPITCH 0x40008 #define MBOX_TAG_FBSETPHYS 0x48003 #define MBOX_TAG_FBSETVIRT 0x48004 #define MBOX_TAG_FBSETDEPTH 0x48005 #define MBOX_TAG_FBSETPIXORD 0x48006 #define MBOX_TAG_FBSETOFF 0x48009 /* 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(int width, int height) { // 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] = width; // FrameBufferInfo.width mbox[6] = height; // FrameBufferInfo.height mbox[7] = MBOX_TAG_FBSETVIRT; // set virt wh mbox[8] = 8; mbox[9] = 0; mbox[10] = width; // FrameBufferInfo.virtual_width mbox[11] = height; // 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[17] = MBOX_TAG_FBSETDEPTH; // set depth mbox[18] = 4; mbox[19] = 0; 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[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[30] = MBOX_TAG_FBGETPITCH; // get pitch mbox[31] = 4; mbox[32] = 0; mbox[33] = 0; // FrameBufferInfo.pitch mbox[34] = MBOX_TAG_LAST; 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]); } else { puts("Unable to set framebuffer!\r\n"); return 0; } 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++; } }