~ruther/qmk_firmware

2d3bd7cfcfd3418507a932f3aca7b7c77df07caa — Sergey Vlasov 3 years ago 0ea72af
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.
M keyboards/cannonkeys/satisfaction75/config.h => keyboards/cannonkeys/satisfaction75/config.h +6 -0
@@ 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:

M keyboards/cannonkeys/satisfaction75/satisfaction75.c => keyboards/cannonkeys/satisfaction75/satisfaction75.c +9 -7
@@ 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();
  }
}


M keyboards/cannonkeys/satisfaction75/satisfaction75.h => keyboards/cannonkeys/satisfaction75/satisfaction75.h +7 -0
@@ 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);

M keyboards/cannonkeys/satisfaction75/satisfaction_oled.c => keyboards/cannonkeys/satisfaction75/satisfaction_oled.c +65 -1
@@ 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++) {