2. Framebuffer + Videobuffer

This section outlines data + operations needed to interact with the framebuffer.

2.1. Actual Framebuffer

The actual linux framebuffer.

2.1.1. typedef + struct contents

<<norns_typedefs>>=
typedef struct norns_framebuffer norns_framebuffer;
<<norns_structs>>=
struct norns_framebuffer {
    int fbfd;
    struct fb_var_screeninfo vinfo;
    struct fb_fix_screeninfo finfo;
    long int screensize;
    char *fbp;
};

2.1.2. allocating/freeing

<<norns_funcdefs>>=
void norns_framebuffer_new(norns_framebuffer **pfb);
void norns_framebuffer_del(norns_framebuffer **pfb);
<<norns_functions>>=
void norns_framebuffer_new(norns_framebuffer **pfb)
{
    norns_framebuffer *fb;
    fb = calloc(1, sizeof(norns_framebuffer));
    *pfb = fb;
}
void norns_framebuffer_del(norns_framebuffer **fb)
{
    free(*fb);
}

2.1.3. opening the framebuffer

<<norns_funcdefs>>=
int norns_framebuffer_open(norns_framebuffer *fb);
<<norns_functions>>=
int norns_framebuffer_open(norns_framebuffer *fb)
{
    int rc;
    fb->fbfd = open("/dev/fb0", O_RDWR);
    if (fb->fbfd == -1) {
        perror("Error: cannot open framebuffer device");
        return 1;
    }

    rc = ioctl(fb->fbfd, FBIOGET_FSCREENINFO, &fb->finfo);

    if (rc == -1) {
        perror("Error reading fixed information");
        return 2;
    }

    rc = ioctl(fb->fbfd, FBIOGET_VSCREENINFO, &fb->vinfo);

    if (rc == -1) {
        perror("Error reading variable information");
        return 3;
    }

    fb->screensize = fb->vinfo.xres *
        fb->vinfo.yres *
        fb->vinfo.bits_per_pixel / 8;

    fb->fbp = (char *)mmap(0,
                           fb->screensize,
                           PROT_READ | PROT_WRITE,
                           MAP_SHARED,
                           fb->fbfd,
                           0);

    return 0;
}

2.1.4. closing the framebuffer

<<norns_funcdefs>>=
void norns_framebuffer_close(norns_framebuffer *fb);
<<norns_functions>>=
void norns_framebuffer_close(norns_framebuffer *fb)
{
    munmap(fb->fbp, fb->screensize);
    close(fb->fbfd);
}

2.1.5. Writing to the framebuffer

<<norns_funcdefs>>=
void norns_framebuffer_write(norns_framebuffer *fb,
                             int x, int y,
                             unsigned char val);
<<norns_functions>>=
void norns_framebuffer_write(norns_framebuffer *fb,
                             int x, int y,
                             unsigned char val)
{
    long int loc;
    loc = (x + fb->vinfo.xoffset) *
        (fb->vinfo.bits_per_pixel/8) +
        (y + fb->vinfo.yoffset) * fb->finfo.line_length;
    fb->fbp[loc] = 0x0;
    fb->fbp[loc + 1] = val;
}

2.2. Video Buffer

An array of 8-bit values to write to before copying over to the framebuffer.

2.2.1. typedef + struct contents

<<norns_typedefs>>=
typedef struct norns_videobuf norns_videobuf;

All that's really needed in a video buffer is a 128x64 array of unsigned 8-bit ints, which reduces to an array of size 8192.

<<norns_structs>>=
struct norns_videobuf {
    unsigned char buf[8192];
};

2.2.2. allocating/freeing

<<norns_funcdefs>>=
void norns_videobuf_new(norns_videobuf **pvb);
void norns_videobuf_del(norns_videobuf **pvb);
<<norns_functions>>=
void norns_videobuf_new(norns_videobuf **pvb)
{
    norns_videobuf *vb;
    vb = calloc(1, sizeof(norns_videobuf));
    *pvb = vb;
}
void norns_videobuf_del(norns_videobuf **vb)
{
    free(*vb);
}

2.2.3. initializing the video buffer

Zero out the array.

<<norns_funcdefs>>=
void norns_videobuf_init(norns_videobuf *vb);
<<norns_functions>>=
void norns_videobuf_init(norns_videobuf *vb)
{
    norns_videobuf_clear(vb);
}

2.2.4. getting the video buffer

<<norns_funcdefs>>=
unsigned char *norns_videobuf_get(norns_videobuf *buf);
<<norns_functions>>=
unsigned char *norns_videobuf_get(norns_videobuf *buf)
{
    return buf->buf;
}

2.2.5. Writing a pixel to the video buffer

<<norns_funcdefs>>=
void norns_videobuf_write(norns_videobuf *vb,
                          int x, int y,
                          unsigned char val);
<<norns_functions>>=
void norns_videobuf_write(norns_videobuf *vb,
                          int x, int y,
                          unsigned char val)
{
    if (x >= 128 || y >= 64) return;
    vb->buf[x + y*128] = val;
}

2.2.6. Clearing the screen

<<norns_funcdefs>>=
void norns_videobuf_clear(norns_videobuf *vb);
<<norns_functions>>=
void norns_videobuf_clear(norns_videobuf *vb)
{
    int x;
    int y;
    for (y = 0; y < 64; y++) {
        for (x = 0; x < 128; x++) {
            vb->buf[x + y*128] = 0;
        }
    }
}

2.2.7. copying the video buffer to the framebuffer

<<norns_funcdefs>>=
void norns_videobuf_copy(norns_videobuf *vb,
                         norns_framebuffer *fb);
<<norns_functions>>=
void norns_videobuf_copy(norns_videobuf *vb,
                         norns_framebuffer *fb)
{
    int x, y;
    unsigned char val;
    int w, h;

    h = fb->vinfo.yres;
    w = fb->vinfo.xres;
    for(y = 0; y < h; y++) {
        for(x = 0; x < w; x++) {
            if (x >= 128 || y >= 64) continue;
            val = vb->buf[x + y * w];
            norns_framebuffer_write(fb, x, y, val);
        }
    }
}



prev | home | next