/* kbdgfx.c -- Demo for drawing realtime graphics to the MNT Reform Keyboard Copyright 2022 MNT Research GmbH (https://mntre.com) License: MIT */ #include #include #include #include #include #include #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 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; x500) { 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++; } }