Help us understand the problem. What is going on with this article?

Infinity ErgoDox の LCD でアニメーション

Infinity ErgoDox の LCD でアニメーションを表示して遊ぶ方法です。

ソースコードはこちら

https://github.com/koktoh/qmk_firmware_koktoh/tree/dev/ergodox_infinity_lcd_animation_pacman/keyboards/ergodox_infinity

※もろもろの事情で動作確認は行っていませんが、たぶん動くと思います。

Infinity ErgoDox とは

Input Club 社が販売している ErgoDox です。
LCD が標準で基板に搭載されており、同社提供の Configurator で簡単にキーマップを変更できます。

出荷状態では独自のファームウェアが載っていますが、 QMK Firmware にもプロジェクトがあり、 QMK Firmware に書き換えることもできます。

今回は QMK Firmware に書き換えることを前提とします。
公式のファームウェアに戻すことも可能なので、ご安心ください。

Infinity ErgoDox の LCD でアニメーションしてみる

LCD に表示するデータを用意する

何はともあれ、表示するためのデータがないと始まりません。
LCD の表示領域は 128 x 32 なので、それに合わせて作りましょう。
今回は、みんな大好き(?)パックマンのアニメーションを作っていきます。

イメージとしてはこんな感じです。

pacman.gif

雑に自作したところ、画像数は28枚となりました。
これらの画像を LCD で表示するためのデータへと変換します。

LCD に表示するためのデータ形式

まずは、 LCD に表示するためのデータ形式について簡単に説明します。
アニメーションに必要なのは主に2つです。

  • 画像のバイナリ配列
  • 画像を表示するためのキーフレーム

画像のバイナリ配列

これは、表示したい画像自体のデータです。
例として、 QMK Firmware のロゴのデータを見てみましょう。( quantum\visualizer\resources\lcd_logo.c にあります)
そのままだと見づらいので少し整形しています。

__attribute__((weak)) const uint8_t resource_lcd_logo[512] = {
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0xf8, 0xfe, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x38, 0x38, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x38, 0x38, 0x38, 0x06, 0x29, 0x41, 0x24, 0x52, 0x24, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x38, 0x38, 0x38, 0x09, 0x55, 0x42, 0xaa, 0xaa, 0xaa, 0xa8, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x38, 0x38, 0x38, 0x09, 0x55, 0x82, 0x28, 0xaa, 0xae, 0x8c, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x38, 0x38, 0x38, 0x09, 0x55, 0x43, 0x28, 0xaa, 0xaa, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x38, 0x38, 0x38, 0x0a, 0x55, 0x42, 0x28, 0xaa, 0xaa, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x38, 0x38, 0x38, 0x05, 0x45, 0x42, 0x28, 0x89, 0x4a, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x18, 0x38, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x1c, 0x38, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x0e, 0x38, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x03, 0xff, 0x80, 0x04, 0x45, 0x14, 0xa4, 0x92, 0x83, 0x52, 0x22, 0x22, 0x36, 0x00, 0x00,
    0x00, 0x00, 0x38, 0x00, 0x0a, 0xaa, 0xaa, 0xaa, 0xba, 0x84, 0x55, 0x55, 0x57, 0x45, 0x00, 0x00,
    0x00, 0x00, 0x38, 0x00, 0x08, 0xaa, 0xaa, 0xaa, 0x92, 0xb2, 0x55, 0x55, 0x42, 0x65, 0x00, 0x00,
    0x00, 0x00, 0x38, 0x00, 0x08, 0xaa, 0xaa, 0xaa, 0x92, 0x81, 0x56, 0x65, 0x42, 0x45, 0x00, 0x00,
    0x00, 0x00, 0x38, 0x00, 0x0a, 0xaa, 0xaa, 0xaa, 0x92, 0x81, 0x54, 0x45, 0x42, 0x45, 0x00, 0x00,
    0x00, 0x00, 0x38, 0x00, 0x04, 0x48, 0xa2, 0x4a, 0x89, 0x06, 0x24, 0x42, 0x41, 0x36, 0x00, 0x00,
    0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 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, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};

8ビットのデータが16列32行並んでいます。バイナリとして考えると、 (8 x 16) x 32 = 128 x 32 ビットと、 LCD の表示サイズと同じになっていることがわかります。
LCD はビットが 1 のピクセルのみ点灯します。
左上から128ビット分描画して、次の行に移ってまた左から128ビット分描画して……、を32行分繰り返しているわけです。
そして、8ビットをひとまとまりとして HEX 値で保持しているわけです。直観的でわかりやすいかと思います。

画像データの保持の仕方がわかったところで、先ほどの画像をすべてこの形式に変換しましょう。
ツールや自分でスクリプト等を組んで行ってもいいです。

例えば、以下のように28枚分の配列を作り、1つのファイルにまとめてしまいます。

const uint8_t pacman_bmp_00[512] = {
    0x00, 0x00, ...
    .
    .
    .
};

