Skip to content

Commit 2d3bd7c

Browse files
authored
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.
1 parent 0ea72af commit 2d3bd7c

File tree

4 files changed

+87
-8
lines changed

4 files changed

+87
-8
lines changed

keyboards/cannonkeys/satisfaction75/config.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
7474
// configure oled driver for the 128x32 oled
7575
#define OLED_UPDATE_INTERVAL 66 // ~15fps
7676

77+
// OLED_TIMEOUT is incompatible with the OLED_OFF mode
78+
#define OLED_TIMEOUT 0
79+
80+
// OLED timeout reimplemented in the keyboard-specific code
81+
#define CUSTOM_OLED_TIMEOUT 60000
82+
7783
// Custom config starts after VIA's EEPROM usage,
7884
// dynamic keymaps start after this.
7985
// Custom config Usage:

keyboards/cannonkeys/satisfaction75/satisfaction75.c

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ uint8_t layer;
2323

2424
bool clock_set_mode = false;
2525
uint8_t oled_mode = OLED_DEFAULT;
26+
bool oled_repaint_requested = false;
27+
bool oled_wakeup_requested = false;
28+
uint32_t oled_sleep_timer;
2629

2730
uint8_t encoder_value = 32;
2831
uint8_t encoder_mode = ENC_MODE_VOLUME;
@@ -158,6 +161,7 @@ void raw_hid_receive_kb( uint8_t *data, uint8_t length )
158161
case id_oled_mode:
159162
{
160163
oled_mode = command_data[1];
164+
oled_request_wakeup();
161165
break;
162166
}
163167
case id_encoder_modes:
@@ -237,10 +241,12 @@ void read_host_led_state(void) {
237241
layer_state_t layer_state_set_kb(layer_state_t state) {
238242
state = layer_state_set_user(state);
239243
layer = biton32(state);
244+
oled_request_wakeup();
240245
return state;
241246
}
242247

243248
bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
249+
oled_request_wakeup();
244250
switch (keycode) {
245251
case OLED_TOGG:
246252
if(!clock_set_mode){
@@ -289,6 +295,7 @@ bool process_record_kb(uint16_t keycode, keyrecord_t *record) {
289295

290296
bool encoder_update_kb(uint8_t index, bool clockwise) {
291297
if (!encoder_update_user(index, clockwise)) return false;
298+
oled_request_wakeup();
292299
encoder_value = (encoder_value + (clockwise ? 1 : -1)) % 64;
293300
if (index == 0) {
294301
if (layer == 0){
@@ -364,6 +371,7 @@ void matrix_init_kb(void)
364371
rtcGetTime(&RTCD1, &last_timespec);
365372
backlight_init_ports();
366373
matrix_init_user();
374+
oled_request_wakeup();
367375
}
368376

369377

@@ -373,13 +381,7 @@ void housekeeping_task_kb(void) {
373381

374382
if (minutes_since_midnight != last_minute){
375383
last_minute = minutes_since_midnight;
376-
}
377-
378-
if((oled_mode == OLED_OFF) && is_oled_on()){
379-
oled_off();
380-
}
381-
if((oled_mode != OLED_OFF) && !is_oled_on()){
382-
oled_on();
384+
oled_request_repaint();
383385
}
384386
}
385387

keyboards/cannonkeys/satisfaction75/satisfaction75.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ extern uint8_t layer;
7272

7373
// OLED Behavior
7474
extern uint8_t oled_mode;
75+
extern bool oled_repaint_requested;
76+
extern bool oled_wakeup_requested;
77+
extern uint32_t oled_sleep_timer;
7578

7679
// Encoder Behavior
7780
extern uint8_t encoder_value;
@@ -107,6 +110,10 @@ void set_custom_encoder_config(uint8_t encoder_idx, uint8_t behavior, uint16_t n
107110

108111
void update_time_config(int8_t increment);
109112

113+
void oled_request_wakeup(void);
114+
void oled_request_repaint(void);
115+
bool oled_task_needs_to_repaint(void);
116+
110117
void backlight_init_ports(void);
111118
void backlight_set(uint8_t level);
112119
bool is_breathing(void);

keyboards/cannonkeys/satisfaction75/satisfaction_oled.c

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ void draw_clock(void);
88
__attribute__((weak)) oled_rotation_t oled_init_user(oled_rotation_t rotation) { return OLED_ROTATION_0; }
99

1010
__attribute__((weak)) void oled_task_user(void) {
11-
if (!is_oled_on()) {
11+
if (!oled_task_needs_to_repaint()) {
1212
return;
1313
}
1414
oled_clear();
@@ -27,6 +27,70 @@ __attribute__((weak)) void oled_task_user(void) {
2727
}
2828
}
2929

30+
// Request a repaint of the OLED image without resetting the OLED sleep timer.
31+
// Used for things like clock updates that should not keep the OLED turned on
32+
// if there is no other activity.
33+
void oled_request_repaint(void) {
34+
if (is_oled_on()) {
35+
oled_repaint_requested = true;
36+
}
37+
}
38+
39+
// Request a repaint of the OLED image and reset the OLED sleep timer.
40+
// Needs to be called after any activity that should keep the OLED turned on.
41+
void oled_request_wakeup(void) {
42+
oled_wakeup_requested = true;
43+
}
44+
45+
// Check whether oled_task_user() needs to repaint the OLED image. This
46+
// function should be called at the start of oled_task_user(); it also handles
47+
// the OLED sleep timer and the OLED_OFF mode.
48+
bool oled_task_needs_to_repaint(void) {
49+
// In the OLED_OFF mode the OLED is kept turned off; any wakeup requests
50+
// are ignored.
51+
if ((oled_mode == OLED_OFF) && !clock_set_mode) {
52+
oled_wakeup_requested = false;
53+
oled_repaint_requested = false;
54+
oled_off();
55+
return false;
56+
}
57+
58+
// If OLED wakeup was requested, reset the sleep timer and do a repaint.
59+
if (oled_wakeup_requested) {
60+
oled_wakeup_requested = false;
61+
oled_repaint_requested = false;
62+
oled_sleep_timer = timer_read32() + CUSTOM_OLED_TIMEOUT;
63+
oled_on();
64+
return true;
65+
}
66+
67+
// If OLED repaint was requested, just do a repaint without touching the
68+
// sleep timer.
69+
if (oled_repaint_requested) {
70+
oled_repaint_requested = false;
71+
return true;
72+
}
73+
74+
// If the OLED is currently off, skip the repaint (which would turn the
75+
// OLED on if the image is changed in any way).
76+
if (!is_oled_on()) {
77+
return false;
78+
}
79+
80+
// If the sleep timer has expired while the OLED was on, turn the OLED off.
81+
if (timer_expired32(timer_read32(), oled_sleep_timer)) {
82+
oled_off();
83+
return false;
84+
}
85+
86+
// Always perform a repaint if the OLED is currently on. (This can
87+
// potentially be optimized to avoid unneeded repaints if all possible
88+
// state changes are covered by oled_request_repaint() or
89+
// oled_request_wakeup(), but then any missed calls to these functions
90+
// would result in displaying a stale image.)
91+
return true;
92+
}
93+
3094

3195
static void draw_line_h(uint8_t x, uint8_t y, uint8_t len) {
3296
for (uint8_t i = 0; i < len; i++) {

0 commit comments

Comments
 (0)