From d80063ff513969f622a6cffd1a9d074ccc3cfa24 Mon Sep 17 00:00:00 2001
From: Pete Johanson <peter@peterjohanson.com>
Date: Fri, 24 Jul 2020 16:39:11 -0400
Subject: [PATCH] Initial display support.

---
 app/CMakeLists.txt                         |  1 +
 app/Kconfig                                | 10 +++-
 app/boards/shields/kyria/Kconfig.defconfig | 44 +++++++++++++++++
 app/boards/shields/kyria/kyria.dtsi        | 18 ++++++-
 app/include/zmk/display.h                  | 10 ++++
 app/src/display.c                          | 56 ++++++++++++++++++++++
 app/src/main.c                             | 10 +++-
 7 files changed, 145 insertions(+), 4 deletions(-)
 create mode 100644 app/include/zmk/display.h
 create mode 100644 app/src/display.c

diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt
index 45c68856..73b15341 100644
--- a/app/CMakeLists.txt
+++ b/app/CMakeLists.txt
@@ -33,6 +33,7 @@ target_sources(app PRIVATE src/keymap.c)
 target_sources(app PRIVATE src/hid_listener.c)
 target_sources(app PRIVATE src/hid.c)
 target_sources(app PRIVATE src/sensors.c)
+target_sources_ifdef(CONFIG_ZMK_DISPLAY app PRIVATE src/display.c)
 target_sources(app PRIVATE src/event_manager.c)
 target_sources(app PRIVATE src/events/position_state_changed.c)
 target_sources(app PRIVATE src/events/keycode_state_changed.c)
diff --git a/app/Kconfig b/app/Kconfig
index 21cc91c7..e86198e6 100644
--- a/app/Kconfig
+++ b/app/Kconfig
@@ -67,6 +67,14 @@ endif
 
 endmenu
 
+config ZMK_DISPLAY
+	bool "ZMK display support"
+	default n
+	select DISPLAY
+	select LVGL
+	select LVGL_THEMES
+	select LVGL_THEME_MONO
+	select LVGL_OBJ_LABEL
 
 menu "Split Support"
 
@@ -139,7 +147,7 @@ config ZMK_ACTION_MOD_TAP
 endmenu
 
 config HEAP_MEM_POOL_SIZE
-	default 1024
+	default 8192
 
 config KERNEL_BIN_NAME
 	default "zmk"
diff --git a/app/boards/shields/kyria/Kconfig.defconfig b/app/boards/shields/kyria/Kconfig.defconfig
index bc0a7b82..b7d6a437 100644
--- a/app/boards/shields/kyria/Kconfig.defconfig
+++ b/app/boards/shields/kyria/Kconfig.defconfig
@@ -19,4 +19,48 @@ if SHIELD_KYRIA_LEFT || SHIELD_KYRIA_RIGHT
 config ZMK_SPLIT
 	default y
 
+config EC11
+	default y
+
+if EC11
+
+choice EC11_TRIGGER
+	default EC11_TRIGGER_GLOBAL_THREAD
+endchoice
+
+endif
+
+if ZMK_DISPLAY
+
+config I2C
+	default y
+
+config SSD1306
+	default y
+
+endif # ZMK_DISPLAY
+
+if LVGL
+
+config LVGL_HOR_RES
+	default 128
+
+config LVGL_VER_RES
+	default 64
+
+config LVGL_VDB_SIZE
+	default 64
+
+config LVGL_DPI
+	default 148
+
+config LVGL_BITS_PER_PIXEL
+	default 1
+
+choice LVGL_COLOR_DEPTH
+	default LVGL_COLOR_DEPTH_1
+endchoice
+
+endif # LVGL
+
 endif
diff --git a/app/boards/shields/kyria/kyria.dtsi b/app/boards/shields/kyria/kyria.dtsi
index 89fc70ff..bbead846 100644
--- a/app/boards/shields/kyria/kyria.dtsi
+++ b/app/boards/shields/kyria/kyria.dtsi
@@ -81,8 +81,22 @@ RC(2,0) RC(2,1) RC(2,2) RC(2,3) RC(2,4) RC(2,5) RC(2,6) RC(2,7) RC(2,8) RC(2,9)
 		sensors = <&left_encoder &right_encoder>;
 	};
 
