~ruther/qmk_firmware

c1e05b14d5a1c73c328e791db2aea5834ffa67c0 — QMK Bot 2 years ago 150572d + 5d7e192
Merge remote-tracking branch 'origin/master' into develop
M keyboards/crkbd/keymaps/jpe230/config.h => keyboards/crkbd/keymaps/jpe230/config.h +39 -32
@@ 1,40 1,47 @@
/*
This is the c configuration file for the keymap
// Copyright 2022 Jose Pablo Ramirez (@jpe230)
// SPDX-License-Identifier: GPL-2.0-or-later

Copyright 2012 Jun Wako <wakojun@gmail.com>
Copyright 2015 Jack Humbert
Copyright 2022 Jose Pablo Ramirez <jp.ramangulo@gmail.com>
#pragma once

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.
/* ---------------------------
 * Common Spit Configuration
 * ---------------------------
 */
#define SPLIT_OLED_ENABLE

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.
/* ---------------------------
 * Common OLED Configuration
 * ---------------------------
 */
#define OLED_TIMEOUT 0
#define CUSTOM_OLED_TIMEOUT 10000

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
/* ---------------------------
 * Common Bootmagic Lite
 * ---------------------------
 */
#define BOOTMAGIC_LITE_ROW 0
#define BOOTMAGIC_LITE_COLUMN 0

#pragma once
/* ---------------------------
 * Common RGB Configuration
 * ---------------------------
 */
#define RGB_DISABLE_WHEN_USB_SUSPENDED
#define RGB_DISABLE_TIMEOUT CUSTOM_OLED_TIMEOUT
#define RGB_MATRIX_MAXIMUM_BRIGHTNESS 128
#define RGB_MATRIX_STARTUP_HUE 215
#define RGB_MATRIX_STARTUP_SAT 255
#define RGB_MATRIX_STARTUP_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS

#ifndef RGB_MATRIX_ENABLE
#   define SPLIT_WPM_ENABLE
#endif
/* ---------------------------
 * Common other Configuration
 * ---------------------------
 */
#define ENABLE_COMPILE_KEYCODE

#ifdef RGB_MATRIX_ENABLE
#   define RGB_DISABLE_WHEN_USB_SUSPENDED
#   define RGB_MATRIX_MAXIMUM_BRIGHTNESS 128
#   define RGB_MATRIX_STARTUP_HUE 215
#   define RGB_MATRIX_STARTUP_SAT 255
#   define RGB_MATRIX_STARTUP_VAL RGB_MATRIX_MAXIMUM_BRIGHTNESS
#   define ENABLE_RGB_MATRIX_ALPHAS_MODS
#   define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
#   define ENABLE_RGB_MATRIX_BAND_VAL
#   define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
#   define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
#   define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS
#if defined CONVERT_TO_KB2040 || defined CONVERT_TO_PROMICRO_RP2040
#    include "config_rp2040.h"
#else
#    include "config_avr.h"
#endif

A keyboards/crkbd/keymaps/jpe230/config_avr.h => keyboards/crkbd/keymaps/jpe230/config_avr.h +15 -0
@@ 0,0 1,15 @@
// Copyright 2022 Jose Pablo Ramirez (@jpe230)
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

/* ---------------------------
 * AVR RGB Configuration
 * ---------------------------
 */
#define ENABLE_RGB_MATRIX_ALPHAS_MODS
#define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
#define ENABLE_RGB_MATRIX_BAND_VAL
#define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
#define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
#define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS

A keyboards/crkbd/keymaps/jpe230/config_rp2040.h => keyboards/crkbd/keymaps/jpe230/config_rp2040.h +73 -0
@@ 0,0 1,73 @@
// Copyright 2022 Jose Pablo Ramirez (@jpe230)
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

/* ---------------------------
 * RP2040 OLED Configuration
 * ---------------------------
 */
#define I2C1_CLOCK_SPEED 400000
#define OLED_UPDATE_INTERVAL 1
#define OLED_I2C_TIMEOUT 1

/* ---------------------------
 * RP2040 Split Configuration
 * ---------------------------
 */
#define SPLIT_WPM_ENABLE

/* ---------------------------
 * RP2040 Debounce
 * ---------------------------
 */
#undef DEBOUNCE
#define DEBOUNCE 1

/* ---------------------------
 * RP2040 RGB Configuration
 * ---------------------------
 */
#define ENABLE_RGB_MATRIX_ALPHAS_MODS
#define ENABLE_RGB_MATRIX_GRADIENT_UP_DOWN
#define ENABLE_RGB_MATRIX_GRADIENT_LEFT_RIGHT
#define ENABLE_RGB_MATRIX_BREATHING
#define ENABLE_RGB_MATRIX_BAND_SAT
#define ENABLE_RGB_MATRIX_BAND_VAL
#define ENABLE_RGB_MATRIX_BAND_PINWHEEL_SAT
#define ENABLE_RGB_MATRIX_BAND_PINWHEEL_VAL
#define ENABLE_RGB_MATRIX_BAND_SPIRAL_SAT
#define ENABLE_RGB_MATRIX_BAND_SPIRAL_VAL
#define ENABLE_RGB_MATRIX_CYCLE_ALL
#define ENABLE_RGB_MATRIX_CYCLE_LEFT_RIGHT
#define ENABLE_RGB_MATRIX_CYCLE_UP_DOWN
#define ENABLE_RGB_MATRIX_RAINBOW_MOVING_CHEVRON
#define ENABLE_RGB_MATRIX_CYCLE_OUT_IN
#define ENABLE_RGB_MATRIX_CYCLE_OUT_IN_DUAL
#define ENABLE_RGB_MATRIX_CYCLE_PINWHEEL
#define ENABLE_RGB_MATRIX_CYCLE_SPIRAL
#define ENABLE_RGB_MATRIX_DUAL_BEACON
#define ENABLE_RGB_MATRIX_RAINBOW_BEACON
#define ENABLE_RGB_MATRIX_RAINBOW_PINWHEELS
#define ENABLE_RGB_MATRIX_RAINDROPS
#define ENABLE_RGB_MATRIX_JELLYBEAN_RAINDROPS
#define ENABLE_RGB_MATRIX_HUE_BREATHING
#define ENABLE_RGB_MATRIX_HUE_PENDULUM
#define ENABLE_RGB_MATRIX_HUE_WAVE
#define ENABLE_RGB_MATRIX_PIXEL_RAIN
#define ENABLE_RGB_MATRIX_PIXEL_FLOW
#define ENABLE_RGB_MATRIX_PIXEL_FRACTAL
#define ENABLE_RGB_MATRIX_TYPING_HEATMAP
#define ENABLE_RGB_MATRIX_DIGITAL_RAIN
#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_SIMPLE
#define ENABLE_RGB_MATRIX_SOLID_REACTIVE
#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_WIDE
#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTIWIDE
#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_CROSS
#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTICROSS
#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_NEXUS
#define ENABLE_RGB_MATRIX_SOLID_REACTIVE_MULTINEXUS
#define ENABLE_RGB_MATRIX_SPLASH
#define ENABLE_RGB_MATRIX_MULTISPLASH
#define ENABLE_RGB_MATRIX_SOLID_SPLASH
#define ENABLE_RGB_MATRIX_SOLID_MULTISPLASH

A keyboards/crkbd/keymaps/jpe230/jpe230.h => keyboards/crkbd/keymaps/jpe230/jpe230.h +15 -0
@@ 0,0 1,15 @@
// Copyright 2022 Jose Pablo Ramirez (@jpe230)
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once

#include QMK_KEYBOARD_H

/* ---------------------------
 * Custom OLED Fncs Prototypes
 * ---------------------------
 */
void render_slave_oled(void);
void render_master_oled(void);
void oled_timer_reset(void);
void set_keylog(uint16_t keycode, keyrecord_t *record);

M keyboards/crkbd/keymaps/jpe230/keymap.c => keyboards/crkbd/keymaps/jpe230/keymap.c +7 -382
@@ 1,35 1,9 @@
/*
Copyright 2019 @foostan
Copyright 2020 Drashna Jaelre <@drashna>
Copyright 2022 Jose Pablo Ramirez <jp.ramangulo@gmail.com>

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/>.
*/
// Copyright 2022 Jose Pablo Ramirez (@jpe230)
// SPDX-License-Identifier: GPL-2.0-or-later

#include QMK_KEYBOARD_H

#ifdef VIA_ENABLE
    #define USER_START USER00
#else
    #define USER_START SAFE_RANGE
#endif

// Keycode to toggle Sarcasm Mode
enum custom_keycodes {
    KC_SCASM = USER_START
};

// clang-format off
const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  [0] = LAYOUT_split_3x6_3(
  //,-----------------------------------------------------.                    ,-----------------------------------------------------.


@@ 72,361 46,12 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = {
  //,-----------------------------------------------------.                    ,-----------------------------------------------------.
      KC_MUTE, KC_WBAK, KC_WFWD,   KC_F7,   KC_F8,   KC_F9,                      _______,    KC_7,    KC_8,    KC_9, _______, QK_BOOT,
  //|--------+--------+--------+--------+--------+--------|                    |--------+--------+--------+--------+--------+--------|
      KC_VOLU, _______, KC_MNXT,   KC_F6,   KC_F5,   KC_F6,                      _______,    KC_6,    KC_5,    KC_4, _______, _______,
      KC_VOLU, _______, KC_MNXT,   KC_F6,   KC_F5,   KC_F6,                      _______,    KC_6,    KC_5,    KC_4, _______, QK_MAKE,
  //|--------+--------+--------+--------+--------+--------|                    |--------+--------+--------+--------+--------+--------|
      KC_VOLD, KC_MPRV, KC_MNXT,   KC_F1,   KC_F2,   KC_F3,                      _______,    KC_1,    KC_2,    KC_3, _______, _______,
      KC_VOLD, KC_MPRV, KC_MNXT,   KC_F1,   KC_F2,   KC_F3,                      _______,    KC_1,    KC_2,    KC_3, _______, DB_TOGG,
  //|--------+--------+--------+--------+--------+--------+--------|  |--------+--------+--------+--------+--------+--------+--------|
                                          KC_LGUI, _______,KC_SCASM,      TG(3), _______, KC_RALT
                                          KC_LGUI, _______, _______,      TG(3), _______, KC_RALT
                                      //`--------------------------'  `--------------------------'
  )
};

#ifdef OLED_ENABLE
oled_rotation_t oled_init_user(oled_rotation_t rotation) {
#ifdef RGB_MATRIX_ENABLE
    if (!is_keyboard_master()) {
        return OLED_ROTATION_180;  // flips the display 180 degrees if offhand
    }
#endif
    return rotation;
}

#define L_BASE 0
#define L_LOWER 2
#define L_RAISE 4
#define L_ADJUST 8

void oled_render_layer_state(void) {
    oled_write_P(PSTR("Layer: "), false);
    switch (layer_state) {
        case L_BASE:
            oled_write_ln_P(PSTR("Default"), false);
            break;
        case L_LOWER:
            oled_write_ln_P(PSTR("Lower"), false);
            break;
        case L_RAISE:
            oled_write_ln_P(PSTR("Raise"), false);
            break;
        case L_ADJUST:
        case L_ADJUST|L_LOWER:
        case L_ADJUST|L_RAISE:
        case L_ADJUST|L_LOWER|L_RAISE:
            oled_write_ln_P(PSTR("Adjust"), false);
            break;
    }
}


static char logged_char = ' ';
static uint8_t logged_row = 0, logged_col = 0;
static uint16_t logged_keycode = 0;

const char code_to_name[60] = {
    ' ', ' ', ' ', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
    'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
    'R', 'E', 'B', 'T', '_', '-', '=', '[', ']', '\\',
    '#', ';', '\'', '`', ',', '.', '/', ' ', ' ', ' '};

void set_keylog(uint16_t keycode, keyrecord_t *record) {
    if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) ||
        (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) { keycode = keycode & 0xFF; }
    if (keycode < 60) {
        logged_char = code_to_name[keycode];
    }

    // update keylog
    logged_row = record->event.key.row;
    logged_col = record->event.key.col;
    logged_keycode = keycode;
}

void oled_render_keylog(void) {
    oled_write(get_u8_str(logged_row, '0'), false);
    oled_write_P(PSTR(":"), false);
    oled_write(get_u8_str(logged_col, '0'), false);
    oled_write_P(PSTR(", "), false);
    oled_write(get_u16_str(logged_keycode, ' '), false);
    oled_write_P(PSTR(" : "), false);
    oled_write((const char *)&logged_char, false);
}

void render_bootmagic_status(bool status) {
    /* Show Ctrl-Gui Swap options */
    static const char PROGMEM logo[][2][3] = {
        {{0x97, 0x98, 0}, {0xb7, 0xb8, 0}},
        {{0x95, 0x96, 0}, {0xb5, 0xb6, 0}},
    };
    if (status) {
        oled_write_ln_P(logo[0][0], false);
        oled_write_ln_P(logo[0][1], false);
    } else {
        oled_write_ln_P(logo[1][0], false);
        oled_write_ln_P(logo[1][1], false);
    }
}

