Skip to content

Instantly share code, notes, and snippets.

@MitchRatquest
Last active November 28, 2019 18:32
Show Gist options
  • Save MitchRatquest/50dec3fc47738401cad6de1ee9eb01ec to your computer and use it in GitHub Desktop.
Save MitchRatquest/50dec3fc47738401cad6de1ee9eb01ec to your computer and use it in GitHub Desktop.
simple osc framebuffer beginnings
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <linux/fb.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <inttypes.h>
#include <math.h>
#include "lo/lo.h"
//liblo below
int done = 0;
void error(int num, const char *m, const char *path);
int quit_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data);
int line_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data);
int circle_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data);
int box_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data);
//framebuffer below
//we're on a 320x240 16bpp rgb565 ili9341 display
int fbfd = 0;
struct fb_var_screeninfo vinfo;
struct fb_fix_screeninfo finfo;
long int screensize = 0;
char *fbp = 0;
int x = 0, y = 0;
long int location = 0;
int maxx, maxy;
void setPixel(int x, int y, uint16_t pixel)
{
//uint16_t pixel = (r << 11) | (g << 5) | b;
uint32_t location = (x+vinfo.xoffset) * (vinfo.bits_per_pixel/8) +
(y/2+vinfo.yoffset) * finfo.line_length;
*((uint16_t*)(fbp + location)) = pixel;
}
int main()
{
fbfd = open("/dev/fb0", O_RDWR);
ioctl(fbfd, FBIOGET_FSCREENINFO, &finfo);
ioctl(fbfd, FBIOGET_VSCREENINFO, &vinfo);
printf("%dx%d, %dbpp\n", vinfo.xres, vinfo.yres, vinfo.bits_per_pixel);
screensize = vinfo.xres * vinfo.yres * vinfo.bits_per_pixel / 8;
fbp = (char *)mmap(0, screensize, PROT_READ | PROT_WRITE, MAP_SHARED, fbfd, 0);
maxx = vinfo.xres-1;
maxy = vinfo.yres-1;
lo_server_thread st = lo_server_thread_new("7770", error);
lo_server_thread_add_method(st, "/quit", "", quit_handler, NULL);
lo_server_thread_add_method(st, "/line", "iiiiiii", line_handler, NULL);
lo_server_thread_add_method(st, "/circle", "iiiiii", circle_handler, NULL);
lo_server_thread_add_method(st, "/box", "iiiiiii", box_handler, NULL);
lo_server_thread_start(st);
while (!done) { usleep(1000); }
lo_server_thread_free(st);
munmap(fbp, screensize);
return 0;
}
void error(int num, const char *msg, const char *path)
{
printf("liblo server error %d in path %s: %s\n", num, path, msg);
fflush(stdout);
}
void circle(int x, int y, int radius, uint16_t color)
{
uint16_t theta = 1;
while (theta < 360)
{
int curx = (int) x + radius*(cos(theta));
int cury = (int) y + radius*(sin(theta));
setPixel( curx, cury, color);
theta += 1;
}
}
void line(int x0, int y0, int x1, int y1, uint16_t color )
{
int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
int dy = abs(y1-y0), sy = y0<y1 ? 1 : -1;
int err = (dx>dy ? dx : -dy)/2, e2;
for(;;){
setPixel(x0,y0,color);
if (x0==x1 && y0==y1) break;
e2 = err;
if (e2 >-dx) { err -= dy; x0 += sx; }
if (e2 < dy) { err += dx; y0 += sy; }
}
}
int min(int num1, int num2) { return (num1 > num2 ) ? num2 : num1; }
int line_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data)
{
int xstart = min(argv[0]->i, maxx);
int ystart = min(argv[1]->i, maxy);
int xend = min(argv[2]->i, maxx);
int yend = min(argv[3]->i, maxy);
uint8_t red = (uint8_t) min(argv[4]->i, 0xFF); //0 through 31
uint8_t green = (uint8_t) min(argv[5]->i, 0xFF); //0 through 63
uint8_t blue = (uint8_t) min(argv[6]->i, 0xFF); //0 through 31
uint16_t color = ((red << 11) & 0xF800 ) | ((green << 6) & 0x07E0) | (blue & 0x1F);
line(xstart, ystart, xend, yend, color);
return 0;
}
int circle_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data)
{
int x = min(argv[0]->i, maxx);
int y = min(argv[1]->i, maxy);
int radius = argv[2]->i;
uint8_t red = (uint8_t) min(argv[3]->i, 0xFF); //0 through 31
uint8_t green = (uint8_t) min(argv[4]->i, 0xFF); //0 through 63
uint8_t blue = (uint8_t) min(argv[5]->i, 0xFF); //0 through 31
uint16_t color = ((red << 11) & 0xF800 ) | ((green << 6) & 0x07E0) | (blue & 0x1F);
circle(x, y, radius, color);
return 0;
}
int box_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data)
{
int x = min(argv[0]->i, maxx);
int y = min(argv[1]->i, maxy);
int width = min(argv[2]->i, maxx);
int height = min(argv[3]->i, maxy);
uint8_t red = (uint8_t) min(argv[4]->i, 0xFF); //0 through 31
uint8_t green = (uint8_t) min(argv[5]->i, 0xFF); //0 through 63
uint8_t blue = (uint8_t) min(argv[6]->i, 0xFF); //0 through 31
uint16_t color = ((red << 11) & 0xF800 ) | ((green << 6) & 0x07E0) | (blue & 0x1F);
line(x,y, min(x+width, maxx), y, color);
line(x,y,x, min(y+height, maxy), color);
line(min(x+width, maxx), y, min(x+width, maxx), min(y+height, maxy), color);
line(x,min(y+height, maxy), min(x+width, maxx), min(y+height, maxy), color);
}
int quit_handler(const char *path, const char *types, lo_arg ** argv,
int argc, void *data, void *user_data)
{
done = 1;
printf("quiting\n\n");
fflush(stdout);
return 0;
}
// gcc osc_fb.c -o f -llo -lm
/*
oscsend 127.0.0.1 7770 /line iiiiiii 0 0 319 240 31 15 0
oscsend 127.0.0.1 7770 /circle iiiiii 160 120 80 31 15 31
oscsend 127.0.0.1 7770 /box iiiiiii 80 80 40 20 31 15 31
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment