~ruther/qmk_firmware

5d775d51d092bc536df6a5bbdac6c56fe3547316 — Casey Borders 2 years ago 2e5bf25
Pomodoro Timer in Lily58 (#21215)

A keyboards/lily58/keymaps/pomodoro/config.h => keyboards/lily58/keymaps/pomodoro/config.h +56 -0
@@ 0,0 1,56 @@
/*
This is the c configuration file for the keymap

Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2015 Jack Humbert

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#pragma once

/* Select hand configuration */

#define MASTER_LEFT
// #define MASTER_RIGHT
// #define EE_HANDS

#define QUICK_TAP_TERM 0
#define TAPPING_TERM 100

#undef RGBLED_NUM
#define RGBLIGHT_EFFECT_BREATHING
#define RGBLIGHT_EFFECT_RAINBOW_MOOD
#define RGBLIGHT_EFFECT_RAINBOW_SWIRL
#define RGBLIGHT_EFFECT_SNAKE
#define RGBLIGHT_EFFECT_KNIGHT
#define RGBLIGHT_EFFECT_CHRISTMAS
#define RGBLIGHT_EFFECT_STATIC_GRADIENT
#define RGBLIGHT_EFFECT_RGB_TEST
#define RGBLIGHT_EFFECT_ALTERNATING
#define RGBLIGHT_EFFECT_TWINKLE
#define RGBLED_NUM 27
#define RGBLIGHT_LIMIT_VAL 120
#define RGBLIGHT_HUE_STEP 10
#define RGBLIGHT_SAT_STEP 17
#define RGBLIGHT_VAL_STEP 17

#define SPLIT_TRANSACTION_IDS_USER SYNC_POMODORO_RUNNING

// Underglow
/*
#undef RGBLED_NUM
#define RGBLED_NUM 14    // Number of LEDs
#define RGBLIGHT_SLEEP
*/

A keyboards/lily58/keymaps/pomodoro/keymap.c => keyboards/lily58/keymaps/pomodoro/keymap.c +154 -0
@@ 0,0 1,154 @@
/*
Copyright 2023 Casey Borders

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include QMK_KEYBOARD_H

enum layer_number {
    _QWERTY = 0,
    _LOWER,
    _RAISE,
    _ADJUST,
};

const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
    /* QWERTY
     * ,-----------------------------------------.                    ,-----------------------------------------.
     * | ESC  |   1  |   2  |   3  |   4  |   5  |                    |   6  |   7  |   8  |   9  |   0  |Backsp|
     * |------+------+------+------+------+------|                    |------+------+------+------+------+------|
     * | Tab  |   Q  |   W  |   E  |   R  |   T  |                    |   Y  |   U  |   I  |   O  |   P  |  -   |
     * |------+------+------+------+------+------|                    |------+------+------+------+------+------|
     * |LCTRL |   A  |   S  |   D  |   F  |   G  |-------.    ,-------|   H  |   J  |   K  |   L  |   ;  |  '   |
     * |------+------+------+------+------+------|   [   |    |    ]  |------+------+------+------+------+------|
     * |LShift|   Z  |   X  |   C  |   V  |   B  |-------|    |-------|   N  |   M  |   ,  |   .  |   /  |RShift|
     * `-----------------------------------------/       /     \      \-----------------------------------------'
     *                   | Play |LOWER | LGUI | / Enter /       \Space \  | RGUI |RAISE | Mute |
     *                   |      |      |      |/       /         \      \ |      |      |      |
     *                   `----------------------------'           '------''--------------------'
     */
    [_QWERTY] = LAYOUT(
      KC_ESC,    KC_1,    KC_2,    KC_3,    KC_4,    KC_5,                             KC_6,    KC_7,    KC_8,    KC_9,     KC_0, KC_BSPC,
      KC_TAB,    KC_Q,    KC_W,    KC_E,    KC_R,    KC_T,                             KC_Y,    KC_U,    KC_I,    KC_O,     KC_P, KC_MINS,
      KC_LCTL,   KC_A,    KC_S,    KC_D,    KC_F,    KC_G,                             KC_H,    KC_J,    KC_K,    KC_L,  KC_SCLN, KC_QUOT,
      KC_LSFT,   KC_Z,    KC_X,    KC_C,    KC_V,    KC_B, KC_LBRC,        KC_RBRC,    KC_N,    KC_M, KC_COMM,  KC_DOT,  KC_SLSH, KC_RSFT,
                             KC_MPLY, MO(_LOWER), KC_LGUI,  KC_ENT,        KC_SPC, KC_RGUI, MO(_RAISE), KC_MUTE
    ),
    /* LOWER
     * ,-----------------------------------------.                    ,-----------------------------------------.
     * |      |      |      |      |      |      |                    |      |      |      |      |      |      |
     * |------+------+------+------+------+------|                    |------+------+------+------+------+------|
     * |      |      |      |      |      |      |                    |      |      |  Up  |      |   \  |      |
     * |------+------+------+------+------+------|                    |------+------+------+------+------+------|
     * |      |      |      |      |      |      |-------.    ,-------|      | Left | Down |Right |   =  |      |
     * |------+------+------+------+------+------|   <   |    |   >   |------+------+------+------+------+------|
     * |      |      |      |      |      |      |-------|    |-------|      |      |      |      |      |      |
     * `-----------------------------------------/       /     \      \-----------------------------------------'
     *                   | Play |LOWER | LGUI | / Enter /       \Space \  | RGUI |RAISE | Mute |
     *                   |      |      |      |/       /         \      \ |      |      |      |
     *                   `----------------------------'           '------''--------------------'
     */
    [_LOWER] = LAYOUT(
      _______, _______, _______, _______, _______, _______,                          _______, _______, _______, _______, _______, _______,
      _______, _______, _______, _______, _______, _______,                          _______, _______,   KC_UP, _______, _______, _______,
      _______, _______, _______, _______, _______, _______,                          _______, KC_LEFT, KC_DOWN, KC_RIGHT, _______, _______,
      _______, _______, _______, _______, _______, _______,   KC_LT,        KC_GT,   _______, _______, _______, _______, _______, _______,
                                 _______, _______, _______, _______,        _______, _______, _______, _______

    ),
    /* RAISE
     * ,-----------------------------------------.                    ,-----------------------------------------.
     * |   `  |  F1  |  F2  |  F3  |  F4  |  F5  |                    |  F6  |  F7  |  F8  |  F9  | F10  | F11  |
     * |------+------+------+------+------+------|                    |------+------+------+------+------+------|
     * |      |      | Vol+ |      |      |      |                    |      |      |      |      |      |      |
     * |------+------+------+------+------+------|                    |------+------+------+------+------+------|
     * |      | Prev | Vol- | Next |      |      |-------.    ,-------|      |      |      |      |      |      |
     * |------+------+------+------+------+------|       |    |       |------+------+------+------+------+------|
     * |      |      |      |      |      |      |-------|    |-------|      |      |      |      |      |      |
     * `-----------------------------------------/       /     \      \-----------------------------------------'
     *                   | Play |LOWER | LGUI | / Enter /       \Space \  | RGUI |RAISE | Mute |
     *                   |      |      |      |/       /         \      \ |      |      |      |
     *                   `----------------------------'           '------''--------------------'
     */
    [_RAISE] = LAYOUT(
       KC_GRV,   KC_F1,   KC_F2,   KC_F3,   KC_F4,   KC_F5,                            KC_F6,   KC_F7,   KC_F8,   KC_F9,  KC_F10,  KC_F12,
      _______, _______, KC_VOLU, _______, _______, _______,                          _______, _______,   KC_UP, _______, _______, _______,
      _______, KC_MPRV, KC_VOLD, KC_MNXT, _______, _______,                          _______, _______, _______, _______, _______, _______,
      _______, _______, _______, _______, _______, _______,   KC_LT,        KC_GT,   _______, _______, _______, _______, _______, _______,
                                 _______, _______, _______, _______,        _______, _______, _______, _______

    ),
    /* ADJUST
     * ,-----------------------------------------.                    ,-----------------------------------------.
     * |      |      |      |      |      |      |                    |      |      |      |      |      |      |
     * |------+------+------+------+------+------|                    |------+------+------+------+------+------|
     * |      |      |      |      |      |      |                    |      |      |      |      | Oper | Out  |
     * |------+------+------+------+------+------|                    |------+------+------+------+------+------|
     * |      |      |      |      |      |      |-------.    ,-------|      |      |      |      |      |      |
     * |------+------+------+------+------+------|       |    |       |------+------+------+------+------+------|
     * |      |      |      |      |      |      |-------|    |-------|      |      |      |      |      |      |
     * `-----------------------------------------/       /     \      \-----------------------------------------'
     *                   | Play |LOWER | LGUI | / Enter /       \Space \  | RGUI |RAISE | Mute |
     *                   |      |      |      |/       /         \      \ |      |      |      |
     *                   `----------------------------'           '------''--------------------'
     */
    [_ADJUST] = LAYOUT(
      _______, _______, _______, _______, _______, _______,                          _______, _______, _______, _______, _______, _______,
      _______, _______, _______, _______, _______, _______,                          _______, _______, _______, _______, KC_OPER,  KC_OUT,
      _______, _______, _______, _______, _______, _______,                          _______, _______, _______, _______, _______, _______,
      _______, _______, _______, _______, _______, _______, _______,        _______, _______, _______, _______, _______, _______, _______,
                                 _______, _______, _______, _______,        _______, _______, _______, _______
    )
};