#ifndef RGB_MATRIX_ENABLE
// frame 0, 128x32px
const char PROGMEM cat_frame_0 [] PROGMEM = {
	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, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0xc0, 0xc0,
	0x60, 0x60, 0x60, 0x60, 0x40, 0x40, 0xc0, 0xc0, 0xc0, 0x70, 0x38, 0x18, 0xec, 0x3c, 0x02, 0x02,
	0x7a, 0x7a, 0xf2, 0xf2, 0x06, 0x04, 0x04, 0x0c, 0x0e, 0x0a, 0x1f, 0xfd, 0xf9, 0x39, 0x0f, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0xff, 0xff, 0x03, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xfc, 0xff, 0x01, 0x08, 0x3c, 0x00,
	0x00, 0x18, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x7e, 0x00, 0x00,
	0x00, 0x00, 0xc0, 0xe0, 0xf0, 0xf8, 0xf0, 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, 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, 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, 0x60, 0xf0, 0xff, 0xff, 0x80, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x00, 0x87, 0x83, 0xc0, 0x80, 0x88,
	0x1e, 0x1e, 0x0f, 0x00, 0x80, 0x80, 0x80, 0x40, 0x40, 0xc0, 0xe0, 0xfe, 0x87, 0xbe, 0xf0, 0x00,
	0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 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, 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, 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, 0x00, 0x00, 0x01, 0x07, 0x0f,
	0x12, 0x34, 0x34, 0x34, 0x34, 0x1e, 0x0e, 0x06, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
	0x01, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// frame 1, 128x32px
const char PROGMEM cat_frame_1 [] PROGMEM = {
	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, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0xc0, 0x60,
	0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x60, 0x60, 0xe0, 0xf0, 0x90,
	0x18, 0x08, 0x08, 0x88, 0x88, 0x98, 0x10, 0x10, 0x30, 0x30, 0x70, 0xf8, 0x08, 0x88, 0xf8, 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, 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, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0xff, 0xff, 0x01, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0x04, 0x06, 0x07, 0x03, 0x01,
	0xc0, 0x00, 0x00, 0x87, 0x87, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x1f, 0xf0, 0x00,
	0x00, 0x00, 0xc0, 0xe0, 0xf0, 0xf0, 0xf0, 0xe0, 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, 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,
	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, 0x70, 0xf8, 0xff, 0xff, 0xc0, 0x80,
	0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x07, 0x10, 0x30, 0xf0, 0xe0, 0x00,
	0x01, 0x00, 0x60, 0xf0, 0xf0, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xe0, 0xfc, 0xc7, 0x00,
	0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x01, 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, 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,
	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, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x02, 0x06,
	0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x06, 0x02, 0x02, 0x07, 0x07, 0x07, 0x04, 0x07, 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, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// frame 2, 128x32px
const char PROGMEM cat_frame_2 [] PROGMEM = {
	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, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc0, 0xc0, 0x60, 0x30,
	0x38, 0x18, 0x18, 0x18, 0x18, 0x30, 0x30, 0x30, 0x78, 0x48, 0x78, 0xc0, 0x80, 0xc0, 0x40, 0x40,
	0x40, 0x40, 0xc0, 0xc0, 0x80, 0x80, 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, 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, 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, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0x03, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x20, 0xf0, 0x80, 0x80, 0x60, 0x18, 0x00, 0x00, 0x00, 0x01, 0x00, 0x1c, 0x3c,
	0x7c, 0x38, 0x00, 0x00, 0x00, 0x01, 0x01, 0x07, 0x06, 0x3c, 0xff, 0xc3, 0x00, 0x00, 0x00, 0x00,
	0x00, 0xe0, 0xe0, 0xf0, 0xf0, 0xf0, 0xe0, 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, 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, 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, 0x70, 0xff, 0xff, 0xf0, 0x80, 0x00,
	0x00, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x1e, 0x7f, 0xc0, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0c,
	0x8c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x01, 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, 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, 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, 0x00, 0x00, 0x00, 0x01, 0x01,
	0x01, 0x01, 0x00, 0x01, 0x01, 0x0f, 0x18, 0x10, 0x18, 0x0f, 0x0e, 0x18, 0x10, 0x30, 0x27, 0x2f,
	0x2f, 0x27, 0x20, 0x30, 0x10, 0x10, 0x10, 0x30, 0x3c, 0x2d, 0x27, 0x3c, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

const char* cat_frames[3] = {
	cat_frame_0,
	cat_frame_1,
	cat_frame_2
};

#define FRAME_SIZE 528

static int      current_frame = 0;
static uint32_t frame_timer = 0;
static uint32_t anim_sleep = 0;
static uint8_t  anim_speed = 120;

#endif

void oled_render_logo(void) {
#ifdef RGB_MATRIX_ENABLE
    static const char PROGMEM crkbd_logo[] = {
        0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94,
        0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4,
        0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4,
        0};
    oled_write_P(crkbd_logo, false);
#endif
#ifndef RGB_MATRIX_ENABLE
    if(get_current_wpm() != 000) {
        oled_on();
        int8_t wpm_speed = (int8_t)(get_current_wpm() / 2);
        if(wpm_speed < 100)
        {
            anim_speed = 120 - wpm_speed;
        }
        if(timer_elapsed32(frame_timer) > anim_speed) {
            frame_timer = timer_read32();  // resets timer
            current_frame = (current_frame + 1) % 3;
        }
        oled_write_raw_P(cat_frames[current_frame], FRAME_SIZE);
        anim_sleep = timer_read32();
    } else {
        anim_speed = 150;
        if(timer_elapsed32(anim_sleep) > OLED_TIMEOUT) {
            oled_off();
        } else {
             if(timer_elapsed32(frame_timer) > anim_speed) {
                frame_timer = timer_read32();  // resets timer
                current_frame = (current_frame + 1) % 3;
            }
            oled_write_raw_P(cat_frames[current_frame], FRAME_SIZE);
        }
    }
#endif
}

bool oled_task_user(void) {
    if (is_keyboard_master()) {
        oled_render_layer_state();
        oled_render_keylog();
    } else {
        oled_render_logo();
    }
    return false;
}

#endif // OLED_ENABLE

// saRcASm MOde
bool tog_sarcasm = false;
bool uppercase = false;
uint8_t prev_upper = 0;
uint8_t prev_lower = 0;
uint8_t prev_mode = 0;
HSV prev_hsv;


bool process_record_sarcasm(uint16_t keycode, keyrecord_t *record) {
    if (keycode == KC_ENTER && record->event.pressed) {
        uppercase = false;
        return true;
    }

    if (uppercase == false && record->event.pressed)  { // Dont start with an uppercase letter on new line
        uppercase = true;
        return true;
    }

    if((KC_A <= keycode) && (keycode <= KC_Z)) {
        if ( record->event.pressed ) {
            bool press = rand() % 2;

            if (prev_upper > 2) {           // if more than 3 lower's in a row print upper
                prev_upper = 0;
                press = false;
            } else if (prev_lower > 2) {    // if more than 3 upper's in a row print lower
                prev_lower = 0;
                press = true;
            }
            if (press) {
                prev_upper++;
                tap_code16(S(keycode));
                clear_mods();
            } else {
                prev_lower++;
                tap_code16(keycode);
            }
        }
        return false;
    }

    return true;
}

bool process_record_user(uint16_t keycode, keyrecord_t *record) {

#ifdef OLED_ENABLE
    if (record->event.pressed) {
        set_keylog(keycode, record);
    }
#endif

    switch (keycode) {
        case KC_SCASM:
            if (record->event.pressed) {
                tog_sarcasm = !tog_sarcasm;

                if (tog_sarcasm) {
                    dprint("Enabling saRCaSm ModE\n");

                    #ifdef RGB_MATRIX_ENABLE
                    prev_hsv = rgb_matrix_get_hsv();
                    prev_mode = rgb_matrix_get_mode();
                    rgb_matrix_mode_noeeprom(RGB_MATRIX_ALPHAS_MODS);
                    rgb_matrix_sethsv_noeeprom(HSV_YELLOW);
                    #endif
                }
                else {
                    dprint("Disabling saRCaSm ModE\n");
                    #ifdef RGB_MATRIX_ENABLE
                    rgb_matrix_mode_noeeprom(prev_mode);
                    rgb_matrix_sethsv_noeeprom(prev_hsv.h, prev_hsv.s, prev_hsv.v);
                    #endif
                }

                uppercase = false;
                prev_upper = 0;
                prev_lower = 0;
            }
            return false;
    }

    if (tog_sarcasm) {
        return process_record_sarcasm(keycode, record);
    }

    return true;
}
// clang-format off

A keyboards/crkbd/keymaps/jpe230/oled/avr/master/oled_master_handler.c => keyboards/crkbd/keymaps/jpe230/oled/avr/master/oled_master_handler.c +75 -0
@@ 0,0 1,75 @@
// Copyright 2022 Jose Pablo Ramirez (@jpe230)
// SPDX-License-Identifier: GPL-2.0-or-later

#include "jpe230.h"

extern uint8_t logged_row;
extern uint8_t logged_col;
extern uint32_t oled_timer;
static char logged_char = ' ';
static uint16_t logged_keycode = 0;

#define L_BASE 0
#define L_LOWER 2
#define L_RAISE 4
#define L_ADJUST 8

void oled_render_layer_state(void) {
    oled_write_P(PSTR("Layer: "), false);
    switch (layer_state) {
        case L_BASE:
            oled_write_ln_P(PSTR("Default"), false);
            break;
        case L_LOWER:
            oled_write_ln_P(PSTR("Lower"), false);
            break;
        case L_RAISE:
            oled_write_ln_P(PSTR("Raise"), false);
            break;
        case L_ADJUST:
        case L_ADJUST|L_LOWER:
        case L_ADJUST|L_RAISE:
        case L_ADJUST|L_LOWER|L_RAISE:
            oled_write_ln_P(PSTR("Adjust"), false);
            break;
    }
}

const char code_to_name[60] = {
    ' ', ' ', ' ', ' ', 'a', 'b', 'c', 'd', 'e', 'f',
    'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
    'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
    '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
    'R', 'E', 'B', 'T', '_', '-', '=', '[', ']', '\\',
    '#', ';', '\'', '`', ',', '.', '/', ' ', ' ', ' '};

void handle_oled_keypress(uint16_t keycode, keyrecord_t *record) {
    if ((keycode >= QK_MOD_TAP && keycode <= QK_MOD_TAP_MAX) ||
        (keycode >= QK_LAYER_TAP && keycode <= QK_LAYER_TAP_MAX)) { keycode = keycode & 0xFF; }
    if (keycode < 60) {
        logged_char = code_to_name[keycode];
    }

    logged_keycode = keycode;
}

void oled_render_keylog(void) {
    oled_write(get_u8_str(logged_row, '0'), false);
    oled_write_P(PSTR(":"), false);
    oled_write(get_u8_str(logged_col, '0'), false);
    oled_write_P(PSTR(", "), false);
    oled_write(get_u16_str(logged_keycode, ' '), false);
    oled_write_P(PSTR(" : "), false);
    oled_write((const char *)&logged_char, false);
}

void render_master_oled() {
    if (timer_elapsed32(oled_timer) > CUSTOM_OLED_TIMEOUT) {
        oled_off();
        return;
    }

    oled_on();
    oled_render_layer_state();
    oled_render_keylog();
}

A keyboards/crkbd/keymaps/jpe230/oled/avr/slave/oled_slave_handler.c => keyboards/crkbd/keymaps/jpe230/oled/avr/slave/oled_slave_handler.c +14 -0
@@ 0,0 1,14 @@
// Copyright 2022 Jose Pablo Ramirez (@jpe230)
// SPDX-License-Identifier: GPL-2.0-or-later

#include "jpe230.h"

void render_slave_oled() {
    static const char PROGMEM crkbd_logo[] = {
        0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93, 0x94,
        0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3, 0xb4,
        0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, 0xd0, 0xd1, 0xd2, 0xd3, 0xd4,
        0};
    oled_write_P(crkbd_logo, false);
}


A keyboards/crkbd/keymaps/jpe230/oled/oled_handler.c => keyboards/crkbd/keymaps/jpe230/oled/oled_handler.c +41 -0
@@ 0,0 1,41 @@
// Copyright 2022 Jose Pablo Ramirez (@jpe230)
// SPDX-License-Identifier: GPL-2.0-or-later

#include "jpe230.h"

uint8_t logged_row;
uint8_t logged_col;
uint32_t oled_timer = 0;

__attribute__ ((weak)) void handle_oled_keypress(uint16_t keycode, keyrecord_t *record) {}

__attribute__ ((weak)) oled_rotation_t rotate_master(oled_rotation_t rotation) {return rotation;}
__attribute__ ((weak)) oled_rotation_t rotate_slave(oled_rotation_t rotation) {return rotation;}

void oled_timer_reset() { oled_timer = timer_read32(); }

oled_rotation_t oled_init_user(oled_rotation_t rotation) {

    if (!is_keyboard_master()) {
        return rotate_slave(rotation);
    }

    return rotate_master(rotation);
}


void set_keylog(uint16_t keycode, keyrecord_t *record) {
    logged_row = record->event.key.row;
    logged_col = record->event.key.col;

    handle_oled_keypress(keycode, record);
}

bool oled_task_user(void) {
    if (is_keyboard_master()) {
        render_master_oled();
    } else {
        render_slave_oled();
    }
    return false;
}

A keyboards/crkbd/keymaps/jpe230/oled/rp2040/master/indicators.h => keyboards/crkbd/keymaps/jpe230/oled/rp2040/master/indicators.h +13 -0
@@ 0,0 1,13 @@
// Copyright 2022 Jose Pablo Ramirez (@jpe230)
// SPDX-License-Identifier: GPL-2.0-or-later

#include "jpe230.h"
#include <stdio.h>

#define ANIM_SIZE 352 // number of bytes in array, max is 1024 (minimize where possible)
#define IDLE_FRAMES 67 //number of total frames

void change_frame_up(uint8_t frame_number);
void change_frame_down(uint8_t frame_number);
const char first_frame[ANIM_SIZE];
const uint8_t key_frame[4];

A keyboards/crkbd/keymaps/jpe230/oled/rp2040/master/indicators_down.c => keyboards/crkbd/keymaps/jpe230/oled/rp2040/master/indicators_down.c +463 -0
@@ 0,0 1,463 @@
// Copyright 2022 Jose Pablo Ramirez (@jpe230)
// SPDX-License-Identifier: GPL-2.0-or-later

#include "indicators.h"

const uint8_t key_frame[4] = {10, 30, 46, 61};

static const uint16_t cumsum_inds[IDLE_FRAMES+1] = {
        0, 8, 50, 82, 113, 141, 199, 261, 283, 294, 294, 294, 294, 294, 294,
        294, 330, 332, 377, 478, 588, 741, 844, 970, 1085, 1172, 1219, 1235, 1242, 1242,
        1243, 1243, 1244, 1318, 1368, 1466, 1491, 1627, 1797, 1900, 2019, 2094, 2215, 2311, 2375,
        2404, 2404, 2404, 2404, 2477, 2479, 2515, 2560, 2614, 2728, 2884, 2961, 3072, 3143, 3164,
        3167, 3167, 3167, 3167, 3169, 3171, 3221, 3221,
};

static const uint16_t change_inds[3221] = {
        173, 174, 175, 176, 177, 207, 208, 209, 135, 136, 137, 138, 139, 140, 141,
        142, 143, 144, 145, 146, 147, 148, 167, 168, 169, 170, 171, 172, 173, 174,
        175, 176, 177, 178, 179, 180, 206, 207, 208, 209, 210, 211, 212, 238, 239,
        240, 241, 242, 243, 244, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
        144, 145, 146, 147, 148, 149, 166, 167, 168, 169, 171, 172, 181, 213, 238,
        239, 240, 241, 242, 243, 244, 245, 134, 135, 136, 137, 138, 139, 140, 141,
        142, 143, 144, 145, 146, 147, 148, 149, 166, 167, 168, 171, 172, 181, 213,
        238, 239, 240, 241, 242, 243, 244, 245, 39, 102, 135, 136, 137, 138, 139,
        140, 141, 142, 143, 144, 145, 146, 147, 148, 167, 169, 170, 171, 173, 238,
        239, 240, 241, 242, 243, 244, 0, 2, 3, 4, 5, 7, 8, 10, 11,
        12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26,
        27, 28, 29, 30, 39, 62, 94, 96, 97, 98, 100, 102, 126, 134, 136,
        137, 140, 148, 158, 166, 180, 190, 198, 212, 222, 230, 244, 254, 262, 286,
        294, 318, 326, 350, 0, 2, 3, 4, 5, 7, 8, 10, 11, 12, 13,
        14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
        29, 30, 62, 64, 65, 66, 67, 94, 96, 97, 98, 99, 100, 102, 126,
        131, 134, 158, 163, 166, 190, 195, 198, 222, 227, 230, 254, 259, 262, 286,
        291, 294, 318, 323, 326, 350, 32, 33, 64, 65, 66, 67, 97, 99, 129,
        131, 161, 163, 193, 195, 225, 227, 257, 259, 289, 291, 321, 323, 32, 33,
        65, 97, 129, 161, 193, 225, 257, 289, 321, 136, 137, 138, 139, 140, 141,
        142, 143, 144, 145, 146, 147, 168, 169, 170, 171, 172, 173, 174, 175, 176,
        177, 178, 179, 206, 207, 208, 209, 210, 211, 238, 239, 240, 241, 242, 243,
        175, 176, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149,
        150, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181,
        182, 183, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212,
        213, 214, 108, 109, 110, 111, 112, 113, 114, 132, 133, 134, 135, 136, 137,
        138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152,
        153, 154, 155, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
        176, 177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 196, 197, 198,
        199, 200, 201, 202, 203, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214,
        215, 216, 217, 218, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238,
        239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 38, 39,
        40, 42, 43, 44, 45, 46, 47, 48, 50, 51, 54, 55, 56, 65, 66,
        67, 90, 91, 92, 97, 108, 109, 110, 111, 112, 113, 114, 120, 121, 122,
        123, 124, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
        146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 164, 165, 168, 169, 171,
        172, 174, 182, 186, 187, 193, 194, 196, 197, 198, 199, 203, 207, 208, 210,
        211, 213, 217, 218, 220, 221, 223, 228, 229, 230, 231, 232, 233, 234, 235,
        236, 237, 238, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 261,
        262, 264, 265, 38, 39, 40, 42, 43, 44, 45, 46, 47, 48, 50, 51,
        54, 55, 56, 65, 66, 67, 89, 90, 91, 92, 93, 94, 95, 97, 111,
        112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 132, 133,
        134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148,
        149, 150, 151, 152, 153, 154, 160, 161, 162, 163, 165, 166, 167, 168, 169,
        170, 172, 179, 183, 184, 185, 186, 193, 194, 197, 198, 202, 205, 206, 207,
        208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 220, 221, 223, 229,
        230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244,
        245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 261, 262, 264, 265,
        266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 290, 291, 292, 293,
        294, 295, 296, 297, 320, 321, 62, 63, 84, 85, 86, 87, 88, 89, 90,
        91, 92, 93, 94, 95, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
        115, 116, 117, 118, 119, 120, 128, 129, 130, 131, 132, 133, 134, 135, 136,
        137, 139, 140, 141, 142, 147, 150, 151, 152, 153, 160, 161, 162, 163, 181,
        184, 185, 230, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 266,
        267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281,
        282, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 320,
        321, 322, 323, 324, 30, 31, 52, 53, 54, 55, 56, 57, 58, 59, 60,
        61, 62, 63, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84,
        85, 86, 87, 88, 89, 90, 91, 92, 93, 96, 97, 98, 99, 100, 101,
        102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116,
        128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 250, 251, 252, 253, 254,
        255, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283,
        284, 285, 286, 287, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302,
        303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 320, 321, 322, 323,
        324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 20, 21, 22, 23, 24,
        25, 26, 27, 28, 29, 30, 31, 41, 42, 43, 44, 45, 46, 47, 48,
        49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64,
        65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
        80, 81, 82, 83, 84, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
        106, 146, 280, 281, 282, 283, 284, 285, 286, 287, 301, 302, 303, 304, 305,
        306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 323,
        324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338,
        339, 340, 341, 342, 343, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
        20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
        35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
        50, 51, 52, 53, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74,
        146, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 331, 332, 333, 334,
        335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349,
        350, 351, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12,
        13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 32, 33, 34, 35, 36,
        37, 38, 39, 40, 41, 42, 43, 64, 341, 342, 343, 344, 345, 346, 347,
        348, 349, 350, 351, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
        11, 12, 32, 33, 351, 0, 1, 2, 3, 4, 5, 6, 146, 146, 135,
        136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150,
        151, 152, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 177, 178, 179,
        180, 181, 182, 183, 184, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
        208, 209, 210, 211, 212, 213, 214, 215, 216, 230, 231, 232, 233, 234, 235,
        236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 137, 138,
        139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 168, 169, 170,
        171, 172, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 200, 201, 202,
        203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 237, 238, 239,
        240, 241, 242, 108, 109, 110, 111, 112, 113, 114, 132, 133, 134, 135, 136,
        137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
        152, 153, 154, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175,
        176, 177, 178, 181, 182, 183, 184, 185, 186, 195, 196, 197, 198, 199, 200,
        201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 213, 214, 215, 216,
        217, 218, 219, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
        240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 108, 109, 110, 111,
        112, 113, 114, 133, 134, 136, 144, 150, 154, 185, 195, 204, 211, 219, 231,
        234, 235, 243, 244, 247, 250, 34, 35, 36, 37, 38, 41, 42, 43, 44,
        45, 46, 47, 48, 49, 52, 53, 55, 64, 65, 89, 90, 91, 92, 122,
        123, 124, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
        142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 161, 164,
        166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 178, 182, 183, 184,
        185, 186, 193, 196, 203, 204, 205, 206, 207, 208, 209, 210, 211, 217, 218,
        225, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240,
        241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 252, 285, 288, 289, 313,
        314, 315, 316, 317, 323, 324, 327, 328, 329, 330, 331, 332, 333, 334, 335,
        336, 337, 338, 339, 340, 342, 343, 26, 27, 28, 29, 30, 31, 34, 35,
        36, 37, 38, 41, 42, 43, 44, 45, 46, 47, 48, 49, 52, 53, 55,
        64, 65, 89, 90, 91, 92, 95, 96, 97, 98, 99, 100, 101, 102, 103,
        104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 119,
        120, 121, 122, 123, 124, 125, 126, 129, 130, 131, 132, 133, 134, 135, 136,
        137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
        152, 153, 161, 165, 171, 172, 177, 183, 184, 185, 193, 197, 198, 199, 200,
        201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 216, 217, 224, 225, 226,
        227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
        242, 243, 244, 245, 246, 247, 248, 249, 250, 252, 281, 282, 283, 284, 285,
        286, 287, 288, 289, 313, 314, 315, 316, 317, 323, 324, 327, 328, 329, 330,
        331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 342, 343, 26, 27, 28,
        29, 30, 31, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
        97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
        112, 113, 114, 115, 116, 117, 119, 120, 121, 122, 123, 124, 125, 126, 224,
        225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
        240, 241, 242, 244, 245, 246, 247, 248, 256, 257, 258, 259, 260, 261, 262,
        263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277,
        278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 63, 64, 65, 66, 67,
        68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
        83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97,
        98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
        113, 114, 115, 116, 117, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265,
        266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280,
        281, 282, 283, 284, 285, 286, 287, 288, 289, 290, 291, 292, 293, 294, 295,
        296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310,
        311, 312, 313, 314, 315, 316, 317, 318, 319, 53, 54, 55, 56, 57, 58,
        59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73,
        74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
        89, 90, 91, 92, 93, 94, 95, 288, 289, 290, 291, 292, 293, 294, 295,
        296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310,
        311, 312, 313, 314, 315, 316, 317, 318, 319, 32, 33, 34, 35, 36, 37,
        38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
        53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67,
        68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82,
        83, 84, 85, 86, 87, 88, 288, 289, 290, 291, 292, 293, 294, 295, 296,
        297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311,
        312, 313, 314, 315, 316, 317, 318, 319, 320, 321, 322, 323, 324, 325, 326,
        327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341,
        342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 0, 1, 2, 3, 4,
        5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
        20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
        35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
        50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 320,
        321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335,
        336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350,
        351, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
        14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
        29, 30, 31, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331,
        332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346,
        347, 348, 349, 350, 351, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
        10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
        25, 26, 27, 28, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
        145, 146, 147, 148, 149, 150, 151, 152, 166, 167, 168, 169, 170, 171, 173,
        174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 198, 199, 200, 201,
        202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216,
        231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245,
        246, 247, 175, 176, 140, 141, 142, 143, 144, 145, 169, 170, 171, 172, 173,
        174, 175, 176, 177, 178, 179, 180, 181, 199, 200, 201, 202, 203, 204, 205,
        206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 137, 138, 139, 140, 141,
        142, 143, 144, 145, 166, 167, 168, 169, 170, 173, 174, 175, 176, 182, 183,
        196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 214, 215,
        216, 217, 218, 241, 242, 243, 244, 245, 246, 247, 136, 137, 138, 139, 140,
        141, 142, 143, 144, 145, 165, 166, 167, 168, 174, 175, 178, 179, 180, 181,
        182, 183, 184, 195, 196, 197, 204, 216, 219, 227, 228, 229, 230, 231, 232,
        233, 234, 235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247,
        248, 249, 250, 251, 20, 21, 22, 23, 49, 50, 51, 52, 78, 79, 80,
        107, 108, 109, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 165, 166,
        167, 168, 174, 175, 178, 179, 180, 181, 182, 183, 184, 193, 194, 195, 196,
        197, 204, 216, 219, 224, 225, 227, 228, 229, 230, 231, 232, 233, 234, 235,
        236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250,
        251, 256, 257, 258, 259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269,
        270, 271, 272, 273, 274, 275, 276, 320, 321, 322, 323, 324, 325, 326, 327,
        328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 15, 16,
        17, 18, 20, 21, 22, 23, 44, 45, 46, 47, 49, 50, 51, 52, 73,
        74, 75, 76, 78, 79, 80, 102, 103, 104, 107, 108, 109, 131, 132, 133,
        136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 160, 161, 162, 165, 166,
        167, 168, 169, 173, 175, 181, 183, 184, 185, 186, 187, 188, 189, 190, 191,
        193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207,
        208, 216, 217, 218, 224, 225, 242, 243, 244, 245, 246, 247, 256, 257, 258,
        259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
        274, 275, 276, 279, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298,
        299, 300, 301, 302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 320, 321,
        322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
        337, 338, 339, 340, 13, 14, 15, 16, 17, 18, 42, 43, 44, 45, 46,
        47, 70, 71, 72, 73, 74, 75, 76, 99, 100, 101, 102, 103, 104, 128,
        129, 130, 131, 132, 133, 160, 161, 162, 183, 184, 185, 186, 187, 188, 189,
        190, 191, 208, 215, 216, 217, 247, 249, 279, 281, 288, 289, 290, 291, 292,
        293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307,
        308, 309, 310, 311, 312, 313, 8, 9, 10, 11, 13, 14, 15, 16, 37,
        38, 39, 40, 42, 43, 44, 45, 66, 67, 68, 69, 70, 71, 72, 73,
        96, 97, 98, 99, 100, 101, 102, 128, 129, 130, 131, 156, 157, 158, 159,
        160, 185, 186, 187, 188, 189, 190, 191, 208, 216, 217, 220, 249, 252, 281,
        284, 288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301,
        302, 303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 316, 320, 321,
        322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336,
        337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 3, 4, 5,
        6, 8, 9, 10, 11, 32, 33, 34, 35, 37, 38, 39, 40, 64, 66,
        67, 68, 69, 96, 97, 98, 156, 157, 158, 159, 188, 189, 191, 206, 208,
        220, 223, 252, 255, 284, 287, 316, 319, 320, 321, 322, 323, 324, 325, 326,
        327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341,
        342, 343, 344, 345, 346, 347, 348, 351, 0, 1, 2, 3, 4, 5, 6,
        32, 33, 34, 35, 64, 159, 191, 205, 206, 223, 255, 287, 319, 351, 0,
        1, 2, 205, 207, 207, 216, 138, 139, 140, 141, 142, 143, 144, 145, 167,
        168, 169, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182, 197,
        198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211, 212,
        213, 214, 215, 216, 217, 241, 242, 243, 244, 245, 246,
};

static const char change_vals[3221] = {
        0x18, 0x1C, 0xFC, 0xFC, 0xFC, 0x0F, 0x0F, 0x0F, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF8, 0xF8,
        0xFC, 0xFC, 0xFE, 0xFE, 0xFE, 0xFC, 0xFC, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01, 0x00, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F, 0x0F,
        0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0xF0, 0xF8, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFE, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0x1F,
        0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0xF0, 0xF0, 0xF0, 0xF8, 0xF8, 0xF8, 0xFC,
        0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x00, 0x00, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00,
        0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x80, 0x80, 0x00, 0xE0, 0xE0, 0xE0, 0xE0,
        0xF0, 0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x00, 0x03, 0x03, 0x03, 0x01, 0x03,
        0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 0x80, 0x40, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x02,
        0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
        0x02, 0x02, 0x02, 0xFC, 0x00, 0xFF, 0xFF, 0x08, 0x04, 0x04, 0x02, 0xFE, 0xFF, 0xFF, 0xC0,
        0xC0, 0xE0, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
        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, 0x00, 0x08, 0x08, 0x04, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x00,
        0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00,
        0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x80, 0x80, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF,
        0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0xA0, 0x60, 0x80, 0xC0, 0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0,
        0x80, 0x06, 0x0F, 0x0F, 0x0F, 0x0F, 0x03, 0x81, 0xC1, 0xC1, 0xE1, 0xFB, 0xFF, 0x7F, 0x3F,
        0x1F, 0x06, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xF7, 0xF3, 0xF1, 0xF1, 0xF0, 0xF0,
        0xF0, 0xF0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xE0, 0xF8, 0xFC, 0xFE, 0xFE, 0xFF,
        0xFF, 0xFF, 0x3F, 0x3F, 0x1F, 0x1F, 0x1F, 0x3F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE,
        0xFC, 0xF8, 0xC0, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0x80, 0xC0, 0xC0,
        0xE0, 0xF0, 0xF8, 0xFC, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x1F, 0x0F, 0x03, 0x80, 0xE0, 0xF0,
        0xF8, 0xF8, 0xFC, 0xFE, 0xFF, 0xBF, 0x9F, 0x9F, 0x8F, 0x87, 0x87, 0x83, 0x81, 0x81, 0x80,
        0x80, 0x80, 0x80, 0x80, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
        0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x80, 0x40,
        0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x80, 0xC0, 0x18,
        0x04, 0x01, 0x04, 0xB0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20,
        0x08, 0x03, 0x00, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFE, 0xFE, 0x7E, 0x3E, 0x3F, 0xBF, 0x7F,
        0x7E, 0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xF8, 0xF0, 0xC0, 0x00, 0x00, 0x43, 0x13, 0x0B, 0x07,
        0x02, 0x80, 0x7F, 0x07, 0x00, 0x02, 0x01, 0x00, 0xC0, 0xE0, 0xF0, 0xFE, 0x8F, 0x87, 0x83,
        0x81, 0x80, 0xC0, 0xA0, 0x10, 0x08, 0x04, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
        0x8F, 0x4F, 0x2F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x40,
        0x60, 0x04, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x60, 0x30, 0x18, 0x0C, 0x02, 0x00, 0x80,
        0x40, 0x40, 0x20, 0x10, 0x08, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
        0xC0, 0xE0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFE, 0xFE, 0x7D, 0x7C, 0x7C, 0x7C, 0xFC, 0xFC, 0xF8,
        0xF8, 0xF8, 0xF0, 0xE0, 0x80, 0x00, 0x04, 0x02, 0x01, 0x01, 0x00, 0x07, 0x07, 0x07, 0x07,
        0x07, 0x01, 0xFF, 0x3F, 0x1F, 0x07, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xFC, 0xFF, 0xCF, 0xCF,
        0xC7, 0xC3, 0xC3, 0xC1, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        0x87, 0x87, 0x47, 0x27, 0x20, 0x10, 0x18, 0x08, 0x04, 0x06, 0x02, 0x00, 0x00, 0x00, 0x00,
        0x80, 0x40, 0x40, 0x20, 0x10, 0x08, 0x08, 0x04, 0x02, 0x02, 0x01, 0xC0, 0x60, 0x30, 0x18,
        0x0C, 0x04, 0x02, 0x01, 0x06, 0x01, 0x80, 0x40, 0x80, 0x80, 0x40, 0x20, 0x30, 0x18, 0x0C,
        0x04, 0x02, 0x01, 0x00, 0x00, 0x80, 0x80, 0x40, 0x60, 0x20, 0x10, 0x08, 0x0C, 0x04, 0x02,
        0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x40, 0x20, 0x30, 0x10, 0x08, 0x0C, 0x04, 0xC2, 0xF1,
        0xF1, 0xF8, 0xF8, 0xFC, 0x7C, 0xF8, 0xF0, 0xE0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F,
        0x0F, 0x00, 0x03, 0x07, 0x07, 0x07, 0x07, 0x00, 0x80, 0x80, 0x40, 0x60, 0x20, 0x30, 0x00,
        0x00, 0x00, 0x00, 0x80, 0x80, 0x40, 0x60, 0x20, 0x10, 0x18, 0x08, 0x04, 0x06, 0x02, 0x01,
        0x01, 0x00, 0x00, 0x80, 0x80, 0x40, 0x20, 0x10, 0x18, 0x0C, 0x04, 0x02, 0x03, 0x01, 0x18,
        0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x80, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x18, 0x0C, 0x06,
        0x03, 0x01, 0x00, 0x80, 0x80, 0xC0, 0x60, 0x20, 0x30, 0x18, 0x0C, 0x04, 0x06, 0x03, 0x01,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x60, 0x30, 0x30, 0x18, 0x0C,
        0x04, 0x06, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0x60,
        0x60, 0x30, 0x10, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0,
        0x60, 0x60, 0x30, 0x18, 0x18, 0x0C, 0x06, 0x06, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x80,
        0xC0, 0x60, 0x30, 0x18, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x01, 0x80, 0x80, 0xC0, 0x60, 0x70,
        0x30, 0x18, 0x0C, 0x0E, 0x07, 0x03, 0x01, 0x80, 0x80, 0xC0, 0xE0, 0x60, 0x30, 0x18, 0x1C,
        0x0C, 0x06, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0,
        0x60, 0x70, 0x30, 0x18, 0x1C, 0x0C, 0x06, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0xE0, 0x60, 0x30, 0x38, 0x18, 0x0C, 0x0C, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0x60, 0x70, 0x30, 0x18, 0x0C,
        0x0E, 0x06, 0x03, 0x03, 0x01, 0x80, 0xC0, 0xE0, 0x60, 0x70, 0x38, 0x1C, 0x0C, 0x0E, 0x07,
        0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0x60,
        0x70, 0x38, 0x1C, 0x0C, 0x0E, 0x07, 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xE0, 0x70, 0x30, 0x38, 0x1C, 0x0C,
        0x0E, 0x07, 0xC0, 0xE0, 0xE0, 0x70, 0x38, 0x3C, 0x1C, 0x0E, 0x0F, 0x07, 0x03, 0x01, 0x01,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x80, 0x3C, 0x1E, 0x0E, 0x07, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0xFC, 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, 0x20, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
        0x01, 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, 0xC0, 0xC0,
        0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0x80, 0x07, 0x07, 0x07,
        0x07, 0x07, 0xE1, 0xE1, 0xE1, 0xE1, 0xF1, 0xFF, 0xFF, 0xFF, 0xBF, 0x1F, 0x38, 0x78, 0xFC,
        0xFC, 0xF8, 0xF0, 0xE1, 0xE0, 0xE1, 0xF1, 0xFF, 0xFF, 0xFF, 0x7F, 0x3F, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF0, 0xFC, 0xFE, 0xFE, 0xFF,
        0xFF, 0xFF, 0x7F, 0x3F, 0x3F, 0x1F, 0x1F, 0x1F, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
        0xFC, 0xF8, 0xF0, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0xF8, 0xF8, 0xF8, 0xF8,
        0xF8, 0xF8, 0xFC, 0xFF, 0xFF, 0xBF, 0x9F, 0x1F, 0x07, 0x60, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0,
        0xF0, 0xF0, 0x80, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 0x83, 0xC7, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFE, 0x30, 0x03, 0x07, 0x0F, 0x1F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
        0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1F, 0x1F, 0x1F, 0x0F, 0x07, 0x03, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0xF8, 0xFC, 0xFE, 0x3F, 0xFE, 0xE0, 0x0F, 0x00, 0x81, 0xD7, 0x00, 0x0F,
        0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x01, 0x80, 0x80, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20,
        0x20, 0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x80, 0x02, 0x01, 0x01, 0x02, 0x08, 0xE0, 0x40,
        0x20, 0x0F, 0xF8, 0x08, 0x08, 0x08, 0xC8, 0xF8, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0x7E, 0x7E,
        0x7E, 0x3E, 0x7E, 0x7E, 0xFE, 0xFC, 0xFC, 0xFC, 0xFC, 0xFA, 0xF1, 0x80, 0x00, 0xFF, 0x00,
        0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x60, 0xF0, 0xF0, 0xF0, 0xF0, 0xF8, 0xBF, 0x9F, 0x1F,
        0x07, 0x00, 0xFF, 0x00, 0xE0, 0xC1, 0x81, 0x81, 0x81, 0x81, 0x81, 0xC3, 0xFF, 0xFE, 0x00,
        0x01, 0x02, 0x02, 0x02, 0x03, 0x03, 0x07, 0x07, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F,
        0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x07, 0x01, 0x08, 0x10, 0x40, 0xFF, 0x40, 0x80, 0x80,
        0x40, 0x20, 0x18, 0x07, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
        0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x04, 0x0C, 0x18, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
        0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10,
        0x10, 0x08, 0x08, 0x0C, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xF0,
        0xF8, 0xF8, 0xF8, 0xF8, 0x7C, 0x7C, 0x7C, 0x7C, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xE0,
        0xC0, 0x00, 0x00, 0x00, 0x03, 0x00, 0xF0, 0x1F, 0x0F, 0x00, 0x00, 0x00, 0x78, 0xF8, 0xF8,
        0xF8, 0xF8, 0xF0, 0xC0, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xE3, 0x7E, 0x00, 0x40, 0x40, 0x40,
        0x40, 0x40, 0x40, 0x40, 0x41, 0x43, 0x43, 0x43, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47,
        0x47, 0x07, 0x87, 0x83, 0x83, 0x81, 0x80, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02,
        0x04, 0x04, 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,
        0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xC0, 0x40, 0x40, 0x60, 0x20, 0x30, 0x10, 0x02,
        0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03, 0x03, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x03, 0x07, 0x07, 0x07, 0x07, 0x07,
        0x07, 0x07, 0x07, 0x07, 0x03, 0x03, 0x01, 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
        0x18, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
        0x10, 0x30, 0x30, 0x20, 0x20, 0x20, 0x60, 0x40, 0x40, 0xC0, 0x80, 0x18, 0x18, 0x18, 0x18,
        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x08, 0x08, 0x08, 0x08, 0x08,
        0x0C, 0x0C, 0x0C, 0x0C, 0x04, 0x04, 0x06, 0x06, 0x02, 0x03, 0x03, 0x01, 0x01, 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, 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, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
        0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x06, 0x06, 0x06, 0x06,
        0x06, 0x04, 0x04, 0x04, 0x0C, 0x0C, 0x0C, 0x08, 0x18, 0x80, 0x80, 0x80, 0x80, 0x80, 0xC0,
        0xC0, 0xC0, 0x40, 0x60, 0x60, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03,
        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10, 0x10, 0x10, 0x30,
        0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x60, 0x60, 0x60, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x0C, 0x0C, 0x0C,
        0x0C, 0x0C, 0x0C, 0x0C, 0x06, 0x06, 0x06, 0x06, 0x03, 0x03, 0x03, 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, 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, 0x00, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
        0x06, 0x06, 0x06, 0x06, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
        0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0x60, 0x60, 0x60,
        0x60, 0x60, 0x70, 0x70, 0x70, 0x30, 0x30, 0x30, 0x38, 0x38, 0x18, 0x18, 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, 0x00, 0x00, 0x00, 0x00, 0xE0,
        0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0,
        0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
        0x80, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        0x07, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 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, 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, 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, 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, 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, 0x00,
        0x00, 0x00, 0xC0, 0x80, 0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0x20, 0xE0, 0xF8, 0xFF, 0xFF, 0xFF,
        0x3F, 0x07, 0x01, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x18, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3C,
        0x3C, 0x3C, 0x3C, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3C, 0x3C, 0xC0, 0xF0, 0xFC, 0xFE, 0xFC,
        0xFE, 0xFE, 0x7E, 0x0C, 0xC0, 0xF0, 0xFE, 0xFF, 0xFF, 0x3F, 0x0F, 0x01, 0x00, 0xC0, 0xC0,
        0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xF8, 0xF8, 0xF8, 0xF8, 0xFF, 0xFF,
        0xF8, 0xF8, 0xF8, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x80, 0xF0, 0xFE, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0x3F, 0x07, 0xC0, 0xF0, 0xFE, 0xFF, 0x07, 0x00, 0xE0, 0xE0, 0xE0, 0xE0,
        0xE0, 0xE0, 0xE0, 0xF8, 0xFE, 0xFF, 0xF8, 0xFF, 0xF8, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F,
        0x1F, 0x01, 0x01, 0x01, 0x80, 0x30, 0x0C, 0x01, 0x80, 0x30, 0x04, 0x01, 0xC0, 0x10, 0x06,
        0xC0, 0x18, 0x06, 0x60, 0x98, 0xF3, 0xFC, 0xFC, 0xFC, 0xFC, 0xFC, 0x7C, 0x0C, 0x60, 0x88,
        0xF3, 0xFC, 0x0F, 0x01, 0xC0, 0xC0, 0xC0, 0xF0, 0xC0, 0xC0, 0x00, 0x80, 0x20, 0x0C, 0xF1,
        0xFE, 0xF9, 0xF8, 0x00, 0x0C, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 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, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
        0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x80, 0x70,
        0x0C, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x30, 0x0E, 0x01, 0x00, 0x00, 0x00, 0x00, 0xC0,
        0x38, 0x06, 0x01, 0x00, 0x00, 0x00, 0xC0, 0x38, 0x07, 0x00, 0x00, 0x00, 0xE0, 0x18, 0x07,
        0x00, 0x00, 0xC0, 0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0x78, 0x18, 0x60, 0x1C, 0x03, 0x00, 0x00,
        0xC0, 0xF8, 0xFE, 0x7F, 0x03, 0xC0, 0xFC, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
        0x00, 0x00, 0x00, 0x00, 0x78, 0x7E, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7D, 0x7C, 0x7C, 0x7C,
        0x7C, 0xFC, 0x78, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0xFF, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0xFF, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
        0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0xC0, 0x38, 0x07, 0x01, 0x00, 0x00, 0xE0, 0x38, 0x07, 0x01, 0x00,
        0x00, 0x80, 0xE0, 0x1C, 0x07, 0x00, 0x00, 0x00, 0x80, 0x70, 0x1C, 0x03, 0x00, 0x00, 0x80,
        0x70, 0x0E, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xFE, 0x02, 0x02, 0x02, 0x02,
        0x02, 0x02, 0x78, 0x7C, 0x7C, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x20, 0x20, 0x20, 0x20, 0x20,
        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
        0x20, 0x20, 0x20, 0x20, 0x20, 0x3F, 0xC0, 0x78, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00, 0xC0,
        0x78, 0x0F, 0x03, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x38, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x3C, 0x0F, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80,
        0x00, 0x00, 0x00, 0x00, 0xFF, 0x01, 0x00, 0x00, 0x7C, 0x78, 0x78, 0xFF, 0x00, 0xFF, 0x00,
        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, 0xFF, 0x30, 0x30,
        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3F, 0xC0, 0xF8, 0x1E,
        0x07, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x78, 0x1F, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00, 0xFF, 0x78, 0x78,
        0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 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, 0x00, 0xFF, 0x3F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x7C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x7C, 0x78, 0x7C, 0x7C, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

uint16_t index_start2 = 0;
uint16_t index_end2 = 0;
void change_frame_up(uint8_t frame_number){
// for n changes this frame, change those bytes by change_inds and change_vals
        index_start2 = cumsum_inds[frame_number-1];
        index_end2 = cumsum_inds[frame_number];
        if (index_start2 != index_end2){  // if a change in buffer
                for (uint16_t i=index_start2; i < index_end2; i++){
                        oled_write_raw_byte(change_vals[i], change_inds[i]);
                }
        }
}

A keyboards/crkbd/keymaps/jpe230/oled/rp2040/master/indicators_up.c => keyboards/crkbd/keymaps/jpe230/oled/rp2040/master/indicators_up.c +461 -0
@@ 0,0 1,461 @@
// Copyright 2022 Jose Pablo Ramirez (@jpe230)
// SPDX-License-Identifier: GPL-2.0-or-later

#include "indicators.h"

static const uint16_t cumsum_inds[IDLE_FRAMES+1] = {
        0, 50, 52, 54, 54, 54, 54, 57, 78, 149, 260, 337, 493, 607, 661,
        706, 742, 744, 817, 817, 817, 817, 846, 910, 1006, 1127, 1202, 1321, 1424, 1594,
        1730, 1755, 1853, 1903, 1977, 1978, 1978, 1979, 1979, 1986, 2002, 2049, 2136, 2251, 2377,
        2480, 2633, 2743, 2844, 2889, 2891, 2927, 2927, 2927, 2927, 2927, 2927, 2927, 2938, 2960,
        3022, 3080, 3108, 3139, 3171, 3213, 3221, 3221,
};

static const uint16_t change_inds[3221] = {
        138, 139, 140, 141, 142, 143, 144, 145, 167, 168, 169, 170, 171, 172, 173,
        174, 175, 177, 178, 179, 180, 181, 182, 197, 198, 199, 200, 201, 202, 203,
        204, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 241,
        242, 243, 244, 245, 246, 207, 216, 205, 207, 0, 1, 2, 0, 1, 2,
        3, 4, 5, 6, 32, 33, 34, 35, 64, 159, 191, 205, 206, 223, 255,
        287, 319, 351, 3, 4, 5, 6, 8, 9, 10, 11, 32, 33, 34, 35,
        37, 38, 39, 40, 64, 66, 67, 68, 69, 96, 97, 98, 156, 157, 158,
        159, 188, 189, 191, 206, 208, 220, 223, 252, 255, 284, 287, 316, 319, 320,
        321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335,
        336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 351, 8,
        9, 10, 11, 13, 14, 15, 16, 37, 38, 39, 40, 42, 43, 44, 45,
        66, 67, 68, 69, 70, 71, 72, 73, 96, 97, 98, 99, 100, 101, 102,
        128, 129, 130, 131, 156, 157, 158, 159, 160, 185, 186, 187, 188, 189, 190,
        191, 208, 216, 217, 220, 249, 252, 281, 284, 288, 289, 290, 291, 292, 293,
        294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306, 307, 308,
        309, 310, 311, 312, 313, 316, 320, 321, 322, 323, 324, 325, 326, 327, 328,
        329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343,
        344, 345, 346, 347, 348, 13, 14, 15, 16, 17, 18, 42, 43, 44, 45,
        46, 47, 70, 71, 72, 73, 74, 75, 76, 99, 100, 101, 102, 103, 104,
        128, 129, 130, 131, 132, 133, 160, 161, 162, 183, 184, 185, 186, 187, 188,
        189, 190, 191, 208, 215, 216, 217, 247, 249, 279, 281, 288, 289, 290, 291,
        292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305, 306,
        307, 308, 309, 310, 311, 312, 313, 15, 16, 17, 18, 20, 21, 22, 23,
        44, 45, 46, 47, 49, 50, 51, 52, 73, 74, 75, 76, 78, 79, 80,
        102, 103, 104, 107, 108, 109, 131, 132, 133, 136, 137, 138, 139, 140, 141,
        142, 143, 144, 145, 160, 161, 162, 165, 166, 167, 168, 169, 173, 175, 181,
        183, 184, 185, 186, 187, 188, 189, 190, 191, 193, 194, 195, 196, 197, 198,
        199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 216, 217, 218, 224, 225,
        242, 243, 244, 245, 246, 247, 256, 257, 258, 259, 260, 261, 262, 263, 264,
        265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 279, 288, 289,
        290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
        305, 306, 307, 308, 309, 310, 311, 320, 321, 322, 323, 324, 325, 326, 327,
        328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 20, 21,
        22, 23, 49, 50, 51, 52, 78, 79, 80, 107, 108, 109, 136, 137, 138,
        139, 140, 141, 142, 143, 144, 145, 165, 166, 167, 168, 174, 175, 178, 179,
        180, 181, 182, 183, 184, 193, 194, 195, 196, 197, 204, 216, 219, 224, 225,
        227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241,
        242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 256, 257, 258, 259, 260,
        261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275,
        276, 320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333,
        334, 335, 336, 337, 338, 339, 340, 136, 137, 138, 139, 140, 141, 142, 143,
        144, 145, 165, 166, 167, 168, 174, 175, 178, 179, 180, 181, 182, 183, 184,
        195, 196, 197, 204, 216, 219, 227, 228, 229, 230, 231, 232, 233, 234, 235,
        236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250,
        251, 137, 138, 139, 140, 141, 142, 143, 144, 145, 166, 167, 168, 169, 170,
        173, 174, 175, 176, 182, 183, 196, 197, 198, 199, 200, 201, 202, 203, 204,
        205, 206, 207, 208, 214, 215, 216, 217, 218, 241, 242, 243, 244, 245, 246,
        247, 140, 141, 142, 143, 144, 145, 169, 170, 171, 172, 173, 174, 175, 176,
        177, 178, 179, 180, 181, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
        209, 210, 211, 212, 213, 214, 215, 175, 176, 134, 135, 136, 137, 138, 139,
        140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 166, 167,
        168, 169, 170, 171, 173, 174, 175, 176, 177, 178, 179, 180, 181, 182, 183,
        184, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208, 209, 210, 211,
        212, 213, 214, 215, 216, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240,
        241, 242, 243, 244, 245, 246, 247, 0, 1, 2, 3, 4, 5, 6, 7,
        8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
        23, 24, 25, 26, 27, 28, 0, 1, 2, 3, 4, 5, 6, 7, 8,
        9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23,
        24, 25, 26, 27, 28, 29, 30, 31, 320, 321, 322, 323, 324, 325, 326,
        327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341,
        342, 343, 344, 345, 346, 347, 348, 349, 350, 351, 0, 1, 2, 3, 4,
        5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
        20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
        35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
        50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 320,
        321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, 335,
        336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349, 350,
        351, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
        46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60,
        61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
        76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 288, 289,
        290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304,
        305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319,
        320, 321, 322, 323, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334,
        335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345, 346, 347, 348, 349,
        350, 351, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,
        66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
        81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
        288, 289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302,
        303, 304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317,
        318, 319, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
        76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90,
        91, 92, 93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105,
        106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 256, 257, 258,
        259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
        274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 288,
        289, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303,
        304, 305, 306, 307, 308, 309, 310, 311, 312, 313, 314, 315, 316, 317, 318,
        319, 26, 27, 28, 29, 30, 31, 85, 86, 87, 88, 89, 90, 91, 92,
        93, 94, 95, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107,
        108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 119, 120, 121, 122, 123,
        124, 125, 126, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235,
        236, 237, 238, 239, 240, 241, 242, 244, 245, 246, 247, 248, 256, 257, 258,
        259, 260, 261, 262, 263, 264, 265, 266, 267, 268, 269, 270, 271, 272, 273,
        274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286, 287, 26,
        27, 28, 29, 30, 31, 34, 35, 36, 37, 38, 41, 42, 43, 44, 45,
        46, 47, 48, 49, 52, 53, 55, 64, 65, 89, 90, 91, 92, 95, 96,
        97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
        112, 113, 114, 115, 116, 117, 119, 120, 121, 122, 123, 124, 125, 126, 129,
        130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
        145, 146, 147, 148, 149, 150, 151, 152, 153, 161, 165, 171, 172, 177, 183,
        184, 185, 193, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
        209, 210, 216, 217, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234,
        235, 236, 237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 249,
        250, 252, 281, 282, 283, 284, 285, 286, 287, 288, 289, 313, 314, 315, 316,
        317, 323, 324, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338,
        339, 340, 342, 343, 34, 35, 36, 37, 38, 41, 42, 43, 44, 45, 46,
        47, 48, 49, 52, 53, 55, 64, 65, 89, 90, 91, 92, 122, 123, 124,
        129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143,
        144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 161, 164, 166, 167,
        168, 169, 170, 171, 172, 173, 174, 175, 176, 178, 182, 183, 184, 185, 186,
        193, 196, 203, 204, 205, 206, 207, 208, 209, 210, 211, 217, 218, 225, 227,
        228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
        243, 244, 245, 246, 247, 248, 249, 250, 252, 285, 288, 289, 313, 314, 315,
        316, 317, 323, 324, 327, 328, 329, 330, 331, 332, 333, 334, 335, 336, 337,
        338, 339, 340, 342, 343, 108, 109, 110, 111, 112, 113, 114, 133, 134, 136,
        144, 150, 154, 185, 195, 204, 211, 219, 231, 234, 235, 243, 244, 247, 250,
        108, 109, 110, 111, 112, 113, 114, 132, 133, 134, 135, 136, 137, 138, 139,
        140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154,
        164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178,
        181, 182, 183, 184, 185, 186, 195, 196, 197, 198, 199, 200, 201, 202, 203,
        204, 205, 206, 207, 208, 209, 210, 211, 213, 214, 215, 216, 217, 218, 219,
        228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
        243, 244, 245, 246, 247, 248, 249, 250, 137, 138, 139, 140, 141, 142, 143,
        144, 145, 146, 147, 148, 149, 150, 168, 169, 170, 171, 172, 173, 174, 175,
        176, 177, 178, 179, 180, 181, 182, 200, 201, 202, 203, 204, 205, 206, 207,
        208, 209, 210, 211, 212, 213, 214, 237, 238, 239, 240, 241, 242, 135, 136,
        137, 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151,
        152, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180,
        181, 182, 183, 184, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
        209, 210, 211, 212, 213, 214, 215, 216, 230, 231, 232, 233, 234, 235, 236,
        237, 238, 239, 240, 241, 242, 243, 244, 245, 246, 247, 248, 146, 146, 0,
        1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 7, 8,
        9, 10, 11, 12, 32, 33, 351, 0, 1, 2, 3, 4, 5, 6, 7,
        8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22,
        32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 64, 341, 342,
        343, 344, 345, 346, 347, 348, 349, 350, 351, 10, 11, 12, 13, 14, 15,
        16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
        31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45,
        46, 47, 48, 49, 50, 51, 52, 53, 64, 65, 66, 67, 68, 69, 70,
        71, 72, 73, 74, 146, 310, 311, 312, 313, 314, 315, 316, 317, 318, 319,
        331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342, 343, 344, 345,
        346, 347, 348, 349, 350, 351, 20, 21, 22, 23, 24, 25, 26, 27, 28,
        29, 30, 31, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
        53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 64, 65, 66, 67, 68,
        69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83,
        84, 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 146, 280, 281,
        282, 283, 284, 285, 286, 287, 301, 302, 303, 304, 305, 306, 307, 308, 309,
        310, 311, 312, 313, 314, 315, 316, 317, 318, 319, 323, 324, 325, 326, 327,
        328, 329, 330, 331, 332, 333, 334, 335, 336, 337, 338, 339, 340, 341, 342,
        343, 30, 31, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
        73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87,
        88, 89, 90, 91, 92, 93, 96, 97, 98, 99, 100, 101, 102, 103, 104,
        105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 128, 129, 130,
        131, 132, 133, 134, 135, 136, 137, 250, 251, 252, 253, 254, 255, 270, 271,
        272, 273, 274, 275, 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, 286,
        287, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302, 303, 304, 305,
        306, 307, 308, 309, 310, 311, 312, 313, 320, 321, 322, 323, 324, 325, 326,
        327, 328, 329, 330, 331, 332, 333, 62, 63, 84, 85, 86, 87, 88, 89,
        90, 91, 92, 93, 94, 95, 105, 106, 107, 108, 109, 110, 111, 112, 113,
        114, 115, 116, 117, 118, 119, 120, 128, 129, 130, 131, 132, 133, 134, 135,
        136, 137, 139, 140, 141, 142, 147, 150, 151, 152, 153, 160, 161, 162, 163,
        181, 184, 185, 230, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255,
        266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 277, 278, 279, 280,
        281, 282, 290, 291, 292, 293, 294, 295, 296, 297, 298, 299, 300, 301, 302,
        320, 321, 322, 323, 324, 38, 39, 40, 42, 43, 44, 45, 46, 47, 48,
        50, 51, 54, 55, 56, 65, 66, 67, 89, 90, 91, 92, 93, 94, 95,
        97, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124,
        132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145, 146,
        147, 148, 149, 150, 151, 152, 153, 154, 160, 161, 162, 163, 165, 166, 167,
        168, 169, 170, 172, 179, 183, 184, 185, 186, 193, 194, 197, 198, 202, 205,
        206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 220, 221,
        223, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
        243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 261, 262,
        264, 265, 266, 267, 268, 269, 270, 271, 272, 273, 274, 275, 276, 290, 291,
        292, 293, 294, 295, 296, 297, 320, 321, 38, 39, 40, 42, 43, 44, 45,
        46, 47, 48, 50, 51, 54, 55, 56, 65, 66, 67, 90, 91, 92, 97,
        108, 109, 110, 111, 112, 113, 114, 120, 121, 122, 123, 124, 132, 133, 134,
        135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 146, 147, 148, 149, 150,
        151, 152, 153, 154, 155, 164, 165, 168, 169, 171, 172, 174, 182, 186, 187,
        193, 194, 196, 197, 198, 199, 203, 207, 208, 210, 211, 213, 217, 218, 220,
        221, 223, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 241, 242,
        243, 244, 245, 246, 247, 248, 249, 250, 251, 261, 262, 264, 265, 108, 109,
        110, 111, 112, 113, 114, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141,
        142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 164,
        165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179,
        180, 181, 182, 183, 184, 185, 186, 187, 196, 197, 198, 199, 200, 201, 202,
        203, 205, 206, 207, 208, 209, 210, 211, 212, 213, 214, 215, 216, 217, 218,
        228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240, 241, 242,
        243, 244, 245, 246, 247, 248, 249, 250, 251, 137, 138, 139, 140, 141, 142,
        143, 144, 145, 146, 147, 148, 149, 150, 168, 169, 170, 171, 172, 173, 174,
        175, 176, 177, 178, 179, 180, 181, 182, 183, 200, 201, 202, 203, 204, 205,
        206, 207, 208, 209, 210, 211, 212, 213, 214, 175, 176, 136, 137, 138, 139,
        140, 141, 142, 143, 144, 145, 146, 147, 168, 169, 170, 171, 172, 173, 174,
        175, 176, 177, 178, 179, 206, 207, 208, 209, 210, 211, 238, 239, 240, 241,
        242, 243, 32, 33, 65, 97, 129, 161, 193, 225, 257, 289, 321, 32, 33,
        64, 65, 66, 67, 97, 99, 129, 131, 161, 163, 193, 195, 225, 227, 257,
        259, 289, 291, 321, 323, 0, 2, 3, 4, 5, 7, 8, 10, 11, 12,
        13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27,
        28, 29, 30, 62, 64, 65, 66, 67, 94, 96, 97, 98, 99, 100, 102,
        126, 131, 134, 158, 163, 166, 190, 195, 198, 222, 227, 230, 254, 259, 262,
        286, 291, 294, 318, 323, 326, 350, 0, 2, 3, 4, 5, 7, 8, 10,
        11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
        26, 27, 28, 29, 30, 39, 62, 94, 96, 97, 98, 100, 102, 126, 134,
        136, 137, 140, 148, 158, 166, 180, 190, 198, 212, 222, 230, 244, 254, 262,
        286, 294, 318, 326, 350, 39, 102, 135, 136, 137, 138, 139, 140, 141, 142,
        143, 144, 145, 146, 147, 148, 167, 169, 170, 171, 173, 238, 239, 240, 241,
        242, 243, 244, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 145,
        146, 147, 148, 149, 166, 167, 168, 171, 172, 181, 213, 238, 239, 240, 241,
        242, 243, 244, 245, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
        145, 146, 147, 148, 149, 166, 167, 168, 169, 171, 172, 181, 213, 238, 239,
        240, 241, 242, 243, 244, 245, 135, 136, 137, 138, 139, 140, 141, 142, 143,
        144, 145, 146, 147, 148, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
        177, 178, 179, 180, 206, 207, 208, 209, 210, 211, 212, 238, 239, 240, 241,
        242, 243, 244, 173, 174, 175, 176, 177, 207, 208, 209,
};

static const char change_vals[3221] = {
        0xC0, 0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0x78, 0x18, 0xC0, 0xF8, 0xFE, 0xFF, 0xFF, 0xFF, 0x7F,
        0x0F, 0x03, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x78, 0x7E, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
        0x7D, 0x7C, 0x7C, 0x7C, 0x78, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7C, 0x7C, 0x78, 0x07,
        0x07, 0x07, 0x07, 0x07, 0x07, 0x78, 0x78, 0x78, 0x7C, 0x3F, 0x07, 0x01, 0x00, 0x00, 0x00,
        0xC0, 0xF8, 0x1E, 0x07, 0xE0, 0x78, 0x1F, 0x03, 0x03, 0xF0, 0xFF, 0x7C, 0x78, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x78, 0x1E, 0x03, 0x00, 0x00, 0x00, 0x00,
        0xC0, 0x78, 0x0F, 0x03, 0x00, 0xE0, 0x38, 0x0F, 0x01, 0x3C, 0x0F, 0x01, 0x80, 0x80, 0x80,
        0x80, 0xFF, 0x01, 0x00, 0x7C, 0x7C, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x30,
        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
        0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3F, 0x00, 0x00,
        0x00, 0x00, 0x00, 0xC0, 0x38, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0xE0, 0x38, 0x07, 0x01,
        0x00, 0x00, 0x00, 0x00, 0x80, 0xE0, 0x1C, 0x07, 0x00, 0x00, 0x00, 0x80, 0x70, 0x1C, 0x03,
        0x80, 0x70, 0x0E, 0x03, 0x00, 0x00, 0x00, 0x00, 0x03, 0xFE, 0x02, 0x02, 0x02, 0x02, 0x02,
        0x02, 0x78, 0x7C, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
        0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
        0x20, 0x20, 0x20, 0x20, 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, 0x00, 0x00, 0x00, 0x00, 0x80, 0x70, 0x0C, 0x03, 0x00, 0x00, 0xC0, 0x30,
        0x0E, 0x01, 0x00, 0x00, 0x00, 0xC0, 0x38, 0x06, 0x01, 0x00, 0x00, 0x00, 0xC0, 0x38, 0x07,
        0x00, 0x00, 0x00, 0xE0, 0x18, 0x07, 0x60, 0x1C, 0x03, 0xFC, 0x04, 0x04, 0x04, 0x04, 0x04,
        0x04, 0x04, 0x04, 0x7C, 0xFF, 0xFC, 0x78, 0xFF, 0x00, 0xFF, 0x00, 0x02, 0x02, 0x02, 0x02,
        0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
        0x02, 0x02, 0x02, 0x02, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x30, 0x0C, 0x01,
        0x00, 0x00, 0x00, 0x00, 0x80, 0x30, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00, 0xC0, 0x10, 0x06,
        0x00, 0x00, 0x00, 0xC0, 0x18, 0x06, 0x00, 0x00, 0x00, 0x60, 0x98, 0xF3, 0xFC, 0xFC, 0xFC,
        0xFC, 0xFC, 0x7C, 0x0C, 0x00, 0x00, 0x00, 0x60, 0x88, 0xF3, 0xFC, 0xFF, 0x3F, 0x01, 0xF0,
        0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x0C, 0xF1, 0xFE, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xF9, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x0C, 0x01,
        0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 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, 0x00, 0x00, 0x00, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
        0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xF0, 0xFE,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0x07, 0xC0, 0xF0, 0xFE, 0xFF, 0x07, 0x00, 0xE0, 0xE0,
        0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0x00, 0x00, 0xF8, 0xFE, 0xFF, 0xF8, 0xFF, 0xF8, 0x00, 0x00,
        0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x1F,
        0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0, 0xFC, 0xFE, 0xFC, 0xFE, 0xFE,
        0x7E, 0x0C, 0x00, 0xC0, 0xF0, 0xFE, 0x0F, 0x01, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x00,
        0x00, 0xF8, 0xFE, 0xF9, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0x20, 0x00, 0x00, 0x00, 0xE0, 0xF8,
        0xFF, 0x3F, 0x07, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
        0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 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, 0xC0, 0xE0, 0xF0, 0xF8, 0xF8, 0xF8,
        0xF8, 0x7C, 0x7C, 0x7C, 0x7C, 0xFC, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xE0, 0xC0, 0x03, 0x03,
        0x03, 0x03, 0x03, 0x03, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF8, 0xFF, 0xFF, 0xFF, 0xBF, 0x1F,
        0x0F, 0x78, 0xF8, 0xF8, 0xF8, 0xF8, 0xF0, 0xC0, 0xC1, 0xC1, 0xC1, 0xC1, 0xC1, 0xE3, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x01, 0x03, 0x03, 0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        0x07, 0x07, 0x07, 0x07, 0x03, 0x03, 0x01, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
        0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
        0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xE0, 0xE0, 0xE0, 0x60, 0x60, 0x60, 0x60, 0x60, 0x70, 0x70,
        0x70, 0x30, 0x30, 0x30, 0x38, 0x38, 0x18, 0x18, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0,
        0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
        0xC0, 0xC0, 0xC0, 0x80, 0x80, 0x80, 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, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18,
        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
        0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x06, 0x06, 0x06, 0x06, 0x03, 0x03, 0x03, 0x03,
        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
        0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
        0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0xC0, 0xC0, 0xC0,
        0x40, 0x60, 0x60, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03, 0x03, 0x03,
        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x18, 0x18,
        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
        0x18, 0x18, 0x10, 0x10, 0x10, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x60, 0x60, 0x60,
        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, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x18, 0x18,
        0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x08, 0x08, 0x08,
        0x08, 0x08, 0x0C, 0x0C, 0x0C, 0x0C, 0x04, 0x04, 0x06, 0x06, 0x02, 0x03, 0x03, 0x01, 0x01,
        0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x02, 0x02, 0x02,
        0x02, 0x02, 0x02, 0x02, 0x06, 0x06, 0x06, 0x06, 0x06, 0x04, 0x04, 0x04, 0x0C, 0x0C, 0x0C,
        0x08, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x80, 0x80, 0xC0, 0x40,
        0x40, 0x60, 0x20, 0x30, 0x10, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
        0x02, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x08, 0x08, 0x08,
        0x08, 0x08, 0x08, 0x08, 0x18, 0x08, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x10, 0x10,
        0x10, 0x10, 0x10, 0x10, 0x10, 0x30, 0x30, 0x20, 0x20, 0x20, 0x60, 0x40, 0x40, 0xC0, 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, 0x00, 0x00, 0x00,
        0x00, 0x01, 0x01, 0x02, 0x04, 0x0C, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x80, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
        0x40, 0x40, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x10, 0x10, 0x08, 0x08, 0x0C,
        0x04, 0x02, 0x01, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x41, 0x43, 0x43, 0x43, 0x47,
        0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x47, 0x87, 0x83, 0x83, 0x81, 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, 0x01, 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x40, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20,
        0x20, 0x20, 0x20, 0x20, 0x40, 0x40, 0x80, 0x02, 0x01, 0x01, 0x02, 0x08, 0xE0, 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, 0x40, 0x20, 0x0F, 0x00, 0x00, 0xF8,
        0x08, 0x08, 0x08, 0xC8, 0xF8, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0x7E, 0x7E, 0x7E, 0x3E, 0x7E,
        0x7E, 0xFE, 0xFC, 0xFC, 0xFC, 0xFC, 0xFA, 0xF1, 0x80, 0xFF, 0x01, 0x01, 0x60, 0xF8, 0x9F,
        0x1F, 0x07, 0xFF, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0xE0, 0xC1, 0x81, 0x81, 0x81, 0x81,
        0x81, 0xC3, 0xFF, 0xFE, 0x00, 0x01, 0x00, 0x02, 0x02, 0x02, 0x03, 0x03, 0x07, 0x07, 0x0F,
        0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x07, 0x07, 0x07, 0x01, 0x08,
        0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x40, 0x80, 0x80, 0x40, 0x20, 0x18,
        0x07, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
        0x02, 0x02, 0x01, 0x01, 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, 0x00, 0xF0, 0xF8, 0xFC, 0xFE, 0xFE, 0xFF, 0xFF, 0x7F, 0x3F, 0x3F, 0x1F, 0x1F,
        0x3F, 0x3F, 0x3F, 0xFF, 0xFF, 0xFF, 0xFE, 0xFE, 0xFC, 0xF8, 0xE0, 0x00, 0x01, 0x01, 0x01,
        0x01, 0x01, 0x01, 0x00, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xFC, 0xFF, 0xBF, 0x9F, 0x0F, 0x07,
        0x00, 0xF0, 0x80, 0x81, 0x01, 0x01, 0x01, 0x01, 0x03, 0x83, 0xD7, 0xFF, 0xFE, 0x00, 0x00,
        0x03, 0x07, 0x0F, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
        0x1F, 0x1F, 0x1F, 0x1F, 0x0F, 0x0F, 0x07, 0x01, 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, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFC, 0xFE, 0xFF,
        0x1F, 0xFF, 0xF0, 0x1F, 0x60, 0x01, 0xC7, 0x30, 0x1F, 0x3F, 0x3F, 0x3F, 0x3F, 0x1F, 0x03,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xE0,
        0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x07, 0x07, 0x07, 0x07, 0x07, 0xE1, 0xE1, 0xE1, 0xE1, 0xF1, 0xFF,
        0xBF, 0x1F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x78, 0xFC, 0xFC,
        0xF8, 0xF0, 0xE1, 0xE0, 0xE1, 0xF1, 0xFF, 0xFF, 0x7F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
        0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xF0,
        0xF0, 0xF8, 0xF8, 0xF8, 0xFC, 0x7C, 0x7C, 0x7C, 0x7C, 0xFC, 0xF8, 0xF8, 0xF8, 0xF0, 0xE0,
        0xC0, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x01, 0x80, 0x80, 0xC0, 0xF0, 0xF8, 0xFF, 0xFF,
        0x7F, 0x7F, 0x3F, 0x0F, 0xC0, 0xF0, 0xF8, 0xFC, 0xFC, 0xFE, 0xFF, 0xFF, 0xCF, 0xCF, 0xC7,
        0xC3, 0xC3, 0xC1, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x03, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
        0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0xF8, 0xFC, 0x3C,
        0x1E, 0x0E, 0x07, 0x07, 0x03, 0x01, 0xC0, 0xE0, 0xE0, 0x70, 0x38, 0x3C, 0x1C, 0x0E, 0x0F,
        0x07, 0x03, 0x01, 0x01, 0x01, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x80, 0xC0, 0xE0, 0x60, 0x70, 0x38, 0x1C, 0x0C, 0x0E, 0x07, 0x03, 0x01, 0x01,
        0xC0, 0xE0, 0x60, 0x70, 0x38, 0x1C, 0x0C, 0x0E, 0x07, 0x03, 0x03, 0x01, 0x01, 0x80, 0xC0,
        0xC0, 0xE0, 0x70, 0x30, 0x38, 0x1C, 0x0C, 0x0E, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0x60, 0x70, 0x30, 0x18, 0x0C, 0x0E, 0x07, 0x03,
        0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0xE0, 0x60,
        0x30, 0x18, 0x1C, 0x0C, 0x06, 0x03, 0x03, 0x01, 0xC0, 0x60, 0x70, 0x30, 0x18, 0x1C, 0x0C,
        0x06, 0x07, 0x03, 0x01, 0xF8, 0x80, 0x80, 0xC0, 0xE0, 0x60, 0x30, 0x38, 0x18, 0x0C, 0x0C,
        0x80, 0xC0, 0xC0, 0x60, 0x70, 0x30, 0x18, 0x0C, 0x0E, 0x06, 0x03, 0x03, 0x01, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x80, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
        0x80, 0xC0, 0x60, 0x30, 0x18, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0xC0, 0x60, 0x20, 0x30, 0x18, 0x0C, 0x04, 0x06, 0x03,
        0x01, 0xC0, 0x60, 0x30, 0x30, 0x18, 0x0C, 0x04, 0x06, 0x03, 0x01, 0x01, 0xFC, 0x80, 0x80,
        0xC0, 0x60, 0x60, 0x30, 0x10, 0x18, 0x80, 0xC0, 0x60, 0x60, 0x30, 0x18, 0x18, 0x0C, 0x06,
        0x06, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0x60, 0x30, 0x18,
        0x18, 0x0C, 0x06, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80, 0x40, 0x20,
        0x30, 0x18, 0x0C, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x80, 0x80, 0x40, 0x60, 0x20, 0x10, 0x08, 0x0C, 0x04, 0x02, 0x01, 0x01, 0x40, 0x20, 0x30,
        0x10, 0x08, 0x0C, 0x04, 0xC2, 0xF1, 0xF1, 0x80, 0x80, 0x40, 0x60, 0x20, 0x30, 0x80, 0x80,
        0x40, 0x60, 0x20, 0x10, 0x18, 0x08, 0x04, 0x06, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x80, 0x80, 0x40, 0x20, 0x10, 0x18, 0x0C, 0x04, 0x02, 0x03, 0x01, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
        0x40, 0x60, 0x30, 0x18, 0x0C, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40,
        0x20, 0x10, 0x08, 0x08, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0xC0, 0xE0,
        0xF0, 0xF8, 0xFC, 0xFE, 0xFE, 0x7D, 0xFC, 0xF8, 0xF0, 0xE0, 0x80, 0x04, 0x02, 0x01, 0x01,
        0xFF, 0x1F, 0x07, 0x07, 0x87, 0x87, 0x47, 0x27, 0x20, 0x10, 0x18, 0x08, 0x04, 0x06, 0x02,
        0x80, 0x40, 0x40, 0x20, 0x10, 0x08, 0x08, 0x04, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x04, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x06, 0x01, 0x00, 0x00, 0x00, 0x80, 0x40, 0x40, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
        0x20, 0x20, 0x40, 0x40, 0x80, 0xC0, 0x18, 0x04, 0x00, 0x01, 0x04, 0xB0, 0x00, 0x00, 0x00,
        0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x40, 0x20, 0x08, 0x03,
        0x00, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFE, 0xFE, 0x7E, 0x3E, 0x3F, 0xBF, 0x7F, 0x3F, 0x7E,
        0xFE, 0xFE, 0xFE, 0xFE, 0xFD, 0xF8, 0xF0, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x43, 0x03, 0x03,
        0x13, 0x0B, 0x03, 0x02, 0xFC, 0x7F, 0x3F, 0x1F, 0x07, 0x02, 0x01, 0xC0, 0xE0, 0xFE, 0xBF,
        0x9F, 0x8F, 0x87, 0x87, 0x83, 0x81, 0x81, 0x80, 0x80, 0x80, 0x80, 0xC0, 0xA0, 0x10, 0x08,
        0x04, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x8F, 0x4F, 0x2F, 0x1F, 0x1F, 0x0F, 0x0F,
        0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x60,
        0x04, 0x02, 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,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xE0, 0xF8, 0xFC,
        0xFE, 0xFE, 0xFF, 0xFF, 0xFF, 0x3F, 0x3F, 0x1F, 0x1F, 0x1F, 0x3F, 0x7F, 0xFF, 0xFF, 0xFF,
        0xFE, 0xFE, 0xFC, 0xF8, 0xC0, 0x03, 0x03, 0x03, 0x03, 0x01, 0x00, 0xC0, 0xFF, 0x0F, 0x03,
        0x00, 0x00, 0x80, 0xE0, 0xF0, 0xF8, 0xFF, 0x9F, 0x8F, 0x87, 0x83, 0x81, 0x80, 0x80, 0x00,
        0x00, 0x00, 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, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xC0, 0xC0, 0xE0, 0xE0,
        0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xE0, 0xC0, 0xC0, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x06, 0x0F, 0x0F, 0x0F, 0x0F, 0x03, 0x81, 0xC1, 0xC1, 0xE1, 0xFB, 0xFF,
        0x7F, 0x3F, 0x1F, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF8, 0xFC,
        0xFE, 0xFF, 0xFF, 0xF7, 0xF3, 0xF1, 0xF1, 0xF0, 0xF0, 0xF0, 0xF0, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0xA0, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xC0, 0xC0, 0xE0, 0xE0,
        0xE0, 0xF0, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0xF8, 0x03, 0x03, 0x03, 0x03, 0x01, 0x01, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x03, 0x07, 0x07, 0x07,
        0x07, 0x07, 0x80, 0x80, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
        0x08, 0x08, 0x04, 0xFC, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00,
        0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x80, 0x40, 0x20, 0x20, 0x10, 0x08, 0x04, 0x02, 0x02, 0x02,
        0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
        0x02, 0x02, 0xFC, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x08, 0x04, 0x04, 0x00, 0x02, 0xFE,
        0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0xFF,
        0xFF, 0x00, 0xFF, 0xFF, 0x00, 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, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
        0xE0, 0xE0, 0xF0, 0xF8, 0x00, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0x00, 0x03, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0xF0, 0xF0, 0xF8, 0xF8, 0xF8, 0xFC, 0xFE,
        0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0x03, 0x01, 0x01, 0x01, 0x00, 0x0F, 0x0F, 0x0F, 0x0F,
        0x0F, 0x0F, 0x0F, 0xF0, 0xF8, 0xF8, 0xF8, 0xFC, 0xFC, 0xFC, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
        0xFF, 0xFF, 0xFF, 0xFF, 0x01, 0x01, 0x01, 0x00, 0x00, 0xFF, 0xFF, 0x1F, 0x1F, 0x1F, 0x1F,
        0x1F, 0x1F, 0x1F, 0x1F, 0x00, 0xE0, 0xE0, 0xF0, 0xF0, 0xF0, 0xF8, 0xF8, 0xFC, 0xFC, 0xFE,
        0xFE, 0xFE, 0xFC, 0xFC, 0x00, 0x00, 0x03, 0x03, 0x03, 0x01, 0x01, 0x00, 0x00, 0x0F, 0x0F,
        0x0F, 0x0F, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x1C, 0xFC, 0xFC,
        0xFC, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x0F, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};

uint16_t index_start = 0;
uint16_t index_end = 0;
void change_frame_down(uint8_t frame_number){
// for n changes this frame, change those bytes by change_inds and change_vals
        index_start = cumsum_inds[frame_number-1];
        index_end = cumsum_inds[frame_number];
        if (index_start != index_end){  // if a change in buffer
                for (uint16_t i=index_start; i < index_end; i++){
                        oled_write_raw_byte(change_vals[i], change_inds[i]);
                }
        }
}

A keyboards/crkbd/keymaps/jpe230/oled/rp2040/master/oled_master_handler.c => keyboards/crkbd/keymaps/jpe230/oled/rp2040/master/oled_master_handler.c +79 -0
@@ 0,0 1,79 @@
// Copyright 2022 Jose Pablo Ramirez (@jpe230)
// SPDX-License-Identifier: GPL-2.0-or-later

#include "jpe230.h"
#include "indicators.h"

extern uint8_t logged_row, logged_col;
extern uint32_t oled_timer;
extern const uint8_t key_frame[4];

static uint32_t frame_limiter;

void oled_render_layer_state(void) {
    int current_layer_idx = get_highest_layer(layer_state | default_layer_state);
    static int current_frame = 0;
    static bool first_run = 1;

    if(first_run){
        first_run = 0;
        char clear[ANIM_SIZE] = {0};
        memset(clear, 0, ANIM_SIZE);
        oled_write_raw_P(clear, ANIM_SIZE);
        frame_limiter = timer_read();
        return;
    }

    if (timer_elapsed(frame_limiter) < 12) {
        return;
    }

    frame_limiter = timer_read();

    if(current_frame < key_frame[current_layer_idx]){
        current_frame = (current_frame + 1) % IDLE_FRAMES;
        change_frame_up(current_frame);
    }else  if(current_frame > key_frame[current_layer_idx]) {
        current_frame = (current_frame - 1) % IDLE_FRAMES;
        change_frame_down(IDLE_FRAMES - current_frame - 1);
    }

}

void render_master_oled() {
    if (timer_elapsed32(oled_timer) > CUSTOM_OLED_TIMEOUT) {
        oled_off();
        return;
    }

    oled_on();

    /* Render the layar state */
    oled_render_layer_state();

    /* Move cursor bellow the graphic */
    oled_set_cursor(0, 12);

    /* Print logged col and row
     * Format: 00x00
     */
    char logged_matrix[9] = {0};
    sprintf(logged_matrix, "%02dx%02d", logged_col, logged_row);

    /* Write a separator char: â—†,
     * make sure to add a NULL terminator otherwise strlen could fail
     */
    static const char PROGMEM separator[] = {4, 4, 4, 4, 4, 0};
    oled_write(separator, false);

    /* Write logged matrix position */
    oled_write(logged_matrix, false);

    /* Write another separator */
    oled_write(separator, false);

    /* Write scanrate */
    oled_write(get_u16_str(get_matrix_scan_rate(), ' '), false);
}

oled_rotation_t rotate_master(oled_rotation_t rotation) {return OLED_ROTATION_270;}

A keyboards/crkbd/keymaps/jpe230/oled/rp2040/slave/ocean_dream.c => keyboards/crkbd/keymaps/jpe230/oled/rp2040/slave/ocean_dream.c +533 -0
@@ 0,0 1,533 @@
// Copyright 2022 Jose Pablo Ramirez (@jpe230)
// SPDX-License-Identifier: GPL-2.0-or-later

#include "ocean_dream.h"
#include "quantum.h"
#include "print.h"

// Calculated Parameters
#define TWINKLE_PROBABILITY_MODULATOR 100 / TWINKLE_PROBABILITY                             // CALCULATED: Don't Touch
#define TOTAL_STARS STARS_PER_LINE *NUMBER_OF_STAR_LINES                                    // CALCULATED: Don't Touch
#define OCEAN_ANIMATION_MODULATOR NUMBER_OF_FRAMES / OCEAN_ANIMATION_SPEED                  // CALCULATED: Don't Touch
#define SHOOTING_STAR_ANIMATION_MODULATOR NUMBER_OF_FRAMES / SHOOTING_STAR_ANIMATION_SPEED  // CALCULATED: Don't Touch
#define STAR_ANIMATION_MODULATOR NUMBER_OF_FRAMES / STAR_ANIMATION_SPEED                    // CALCULATED: Don't Touch

uint8_t    animation_counter       = 0;  // global animation counter.
bool       is_calm                 = false;
uint32_t   starry_night_anim_timer = 0;
uint32_t   starry_night_anim_sleep = 0;
static int current_wpm             = 0;

static uint8_t increment_counter(uint8_t counter, uint8_t max) {
    counter++;
    if (counter >= max) {
        return 0;
    } else {
        return counter;
    }
}

#ifdef ENABLE_WAVE
static uint8_t decrement_counter(uint8_t counter, uint8_t max) {
    counter--;
    if (counter < 0 || counter > max) {
        return max;
    } else {
        return counter;
    }
}
#endif

#ifdef ENABLE_MOON  // region
#    ifndef STATIC_MOON
uint8_t  moon_animation_frame   = 0;  // keeps track of current moon frame
uint16_t moon_animation_counter = 0;  // counts how many frames to wait before animating moon to next frame
#    endif

#    ifdef STATIC_MOON
static const char PROGMEM moon[6] = {
    0x18, 0x7E, 0xFF, 0xC3, 0x81, 0x81,
};
#    endif

#    ifndef STATIC_MOON
static const char PROGMEM moon_animation[14][8] = {
    // clang-format off
    { 0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C, },
    { 0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xFF, 0x42, 0x00, },
    { 0x3C, 0x7E, 0xFF, 0xFF, 0xFF, 0xC3, 0x00, 0x00, },
    { 0x3C, 0x7E, 0xFF, 0xFF, 0xC3, 0x81, 0x00, 0x00, },
    { 0x3C, 0x7E, 0xFF, 0xC3, 0x81, 0x00, 0x00, 0x00, },
    { 0x3C, 0x7E, 0xC3, 0x81, 0x81, 0x00, 0x00, 0x00, },
    { 0x3C, 0x42, 0x81, 0x81, 0x00, 0x00, 0x00, 0x00, },
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, },
    { 0x00, 0x00, 0x00, 0x00, 0x81, 0x81, 0x42, 0x3C, },
    { 0x00, 0x00, 0x00, 0x81, 0x81, 0xC3, 0x7E, 0x3C, },
    { 0x00, 0x00, 0x00, 0x81, 0xC3, 0xFF, 0x7E, 0x3C, },
    { 0x00, 0x00, 0x81, 0xC3, 0xFF, 0xFF, 0x7E, 0x3C, },
    { 0x00, 0x00, 0xC3, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C, },
    { 0x00, 0x42, 0xFF, 0xFF, 0xFF, 0xFF, 0x7E, 0x3C, },
    // clang-format on
};
#    endif

static void draw_moon(void) {
#    ifdef STATIC_MOON
    oled_set_cursor(MOON_COLUMN, MOON_LINE);
    oled_write_raw_P(moon, 6);
#    endif
#    ifndef STATIC_MOON
    moon_animation_counter = increment_counter(moon_animation_counter, ANIMATE_MOON_EVERY_N_FRAMES);
    if (moon_animation_counter == 0) {
        moon_animation_frame = increment_counter(moon_animation_frame, 14);
        oled_set_cursor(MOON_COLUMN, MOON_LINE);
        oled_write_raw_P(moon_animation[moon_animation_frame], 8);
    }
#    endif
}
#endif  // endregion

#ifdef ENABLE_WAVE  // region
uint8_t starry_night_wave_frame_width_counter = 31;
uint8_t rough_waves_frame_counter             = 0;

// clang-format off
static const char PROGMEM ocean_top[8][32] = {
    // still ocean
    {
        0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
        0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
        0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
        0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
    },
    // small ripples
    {
        0x20, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
        0x20, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
        0x20, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
        0x20, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, 0x40,
    },
    // level 2 ripples
    {
        0x20, 0x60, 0x40, 0x40, 0x20, 0x60, 0x40, 0x40,
        0x20, 0x60, 0x40, 0x40, 0x20, 0x60, 0x40, 0x40,
        0x20, 0x60, 0x40, 0x40, 0x20, 0x60, 0x40, 0x40,
        0x20, 0x60, 0x40, 0x40, 0x20, 0x60, 0x40, 0x40,
    },
    // level 3 waves
    {
        0x40, 0x20, 0x10, 0x20, 0x40, 0x40, 0x40, 0x40,
        0x40, 0x20, 0x10, 0x20, 0x40, 0x40, 0x40, 0x40,
        0x40, 0x20, 0x10, 0x20, 0x40, 0x40, 0x40, 0x40,
        0x40, 0x20, 0x10, 0x20, 0x40, 0x40, 0x40, 0x40,
    },
    {
        0x40, 0x40, 0x20, 0x10, 0x28, 0x50, 0x40, 0x40,
        0x40, 0x40, 0x20, 0x10, 0x28, 0x50, 0x40, 0x40,
        0x40, 0x40, 0x20, 0x10, 0x28, 0x50, 0x40, 0x40,
        0x40, 0x40, 0x20, 0x10, 0x28, 0x50, 0x40, 0x40,
    },
    {
        0x40, 0x40, 0x40, 0x20, 0x10, 0x30, 0x70, 0x60,
        0x40, 0x40, 0x40, 0x20, 0x10, 0x30, 0x70, 0x60,
        0x40, 0x40, 0x40, 0x20, 0x10, 0x30, 0x70, 0x60,
        0x40, 0x40, 0x40, 0x20, 0x10, 0x30, 0x70, 0x60,
    },
};
static const char PROGMEM ocean_bottom[8][32] = {
    // still ocean
    {
        0x00, 0x40, 0x40, 0x41, 0x01, 0x01, 0x01, 0x21,
        0x20, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x44,
        0x44, 0x40, 0x40, 0x00, 0x00, 0x08, 0x08, 0x00,
        0x01, 0x01, 0x01, 0x00, 0x40, 0x40, 0x00, 0x00,
    },
    // small ripples
    {
        0x00, 0x00, 0x40, 0x40, 0x01, 0x01, 0x01, 0x20,
        0x20, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04,
        0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
        0x00, 0x01, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00,
    },
    // level 2 ripples
    {
        0x00, 0x00, 0x40, 0x40, 0x01, 0x01, 0x01, 0x20,
        0x20, 0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04,
        0x40, 0x40, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
        0x00, 0x01, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00,
    },
    // level 3 waves
    {
        0x00, 0x40, 0x40, 0x42, 0x42, 0x03, 0x11, 0x11,
        0x20, 0x20, 0x00, 0x00, 0x08, 0x0C, 0x0C, 0x04,
        0x05, 0x41, 0x41, 0x21, 0x20, 0x00, 0x00, 0x08,
        0x0A, 0x0A, 0x0B, 0x41, 0x41, 0x41, 0x41, 0x00,
    },
    {
        0x10, 0x10, 0x00, 0x80, 0x84, 0xC4, 0x02, 0x06,
        0x84, 0x44, 0xC0, 0x80, 0x80, 0x20, 0x20, 0x10,
        0x08, 0x12, 0x91, 0x81, 0x42, 0x40, 0x00, 0x00,
        0x10, 0x12, 0x22, 0x22, 0x24, 0x04, 0x84, 0x80,
    },
    {
        0x08, 0x80, 0x80, 0x82, 0x82, 0x03, 0x21, 0x21,
        0x10, 0x10, 0x00, 0x00, 0x04, 0x04, 0x0C, 0x08,
        0x09, 0x41, 0x42, 0x22, 0x20, 0x00, 0x00, 0x08,
        0x0A, 0x0A, 0x0B, 0x41, 0x43, 0x42, 0x42, 0x00,
    },
};
// clang-format on

static void animate_waves(void) {
    starry_night_wave_frame_width_counter = decrement_counter(starry_night_wave_frame_width_counter, WIDTH - 1);  // only 3 frames for last wave type
    rough_waves_frame_counter             = increment_counter(rough_waves_frame_counter, 3);                      // only 3 frames for last wave type

    void draw_ocean(uint8_t frame, uint16_t offset, uint8_t byte_index) {
        oled_write_raw_byte(pgm_read_byte(ocean_top[frame] + byte_index), offset);
        oled_write_raw_byte(pgm_read_byte(ocean_bottom[frame] + byte_index), offset + WIDTH);
    }

    for (int i = 0; i < WIDTH; ++i) {
        uint16_t offset     = OCEAN_LINE * WIDTH + i;
        uint8_t  byte_index = starry_night_wave_frame_width_counter + i;
        if (byte_index >= WIDTH) {
            byte_index = byte_index - WIDTH;
        }
        if (is_calm || current_wpm <= WAVE_CALM) {
            draw_ocean(0, offset, byte_index);
        } else if (current_wpm <= WAVE_HEAVY_STORM) {
            draw_ocean(1, offset, byte_index);
        } else if (current_wpm <= WAVE_HURRICANE) {
            draw_ocean(2, offset, byte_index);
        } else {
            draw_ocean(3 + rough_waves_frame_counter, offset, byte_index);
        }
    }
}
#endif  // endregion

#ifdef ENABLE_ISLAND  // region
uint8_t island_frame_1 = 0;

// clang-format off
// only use 46 bytes (first 18 are blank, so we don't write them, makes it smaller and we can see the shooting stars properly!)

// To save space and allow the shooting stars to be seen, only draw the tree on every frame.
// Tree is only 14bytes wide so we save 108 bytes on just the first row. Second row, the
// first 18 bytes is always the same piece of land, so only store that once, which saves 90 bytes
static const char PROGMEM islandRightTop[6][14] = {
    {0x84, 0xEC, 0x6C, 0x3C, 0xF8, 0xFE, 0x3F, 0x6B, 0xDB, 0xB9, 0x30, 0x40, 0x00, 0x00,},
    {0x80, 0xC3, 0xEE, 0x7C, 0xB8, 0xFC, 0xFE, 0x6F, 0xDB, 0x9B, 0xB2, 0x30, 0x00, 0x00,},
    {0x00, 0xC0, 0xEE, 0x7F, 0x3D, 0xF8, 0xFC, 0x7E, 0x57, 0xDB, 0xDB, 0x8A, 0x00, 0x00,},
    {0x00, 0xC0, 0xE6, 0x7F, 0x3B, 0xF9, 0xFC, 0xFC, 0xB6, 0xB3, 0x33, 0x61, 0x00, 0x00,},
    {0x00, 0x00, 0x00, 0x00, 0x80, 0xEE, 0xFF, 0xFB, 0xF9, 0xFC, 0xDE, 0xB6, 0xB6, 0x24,},
    {0x00, 0x00, 0x00, 0x00, 0xC0, 0xEE, 0xFE, 0xFF, 0xFB, 0xFD, 0xEE, 0xB6, 0xB6, 0x92,},
};
static const char PROGMEM islandRightBottom[6][14] = {
    {0x41, 0x40, 0x60, 0x3E, 0x3F, 0x23, 0x20, 0x60, 0x41, 0x43, 0x40, 0x40, 0x40, 0x80,},
    {0x40, 0x41, 0x60, 0x3E, 0x3F, 0x23, 0x20, 0x60, 0x40, 0x40, 0x41, 0x41, 0x40, 0x80,},
    {0x40, 0x40, 0x61, 0x3D, 0x3F, 0x27, 0x21, 0x60, 0x40, 0x40, 0x40, 0x40, 0x40, 0x80,},
    {0x40, 0x43, 0x61, 0x3C, 0x3F, 0x27, 0x21, 0x60, 0x41, 0x43, 0x43, 0x42, 0x40, 0x80,},
    {0x40, 0x40, 0x60, 0x3C, 0x3F, 0x27, 0x23, 0x63, 0x44, 0x40, 0x41, 0x41, 0x41, 0x81,},
    {0x40, 0x40, 0x60, 0x3C, 0x3F, 0x27, 0x23, 0x63, 0x42, 0x42, 0x41, 0x41, 0x41, 0x80,},
};
static const char PROGMEM islandLeft[18] = {
    0x80, 0x40, 0x40, 0x40, 0x40, 0x60,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x60, 0x40, 0x40,
};
// clang-format on

static void animate_island(void) {
    if (animation_counter == 0) {
        island_frame_1 = increment_counter(island_frame_1, 2);
    }

    void draw_island_parts(uint8_t frame) {
        oled_set_cursor(ISLAND_COLUMN + 3, ISLAND_LINE);
        oled_write_raw_P(islandRightTop[frame], 14);
        oled_set_cursor(ISLAND_COLUMN + 0, ISLAND_LINE + 1);
        oled_write_raw_P(islandLeft, 18);
        oled_set_cursor(ISLAND_COLUMN + 3, ISLAND_LINE + 1);
        oled_write_raw_P(islandRightBottom[frame], 14);
    }

    if (is_calm || current_wpm < ISLAND_CALM) {
        draw_island_parts(0);
    } else if (current_wpm >= ISLAND_CALM && current_wpm < ISLAND_HEAVY_STORM) {
        draw_island_parts(island_frame_1 + 1);
    } else if (current_wpm >= ISLAND_HEAVY_STORM && current_wpm < ISLAND_HURRICANE) {
        draw_island_parts(island_frame_1 + 2);
    } else {
        draw_island_parts(island_frame_1 + 4);
    }
}
#endif  // endregion

#ifdef ENABLE_STARS  // region
bool stars_setup = false;  // only setup stars once, then we just twinkle them
struct Coordinate {
    int  x;
    int  y;
    bool exists;
};

struct Coordinate stars[TOTAL_STARS];  // tracks all stars/coordinates

/**
 * Setup all the initial stars on the screen
 * This function divides the screen into regions based on STARS_PER_LINE and NUMBER_OF_STAR_LINES
 * where each line is made up of 8x8 pixel groups, that are populated by a single star.
 *
 * Not sure how this function will work with larger or smaller screens.
 * It should be fine, as long as the screen width is a multiple of 8
 */
static void setup_stars(void) {
    // For every line, split the line into STARS_PER_LINE, find a random point in that region, and turn the pixel on
    // 36% probability it will not be added
    // (said another way, 80% chance it will start out lit in the x direction, then 80% chance it will start out lit in the y direction = 64% probability it will start out lit at all)
    for (int line = 0; line < NUMBER_OF_STAR_LINES; ++line) {
        for (int column_group = 0; column_group < STARS_PER_LINE; ++column_group) {
            uint8_t rand_column = rand() % 10;
            uint8_t rand_row    = rand() % 10;
            if (rand_column < 8 && rand_row < 8) {
                int column_adder = column_group * 8;
                int line_adder   = line * 8;
                int x            = rand_column + column_adder;
                int y            = rand_row + line_adder;
                oled_write_pixel(x, y, true);
                stars[column_group + (line * STARS_PER_LINE)].x      = x;
                stars[column_group + (line * STARS_PER_LINE)].y      = y;
                stars[column_group + (line * STARS_PER_LINE)].exists = true;
            } else {
                stars[column_group + (line * STARS_PER_LINE)].exists = false;
            }
        }
    }
    stars_setup = true;
}

/**
 * Twinkle the stars (move them one pixel in any direction) with a probability of 50% to twinkle any given star
 */
static void twinkle_stars(void) {
    for (int line = 0; line < NUMBER_OF_STAR_LINES; ++line) {
        for (int column_group = 0; column_group < STARS_PER_LINE; ++column_group) {
            struct Coordinate star = stars[column_group + (line * STARS_PER_LINE)];

            // skip stars that were never added
            if (!star.exists) {
                continue;
            }
            if (rand() % TWINKLE_PROBABILITY_MODULATOR == 0) {
                oled_write_pixel(star.x, star.y, false);  // black out pixel

                // don't allow stars to leave their own region
                if (star.x == (column_group * 8)) {                     // star is the farthest left it can go in its region
                    star.x++;                                           // move it right immediately
                } else if (star.x == (((column_group + 1) * 8) - 1)) {  // star is farthest right it can go in its region
                    star.x--;                                           // move it left immediately
                }
                if (star.y == (line * 8)) {                     // star is the farthest up it can go in its region
                    star.y++;                                   // move it down immediately
                } else if (star.y == (((line + 1) * 8) - 1)) {  // star is farthest down it can go in its region
                    star.y--;                                   // move it up immediately
                }

                // now decide direction
                int new_x;
                int x_choice = rand() % 3;
                if (x_choice == 0) {
                    new_x = star.x - 1;
                } else if (x_choice == 1) {
                    new_x = star.x + 1;
                } else {
                    new_x = star.x;
                }

                int new_y;
                int y_choice = rand() % 3;
                if (y_choice == 0) {
                    new_y = star.y - 1;
                } else if (y_choice == 1) {
                    new_y = star.y + 1;
                } else {
                    new_y = star.y;
                }

                star.x = new_x;
                star.y = new_y;
                oled_write_pixel(new_x, new_y, true);
            }

            stars[column_group + (line * STARS_PER_LINE)] = star;
        }
    }
}

/**
 * Setup the stars and then animate them on subsequent frames
 */
static void animate_stars(void) {
    if (!stars_setup) {
        setup_stars();
    } else {
        twinkle_stars();
    }
}
#endif  // endregion

#ifdef ENABLE_SHOOTING_STARS  // region
bool shooting_stars_setup = false;  // only setup shooting stars array once with defaults

struct ShootingStar {
    int  x_1;
    int  y_1;
    int  x_2;
    int  y_2;
    bool running;
    int  frame;
    int  delay;
};

struct ShootingStar shooting_stars[MAX_NUMBER_OF_SHOOTING_STARS];  // tracks all the shooting stars

static void setup_shooting_star(struct ShootingStar *shooting_star) {
    int column_to_start = rand() % (WIDTH / 2);
    int row_to_start    = rand() % (HEIGHT - 48);  // shooting_stars travel diagonally 1 down, 1 across. So the lowest a shooting_star can start and not 'hit' the ocean is 32 above the ocean.

    shooting_star->x_1     = column_to_start;
    shooting_star->y_1     = row_to_start;
    shooting_star->x_2     = column_to_start + 1;
    shooting_star->y_2     = row_to_start + 1;
    shooting_star->running = true;
    shooting_star->frame++;
    shooting_star->delay = rand() % SHOOTING_STAR_DELAY;
}

static void move_shooting_star(struct ShootingStar *shooting_star) {
    oled_write_pixel(shooting_star->x_1, shooting_star->y_1, false);
    oled_write_pixel(shooting_star->x_2, shooting_star->y_2, false);

    shooting_star->x_1++;
    shooting_star->y_1++;
    shooting_star->x_2++;
    shooting_star->y_2++;
    shooting_star->frame++;

    oled_write_pixel(shooting_star->x_1, shooting_star->y_1, true);
    oled_write_pixel(shooting_star->x_2, shooting_star->y_2, true);
}

static void finish_shooting_star(struct ShootingStar *shooting_star) {
    oled_write_pixel(shooting_star->x_1, shooting_star->y_1, false);
    oled_write_pixel(shooting_star->x_2, shooting_star->y_2, false);
    shooting_star->running = false;
    shooting_star->frame   = 0;
}

static void animate_shooting_star(struct ShootingStar *shooting_star) {
    if (shooting_star->frame > SHOOTING_STAR_FRAMES) {
        finish_shooting_star(shooting_star);
        return;
    } else if (!shooting_star->running) {
        setup_shooting_star(shooting_star);
    } else {
        if (shooting_star->delay == 0) {
            move_shooting_star(shooting_star);
        } else {
            shooting_star->delay--;
        }
    }
}

static void animate_shooting_stars(void) {
    if (is_calm) {
        return;
    }
    if (!shooting_stars_setup) {
        for (int i = 0; i < MAX_NUMBER_OF_SHOOTING_STARS; ++i) {
            shooting_stars[i].running = false;
        }
        shooting_stars_setup = true;
    }
    /**
     * Fixes issue with stars that were falling _while_ the
     * wpm dropped below the condition for them to keep falling
     */
    void end_extra_stars(uint8_t starting_index) {
        for (int shooting_star_index = starting_index; shooting_star_index < MAX_NUMBER_OF_SHOOTING_STARS; ++shooting_star_index) {
            struct ShootingStar shooting_star = shooting_stars[shooting_star_index];
            if (shooting_star.running) {
                finish_shooting_star(&shooting_star);
                shooting_stars[shooting_star_index] = shooting_star;
            }
        }
    }

    int number_of_shooting_stars = current_wpm / SHOOTING_STAR_WPM_INCREMENT;
    number_of_shooting_stars     = (number_of_shooting_stars > MAX_NUMBER_OF_SHOOTING_STARS) ? MAX_NUMBER_OF_SHOOTING_STARS : number_of_shooting_stars;

    if (number_of_shooting_stars == 0) {
        // make sure all shooting_stars are ended
        end_extra_stars(0);
    } else {
        for (int shooting_star_index = 0; shooting_star_index < number_of_shooting_stars; ++shooting_star_index) {
            struct ShootingStar shooting_star = shooting_stars[shooting_star_index];
            animate_shooting_star(&shooting_star);
            shooting_stars[shooting_star_index] = shooting_star;
        }
        end_extra_stars(number_of_shooting_stars);
    }
}
#endif  // endregion

/**
 * Main rendering function
 *
 * Calls all different animations at different rates
 */
void render_stars(void) {
    //    // animation timer
    if (timer_elapsed32(starry_night_anim_timer) > STARRY_NIGHT_ANIM_FRAME_DURATION) {
        starry_night_anim_timer = timer_read32();
        current_wpm             = get_current_wpm();

#ifdef ENABLE_ISLAND
        animate_island();
#endif

#ifdef ENABLE_SHOOTING_STARS
        if (animation_counter % SHOOTING_STAR_ANIMATION_MODULATOR == 0) {
            animate_shooting_stars();
        }
#endif

#ifdef ENABLE_STARS
        // TODO offsetting the star animation from the wave animation would look better,
        // but if I do that, then the stars appear in the water because
        // the ocean animation has to wait a bunch of frames to overwrite it.
        // Possible solutions:
        // 1. Only draw stars to the top of the island/ocean.
        // 2. Draw ocean every frame, only move ocean on frames matching modulus
        // Problems:
        // 1. What if someone wants to move the island up a bit, or they want to have the stars reflect in the water?
        // 2. More cpu intensive. And I'm already running out of cpu as it is...
        if (animation_counter % STAR_ANIMATION_MODULATOR == 0) {
            animate_stars();
        }
#endif

#ifdef ENABLE_WAVE
        if (animation_counter % OCEAN_ANIMATION_MODULATOR == 0) {
            animate_waves();
        }
#endif

#ifdef ENABLE_MOON
        draw_moon();
#endif

        animation_counter = increment_counter(animation_counter, NUMBER_OF_FRAMES);
    }
}

A keyboards/crkbd/keymaps/jpe230/oled/rp2040/slave/ocean_dream.h => keyboards/crkbd/keymaps/jpe230/oled/rp2040/slave/ocean_dream.h +89 -0
@@ 0,0 1,89 @@
// Copyright 2022 Jose Pablo Ramirez (@jpe230)
// SPDX-License-Identifier: GPL-2.0-or-later

#pragma once
#include "quantum.h"

/**
 * Features:
 * You can turn on and off features in this section
 */
#define ENABLE_MOON            // Uses 182 bytes
#define ENABLE_WAVE            // Uses 844 bytes
#define ENABLE_SHOOTING_STARS  // Uses 872 bytes
#define ENABLE_ISLAND
#define ENABLE_STARS  // Uses 606 bytes

/**
 * Global Settings
 */
#define STARRY_NIGHT_ANIM_FRAME_DURATION 30  // how long each frame lasts in ms
#define NUMBER_OF_FRAMES 20                  // Self explanatory. Probably shouldn't touch this, not sure how stuff will work if it's changed. If changed should be multiple of 1, 2, 3, 4, and 5
#define WIDTH OLED_DISPLAY_HEIGHT            // for vertical displays
#define HEIGHT OLED_DISPLAY_WIDTH            // for vertical displays

/**
 * Moon Parameters
 */
#define MOON_LINE 4    // the line you want the moon to appear at
#define MOON_COLUMN 4  // the column you want the moon to appear at
//#define STATIC_MOON  // uncomment this to make the moon a static image, no animation
#ifndef STATIC_MOON
#    define ANIMATE_MOON_EVERY_N_FRAMES 100  // animate the moon every n frames
#endif

/**
 * Wave Parameters
 */
#define OCEAN_LINE 14        // Line you want to render the ocean starting at (best at oled_max_lines() - 2)
#define WAVE_CALM 20         // render calm ocean under this WPM and ripple ocean at this WPM
#define WAVE_HEAVY_STORM 40  // render medium ocean at this WPM
#define WAVE_HURRICANE 60    // render heavy waves above this WPM
// What number of frames you want to animate the ocean at.
// Should be equal to or smaller than NUMBER_OF_FRAMES, e.g. 30, would animate on every other frame, 20, every third frame, etc
// Don't set equal to 0.
#define OCEAN_ANIMATION_SPEED 1

/**
 * Shooting Star Parameters
 */
#define SHOOTING_STAR_DELAY 12           // delay modulus for time between shooting stars. Decides number of frames to delay, e.g. 12 means 0-11 frames of delay between each shooting star
#define SHOOTING_STAR_FRAMES 16          // how many 2 pixel frames per shooting star. Increment this for longer shooting stars
#define MAX_NUMBER_OF_SHOOTING_STARS 12  // maximum number of shooting stars that can be on screen at the same time
#define SHOOTING_STAR_WPM_INCREMENT 10   // every n WPM increase, add an extra star, up to MAX_NUMBER_OF_SHOOTING_STARS, e.g. an increment of 5 would result in 1 shooting star at 5-9wpm, 2 at 10-14, etc.
// What number of frames you want to animate the shooting stars at.
// Should be equal to or smaller than NUMBER_OF_FRAMES, e.g. 30, would animate on every other frame, 20, every third frame, etc
// Don't set equal to 0.
#define SHOOTING_STAR_ANIMATION_SPEED 30

/**
 * Star Parameters
 */
#define STARS_PER_LINE 4         // number of stars per line (for a display that is 128x32, this would be 4 stars spread out evenly over the 32byte width, one every 8 bytes)
#define NUMBER_OF_STAR_LINES 16  // number of lines to fill up with stars (for a display that is 128x32, 16 bytes are filled with the ocean animation, so that leaves 112 pixels left over. The number of lines depends on your OLED_FONT_HEIGHT)
#define TWINKLE_PROBABILITY 25   // probability that any star twinkles on a given frame
// What number of frames you want to animate the stars at.
// Should be equal to or smaller than NUMBER_OF_FRAMES, e.g. 20, would animate on every frame, 10, every other frame, etc
// Don't set equal to 0.
#define STAR_ANIMATION_SPEED 1

/**
 * Island Parameters
 */
#define ISLAND_LINE 12         // line that the island starts at. Island is 2 lines tall
#define ISLAND_COLUMN 0        // column that the island starts at
#define ISLAND_CALM 20         // WPM at which the palm tree calmly moves
#define ISLAND_HEAVY_STORM 40  // WPM at which the heavy storm occurs
#define ISLAND_HURRICANE 60    // WPM at which THE HURRICANE STARTS

/*
 * DON'T TOUCH
 */

extern bool is_calm;

// timers
extern uint32_t starry_night_anim_timer;
extern uint32_t starry_night_anim_sleep;

void render_stars(void);

A keyboards/crkbd/keymaps/jpe230/oled/rp2040/slave/oled_slave_handler.c => keyboards/crkbd/keymaps/jpe230/oled/rp2040/slave/oled_slave_handler.c +11 -0
@@ 0,0 1,11 @@
// Copyright 2022 Jose Pablo Ramirez (@jpe230)
// SPDX-License-Identifier: GPL-2.0-or-later

#include "jpe230.h"
#include "ocean_dream.h"

void render_slave_oled() {
    render_stars();
}

oled_rotation_t rotate_slave(oled_rotation_t rotation) {return OLED_ROTATION_270;}

A keyboards/crkbd/keymaps/jpe230/process_record.c => keyboards/crkbd/keymaps/jpe230/process_record.c +20 -0
@@ 0,0 1,20 @@
// Copyright 2022 Jose Pablo Ramirez (@jpe230)
// SPDX-License-Identifier: GPL-2.0-or-later

#include "jpe230.h"

bool process_record_user(uint16_t keycode, keyrecord_t *record) {
    if (record->event.pressed) {
        oled_timer_reset();
        set_keylog(keycode, record);

        switch (keycode) {
            case QK_BOOT:
                rgb_matrix_set_color_all(30, 0, 0);
                rgb_matrix_driver.flush();
                oled_off();
                return true;
        }
    }
    return true;
}

M keyboards/crkbd/keymaps/jpe230/readme.md => keyboards/crkbd/keymaps/jpe230/readme.md +12 -4
@@ 6,10 6,18 @@ The four layers:
- LOWER Layer: Numbers + Arrows
- RAISE Layer: Symbols
- ADJUST Layer: Numpad + Media Keys + Fn keys

## OLED
-Master: Renders layer state + keylog
-Slave : Renders an animation of a cat that varies its animation speed based on the current WPM
The graphics for the OLED varies depending on the target platform:

| Half   | RP2040                               | Pro Micro                            |
|--------|--------------------------------------|--------------------------------------|
| Master | ![](https://i.imgur.com/FF0EuWoh.png) | ![](https://i.imgur.com/stxRevvh.png) |
| Slave  | ![](https://i.imgur.com/hyjdDITh.png) | ![](https://i.imgur.com/UrTCd2sh.png) |


## Flashing
Flash using `qmk compile -kb crkbd -km jpe230` for Pro Micro
For Arduino Pro Micro:
- `qmk compile -kb crkbd -km jpe230`

For Pro Micro Compatible board (See [Converters](https://docs.qmk.fm/#/feature_converters?id=converters)):
- `qmk compile -kb crkbd -km jpe230 -e CONVERT_TO<target>`

M keyboards/crkbd/keymaps/jpe230/rules.mk => keyboards/crkbd/keymaps/jpe230/rules.mk +19 -6
@@ 1,12 1,25 @@
# Shared rules for both of my Corne
OLED_ENABLE       = yes
OLED_DRIVER       = SSD1306
LTO_ENABLE        = yes
VIA_ENABLE        = yes
RGB_MATRIX_ENABLE = yes

# Rules for my Corne without RGB
# WPM_ENABLE        = yes
# MOUSEKEY_ENABLE   = yes
SRC += oled/oled_handler.c process_record.c

ifneq ($(CONVERT_TO),)
    # Asume ARM
    DEBUG_MATRIX_SCAN_RATE_ENABLE = yes
    WPM_ENABLE = yes
    CONSOLE_ENABLE = yes
    SRC +=  oled/rp2040/master/oled_master_handler.c \
            oled/rp2040/master/indicators_down.c \
            oled/rp2040/master/indicators_up.c \
            oled/rp2040/slave/oled_slave_handler.c \
            oled/rp2040/slave/ocean_dream.c
else
    # Asume AVR
    LTO_ENABLE = yes
    SRC +=  oled/avr/master/oled_master_handler.c \
            oled/avr/slave/oled_slave_handler.c
endif

# Rules for my Corne with RGB
RGB_MATRIX_ENABLE = yes