-	// TODO: Encoder node(s)
-	// TODO: OLED node
 	// TODO: RGB node(s)
 };
 
+&pro_micro_i2c {
+	status = "okay";
+
+	ssd1306@3c {
+		compatible = "solomon,ssd1306fb";
+		reg = <0x3c>;
+		label = "DISPLAY";
+		width = <128>;
+		height = <64>;
+		segment-offset = <0>;
+		page-offset = <0>;
+		display-offset = <0>;
+		multiplex-ratio = <63>;
+		prechargep = <0x22>;
+	};
+};
diff --git a/app/include/zmk/display.h b/app/include/zmk/display.h
new file mode 100644
index 00000000..93ac3ffd
--- /dev/null
+++ b/app/include/zmk/display.h
@@ -0,0 +1,10 @@
+/*
+ * Copyright (c) 2020 Peter Johanson <peter@peterjohanson.com>
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#pragma once
+
+int zmk_display_init();
+void zmk_display_task_handler();
\ No newline at end of file
diff --git a/app/src/display.c b/app/src/display.c
new file mode 100644
index 00000000..9021914f
--- /dev/null
+++ b/app/src/display.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2020 Peter Johanson
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include <init.h>
+#include <device.h>
+#include <devicetree.h>
+
+#include <logging/log.h>
+LOG_MODULE_DECLARE(zmk, CONFIG_ZMK_LOG_LEVEL);
+
+#include <drivers/display.h>
+#include <lvgl.h>
+
+#define ZMK_DISPLAY_NAME CONFIG_LVGL_DISPLAY_DEV_NAME
+
+static struct device *display;
+
+static lv_obj_t *screen;
+
+int zmk_display_init()
+{
+    lv_obj_t *hello_world_label;
+    lv_obj_t *count_label;
+
+    LOG_DBG("");
+
+    display = device_get_binding(ZMK_DISPLAY_NAME);
+    if (display == NULL) {
+        LOG_ERR("Failed to find display device");
+        return -EINVAL;
+    }
+
+    screen = lv_obj_create(NULL, NULL);
+    lv_scr_load(screen);
+
+    hello_world_label = lv_label_create(lv_scr_act(), NULL);
+    lv_label_set_text(hello_world_label, "ZMK v0.1.0");
+    lv_obj_align(hello_world_label, NULL, LV_ALIGN_CENTER, 0, 0);
+    count_label = lv_label_create(lv_scr_act(), NULL);
+    lv_label_set_text(count_label, CONFIG_ZMK_KEYBOARD_NAME);
+    lv_obj_align(count_label, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
+    lv_task_handler();
+    display_blanking_off(display);
+
+    return 0;
+}
+
+void zmk_display_task_handler()
+{
+    lv_tick_inc(10);
+    lv_task_handler();
+    k_sleep(K_MSEC(10));
+}
diff --git a/app/src/main.c b/app/src/main.c
index 5f28158e..5a678ee0 100644
--- a/app/src/main.c
+++ b/app/src/main.c
@@ -14,7 +14,7 @@ LOG_MODULE_REGISTER(zmk, CONFIG_ZMK_LOG_LEVEL);
 
 #include <zmk/matrix.h>
 #include <zmk/kscan.h>
-#include <zmk/endpoints.h>
+#include <zmk/display.h>
 
 #define ZMK_KSCAN_DEV DT_LABEL(ZMK_MATRIX_NODE_ID)
 
@@ -26,4 +26,12 @@ void main(void)
 	{
 		return;
 	}
+
+#ifdef CONFIG_ZMK_DISPLAY
+	zmk_display_init();
+
+	while (1) {
+		zmk_display_task_handler();
+	}
+#endif /* CONFIG_ZMK_DISPLAY */
 }