summary refs log tree commit diff
diff options
context:
space:
mode:
authorSergey Vlasov <sigprof@gmail.com>2021-10-10 19:01:29 +0300
committerGitHub <noreply@github.com>2021-10-10 17:01:29 +0100
commit2d3bd7cfcfd3418507a932f3aca7b7c77df07caa (patch)
tree345d092f6d65b507c590d2d75099f3b93397a54a
parent0ea72af8b79c9084105f467f764161a7b53d9612 (diff)
Fix OLED timeout on satisfaction75 after migration from QWIIC (#14780)
The custom OLED_OFF mode implemented on satisfaction75 is incompatible
with the OLED_TIMEOUT feature (the OLED_TIMEOUT code assumes that any
key or encoder action should turn the OLED display on, and does not
provide any way to disable that behavior).  To keep the OLED_OFF mode
functioning as before while still having a working OLED idle timeout, a
custom implementation of the OLED idle timeout code is added.
-rw-r--r--keyboards/cannonkeys/satisfaction75/config.h6
-rw-r--r--keyboards/cannonkeys/satisfaction75/satisfaction75.c16
-rw-r--r--keyboards/cannonkeys/satisfaction75/satisfaction75.h7
-rw-r--r--keyboards/cannonkeys/satisfaction75/satisfaction_oled.c66
4 files changed, 87 insertions, 8 deletions
diff --git a/keyboards/cannonkeys/satisfaction75/config.h b/keyboards/cannonkeys/satisfaction75/config.h
index 7fca7226b1..53e4c18e5e 100644
--- a/keyboards/cannonkeys/satisfaction75/config.h
+++ b/keyboards/cannonkeys/satisfaction75/config.h
@@ -74,6 +74,12 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 // configure oled driver for the 128x32 oled
 #define OLED_UPDATE_INTERVAL 66 // ~15fps
 
+// OLED_TIMEOUT is incompatible with the OLED_OFF mode
+#define OLED_TIMEOUT 0
+
+// OLED timeout reimplemented in the keyboard-specific code
+#define CUSTOM_OLED_TIMEOUT 60000
+
 // Custom config starts after VIA's EEPROM usage,
 // dynamic keymaps start after this.
 // Custom config Usage:
diff --git a/keyboards/cannonkeys/satisfaction75/satisfaction75.c b/keyboards/cannonkeys/satisfaction75/satisfaction75.c
index 304df33258..8b5016437c 100644
--- a/keyboards/cannonkeys/satisfaction75/satisfaction75.c
+++ b/keyboards/cannonkeys/satisfaction75/satisfaction75.c
@@ -23,6 +23,9 @@ uint8_t layer;
 
 bool clock_set_mode = false;
 uint8_t oled_mode = OLED_DEFAULT;
+bool oled_repaint_requested = false;
+bool oled_wakeup_requested = false;
+uint32_t oled_sleep_timer;
 
 uint8_t encoder_value = 32;
 uint8_t encoder_mode = ENC_MODE_VOLUME;
@@ -158,6 +161,7 @@ void raw_hid_receive_kb( uint8_t *data, uint8_t length )
         case id_oled_mode:
         {
           oled_mode = command_data[1];
+          oled_request_wakeup();
           break;
         }
         case id_encoder_modes:
@@ -237,10 +241,12 @@ void read_host_led_state(void) {
 layer_state_t layer_state_set_kb(layer_state_t state) {
   state = layer_state_set_user(state);
   layer = biton32(state);
+  oled_request_wakeup();
   return state;
 }
 
 bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
+  oled_request_wakeup();
   switch (keycode) {
     case OLED_TOGG:
       if(!clock_set_mode){
@@ -289,6 +295,7 @@ bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
 
 bool encoder_update_kb(uint8_t index, bool clockwise) {
     if (!encoder_update_user(index, clockwise)) return false;
+    oled_request_wakeup();
   encoder_value = (encoder_value + (clockwise ? 1 : -1)) % 64;
   if (index == 0) {
     if (layer == 0){
@@ -364,6 +371,7 @@ void matrix_init_kb(void)
   rtcGetTime(&RTCD1, &last_timespec);
   backlight_init_ports();
   matrix_init_user();
+  oled_request_wakeup();
 }
 
 
@@ -373,13 +381,7 @@ void housekeeping_task_kb(void) {
 
   if (minutes_since_midnight != last_minute){
     last_minute = minutes_since_midnight;
-  }
-
-  if((oled_mode == OLED_OFF) && is_oled_on()){
-      oled_off();
-  }
-  if((oled_mode != OLED_OFF) && !is_oled_on()){
-      oled_on();
+    oled_request_repaint();
   }
 }
 
diff --git a/keyboards/cannonkeys/satisfaction75/satisfaction75.h b/keyboards/cannonkeys/satisfaction75/satisfaction75.h
index 9d20dd9c93..c6dbc31f1b 100644
--- a/keyboards/cannonkeys/satisfaction75/satisfaction75.h
+++ b/keyboards/cannonkeys/satisfaction75/satisfaction75.h
@@ -72,6 +72,9 @@ extern uint8_t layer;
 
 // OLED Behavior
 extern uint8_t oled_mode;
+extern bool oled_repaint_requested;
+extern bool oled_wakeup_requested;
+extern uint32_t oled_sleep_timer;
 
 // Encoder Behavior
 extern uint8_t encoder_value;
@@ -107,6 +110,10 @@ void set_custom_encoder_config(uint8_t encoder_idx, uint8_t behavior, uint16_t n
 
 void update_time_config(int8_t increment);
 
+void oled_request_wakeup(void);
+void oled_request_repaint(void);
+bool oled_task_needs_to_repaint(void);
+
 void backlight_init_ports(void);
 void backlight_set(uint8_t level);
 bool is_breathing(void);
diff --git a/keyboards/cannonkeys/satisfaction75/satisfaction_oled.c b/keyboards/cannonkeys/satisfaction75/satisfaction_oled.c
index 9589ecea86..443482eace 100644
--- a/keyboards/cannonkeys/satisfaction75/satisfaction_oled.c
+++ b/keyboards/cannonkeys/satisfaction75/satisfaction_oled.c
@@ -8,7 +8,7 @@ void draw_clock(void);
 __attribute__((weak)) oled_rotation_t oled_init_user(oled_rotation_t rotation) { return OLED_ROTATION_0; }
 
 __attribute__((weak)) void oled_task_user(void) {
-    if (!is_oled_on()) {
+    if (!oled_task_needs_to_repaint()) {
         return;
     }
     oled_clear();
@@ -27,6 +27,70 @@ __attribute__((weak)) void oled_task_user(void) {
     }
 }
 
+// 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++) {