M5 Cardputer を USB キーボードに

M5Cardputer のサンプルプログラムに「M5Cardputer を USBキーボードにする」というものがありました!
これは、長らく探し続けていた「小型USB有線キーボード」…なのでは!

https://github.com/m5stack/M5Cardputer/tree/master/examples/Basic/keyboard/usbKeyboard

シンプルな機能のみですが、USBキーボードとしてしっかり動作します!

キーコードのみを返してるので、OSの標準キーボードとして認識されるみたいですね。日本語版Windowsからは日本語キーボード扱いされるので、記号と入力文字が合わなくなります。(そういうものだと思って使うなら問題なしです。)

Fnキーを押したときに、カーソルキーのコードを返すようにしました。これでカーソルキー使えます!

あとは押しっぱなしの時のキーリピートが欲しいとこですね。いろいろ試してみた結果、keyboard.releaseAll() の位置を is Pressed() の else のところに移動するとバッチリでした。

おそらく、近いうちに、本体単独でプログラムを入れ替え実行可能な Lovyan Launcher for Cardputer が登場すると思いますが、その前に、プログラム入れ替えの M5Stack-SD-Updater 単体で動作させてみました。

「A」キーを押しながらリセットすることで、指定したプログラムに入れ替わります。


プログラム全体はこういう感じです。(M5Stack-SD-Updater 対応で SD 関連も入ってます。)

/**
 * @file usbKeyboard.ino
 * @author SeanKwok (shaoxiang@m5stack.com)
 * @brief M5Cardputer USB Keyboard test
 * @version 0.1
 * @date 2023-10-13
 *
 *
 * @Hardwares: M5Cardputer
 * @Platform Version: Arduino M5Stack Board Manager v2.0.7
 * @Dependent Library:
 * M5GFX: https://github.com/m5stack/M5GFX
 * M5Unified: https://github.com/m5stack/M5Unified
 *
 * modified by @shikarunochi
 */

#include <SD.h>
#include <M5Cardputer.h>
#include <USB.h>
#include <USBHIDKeyboard.h>

#include <M5StackUpdater.h>

USBHIDKeyboard Keyboard;
SPIClass SPI2;

void setup() {
     auto cfg = M5.config();
     M5Cardputer.begin(cfg, true);
     SPI2.begin(
      M5.getPin(m5::pin_name_t::sd_spi_sclk),
      M5.getPin(m5::pin_name_t::sd_spi_miso),
      M5.getPin(m5::pin_name_t::sd_spi_mosi),
      M5.getPin(m5::pin_name_t::sd_spi_ss)
    );
    while (false == SD.begin(M5.getPin(m5::pin_name_t::sd_spi_ss),SPI2)) {
      delay(500);
    }

    M5Cardputer.update();
    
    if (M5Cardputer.Keyboard.isKeyPressed('a')) {
      updateFromFS(SD,"/helloWorld.bin");
      ESP.restart();
    }
    
    M5Cardputer.Display.setRotation(1);
    M5Cardputer.Display.setTextColor(GREEN);
    M5Cardputer.Display.setTextDatum(middle_center);
    M5Cardputer.Display.setTextFont(&fonts::Orbitron_Light_24);
    M5Cardputer.Display.setTextSize(1);
    M5Cardputer.Display.drawString("USB Keyboard",
                                   M5Cardputer.Display.width() / 2,
                                   M5Cardputer.Display.height() / 2);
    
    USB.begin();
}

void loop() {
    M5Cardputer.update();
    // max press 3 button at the same time
    if (M5Cardputer.Keyboard.isChange()) {
        if (M5Cardputer.Keyboard.isPressed()) {
            Keyboard_Class::KeysState status = M5Cardputer.Keyboard.keysState();
            KeyReport report = {0};
            report.modifiers = status.modifiers;
            uint8_t index    = 0;
            for (auto i : status.hid_keys) {
                auto fixedI = i;
                if(status.fn){
                    switch(i)
                    {
                        //https://wiki.onakasuita.org/pukiwiki/?HID%2F%E3%82%AD%E3%83%BC%E3%82%B3%E3%83%BC%E3%83%89
                        case 0x36:fixedI = 0x50;break; //, LeftArrow
                        case 0x37:fixedI = 0x51;break; //. DownArrow
                        case 0x33:fixedI = 0x52;break; //; UpArrow
                        case 0x38:fixedI = 0x4F;break; /// RightArrow
                    }
                }
                report.keys[index] = fixedI;
                index++;
                if (index > 5) {
                    index = 5;
                }
            }
            Keyboard.sendReport(&report);
            //Keyboard.releaseAll();

            // only text for display
            String keyStr = "";
            for (auto i : status.word) {
                if (keyStr != "") {
                    keyStr = keyStr + "+" + i;
                } else {
                    keyStr += i;
                }
            }

            if (keyStr.length() > 0) {
                M5Cardputer.Display.clear();
                M5Cardputer.Display.drawString(
                    keyStr, M5Cardputer.Display.width() / 2,
                    M5Cardputer.Display.height() / 2);
            }

        } else {
            M5Cardputer.Display.clear();
            M5Cardputer.Display.drawString("USB Keyboard",
                                           M5Cardputer.Display.width() / 2,
                                           M5Cardputer.Display.height() / 2);
            Keyboard.releaseAll();
        }
    }
}

platform.ini

[env:m5stack-cardputer]
platform = espressif32

framework = arduino
board = esp32-s3-devkitc-1
board_build.mcu = esp32s3

lib_ldf_mode = deep
board_build.f_cpu = 240000000L
lib_deps = 	
	https://github.com/m5stack/M5Unified
	https://github.com/m5stack/M5Cardputer
	https://github.com/pfeerick/elapsedMillis
	https://github.com/tobozo/M5Stack-SD-Updater