From 9934f27cc16e8a2da43033a1f957761e00db4916 Mon Sep 17 00:00:00 2001 From: jaseg Date: Sun, 16 Feb 2014 11:57:21 +0100 Subject: The fundamentals of the new ctypes interface are working --- host/Makefile | 4 ++-- host/font.c | 26 +++++++++++++++----------- host/font.h | 6 ++++-- host/main.c | 2 +- host/main.h | 2 +- host/matelight.py | 35 +++++++++++++++++++++++++++++++++++ host/server.py | 32 ++++++++++++++++++++++++++++++++ 7 files changed, 90 insertions(+), 17 deletions(-) create mode 100644 host/matelight.py create mode 100755 host/server.py diff --git a/host/Makefile b/host/Makefile index 345058b..a6b892f 100644 --- a/host/Makefile +++ b/host/Makefile @@ -1,6 +1,6 @@ -all: main.c font.c font.h color.c color.h gif.h gif.c - gcc -shared -std=gnu11 -Wall -lm -o libbdf.so -g -O0 main.c font.c color.c +all: main.c font.c font.h color.c color.h + gcc -shared -fPIC -std=gnu11 -Wall -lm -o libbdf.so -g -O0 main.c font.c color.c clean: rm libbdf.so diff --git a/host/font.c b/host/font.c index 494210d..85882ad 100644 --- a/host/font.c +++ b/host/font.c @@ -4,6 +4,7 @@ #include #include #include +#include void render_glyph(glyph_t *g, color_t *buf, unsigned int bufwidth, unsigned int offx, unsigned int offy, color_t fg, color_t bg){ unsigned int bitmap_row_width = g->width/8; @@ -30,7 +31,7 @@ glyphtable_t *read_bdf_file(char *filename){ goto error; } - glyphtable_t *glyph_table = read_bdf(fontfile, glyph_table, BLP_SIZE) + glyphtable_t *glyph_table = read_bdf(fontfile); if(!glyph_table){ fprintf(stderr, "Error reading font file.\n"); goto error; @@ -50,15 +51,16 @@ glyphtable_t *extend_glyphtable(glyphtable_t *glyph_table){ size_t newlen = oldlen + (oldlendata, newlen*sizeof(glyph_t)); + glyph_t **newdata = realloc(glyph_table->data, newlen*sizeof(glyph_t*)); if(!newdata){ fprintf(stderr, "Cannot allocate bdf glyph buffer\n"); goto error; } glyph_table->data = newdata; // Clear newly allocated memory area - memset(glyph_table->data+oldlen, 0, (newlen-oldlen)*sizeof(glyph_t)); + memset(glyph_table->data+oldlen, 0, (newlen-oldlen)*sizeof(glyph_t*)); glyph_table->size = newlen; + return glyph_table; error: free_glyphtable(glyph_table); return NULL; @@ -66,7 +68,7 @@ error: void free_glyphtable(glyphtable_t *glyph_table){ if(glyph_table){ - for(unsigned int i=0; ilength; i++){ + for(unsigned int i=0; isize; i++){ free(glyph_table->data[i]); } free(glyph_table->data); @@ -119,13 +121,6 @@ glyphtable_t *read_bdf(FILE *f){ fprintf(stderr, "Invalid ENCODING line: %s %s\n", line, args); goto error; } - if(encoding > glyph_table->size){ - glyph_table = extend_glyphtable(glyph_table); - if(!glyph_table){ - fprintf(stderr, "Cannot allocate glyph table.\n"); - goto error; - } - } }else if(strcmp("BBX", line) == 0){ if(!args){ @@ -228,6 +223,15 @@ glyphtable_t *read_bdf(FILE *f){ } i++; } + + if(encoding >= glyph_table->size){ + glyph_table = extend_glyphtable(glyph_table); + if(!glyph_table){ + fprintf(stderr, "Cannot extend glyph table.\n"); + goto error; + } + } + memcpy(glyph_data, ¤t_glyph, sizeof(glyph_t)); glyph_table->data[encoding] = glyph_data; diff --git a/host/font.h b/host/font.h index 4a7fe63..e9fbb35 100644 --- a/host/font.h +++ b/host/font.h @@ -15,7 +15,7 @@ typedef struct { } glyph_t; typedef struct { - glyph_t *t; + glyph_t **data; size_t size; } glyphtable_t; @@ -25,7 +25,9 @@ typedef struct { #define MAX_CSI_ELEMENTS 8 // We could also use some fancy hashtable here, but unifont includes about 57k glyphs so we would hardly save any memory. -int read_bdf(FILE *f, glyph_t **glyph_table, unsigned int glyph_table_size); +glyphtable_t *read_bdf(FILE *f); + +void free_glyphtable(glyphtable_t *glyph_table); // Requires buf to point to a buffer at least of size glyph->width*glyph->height. void render_glyph(glyph_t *glyph, color_t *buf, unsigned int bufwidth, unsigned int offx, unsigned int offy, color_t fg, color_t bg); diff --git a/host/main.c b/host/main.c index 0d5af6e..c6086e1 100644 --- a/host/main.c +++ b/host/main.c @@ -65,7 +65,7 @@ framebuffer_t *framebuffer_render_text(char *s, glyphtable_t *glyph_table){ p += inc; if(c > glyph_table->size){ - fprintf(stderr, "Error rendering string: Codepoint 0x%lx out of valid range (0-%d).\n", (long int)c, glyph_table->size); + fprintf(stderr, "Error rendering string: Codepoint 0x%lx out of valid range (0-%ld).\n", (long int)c, glyph_table->size); goto error; } diff --git a/host/main.h b/host/main.h index 98c4ded..cf1dba7 100644 --- a/host/main.h +++ b/host/main.h @@ -4,7 +4,7 @@ #include "color.h" #include "font.h" -framebuffer_t *framebuffer_render_text(char *s, glyph_t **glyph_table, unsigned int glyph_table_size); +framebuffer_t *framebuffer_render_text(char *s, glyphtable_t *glyph_table); void console_render_buffer(framebuffer_t *fb); #endif//__MAIN_H__ diff --git a/host/matelight.py b/host/matelight.py new file mode 100644 index 0000000..f75ae80 --- /dev/null +++ b/host/matelight.py @@ -0,0 +1,35 @@ +import usb +import colorsys +import numpy as np +import itertools + +CRATE_WIDTH = 5 +CRATE_HEIGHT = 4 +CRATES_X = 8 +CRATES_Y = 4 + +DISPLAY_WIDTH = CRATES_X*CRATE_WIDTH +DISPLAY_HEIGHT = CRATES_Y*CRATE_HEIGHT +FRAME_SIZE = CRATE_WIDTH*CRATE_HEIGHT*3 + +dev = usb.core.find(idVendor=0x1cbe, idProduct=0x0003) + +def sendframe(framedata): + """ Send a frame to the display + + The argument contains a h * w array of 3-tuples of (r, g, b)-data or 4-tuples of (r, g, b, a)-data where the a + channel is ignored. + """ + def chunks(l, n): + for i in xrange(0, len(l), n): + yield l[i:i+n] + + for cx, cy in itertools.product(range(DISPLAY_WIDTH), range(DISPLAY_HEIGHT)): + data = [ v for x in range(CRATE_WIDTH) for y in range(CRATE_HEIGHT) for v in framedata[cy*CRATE_HEIGHT + y][cx*CRATE_WIDTH + x][:3] ] + if len(data) != FRAME_SIZE: + raise ValueError('Invalid frame data. Expected {} bytes, got {}.'.format(FRAME_SIZE, len(data))) + # Send framebuffer data + dev.write(0x01, bytes([0, x, y])+bytes(data)) + # Send latch command + dev.write(0x01, b'\x01') + diff --git a/host/server.py b/host/server.py new file mode 100755 index 0000000..c8e665a --- /dev/null +++ b/host/server.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python + +from ctypes import CDLL, POINTER, c_void_p, Structure, c_uint8, c_size_t, cast +import numpy as np +from matelight import sendframe + +class COLOR(Structure): + _fields_ = ('r', c_uint8), ('g', c_uint8), ('b', c_uint8), ('a', c_uint8) + +class FRAMEBUFFER(Structure): + _fields_ = ('data', POINTER(COLOR)), ('w', c_size_t), ('h', c_size_t) + +bdf = CDLL('./libbdf.so') +bdf.read_bdf_file.restype = c_void_p +bdf.framebuffer_render_text.restype = POINTER(FRAMEBUFFER) + +unifont = bdf.read_bdf_file('unifont.bdf') + +def render_text(text): + assert unifont + fb = bdf.framebuffer_render_text(str(text), unifont) + fbd = fb.contents + buf = np.ctypeslib.as_array(cast(fbd.data, POINTER(c_uint8)), shape=(fbd.h, fbd.w, 4)) + # Set data pointer to NULL before freeing framebuffer struct to prevent free_framebuffer from also freeing the data + # buffer that is now used by numpy + fb.data = cast(c_void_p(), POINTER(COLOR)) + bdf.free_framebuffer(fb) + return buf + +if __name__ == '__main__': + sendframe(render_text('test')); + -- cgit