reform

MNT Reform: Open Source Portable Computer
Log (Feed) | Files | Refs (Tags) | README

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 }