layer_state_t layer_state_set_user(layer_state_t state) {
    return update_tri_layer_state(state, _LOWER, _RAISE, _ADJUST);
}

// SSD1306 OLED update loop, make sure to enable OLED_ENABLE=yes in rules.mk
#ifdef OLED_ENABLE

// When you add source files to SRC in rules.mk, you can use functions.
const char *read_layer_state(void);
const char *read_logo(void);
const char *read_timelog(void);

void toggle_pomodoro(void);
const char* read_pomodoro_running(void);
void update_pomodoro_display(void);

oled_rotation_t oled_init_user(oled_rotation_t rotation) {
    if (!is_keyboard_master())
        return OLED_ROTATION_90;
    return rotation;
}

bool oled_task_user(void) {
    if (is_keyboard_master()) {
        oled_write_ln(read_layer_state(), false);
        oled_write_ln(read_pomodoro_running(), false);
    } else {
        update_pomodoro_display();
    }
    return false;
}

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    if (record->event.pressed && keycode == KC_OPER) {
        toggle_pomodoro();
    }
    return true;
}

#endif // OLED_ENABLE

A keyboards/lily58/keymaps/pomodoro/pomodoro.c => keyboards/lily58/keymaps/pomodoro/pomodoro.c +249 -0
@@ 0,0 1,249 @@
/*
Copyright 2023 Casey Borders

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include QMK_KEYBOARD_H

#include <string.h>

#include "transactions.h"

#ifdef OLED_ENABLE

#define HEADER_SIZE 32
const char headerBase[] PROGMEM = {
    0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF,
    0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF,
    0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF,
    0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFF
};
char header[HEADER_SIZE];

#define STATUS_WIDTH 15
#define STATUS_HEIGHT 32
#define STATUS_PIXELS (STATUS_WIDTH * 8)
#define STATUS_SIZE (STATUS_WIDTH * STATUS_HEIGHT)
const char logoBase[] PROGMEM = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x80, 0x80, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7F, 0x7F, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x61, 0x61, 0x81, 0x81, 0x01, 0x01, 0xC1, 0xC1, 0x30, 0x30, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xC0, 0xC0, 0xFF, 0xFF, 0xC3, 0xC3, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xF0, 0xF0, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xF0, 0xF0, 0x00, 0x00, 0xF0, 0xF0, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xF0, 0xF0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x0F, 0x0F, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x0F, 0x0F, 0x00, 0x00, 0x0F, 0x0F, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x0F, 0x0F, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x06, 0x06, 0x9E, 0x9E, 0x66, 0x66, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x00, 0x00, 0xF8, 0xF8, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0xF8, 0xF8, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x86, 0x86, 0x67, 0x67, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x86, 0x86, 0x00, 0x00, 0x07, 0x07, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x7F, 0x7F, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0xC0, 0xC0, 0x31, 0x31, 0xC1, 0xC1, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x3F, 0x3F, 0x30, 0x30, 0x3F, 0x3F, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x81, 0xF3, 0x7F, 0x3F, 0x7F, 0xFF, 0xFF, 0x3B, 0xF1, 0xF7, 0xFF, 0x3F, 0x39, 0x30, 0x00, 0x01, 0x01, 0x01, 0x83, 0x86, 0x0C, 0xF8, 0xF0, 0x80, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xCF, 0x07, 0x1F, 0x3F, 0x3F, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1F, 0xDF, 0xFC, 0x7F, 0x07, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x07, 0x0E, 0x1C, 0x18, 0x30, 0x30, 0x30, 0x60, 0x60, 0x60, 0x60, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00
};

const char workBase[] PROGMEM = {
    0x00, 0x00, 0x00, 0x00, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x3E, 0x3E, 0x3E, 0x3E, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x3E, 0x3E, 0x3E, 0x3E, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7C, 0x7C, 0x7C, 0x7C, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFC, 0xFC, 0xFC, 0xFC, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xC0, 0xC0, 0xC0, 0xC0, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x83, 0x83, 0x83, 0x83, 0x83, 0x7F, 0x7F, 0x7F, 0x7F, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00
};

const char restBase[] PROGMEM = {
    0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFC, 0xFC, 0xFC, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x7C, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF0, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF0, 0xF0, 0xF0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x7C, 0x7C, 0x7C, 0x7C, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x07, 0x07, 0x07, 0x07, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00
};
char displayBuffer[STATUS_SIZE];

#define WORK_TIME ((uint32_t)25 * 60 * 1000)
#define REST_TIME ((uint32_t)5 * 60 * 1000)

typedef enum pomo_state {
    _STOPPED,
    _WORK,
    _REST,
} pomo_state;

/* The master only needs to know if the timer is running or not */
bool isRunning = false;

