summaryrefslogtreecommitdiff
path: root/keyboards/cannonkeys/lib/satisfaction75/satisfaction_oled.c
diff options
context:
space:
mode:
Diffstat (limited to 'keyboards/cannonkeys/lib/satisfaction75/satisfaction_oled.c')
-rw-r--r--keyboards/cannonkeys/lib/satisfaction75/satisfaction_oled.c279
1 files changed, 279 insertions, 0 deletions
diff --git a/keyboards/cannonkeys/lib/satisfaction75/satisfaction_oled.c b/keyboards/cannonkeys/lib/satisfaction75/satisfaction_oled.c
new file mode 100644
index 0000000000..18ae368e53
--- /dev/null
+++ b/keyboards/cannonkeys/lib/satisfaction75/satisfaction_oled.c
@@ -0,0 +1,279 @@
+// Copyright 2023 Andrew Kannan
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "satisfaction_core.h"
+#include <stdio.h>
+
+void draw_default(void);
+void draw_clock(void);
+
+#ifdef OLED_ENABLE
+
+oled_rotation_t oled_init_kb(oled_rotation_t rotation) { return OLED_ROTATION_0; }
+
+bool oled_task_kb(void) {
+ if (!oled_task_user()) { return false; }
+ if (!oled_task_needs_to_repaint()) {
+ return false;
+ }
+ oled_clear();
+ if (clock_set_mode) {
+ draw_clock();
+ return false;
+ }
+ switch (oled_mode) {
+ default:
+ case OLED_DEFAULT:
+ draw_default();
+ break;
+ case OLED_TIME:
+ draw_clock();
+ break;
+ }
+ return false;
+}
+
+// Request a repaint of the OLED image without resetting the OLED sleep timer.
+// Used for things like clock updates that should not keep the OLED turned on
+// if there is no other activity.
+void oled_request_repaint(void) {
+ if (is_oled_on()) {
+ oled_repaint_requested = true;
+ }
+}
+
+// Request a repaint of the OLED image and reset the OLED sleep timer.
+// Needs to be called after any activity that should keep the OLED turned on.
+void oled_request_wakeup(void) {
+ oled_wakeup_requested = true;
+}
+
+// Check whether oled_task_user() needs to repaint the OLED image. This
+// function should be called at the start of oled_task_user(); it also handles
+// the OLED sleep timer and the OLED_OFF mode.
+bool oled_task_needs_to_repaint(void) {
+ // In the OLED_OFF mode the OLED is kept turned off; any wakeup requests
+ // are ignored.
+ if ((oled_mode == OLED_OFF) && !clock_set_mode) {
+ oled_wakeup_requested = false;
+ oled_repaint_requested = false;
+ oled_off();
+ return false;
+ }
+
+ // If OLED wakeup was requested, reset the sleep timer and do a repaint.
+ if (oled_wakeup_requested) {
+ oled_wakeup_requested = false;
+ oled_repaint_requested = false;
+ oled_sleep_timer = timer_read32() + CUSTOM_OLED_TIMEOUT;
+ oled_on();
+ return true;
+ }
+
+ // If OLED repaint was requested, just do a repaint without touching the
+ // sleep timer.
+ if (oled_repaint_requested) {
+ oled_repaint_requested = false;
+ return true;
+ }
+
+ // If the OLED is currently off, skip the repaint (which would turn the
+ // OLED on if the image is changed in any way).
+ if (!is_oled_on()) {
+ return false;
+ }
+
+ // If the sleep timer has expired while the OLED was on, turn the OLED off.
+ if (timer_expired32(timer_read32(), oled_sleep_timer)) {
+ oled_off();
+ return false;
+ }
+
+ // Always perform a repaint if the OLED is currently on. (This can
+ // potentially be optimized to avoid unneeded repaints if all possible
+ // state changes are covered by oled_request_repaint() or
+ // oled_request_wakeup(), but then any missed calls to these functions
+ // would result in displaying a stale image.)
+ return true;
+}
+
+
+static void draw_line_h(uint8_t x, uint8_t y, uint8_t len) {
+ for (uint8_t i = 0; i < len; i++) {
+ oled_write_pixel(i + x, y, true);
+ }
+}
+
+static void draw_line_v(uint8_t x, uint8_t y, uint8_t len) {
+ for (uint8_t i = 0; i < len; i++) {
+ oled_write_pixel(x, i + y, true);
+ }
+}
+
+static char* get_enc_mode(void) {
+ switch (encoder_mode) {
+ default:
+ case ENC_MODE_VOLUME:
+ return "VOL";
+ case ENC_MODE_MEDIA:
+ return "MED";
+ case ENC_MODE_SCROLL:
+ return "SCR";
+ case ENC_MODE_BRIGHTNESS:
+ return "BRT";
+ case ENC_MODE_BACKLIGHT:
+ return "BKL";
+ case ENC_MODE_CLOCK_SET:
+ return "CLK";
+ case ENC_MODE_CUSTOM0:
+ return "CS0";
+ case ENC_MODE_CUSTOM1:
+ return "CS1";
+ case ENC_MODE_CUSTOM2:
+ return "CS2";
+ }
+}
+
+static char* get_time(void) {
+ uint8_t hour = last_minute / 60;
+ uint16_t minute = last_minute % 60;
+
+ if (encoder_mode == ENC_MODE_CLOCK_SET) {
+ hour = hour_config;
+ minute = minute_config;
+ }
+
+ bool is_pm = (hour / 12) > 0;
+ hour = hour % 12;
+ if (hour == 0) {
+ hour = 12;
+ }
+
+ static char time_str[8] = "";
+ snprintf(time_str, sizeof(time_str), "%02hhu:%02hu%s", hour, minute, is_pm ? "pm" : "am");
+
+ return time_str;
+}
+
+static char* get_date(void) {
+ int16_t year = last_timespec.year + 1980;
+ int8_t month = last_timespec.month;
+ int8_t day = last_timespec.day;
+
+ if (encoder_mode == ENC_MODE_CLOCK_SET) {
+ year = year_config + 1980;
+ month = month_config;
+ day = day_config;
+ }
+
+ static char date_str[11] = "";
+ snprintf(date_str, sizeof(date_str), "%04hd-%02hhd-%02hhd", year, month, day);
+
+ return date_str;
+}
+
+void draw_default(void) {
+ oled_write_P(PSTR("LAYER "), false);
+ oled_write_char(get_highest_layer(layer_state) + 0x30, true);
+
+ oled_write_P(PSTR(" ENC "), false);
+ oled_write(get_enc_mode(), true);
+
+ led_t led_state = host_keyboard_led_state();
+ oled_set_cursor(18, 0);
+ oled_write_P(PSTR("CAP"), led_state.caps_lock);
+ oled_set_cursor(18, 1);
+ oled_write_P(PSTR("SCR"), led_state.scroll_lock);
+
+ uint8_t mod_state = get_mods();
+ oled_set_cursor(6, 3);
+ oled_write_P(PSTR("S"), mod_state & MOD_MASK_SHIFT);
+ oled_advance_char();
+ oled_write_P(PSTR("C"), mod_state & MOD_MASK_CTRL);
+ oled_advance_char();
+ oled_write_P(PSTR("A"), mod_state & MOD_MASK_ALT);
+ oled_advance_char();
+ oled_write_P(PSTR("G"), mod_state & MOD_MASK_GUI);
+ oled_advance_char();
+
+ oled_write(get_time(), false);
+
+/* Matrix display is 12 x 12 pixels */
+#define MATRIX_DISPLAY_X 0
+#define MATRIX_DISPLAY_Y 18
+
+ // matrix
+ for (uint8_t x = 0; x < MATRIX_ROWS; x++) {
+ for (uint8_t y = 0; y < MATRIX_COLS; y++) {
+ bool on = (matrix_get_row(x) & (1 << y)) > 0;
+ oled_write_pixel(MATRIX_DISPLAY_X + y + 2, MATRIX_DISPLAY_Y + x + 2, on);
+ }
+ }
+
+ // outline
+ draw_line_h(MATRIX_DISPLAY_X, MATRIX_DISPLAY_Y, 19);
+ draw_line_h(MATRIX_DISPLAY_X, MATRIX_DISPLAY_Y + 9, 19);
+ draw_line_v(MATRIX_DISPLAY_X, MATRIX_DISPLAY_Y, 9);
+ draw_line_v(MATRIX_DISPLAY_X + 19, MATRIX_DISPLAY_Y, 9);
+
+ // oled location
+ draw_line_h(MATRIX_DISPLAY_X + 14, MATRIX_DISPLAY_Y + 2, 3);
+
+ // bodge extra lines for invert layer and enc mode
+ draw_line_v(35, 0, 8);
+ draw_line_v(71, 0, 8);
+}
+
+void draw_clock(void) {
+ oled_set_cursor(0, 0);
+ oled_write(get_date(), false);
+ oled_set_cursor(0, 2);
+ oled_write(get_time(), false);
+
+ oled_set_cursor(12, 0);
+ oled_write_P(PSTR(" ENC "), false);
+ oled_write(get_enc_mode(), true);
+
+ oled_set_cursor(13, 1);
+ oled_write_P(PSTR("LAYER "), false);
+ oled_write_char(get_highest_layer(layer_state) + 0x30, true);
+
+ led_t led_state = host_keyboard_led_state();
+ oled_set_cursor(15, 3);
+ oled_write_P(PSTR("CAPS"), led_state.caps_lock);
+
+ if (clock_set_mode) {
+ switch (time_config_idx) {
+ case 0: // hour
+ default:
+ draw_line_h(0, 25, 10);
+ break;
+ case 1: // minute
+ draw_line_h(18, 25, 10);
+ break;
+ case 2: // year
+ draw_line_h(0, 9, 24);
+ break;
+ case 3: // month
+ draw_line_h(30, 9, 10);
+ break;
+ case 4: // day
+ draw_line_h(48, 9, 10);
+ break;
+ }
+ }
+
+ // bodge extra lines for invert layer and enc mode
+ draw_line_v(101, 0, 8);
+ draw_line_v(113, 8, 8);
+}
+
+#else
+
+void oled_request_repaint(void){
+}
+
+void oled_request_wakeup(void){
+}
+
+#endif \ No newline at end of file