commit db1afb84ce837bd34bd410c26422ee9a0b8c5a4c
parent 650412076baf5c2024375044de12a56db911df5c
Author: Lukas F. Hartmann <lukas@mntre.com>
Date: Mon, 21 Feb 2022 18:48:21 +0100
Merge branch 'kbd-bitmaps' of source.mnt.re:reform/reform into kbd-bitmaps
Diffstat:
7 files changed, 179 insertions(+), 3 deletions(-)
diff --git a/reform2-keyboard-fw/kbdgfx-demo/build.sh b/reform2-keyboard-fw/kbdgfx-demo/build.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+gcc -O2 -o kbdgfx ./kbdgfx.c -lm
+
diff --git a/reform2-keyboard-fw/kbdgfx-demo/kbdgfx.c b/reform2-keyboard-fw/kbdgfx-demo/kbdgfx.c
@@ -0,0 +1,140 @@
+/*
+ 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 4
+#define COLS 126
+#define BUFSZ (5+COLS*ROWS)
+#define FBUFSZ COLS*ROWS*8
+
+// our unpacked, wasteful framebuffer (one byte per pixel, 126x32)
+uint8_t fb[FBUFSZ];
+
+// the buffer we're sending to the keyboard (bit packed and column byte order)
+uint8_t buf[BUFSZ];
+
+void oled_blit(uint8_t* src, uint8_t* dst) {
+ for (int y = 0; y < ROWS; y++) {
+ // right-to-left
+ for (int x = 0; x < COLS; x++) {
+ uint8_t column = 0;
+
+ for (int z = 0; z < 8; z++) {
+ // look up the pixel and threshold it to black and white at 127
+ uint8_t bit = src[((y * 8 + 7 - z)*COLS + x)] > 127;
+
+ // bitshift the column byte to the left to make room for new pixel
+ column <<= 1;
+ // OR the bit (the pixel) to the column byte
+ column |= bit;
+ }
+
+ // store in the destination buffer
+ dst[y*COLS + x] = column;
+ }
+ }
+}
+
+// unused
+void fill_pattern(uint8_t bitpattern, uint8_t* dst) {
+ int i = 0;
+ for (int y = 0; y < 32; y++) {
+ for (int x = 0; x < COLS; x++) {
+ uint8_t pos = x % 8;
+ uint8_t b = bitpattern & (1<<pos);
+
+ dst[i++] = b ? 1 : 0;
+ }
+ }
+}
+
+void draw_sine(float t, uint8_t* dst) {
+ for (int x=0; x<126; x++) {
+ int y = 16 + sin(t + ((float)x/126.0 * 3.141))*12;
+ if (y < 0) y = 0;
+ if (y > 31) y = 31;
+
+ dst[y*COLS + x] = 0xff;
+ }
+}
+
+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) {
+ FILE* f = fopen(argv[1],"w");
+
+ if (!f) {
+ printf("Couldn't open %s. Try sudo.\n", argv[1]);
+ exit(1);
+ }
+
+ // start with the command
+ buf[0] = 'x';
+ buf[1] = 'W';
+ buf[2] = 'B';
+ buf[3] = 'I';
+ buf[4] = 'T';
+
+ // 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]);
+ fclose(f);
+ 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]);
+ fclose(f);
+ exit(3);
+ }
+ } else {
+ // graphics demo
+
+ // paint
+ draw_sine((float)t*0.03, fb);
+ draw_sine((float)t*0.05, fb);
+ }
+
+ // convert to weird OLED buffer format
+ oled_blit(fb, buf+5);
+
+ // send our buffer to the keyboard
+ fwrite(buf, BUFSZ, 1, f);
+
+ fclose(f);
+
+ // if we're in bitmap file mode, exit now
+ if (argc == 3) exit(0);
+
+ // ~50 FPS
+ usleep(1000*20);
+ // ~2 FPS
+ //usleep(1000*500);
+ t++;
+ }
+}
diff --git a/reform2-keyboard-fw/kbdgfx-demo/picture-floyd.sh b/reform2-keyboard-fw/kbdgfx-demo/picture-floyd.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+# Usage: ./picture-floyd.sh /dev/hidraw3 picture.jpg
+
+#convert $2 -resize 126 -crop 126x32+0+0 -depth 8 -dither FloydSteinberg -remap pattern:gray50 gray:temp.bin
+
+convert $2 -resize 126 -gravity center -extent 126x32 -depth 8 -dither FloydSteinberg -remap pattern:gray50 gray:temp.bin
+sudo ./kbdgfx $1 ./temp.bin
+
diff --git a/reform2-keyboard-fw/kbdgfx-demo/picture.sh b/reform2-keyboard-fw/kbdgfx-demo/picture.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+# Usage: ./picture.sh /dev/hidraw3 picture.png
+
+convert $2 -resize 126 -gravity center -extent 126x32 -depth 8 gray:temp.bin
+sudo ./kbdgfx $1 ./temp.bin
+
diff --git a/reform2-keyboard-fw/kbdgfx-demo/text.sh b/reform2-keyboard-fw/kbdgfx-demo/text.sh
@@ -0,0 +1,7 @@
+#!/bin/bash
+
+# Usage: ./text.sh /dev/hidraw3 18 "hello world"
+
+convert -size 126x32 -background black -font Inter-Bold.ttf -pointsize $2 -fill white -gravity center caption:"$3" -depth 8 -flatten gray:temp.bin
+sudo ./kbdgfx $1 ./temp.bin
+
diff --git a/reform2-keyboard-fw/matrix.h b/reform2-keyboard-fw/matrix.h
@@ -22,7 +22,7 @@ uint8_t matrix[KBD_MATRIX_SZ] = {
// When holding down HYPER
uint8_t matrix_fn[KBD_MATRIX_SZ] = {
- // Media keys (not working, FIXME)
+ // Media keys on Hyper + F7-F12
KEY_ESCAPE,
KEY_F1,
KEY_F2,
diff --git a/reform2-keyboard-fw/menu.c b/reform2-keyboard-fw/menu.c
@@ -17,12 +17,13 @@ int current_menu_y = 0;
int current_scroll_y = 0;
#ifdef KBD_VARIANT_STANDALONE
-#define MENU_NUM_ITEMS 4
+#define MENU_NUM_ITEMS 5
const MenuItem menu_items[] = {
{ "Exit Menu ESC", KEY_ESCAPE },
{ "Key Backlight- F1", KEY_F1 },
{ "Key Backlight+ F2", KEY_F2 },
- { "System Status s", KEY_S }
+ { "System Status s", KEY_S },
+ { "USB Flashing Mode x", KEY_X },
};
#else
#define MENU_NUM_ITEMS 9
@@ -67,6 +68,11 @@ int execute_menu_function(int y) {
return execute_meta_function(KEY_ESCAPE);
}
+#define BOOTLOADER_START_ADDRESS ((0x8000-0x1000) >> 1)
+void jump_to_bootloader(void) {
+ ((void (*)(void))BOOTLOADER_START_ADDRESS)();
+}
+
// returns 1 for navigation function (stay in meta mode), 0 for terminal function
int execute_meta_function(int keycode) {
if (keycode == KEY_0) {
@@ -133,6 +139,9 @@ int execute_meta_function(int keycode) {
gfx_clear();
gfx_flush();
}
+ else if (keycode == KEY_X) {
+ jump_to_bootloader();
+ }
gfx_clear();
gfx_flush();