/* The slave needs more info about the state and what's going on */
pomo_state state = _STOPPED;
uint8_t pomoCount = 0;
uint32_t pomoTimer;
uint32_t totalTime = 0;
uint32_t currTime = 0;
uint32_t lastTime = 0;
uint16_t lastProgress = 0;

const char* read_pomodoro_state(void) {
    switch (state) {
        case _STOPPED: return "STOPPED";
        case _REST: return "REST";
        case _WORK: return "WORK";
        default: return "UNKNOWN";
    }
}

const char* read_pomodoro_running(void) {
    if (isRunning) { return "RUNNING"; }
    else { return "STOPPED"; }
}

void update_display_base(void) {
    switch (state) {
        case _STOPPED: {
            memcpy_P(displayBuffer, logoBase, STATUS_SIZE);
            memset(header, 0, HEADER_SIZE);
        } break;
        case _WORK: {
            memcpy_P(displayBuffer, workBase, STATUS_SIZE);
            memcpy_P(header, headerBase, HEADER_SIZE);
        } break;
        case _REST: {
            memcpy_P(displayBuffer, restBase, STATUS_SIZE);
            memcpy_P(header, headerBase, HEADER_SIZE);
        } break;
    }
}

void update_cycle_display(void) {
    if (state == _STOPPED) { return; }
    uint8_t start = (HEADER_SIZE / 4) * (4 - pomoCount);
    for (uint8_t i = start; i < HEADER_SIZE; i++) {
        header[i] = ~header[i];
    }
}

