pico-jxglib とコマンドライン編集機能の話
pico-jxglib は、ワンボードマイコン Raspberry Pi Pico の Pico SDK プログラミングをサポートするライブラリです。
「pico-jxglib で Pico ボードに USB キーボード・マウスを接続する話」 で、Pico ボードに USB キーボードをつなげました。今回はそれを使って Linux の bash シェルなどで使われている readline に似たコマンドライン編集機能を Pico ボードで実現する話です。
USB キーボードのほかに、タクトスイッチやキーボードマトリクスも入力デバイスとして使えますし、PC とのシリアル通信上でもコマンドライン編集が可能になります。
キーボードでの編集入力ができると、Pico ボードがいよいよ独立したマイコンになった気がしますね。「マイコンのモニタプログラム」と聞いて思わずときめいてしまう人には、ぜひ試してもらいたいです。
コマンドライン編集機能について
pico-jxglib のコマンドライン編集機能は以下のキー操作を受け付けます。
Ctrl キー | 単独キー | 機能 |
---|---|---|
Ctrl + P
|
Up |
一つ前のヒストリを表示します |
Ctrl + N
|
Down |
一つ後のヒストリを表示します |
Ctrl + B
|
Left |
カーソルを一文字左に移動します |
Ctrl + F
|
Right |
カーソルを一文字右に移動します |
Ctrl + A
|
Home |
カーソルを行の先頭に移動します |
Ctrl + E
|
End |
カーソルを行の最後に移動します |
Ctrl + D
|
Delete |
カーソル位置の文字を消去します |
Ctrl + H
|
Back |
カーソル位置の一つ前の文字を消去します |
Ctrl + J
|
Return |
入力内容を確定します |
Ctrl + K
|
カーソル位置から末尾までを消去します | |
Ctrl + U
|
カーソル位置の一つ前から行頭までを消去します |
Pico ボードに接続したディスプレイを使う場合はさらに以下のキー操作を受け付けます。
Ctrl キー | 単独キー | 機能 |
---|---|---|
PageUp |
ロールバック画面を一行上に移動します。Shift を押すとページ単位で移動します |
|
PageDown |
ロールバック画面を一行下に移動します。Shift を押すとページ単位で移動します |
二つの Terminal
コマンドライン編集機能は、以下の二つの Terminal で利用できます。
-
Display::Terminal
... Pico ボードに接続したディスプレイを使ってコマンドライン入力をします。Pico 単独でコマンド編集ができます -
Serial::Terminal
.. シリアル通信を使ってコマンドライン入力をします。Pico に接続したホスト PC のターミナルソフト上でコマンド編集をします
Display::Terminal
は ST7789
などのディスプレイデバイスを出力先に指定し、入力機器として USBHost::Keyboard
(USB キーボード)、Stdio::Keyboard
(Stdio を経由したホストからのキーボード入力)、GPIO::Keyboard
(GPIO に接続されたスイッチ入力)、GPIO::KeyboardMatrix
(GPIO にマトリクス接続されたスイッチ入力) を設定します。
Serial::Terminal
は Stdio を出力先に指定します[1]。入力機器として USBHost::Keyboard
、Stdio::Keyboard
、GPIO::Keyboard
、GPIO::KeyboardMatrix
を設定します。
実際のプロジェクト
開発環境のセットアップ
Visual Studio Code や Git ツール、Pico SDK のセットアップが済んでいない方は「Pico SDK ことはじめ」 をご覧ください。
pico-jxglib は GitHub からレポジトリをクローンすることで入手できます。
git clone https://github.com/ypsitau/pico-jxglib.git
cd pico-jxglib
git submodule update --init
Display::Terminal を使う
Pico ボードにキーボードとディスプレイをつなげて、Pico ボード単体でコマンド入力ができます。いろいろな組み合わせが可能なので、いくつか具体例を紹介します。
Display::Terminal 用プロジェクトの作成
VSCode のコマンドパレットから >Raspberry Pi Pico: New Pico Project
を実行し、以下の内容でプロジェクトを作成します。Pico SDK プロジェクト作成の詳細や、ビルド、ボードへの書き込み方法については「Pico SDK ことはじめ」 を参照ください。
-
Name ... プロジェクト名を入力します。今回は例として
cmdedit-display-test
を入力します - Board type ... ボード種別を選択します
- Location ... プロジェクトディレクトリを作る一つ上のディレクトリを選択します
- Stdio support .. Stdio に接続するポート (UART または USB) を選択しますが、USB はこのプログラムで使うので選択できません。UART のみ選択するか、どちらも未チェックのままにしておきます
-
Code generation options ...
Generate C++ code
にチェックをつけます
プロジェクトディレクトリと pico-jxglib
のディレクトリ配置が以下のようになっていると想定します。
+-[pico-jxglib]
+-[cmdedit-display-test]
+-CMakeLists.txt
+-cmdedit-display-test.cpp
+- ...
以下、このプロジェクトをもとに CMakeLists.txt
やソースファイルを編集してプログラムを作成していきます。
USB キーボード + TFT LCD (ST7789)
USB キーボードは USB 端子に microB-TypeA 変換アダプタを使って接続します (詳細はこちら)。TFT LCD は ST7789 を使用しますが、他のディスプレイデバイスを接続する場合は「pico-jxblib と TFT LCD の話」 を参照してください。
ブレッドボードの配線イメージを以下に示します。5V の電源をPico ボードの VBUS (40 番ピン) につなげていることに注意してください。
CMakeLists.txt
の最後に以下の行を追加してください。
target_link_libraries(cmdedit-display-test jxglib_USBHost jxglib_ST7789)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../pico-jxglib pico-jxglib)
jxglib_configure_USBHost(cmdedit-display-test CFG_TUH_HID 3)
ソースファイルを以下のように編集します。
#include <stdio.h>
#include "pico/stdlib.h"
#include "jxglib/USBHost.h"
#include "jxglib/ST7789.h"
#include "jxglib/Font/shinonome16.h"
using namespace jxglib;
Display::Terminal terminal;
int main()
{
::stdio_init_all();
USBHost::Initialize();
USBHost::Keyboard keyboard;
::spi_init(spi1, 125 * 1000 * 1000);
GPIO14.set_function_SPI1_SCK();
GPIO15.set_function_SPI1_TX();
ST7789 display(spi1, 240, 320, {RST: GPIO10, DC: GPIO11, CS: GPIO12, BL: GPIO13});
display.Initialize(Display::Dir::Rotate0);
terminal.SetFont(Font::shinonome16).AttachDisplay(display).AttachKeyboard(keyboard);
terminal.Println("ReadLine Test Program");
for (;;) {
char* str = terminal.ReadLine(">");
terminal.Printf("%s\n", str);
}
}
terminal.ReadLine()
は入力された文字列へのポインタを返します。
写真では分かりませんが、カーソルもしっかり点滅しています。
USB キーボード + OLED (SSD1306)
USB キーボードは USB 端子に microB-TypeA 変換アダプタを使って接続します。OLED は SSD1306 を使用します。
ブレッドボードの配線イメージを以下に示します。5V の電源をPico ボードの VBUS (40 番ピン) につなげていることに注意してください。
CMakeLists.txt
の最後に以下の行を追加してください。
target_link_libraries(cmdedit-display-test jxglib_USBHost jxglib_SSD1306)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../pico-jxglib pico-jxglib)
jxglib_configure_USBHost(cmdedit-display-test CFG_TUH_HID 3)
ソースファイルを以下のように編集します。
#include <stdio.h>
#include "pico/stdlib.h"
#include "jxglib/USBHost.h"
#include "jxglib/SSD1306.h"
#include "jxglib/Font/shinonome12.h"
using namespace jxglib;
Display::Terminal terminal;
int main()
{
::stdio_init_all();
USBHost::Initialize();
USBHost::Keyboard keyboard;
::i2c_init(i2c0, 400 * 1000);
GPIO4.set_function_I2C0_SDA().pull_up();
GPIO5.set_function_I2C0_SCL().pull_up();
SSD1306 display(i2c0, 0x3c);
display.Initialize();
terminal.SetFont(Font::shinonome12)
.AttachDisplay(display).AttachKeyboard(keyboard);
terminal.Println("ReadLine Test Program");
for (;;) {
char* str = terminal.ReadLine(">");
terminal.Printf("%s\n", str);
}
}
GPIO キーボードマトリクス + TFT LCD (ST7789)
GPIO に接続したキーボードマトリクス接続します。ここでは Amazon などで容易に入手できる 4x4 マトリクスタイプのものを使用します。
ブレッドボードの配線イメージを以下に示します。
CMakeLists.txt
の最後に以下の行を追加してください。
target_link_libraries(cmdedit-display-test jxglib_ST7789)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../pico-jxglib pico-jxglib)
ソースファイルを以下のように編集します。
#include <stdio.h>
#include "pico/stdlib.h"
#include "jxglib/ST7789.h"
#include "jxglib/Font/shinonome16.h"
using namespace jxglib;
Display::Terminal terminal;
int main()
{
::stdio_init_all();
GPIO::KeyboardMatrix keyboard;
const Keyboard::KeySet keySetTbl[] = {
VK_1, VK_2, VK_3, VK_BACK,
VK_4, VK_5, VK_6, VK_UP,
VK_7, VK_8, VK_9, VK_DOWN,
VK_LEFT, VK_0, VK_RIGHT, VK_RETURN,
};
const GPIO::KeyRow keyRowTbl[] = { GPIO16, GPIO17, GPIO18, GPIO19 };
const GPIO::KeyCol keyColTbl[] = {
GPIO20.pull_up(), GPIO21.pull_up(), GPIO26.pull_up(), GPIO27.pull_up()
};
keyboard.Initialize(keySetTbl,
keyRowTbl, count_of(keyRowTbl),
keyColTbl, count_of(keyColTbl), GPIO::LogicNeg);
::spi_init(spi1, 125 * 1000 * 1000);
GPIO14.set_function_SPI1_SCK();
GPIO15.set_function_SPI1_TX();
ST7789 display(spi1, 240, 320, {RST: GPIO10, DC: GPIO11, CS: GPIO12, BL: GPIO13});
display.Initialize(Display::Dir::Rotate0);
terminal.SetFont(Font::shinonome16)
.AttachDisplay(display).AttachKeyboard(keyboard);
terminal.Println("ReadLine Test Program");
for (;;) {
char* str = terminal.ReadLine(">");
terminal.Printf("%s\n", str);
}
}
キーボードマトリクスには、回り込み防止用のダイオードが入ったものとないものがあります。回り込み防止用のダイオードが入っている場合、ダイオードの極性によって以下にようにコードを変更してください。
-
極性が col → row の場合
keyColTbl
中の GPIO の設定をpull_up()
にして、keyboard.Initialize()
の最後の引数にGPIO::LogicNeg
を設定してください。 -
極性が row → col の場合
keyColTbl
中の GPIO の設定をpull_down()
にして、keyboard.Initialize()
の最後の引数にGPIO::LogicPos
を設定してください。
ダイオードが入っていない場合はどちらでもかまいません。
Serial::Terminal を使う
シリアル回線で Pico ボードを PC に接続します。
Serial::Terminal 用プロジェクトの作成
VSCode のコマンドパレットから >Raspberry Pi Pico: New Pico Project
を実行し、以下の内容でプロジェクトを作成します。Pico SDK プロジェクト作成の詳細や、ビルド、ボードへの書き込み方法については「Pico SDK ことはじめ」 を参照ください。
-
Name ... プロジェクト名を入力します。今回は例として
cmdedit-serial-test
を入力します - Board type ... ボード種別を選択します
- Location ... プロジェクトディレクトリを作る一つ上のディレクトリを選択します
- Stdio support .. Stdio に接続するポート (UART または USB) を選択します
-
Code generation options ...
Generate C++ code
にチェックをつけます
プロジェクトディレクトリと pico-jxglib
のディレクトリ配置が以下のようになっていると想定します。
+-[pico-jxglib]
+-[cmdedit-serial-test]
+-CMakeLists.txt
+-cmdedit-serial-test.cpp
+- ...
Stdio 経由でホスト PC と接続
Pico ボードを UART または USB 経由でホスト PC と接続します (詳細はこちら)。
CMakeLists.txt
の最後に以下の行を追加してください。
target_link_libraries(cmdedit-serial-test jxglib_Serial)
add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../pico-jxglib pico-jxglib)
ソースファイルを以下のように編集します。
#include <stdio.h>
#include "pico/stdlib.h"
#include "jxglib/Serial.h"
using namespace jxglib;
Serial::Terminal terminal;
int main()
{
::stdio_init_all();
terminal.Initialize();
terminal.AttachPrintable(Stdio::Instance).AttachKeyboard(Stdio::GetKeyboard());
terminal.Println("ReadLine Test Program");
for (;;) {
char* str = terminal.ReadLine(">");
terminal.Printf("%s\n", str);
}
}
ホスト PC のターミナルソフトで、コマンドラインの編集入力ができます。
-
将来ソケットインターフェースが追加される予定です ↩︎
Discussion