pocket-reform/pocket-reform-keyboard-fw/kbdgfx-demo/kbdgfx.c

129 lines
3.4 KiB
C

/*
kbdgfx.c -- Demo for drawing realtime graphics to the MNT Reform Keyboard
Copyright 2022 MNT Research GmbH (https://mntre.com)
License: MIT
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <math.h>
#include <unistd.h>
#define ROWS 6
#define COLS 12
#define BUFSZ (6+COLS*3)
#define FBUFSZ COLS*ROWS*3
// our unpacked, wasteful framebuffer (3 bytes per pixel)
uint8_t fb[FBUFSZ];
// the buffer we send over HID
uint8_t buf[BUFSZ];
void draw_sine(float t, uint8_t* dst, uint8_t r, uint8_t g, uint8_t b, float brite) {
for (int x=0; x<COLS; x++) {
float fy = 2.5 + sin(t + ((float)x/12.0 * 3.141))*2;
for (int y=0; y<ROWS; y++) {
float d = 1.0 / (10.0 * (abs((float)y - fy)));
if (d > 1) d = 1;
dst[3*(y*COLS + x)] |= (uint8_t)(r * d * brite);
dst[3*(y*COLS + x)+1] |= (uint8_t)(g * d * brite);
dst[3*(y*COLS + x)+2] |= (uint8_t)(b * d * brite);
}
}
}
void draw_box(uint8_t* dst, uint8_t r, uint8_t g, uint8_t b, float brite) {
for (int x=0; x<COLS; x++) {
for (int y=0; y<ROWS; y++) {
dst[3*(y*COLS + x)] |= (uint8_t)(r * brite);
dst[3*(y*COLS + x)+1] |= (uint8_t)(g * brite);
dst[3*(y*COLS + x)+2] |= (uint8_t)(b * brite);
}
}
}
int main(int argc, char** argv) {
// just a counter
uint32_t t = 0;
if (argc < 2) {
printf("Usage: sudo kbdgfx /dev/hidraw0 [bitmap.raw]\n");
exit(1);
}
// loop forever
while (1) {
// start with the command
buf[0] = 'x';
buf[1] = 'X';
buf[2] = 'R';
buf[3] = 'G';
buf[4] = 'B';
// clear
memset(fb, 0, FBUFSZ);
if (argc == 3) {
// read bitmap from file
FILE* bmf = fopen(argv[2],"r");
if (!bmf) {
printf("Couldn't open bitmap %s!\n", argv[2]);
exit(2);
}
int res = fread(fb, FBUFSZ, 1, bmf);
fclose(bmf);
if (res<1) {
printf("Couldn't read bitmap or wrong size.\n", argv[2]);
exit(3);
}
} else {
// graphics demo
// paint
//draw_sine((float)t*0.03, fb);
if (t>500) {
draw_sine((float)t*0.025+1.0, fb, 0xff, 0x00, 0x00, fmaxf(0.0, fminf(1.0, (700-((float)t/1.6))/200.0)));
draw_sine((float)t*0.025, fb, 0x00, 0x00, 0xff, fmaxf(0.0, fminf(1.0, (700-((float)t/1.5))/200.0)));
draw_sine((float)t*0.025-1.0, fb, 0x00, 0xff, 0x00, fmaxf(0.0, fminf(1.0, (700-((float)t/1.2))/200.0)));
if (t>700) {
draw_box(fb, 0xff, 0xff, 0xff, fmaxf(0.0, fminf(1.0, (((float)t/1.5)-500.0)/200.0)));
}
} else {
draw_sine((float)t*0.025+1.0, fb, 0xff, 0x00, 0x00, fmaxf(0.0, fminf(1.0, (((float)t)-100)/200.0)));
draw_sine((float)t*0.025, fb, 0x00, 0x00, 0xff, fmaxf(0.0, fminf(1.0, (((float)t/1.2)-200)/200.0)));
draw_sine((float)t*0.025-1.0, fb, 0x00, 0xff, 0x00, fmaxf(0.0, fminf(1.0, (((float)t/1.1)-300)/200.0)));
}
}
// send our buffer to the keyboard, one line at a time
for (int row = 0; row < 6; row++) {
FILE* f = fopen(argv[1],"w");
if (!f) {
printf("Couldn't open %s. Try sudo.\n", argv[1]);
exit(1);
}
buf[5] = row;
memcpy(buf+6, fb+row*(COLS*3), COLS*3);
fwrite(buf, BUFSZ, 1, f);
fclose(f);
}
// if we're in bitmap file mode, exit now
if (argc == 3) exit(0);
// ~50 FPS
usleep(100*20);
// ~2 FPS
//usleep(1000*500);
t++;
}
}