bool syncRunning = false;
void toggle_pomodoro(void) {
    isRunning = !isRunning;
    syncRunning = true;
}

void set_slave_pomodoro_running(uint8_t in_buflen, const void *in_data, uint8_t out_buflen, void *out_data) {
    isRunning = *(bool*)in_data;
    if (isRunning) {
        /* Reset stuff and start the timer */
        pomoTimer = timer_read32();
        state = _WORK;
        totalTime = WORK_TIME;
        lastTime = 0;
        lastProgress = 0;
        currTime = 0;
        pomoCount = 1;
        update_display_base();
        update_cycle_display();
    } else {
        state = _STOPPED;
        update_display_base();
    }
}

void keyboard_post_init_user(void) {
    memcpy_P(displayBuffer, logoBase, STATUS_SIZE);
    memset(header, 0, HEADER_SIZE);
    transaction_register_rpc(SYNC_POMODORO_RUNNING, set_slave_pomodoro_running);
}

void update_pomodoro_display(void) {
    oled_set_cursor(0, 0);
    oled_write_raw(displayBuffer, STATUS_SIZE);
    oled_set_cursor(0, STATUS_WIDTH);
    oled_write_raw(header, HEADER_SIZE);
}

void update_time_display(void) {
    if (currTime > lastTime) {
        float ratio = (float)currTime / totalTime;
        uint16_t progress = (uint16_t)(ratio * STATUS_PIXELS);

        for (int i = lastProgress + 1; i <= progress; i++) {
            uint16_t row = i / 8;
            uint16_t bit = i % 8;
            char mask = 1 << bit;
            for (int j = 0; j < STATUS_HEIGHT; j++) {
                uint16_t index = row * STATUS_HEIGHT + j;
                if (index > STATUS_SIZE) break;
                displayBuffer[index] = displayBuffer[index] ^ mask;
            }
        }

        lastTime = currTime;
        lastProgress = progress;
    }
}