const uint8_t pacman_bmp_01[512] = {
    0x00, 0x00, ...
    .
    .
    .
};

.
.
.

const uint8_t pacman_bmp_27[512] = {
    0x00, 0x00, ...
    .
    .
    .
};

キーフレーム

次に、画像を表示するためのキーフレームを作成します。
画像1枚に対して1つキーフレームを定義します。

bool lcd_keyframe_draw_pacman_00(keyframe_animation_t* animation, visualizer_state_t* state) {
    (void)state;
    gdispClear(White);

    gdispGBlitArea(GDISP, 0, 0, LCD_WIDTH, LCD_HEIGHT, 0, 0, LCD_WIDTH, (pixel_t*)pacman_bmp_00);

    return false;
};

gdispGBlitArea 関数で描画範囲や描画するデータを指定しています。ここでは、画像データに先ほど作った pacman_bmp_00 を指定しています。

これも先ほどと同様に28枚分作ってファイルにまとめます。

LCD に表示するようにする

これで準備が整いました。 LCD でアニメーションするようにしていきましょう。

なお、 Infinity ErgoDox では一般的な OLED ドライバ API を使いません。
キーボードプロジェクト配下にある、 visualizer.c で制御します。

各関数についてはコメントで説明がついているので、そんなに迷うことはないと思います。

今回いじるのは以下の関数です。

static keyframe_animation_t lcd_bitmap_animation = {
    .num_frames = 1,
    .loop = false,
    .frame_lengths = {gfxMillisecondsToTicks(0)},
    .frame_functions = {lcd_keyframe_display_layer_bitmap},
};

他にも同様の関数がいくつか定義されていますが、これと同じように編集すれば対応できます。

それぞれの設定は以下のようになっています。

項目 説明
.num_frames アニメーションのフレーム数
.loop ループするか
.frame_lengths 各キーフレームの表示時間の配列
.frame_functions キーフレームの配列

今回は28個のキーフレームを 200ms ずつ表示して無限ループさせるようにします。

static keyframe_animation_t lcd_bitmap_animation = {
    .num_frames = 28,
    .loop = true,
    .frame_lengths = { gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200), gfxMillisecondsToTicks(200) },
    .frame_functions = { lcd_keyframe_draw_pacman_00, lcd_keyframe_draw_pacman_01, lcd_keyframe_draw_pacman_02, lcd_keyframe_draw_pacman_03, lcd_keyframe_draw_pacman_04, lcd_keyframe_draw_pacman_05, lcd_keyframe_draw_pacman_06, lcd_keyframe_draw_pacman_07, lcd_keyframe_draw_pacman_08, lcd_keyframe_draw_pacman_09, lcd_keyframe_draw_pacman_10, lcd_keyframe_draw_pacman_11, lcd_keyframe_draw_pacman_12, lcd_keyframe_draw_pacman_13, lcd_keyframe_draw_pacman_14, lcd_keyframe_draw_pacman_15, lcd_keyframe_draw_pacman_16, lcd_keyframe_draw_pacman_17, lcd_keyframe_draw_pacman_18, lcd_keyframe_draw_pacman_19, lcd_keyframe_draw_pacman_20, lcd_keyframe_draw_pacman_21, lcd_keyframe_draw_pacman_22, lcd_keyframe_draw_pacman_23, lcd_keyframe_draw_pacman_24, lcd_keyframe_draw_pacman_25, lcd_keyframe_draw_pacman_26, lcd_keyframe_draw_pacman_27 },
};

これで LCD でアニメーションがされるようになりました。
なお、今回の変更ではレイヤーを変更すると別のアニメーションが実行され、また最初から再生されます。
それを避ける方法もありますが、今回は割愛します。

さて、実は、これではコンパイル時にエラーが発生します。
次はそれを解決しましょう。

最大キーフレーム数を拡張する

実は、 quantum\visualizer\visualizer.h で最大キーフレーム数が定義されているのですが、16個までとなっています。
今回はキーフレーム数が28あるので最大値を超えてしまい、コンパイルが通りません。

なので、定義を変えてしまいましょう。

// #define MAX_VISUALIZER_KEY_FRAMES 16
#define MAX_VISUALIZER_KEY_FRAMES 32

雑に 32 に変更しました。
これでコンパイルが通るようになります。

LCD でアニメーションを楽しもう!

あとはコンパイルしてファームウェアを焼けば LCD でアニメーションが表示されます。(焼き方は readme を読んでください)
なお、今回作成したコードのヘッダーファイルの設定やインクルード宣言など、基本的なことは省略していますので、適宜追加してください。

ちなみに、私はこんなことをしています。

響ちゃんかわいい……

参考になったかはわかりませんが、こんな感じで Infinity ErgoDox の LCD で遊べるよ、というお話でした。
皆さんも、好きなキャラを LCD に表示してみたり、好き勝手アニメーションさせてみたり、遊んでみてください。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした