kbdgfx.c (2971B)
1 /* 2 kbdgfx.c -- Demo for drawing realtime graphics to the MNT Reform Keyboard 3 Copyright 2022 MNT Research GmbH (https://mntre.com) 4 License: MIT 5 */ 6 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <stdint.h> 11 #include <math.h> 12 #include <unistd.h> 13 14 #define ROWS 4 15 #define COLS 128 16 #define BUFSZ (5+COLS*ROWS) 17 #define FBUFSZ COLS*ROWS*8 18 19 // our unpacked, wasteful framebuffer (one byte per pixel, 128x32) 20 uint8_t fb[FBUFSZ]; 21 22 // the buffer we're sending to the keyboard (bit packed and column byte order) 23 uint8_t buf[BUFSZ]; 24 25 void oled_blit(uint8_t* src, uint8_t* dst) { 26 for (int y = 0; y < ROWS; y++) { 27 // right-to-left 28 for (int x = 0; x < COLS; x++) { 29 uint8_t column = 0; 30 31 for (int z = 0; z < 8; z++) { 32 // look up the pixel and threshold it to black and white at 127 33 uint8_t bit = src[((y * 8 + 7 - z)*COLS + x)] > 127; 34 35 // bitshift the column byte to the left to make room for new pixel 36 column <<= 1; 37 // OR the bit (the pixel) to the column byte 38 column |= bit; 39 } 40 41 // store in the destination buffer 42 dst[y*COLS + x] = column; 43 } 44 } 45 } 46 47 // unused 48 void fill_pattern(uint8_t bitpattern, uint8_t* dst) { 49 int i = 0; 50 for (int y = 0; y < 32; y++) { 51 for (int x = 0; x < COLS; x++) { 52 uint8_t pos = x % 8; 53 uint8_t b = bitpattern & (1<<pos); 54 55 dst[i++] = b ? 1 : 0; 56 } 57 } 58 } 59 60 void draw_sine(float t, uint8_t* dst) { 61 for (int x=0; x<128; x++) { 62 int y = 16 + sin(t + ((float)x/128.0 * 3.141))*12; 63 if (y < 0) y = 0; 64 if (y > 31) y = 31; 65 66 dst[y*COLS + x] = 0xff; 67 } 68 } 69 70 int main(int argc, char** argv) { 71 // just a counter 72 uint32_t t = 0; 73 74 if (argc < 2) { 75 printf("Usage: sudo kbdgfx /dev/hidraw0 [bitmap.raw]\n"); 76 exit(1); 77 } 78 79 // loop forever 80 while (1) { 81 FILE* f = fopen(argv[1],"w"); 82 83 if (!f) { 84 printf("Couldn't open %s. Try sudo.\n", argv[1]); 85 exit(1); 86 } 87 88 // start with the command 89 buf[0] = 'x'; 90 buf[1] = 'W'; 91 buf[2] = 'B'; 92 buf[3] = 'I'; 93 buf[4] = 'T'; 94 95 // clear 96 memset(fb, 0, FBUFSZ); 97 98 if (argc == 3) { 99 // read bitmap from file 100 FILE* bmf = fopen(argv[2],"r"); 101 if (!bmf) { 102 printf("Couldn't open bitmap %s!\n", argv[2]); 103 fclose(f); 104 exit(2); 105 } 106 107 int res = fread(fb, FBUFSZ, 1, bmf); 108 fclose(bmf); 109 110 if (res<1) { 111 printf("Couldn't read bitmap or wrong size.\n", argv[2]); 112 fclose(f); 113 exit(3); 114 } 115 } else { 116 // graphics demo 117 118 // paint 119 draw_sine((float)t*0.03, fb); 120 draw_sine((float)t*0.05, fb); 121 } 122 123 // convert to weird OLED buffer format 124 oled_blit(fb, buf+5); 125 126 // send our buffer to the keyboard 127 fwrite(buf, BUFSZ, 1, f); 128 129 fclose(f); 130 131 // if we're in bitmap file mode, exit now 132 if (argc == 3) exit(0); 133 134 // ~50 FPS 135 usleep(1000*20); 136 // ~2 FPS 137 //usleep(1000*500); 138 t++; 139 } 140 }