void housekeeping_task_user(void) {
    if (is_keyboard_master()) {
        if (syncRunning && transaction_rpc_send(SYNC_POMODORO_RUNNING, sizeof(bool), &isRunning)) {
            syncRunning = false;
        }
    } else {
        /* This is where the time will be updated */
        if (isRunning) {
            currTime = timer_elapsed32(pomoTimer);
            if (currTime >= totalTime) {
                if (state == _WORK) {
                    state = _REST;
                    totalTime = REST_TIME;
                } else if (state == _REST) {
                    state = _WORK;
                    totalTime = WORK_TIME;
                    pomoCount++;
                }

                if (pomoCount > 4) {
                    isRunning = false;
                    state = _STOPPED;
                }

                pomoTimer = timer_read32();
                currTime = 0;
                lastTime = 0;
                lastProgress = 0;
                update_display_base();
                update_cycle_display();
            } else {
                update_time_display();
            }
        }
    }
}

#endif // OLED_ENABLE

A keyboards/lily58/keymaps/pomodoro/rules.mk => keyboards/lily58/keymaps/pomodoro/rules.mk +23 -0
@@ 0,0 1,23 @@
BOOTMAGIC_ENABLE  = no   # Enable Bootmagic Lite
MOUSEKEY_ENABLE   = no   # Mouse keys
CONSOLE_ENABLE    = no   # Console for debug
COMMAND_ENABLE    = no   # Commands for debug and configuration
NKRO_ENABLE       = no
BACKLIGHT_ENABLE  = no   # Enable keyboard backlight functionality
AUDIO_ENABLE      = no   # Audio output
RGBLIGHT_ENABLE   = no   # Enable WS2812 RGB underlight.
SWAP_HANDS_ENABLE = no   # Enable one-hand typing
OLED_ENABLE       = yes  # OLED display
LTO_ENABLE        = yes  # Link time optimisations
EXTRAKEY_ENABLE   = yes  # Audio control and System control

# If you want to change the display of OLED, you need to change here
SRC +=  ./lib/rgb_state_reader.c \
        ./lib/layer_state_reader.c \
        ./lib/logo_reader.c \
        ./lib/keylogger.c \
        ./lib/mode_icon_reader.c \
        ./lib/host_led_state_reader.c \
        ./lib/timelogger.c \
        ./lib/keylogger.c \
        pomodoro.c \