diff --git a/pocket-reform-keyboard-fw/pocket-hid/CMakeLists.txt b/pocket-reform-keyboard-fw/pocket-hid/CMakeLists.txt index 2e9db5c..3cbf88b 100644 --- a/pocket-reform-keyboard-fw/pocket-hid/CMakeLists.txt +++ b/pocket-reform-keyboard-fw/pocket-hid/CMakeLists.txt @@ -16,6 +16,7 @@ add_executable(${PROJECT}) target_sources(${PROJECT} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src/main.c ${CMAKE_CURRENT_SOURCE_DIR}/src/usb_descriptors.c + ${CMAKE_CURRENT_SOURCE_DIR}/src/oled.c ) # Example include diff --git a/pocket-reform-keyboard-fw/pocket-hid/src/font.c b/pocket-reform-keyboard-fw/pocket-hid/src/font.c new file mode 100644 index 0000000..4cb722e --- /dev/null +++ b/pocket-reform-keyboard-fw/pocket-hid/src/font.c @@ -0,0 +1,259 @@ +const unsigned char font[] = { +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x5f, 0x00, 0x00, 0x00, +0x00, 0x07, 0x00, 0x00, 0x07, 0x00, +0x24, 0x7e, 0x24, 0x7e, 0x24, 0x00, +0x26, 0x49, 0x7f, 0x49, 0x32, 0x00, +0x00, 0x22, 0x10, 0x08, 0x44, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x04, 0x03, 0x00, 0x00, +0x00, 0x3e, 0x41, 0x41, 0x00, 0x00, +0x00, 0x41, 0x41, 0x3e, 0x00, 0x00, +0x2a, 0x1c, 0x3e, 0x1c, 0x2a, 0x00, +0x08, 0x08, 0x3e, 0x08, 0x08, 0x00, +0x00, 0x00, 0x40, 0x30, 0x00, 0x00, +0x08, 0x08, 0x08, 0x08, 0x08, 0x00, +0x00, 0x00, 0x40, 0x00, 0x00, 0x00, +0x20, 0x10, 0x08, 0x04, 0x02, 0x00, +0x3e, 0x51, 0x49, 0x45, 0x3e, 0x00, +0x08, 0x04, 0x02, 0x7f, 0x00, 0x00, +0x42, 0x61, 0x51, 0x49, 0x46, 0x00, +0x22, 0x41, 0x49, 0x49, 0x36, 0x00, +0x18, 0x14, 0x12, 0x7f, 0x10, 0x00, +0x2f, 0x49, 0x49, 0x49, 0x31, 0x00, +0x3e, 0x49, 0x49, 0x49, 0x31, 0x00, +0x41, 0x21, 0x11, 0x09, 0x07, 0x00, +0x36, 0x49, 0x49, 0x49, 0x36, 0x00, +0x26, 0x49, 0x49, 0x49, 0x3e, 0x00, +0x00, 0x00, 0x24, 0x00, 0x00, 0x00, +0x00, 0x00, 0x40, 0x34, 0x00, 0x00, +0x08, 0x14, 0x22, 0x41, 0x00, 0x00, +0x14, 0x14, 0x14, 0x14, 0x14, 0x00, +0x00, 0x41, 0x22, 0x14, 0x08, 0x00, +0x02, 0x01, 0x51, 0x09, 0x06, 0x00, +0x3e, 0x41, 0x4d, 0x51, 0x4e, 0x00, +0x7e, 0x09, 0x09, 0x09, 0x7e, 0x00, +0x7f, 0x49, 0x49, 0x49, 0x36, 0x00, +0x3e, 0x41, 0x41, 0x41, 0x41, 0x00, +0x7f, 0x41, 0x41, 0x41, 0x3e, 0x00, +0x7f, 0x49, 0x49, 0x49, 0x41, 0x00, +0x7f, 0x09, 0x09, 0x09, 0x01, 0x00, +0x3e, 0x41, 0x49, 0x49, 0x79, 0x00, +0x7f, 0x08, 0x08, 0x08, 0x7f, 0x00, +0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, +0x31, 0x41, 0x41, 0x41, 0x3f, 0x00, +0x7f, 0x08, 0x14, 0x22, 0x41, 0x00, +0x7f, 0x40, 0x40, 0x40, 0x40, 0x00, +0x7f, 0x02, 0x04, 0x02, 0x7f, 0x00, +0x7f, 0x02, 0x04, 0x08, 0x7f, 0x00, +0x3e, 0x41, 0x41, 0x41, 0x3e, 0x00, +0x7f, 0x09, 0x09, 0x09, 0x06, 0x00, +0x3e, 0x41, 0x51, 0x21, 0x5e, 0x00, +0x7f, 0x09, 0x09, 0x09, 0x76, 0x00, +0x26, 0x49, 0x49, 0x49, 0x32, 0x00, +0x01, 0x01, 0x7f, 0x01, 0x01, 0x00, +0x3f, 0x40, 0x40, 0x40, 0x3f, 0x00, +0x1f, 0x20, 0x40, 0x20, 0x1f, 0x00, +0x7f, 0x20, 0x10, 0x20, 0x7f, 0x00, +0x63, 0x14, 0x08, 0x14, 0x63, 0x00, +0x03, 0x04, 0x78, 0x04, 0x03, 0x00, +0x61, 0x51, 0x49, 0x45, 0x43, 0x00, +0x00, 0x7f, 0x41, 0x41, 0x00, 0x00, +0x02, 0x04, 0x08, 0x10, 0x20, 0x00, +0x00, 0x41, 0x41, 0x7f, 0x00, 0x00, +0x08, 0x04, 0x02, 0x04, 0x08, 0x00, +0x40, 0x40, 0x40, 0x40, 0x40, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x38, 0x44, 0x44, 0x48, 0x7c, 0x00, +0x7f, 0x44, 0x44, 0x44, 0x38, 0x00, +0x38, 0x44, 0x44, 0x44, 0x44, 0x00, +0x38, 0x44, 0x44, 0x44, 0x7f, 0x00, +0x38, 0x54, 0x54, 0x54, 0x48, 0x00, +0x04, 0x7e, 0x05, 0x05, 0x05, 0x00, +0x08, 0x54, 0x54, 0x54, 0x38, 0x00, +0x7f, 0x08, 0x04, 0x04, 0x78, 0x00, +0x00, 0x00, 0x7a, 0x00, 0x00, 0x00, +0x20, 0x40, 0x40, 0x40, 0x3a, 0x00, +0x7f, 0x08, 0x14, 0x22, 0x40, 0x00, +0x3f, 0x40, 0x40, 0x40, 0x40, 0x00, +0x7c, 0x04, 0x08, 0x04, 0x78, 0x00, +0x7c, 0x04, 0x04, 0x04, 0x78, 0x00, +0x38, 0x44, 0x44, 0x44, 0x38, 0x00, +0x7c, 0x24, 0x24, 0x24, 0x18, 0x00, +0x18, 0x24, 0x24, 0x24, 0x7c, 0x00, +0x7c, 0x08, 0x04, 0x04, 0x04, 0x00, +0x48, 0x54, 0x54, 0x54, 0x24, 0x00, +0x04, 0x3e, 0x44, 0x44, 0x44, 0x00, +0x3c, 0x40, 0x40, 0x40, 0x3c, 0x00, +0x1c, 0x20, 0x40, 0x20, 0x1c, 0x00, +0x3c, 0x40, 0x20, 0x40, 0x3c, 0x00, +0x44, 0x28, 0x10, 0x28, 0x44, 0x00, +0x4c, 0x50, 0x50, 0x20, 0x1c, 0x00, +0x44, 0x64, 0x54, 0x4c, 0x44, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x3c, 0x7e, 0x42, 0x42, 0x42, 0x42, +0x42, 0x42, 0x42, 0x42, 0x42, 0x7e, +0x3c, 0x7e, 0x42, 0x5a, 0x5a, 0x42, +0x42, 0x42, 0x42, 0x42, 0x42, 0x7e, +0x3c, 0x7e, 0x42, 0x5a, 0x5a, 0x5a, +0x5a, 0x42, 0x42, 0x42, 0x42, 0x7e, +0x3c, 0x7e, 0x42, 0x5a, 0x5a, 0x5a, +0x5a, 0x5a, 0x5a, 0x42, 0x42, 0x7e, +0x3c, 0x7e, 0x42, 0x5a, 0x5a, 0x5a, +0x5a, 0x5a, 0x5a, 0x5a, 0x42, 0x7e, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, +0xc0, 0x80, 0x00, 0xff, 0xfe, 0xfc, +0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00, +0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, +0xc0, 0x80, 0x00, 0xf0, 0xf0, 0xf0, +0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, +0xf0, 0xf0, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x3f, 0x3f, 0x3f, 0x3f, 0x07, 0x0f, +0x1f, 0x3f, 0x7f, 0xff, 0xff, 0xff, +0xff, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, +0xff, 0xff, 0xff, 0xff, 0x07, 0x0f, +0x1f, 0x3f, 0x7f, 0xff, 0xff, 0xff, +0xff, 0x00, 0x00, 0x00, 0xf0, 0xf0, +0x30, 0xb0, 0xb0, 0x70, 0xf0, 0x30, +0xb0, 0xb0, 0xb0, 0xf0, 0x70, 0xb0, +0xb0, 0xb0, 0xf0, 0x70, 0xb0, 0xb0, +0xb0, 0x70, 0xf0, 0x30, 0xb0, 0xb0, +0x70, 0xf0, 0x30, 0x70, 0xf0, 0xf0, +0xf0, 0x70, 0x30, 0xf0, 0xf0, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x03, +0x07, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x01, 0x03, 0x07, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x01, 0x03, +0x07, 0x00, 0x00, 0x00, 0x7f, 0x7f, +0x60, 0x7d, 0x7d, 0x62, 0x7f, 0x60, +0x6d, 0x6d, 0x6d, 0x7f, 0x60, 0x7d, +0x7d, 0x7f, 0x7f, 0x70, 0x6f, 0x6f, +0x6f, 0x70, 0x7f, 0x60, 0x7d, 0x7d, +0x62, 0x7f, 0x60, 0x7f, 0x7e, 0x7d, +0x7e, 0x7f, 0x60, 0x7f, 0x7f, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + +}; diff --git a/pocket-reform-keyboard-fw/pocket-hid/src/main.c b/pocket-reform-keyboard-fw/pocket-hid/src/main.c index 3baa4f6..9a72d7e 100644 --- a/pocket-reform-keyboard-fw/pocket-hid/src/main.c +++ b/pocket-reform-keyboard-fw/pocket-hid/src/main.c @@ -38,6 +38,7 @@ #include "hardware/irq.h" #include "usb_descriptors.h" +#include "oled.h" #define KBD_VARIANT_QWERTY_US #define KBD_COLS 12 @@ -204,6 +205,10 @@ int main(void) led_task(0x000000); }*/ + gfx_init(false); + gfx_poke_str(0, 0, "Hello Pocket!"); + gfx_flush(); + while (1) { pressed_keys = process_keyboard(pressed_scancodes); tud_task(); // tinyusb device task diff --git a/pocket-reform-keyboard-fw/pocket-hid/src/oled.c b/pocket-reform-keyboard-fw/pocket-hid/src/oled.c new file mode 100644 index 0000000..8d00ba2 --- /dev/null +++ b/pocket-reform-keyboard-fw/pocket-hid/src/oled.c @@ -0,0 +1,316 @@ +/* + MNT Reform 2.0 Keyboard Firmware + See keyboard.c for Copyright + SPDX-License-Identifier: MIT +*/ + +// OLED (SSD1306) rendering code. The OLED is interfaced via I2C. + +#include "oled.h" +#include "hardware/i2c.h" +#include +#include +#include "font.c" + +int oledbrt = 0; +struct CharacterMatrix display; + +// Write command sequence. +// Returns true on success. +static inline bool _send_cmd1(uint8_t cmd) { + char buf[] = {0x00, cmd}; + i2c_write_blocking(i2c0, SSD1306_ADDRESS, buf, 2, false); + return true; +} + +// Write 2-byte command sequence. +// Returns true on success +static inline bool _send_cmd2(uint8_t cmd, uint8_t opr) { + _send_cmd1(cmd); + _send_cmd1(opr); + return true; +} + +// Write 3-byte command sequence. +// Returns true on success +static inline bool _send_cmd3(uint8_t cmd, uint8_t opr1, uint8_t opr2) { + _send_cmd1(cmd); + _send_cmd1(opr1); + _send_cmd1(opr2); + return true; +} + +#define send_cmd1(c) if (!_send_cmd1(c)) {goto done;} +#define send_cmd2(c,o) if (!_send_cmd2(c,o)) {goto done;} +#define send_cmd3(c,o1,o2) if (!_send_cmd3(c,o1,o2)) {goto done;} + +static void clear_display(void) { + matrix_clear(&display); + + // Clear all of the display bits (there can be random noise + // in the RAM on startup) + send_cmd3(PageAddr, 0, (DisplayHeight / 8) - 1); + send_cmd3(ColumnAddr, 0, DisplayWidth - 1); + + char buf[1 + MatrixRows * DisplayWidth]; + + buf[0] = 0x40; + for (int i=0; icursor = c; + ++matrix->cursor; + + if (matrix->cursor - &matrix->display[0][0] == sizeof(matrix->display)) { + // We went off the end; scroll the display upwards by one line + memmove(&matrix->display[0], &matrix->display[1], + MatrixCols * (MatrixRows - 1)); + matrix->cursor = &matrix->display[MatrixRows - 1][0]; + memset(matrix->cursor, ' ', MatrixCols); + } +} + +void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c) { + matrix->dirty = true; + + if (c == '\n') { + // Clear to end of line from the cursor and then move to the + // start of the next line + uint8_t cursor_col = (matrix->cursor - &matrix->display[0][0]) % MatrixCols; + + while (cursor_col++ < MatrixCols) { + matrix_write_char_inner(matrix, ' '); + } + return; + } + + matrix_write_char_inner(matrix, c); +} + +void gfx_poke(uint8_t x, uint8_t y, uint8_t c) { + display.display[y][x] = c; +} + +void gfx_poke_str(uint8_t x, uint8_t y, char* str) { + int len = strlen(str); + if (len>21) len = 21; + // clip + if (y<0 || y>3) return; + + for (int xx=x; xx=0 && xx<21) { + display.display[y][xx] = (uint8_t)str[xx-x]; + } + } +} + +void gfx_write_char(uint8_t c) { + matrix_write_char(&display, c); +} + +void matrix_write(struct CharacterMatrix *matrix, const char *data) { + const char *end = data + strlen(data); + while (data < end) { + matrix_write_char(matrix, *data); + ++data; + } +} + +void matrix_write_ln(struct CharacterMatrix *matrix, const char *data) { + char data_ln[strlen(data)+2]; + snprintf(data_ln, sizeof(data_ln), "%s\n", data); + matrix_write(matrix, data_ln); +} + +void gfx_write(const char *data) { + matrix_write(&display, data); +} + +void matrix_write_P(struct CharacterMatrix *matrix, const char *data) { + while (true) { + uint8_t c = *data; + if (c == 0) { + return; + } + matrix_write_char(matrix, c); + ++data; + } +} + +void gfx_write_P(const char *data) { + matrix_write_P(&display, data); +} + +void matrix_clear(struct CharacterMatrix *matrix) { + memset(matrix->display, ' ', sizeof(matrix->display)); + matrix->cursor = &matrix->display[0][0]; + matrix->dirty = true; +} + +void gfx_clear_screen(void) { + matrix_clear(&display); +} + +void gfx_clear_invert(void) { + for (int y=0;y<4;y++) { + for (int x=0;x<21;x++) { + display.invert[y][x] = 0; + } + } +} + +void gfx_invert_row(uint8_t y) { + if (y<0 || y>3) return; + for (int x=0;x<21;x++) { + display.invert[y][x] = 1; + } +} + +void matrix_render(struct CharacterMatrix *matrix) { + gfx_on(); + + // Move to the home position + send_cmd3(PageAddr, 0, MatrixRows - 1); + send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1); + + char buf[1 + MatrixRows * DisplayWidth]; + buf[0] = 0x40; + + int i = 1; + for (uint8_t row = 0; row < MatrixRows; ++row) { + for (uint8_t col = 0; col < MatrixCols; ++col) { + const uint8_t *glyph = font + (matrix->display[row][col] * FontWidth); + const uint8_t invert = matrix->invert[row][col]; + + for (uint8_t glyphCol = 0; glyphCol < FontWidth; ++glyphCol) { + uint8_t colBits = *(glyph + glyphCol); + if (invert) colBits = ~colBits; + buf[i++] = colBits; + } + } + } + i2c_write_blocking(i2c0, SSD1306_ADDRESS, buf, 1 + MatrixRows * DisplayWidth, false); + + matrix->dirty = false; +done: + return; +} + +// bitmap[0] needs to be 0x40! +void matrix_render_direct(uint8_t* bitmap) { + gfx_on(); + + // Move to the home position + send_cmd3(PageAddr, 0, MatrixRows - 1); + send_cmd3(ColumnAddr, 0, (MatrixCols * FontWidth) - 1); + + bitmap[0] = 0x40; + i2c_write_blocking(i2c0, SSD1306_ADDRESS, bitmap, 1 + MatrixRows * DisplayWidth, false); + +done: + return; +} + +void gfx_flush(void) { + matrix_render(&display); +} + +void oled_brightness_inc(void) { + oledbrt+=10; + if (oledbrt>=0xff) oledbrt = 0xff; + gfx_contrast(oledbrt); +} + +void oled_brightness_dec(void) { + oledbrt-=10; + if (oledbrt<0) oledbrt = 0; + gfx_contrast(oledbrt); +} diff --git a/pocket-reform-keyboard-fw/pocket-hid/src/oled.h b/pocket-reform-keyboard-fw/pocket-hid/src/oled.h new file mode 100644 index 0000000..a733574 --- /dev/null +++ b/pocket-reform-keyboard-fw/pocket-hid/src/oled.h @@ -0,0 +1,99 @@ +/* + MNT Reform 2.0 Keyboard Firmware + See keyboard.c for Copyright + SPDX-License-Identifier: MIT +*/ + +#ifndef _OLED_H_ +#define _OLED_H_ + +#include +#include + +enum ssd1306_cmds { + DisplayOff = 0xAE, + DisplayOn = 0xAF, + + SetContrast = 0x81, + DisplayAllOnResume = 0xA4, + + DisplayAllOn = 0xA5, + NormalDisplay = 0xA6, + InvertDisplay = 0xA7, + SetDisplayOffset = 0xD3, + SetComPins = 0xda, + SetVComDetect = 0xdb, + SetDisplayClockDiv = 0xD5, + SetPreCharge = 0xd9, + SetMultiPlex = 0xa8, + SetLowColumn = 0x00, + SetHighColumn = 0x10, + SetStartLine = 0x40, + + SetMemoryMode = 0x20, + ColumnAddr = 0x21, + PageAddr = 0x22, + + ComScanInc = 0xc0, + ComScanDec = 0xc8, + SegRemap = 0xa0, + SetChargePump = 0x8d, + ExternalVcc = 0x01, + SwitchCapVcc = 0x02, + + ActivateScroll = 0x2f, + DeActivateScroll = 0x2e, + SetVerticalScrollArea = 0xa3, + RightHorizontalScroll = 0x26, + LeftHorizontalScroll = 0x27, + VerticalAndRightHorizontalScroll = 0x29, + VerticalAndLeftHorizontalScroll = 0x2a, +}; + +#define SSD1306_ADDRESS 0x3C + +#define DisplayHeight 32 +#define DisplayWidth 128 + +#define FontHeight 8 +#define FontWidth 6 + +#define MatrixRows (DisplayHeight / FontHeight) +#define MatrixCols (DisplayWidth / FontWidth) + +struct CharacterMatrix { + uint8_t display[MatrixRows][MatrixCols]; + uint8_t invert[MatrixRows][MatrixCols]; + uint8_t *cursor; + bool dirty; +}; + +void gfx_poke(uint8_t x, uint8_t y, uint8_t c); +void gfx_poke_str(uint8_t x, uint8_t y, char* str); +void gfx_clear_invert(void); +void gfx_invert_row(uint8_t y); +bool gfx_init(bool rotate); +void gfx_task(void); +bool gfx_off(void); +bool gfx_on(void); +void gfx_flush(void); +void gfx_clear(void); +void gfx_write_char(uint8_t c); +void gfx_write(const char *data); +void gfx_write_P(const char *data); +void gfx_clear_screen(void); +void gfx_contrast(int c); + +void matrix_clear(struct CharacterMatrix *matrix); +void matrix_write_char_inner(struct CharacterMatrix *matrix, uint8_t c); +void matrix_write_char(struct CharacterMatrix *matrix, uint8_t c); +void matrix_write(struct CharacterMatrix *matrix, const char *data); +void matrix_write_ln(struct CharacterMatrix *matrix, const char *data); +void matrix_write_P(struct CharacterMatrix *matrix, const char *data); +void matrix_render(struct CharacterMatrix *matrix); +void matrix_render_direct(uint8_t* bitmap); + +void oled_brightness_inc(void); +void oled_brightness_dec(void); + +#endif