{"id":16219952,"url":"https://github.com/sago35/tinygo-workshop-keyboard","last_synced_at":"2025-04-03T02:30:54.179Z","repository":{"id":171808651,"uuid":"646814590","full_name":"sago35/tinygo-workshop-keyboard","owner":"sago35","description":"2023/06/02 開催の Go Conference 2023 内の TinyGo で自作キーボードを作るハンズオン用の記事 ","archived":false,"fork":false,"pushed_at":"2023-06-02T02:39:06.000Z","size":644,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-02T14:18:22.922Z","etag":null,"topics":["firmware","go","hid","keeb","keyboard","tinygo","usb","usbhid"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sago35.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-05-29T11:59:40.000Z","updated_at":"2024-08-04T06:55:46.000Z","dependencies_parsed_at":null,"dependency_job_id":"429e962c-183a-44ed-839e-a025cd201052","html_url":"https://github.com/sago35/tinygo-workshop-keyboard","commit_stats":null,"previous_names":["sago35/tinygo-workshop-keyboard"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sago35%2Ftinygo-workshop-keyboard","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sago35%2Ftinygo-workshop-keyboard/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sago35%2Ftinygo-workshop-keyboard/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sago35%2Ftinygo-workshop-keyboard/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sago35","download_url":"https://codeload.github.com/sago35/tinygo-workshop-keyboard/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246925209,"owners_count":20855858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["firmware","go","hid","keeb","keyboard","tinygo","usb","usbhid"],"created_at":"2024-10-10T11:56:39.689Z","updated_at":"2025-04-03T02:30:53.595Z","avatar_url":"https://github.com/sago35.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# お知らせ\n\nTinyGo 0.26 + Wio Terminal という組み合わせで技術書「基礎から学ぶ TinyGoの組込み開発」 (2022/11/12 発売) を執筆しました。本ページと合わせて確認してみてください。\n\n* https://sago35.hatenablog.com/entry/2022/11/04/230919\n\n----\n\n![](./images/sgkb-0.2.0.jpg)\n\nこのページは 2023/06/02 に開催される Go Conference 2023 内の TinyGo で自作キーボードを作るハンズオン用の記事です。\n不明点は、このリポジトリの Issue や [twitter:sago35tk](https://twitter.com/sago35tk) で質問いただければサポートします。\nTwitter のハッシュタグは [#gocon](https://twitter.com/hashtag/gocon) および [#tinygo](https://twitter.com/hashtag/tinygo) です。\n\n# 環境設定／参加に必要なもの\n\n## TinyGo のインストール\n\n以下のインストールが必要です。\nTinyGo については、このページの記入時点の最新版である v0.27.0 の URL を記載しましたが、このハンズオンでは後述する dev branch 版 (開発最新版) を使うことを推奨します。\n\n* Git\n    * https://git-scm.com/downloads\n* Go\n    * https://go.dev/dl/\n* TinyGo\n    * https://github.com/tinygo-org/tinygo/releases/tag/v0.27.0\n\nそれぞれの実行体に PATH が通っていれば使うことができます。\n少し Version が古いですが以下も参考になると思います。\n\n* [TinyGo のインストール](https://qiita.com/sago35/items/92b22e8cbbf99d0cd3ef#tinygo-%E3%81%AE%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB)\n\n### TinyGo の dev branch 版\n\nGitHub Actions でビルドされた Artifact \u003e release-double-zipped をダウンロードしてください。\n\n* windows\n  * https://github.com/tinygo-org/tinygo/actions/workflows/windows.yml?query=branch%3Adev\n* linux\n  * https://github.com/tinygo-org/tinygo/actions/workflows/linux.yml?query=branch%3Adev\n* macos\n  * https://github.com/tinygo-org/tinygo/actions/workflows/build-macos.yml?query=branch%3Adev\n\n\n詳細は以下を参照してください。\n\n* [TinyGo の開発版のビルド方法と、ビルドせずに開発版バイナリを手に入れる方法](https://qiita.com/sago35/items/33e63ca5073f572ad69c#pr-%E5%86%85%E3%81%A7%E4%BD%9C%E6%88%90%E3%81%95%E3%82%8C%E3%81%9F%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA%E3%82%92%E4%BD%BF%E3%81%86)\n\n### LSP / gopls 対応\n\nTinyGo は、 machine package などを GOROOT に配置しているため設定を行うまでは gopls 等でエラーが表示され machine.LED の定義元へのジャンプ等が出来ません。\nTinyGo は machine package など (Go を良く知っていても) 慣れていない package 構成であったり、 build-tag による分岐などが多いため TinyGo 用の LSP の設定をしておいた方が無難です。\n\n公式ドキュメントは以下にあります。\n\n* https://tinygo.org/docs/guides/ide-integration/\n\nVSCode の場合は TinyGo という拡張をインストールすると良いです。\nVim (+ vim-lsp) の場合は github.com/sago35/tinygo.vim を使ってみてください。\n\n日本語の情報としては以下に記載しています。\n\n* [TinyGo + 'VSCode or Vim (もしくはそれ以外の LSP 対応エディタ)' で gopls 連携する方法](https://qiita.com/sago35/items/c30cbce4a0a3e12d899c)\n* [TinyGo + Vim で gopls するための設定](https://qiita.com/sago35/items/f0b058ed5c32b6446834)\n\n\n## マイコンボード\n\n参加にあたっては、各自でマイコンボードを準備お願いします。\n推奨は以下です。\n\n* Wio Terminal\n  * https://akizukidenshi.com/catalog/g/gM-15275/\n  * 本体にボタンがたくさんあるのでそのままでも楽しめますが、後述の wiokey があるとより楽しめます\n* XIAO RP2040\n  * https://akizukidenshi.com/catalog/g/gM-17044/\n  * 本体にボタンが無いため、後述の sgkey か外付けボタン等があったほうが良い\n* Raspberry Pi Pico\n  * https://akizukidenshi.com/catalog/g/gM-16132/\n  * 本体にボタンが無いため、外付けボタン等があったほうが良い\n    * 現時点の TinyGo では BOOTSEL ボタンをボタンとして使用することは出来ません\n\n一応、マイコンの種類が ATSAMD51 / ATSAMD21 / RP2040 / nRF52840 であれば問題ありません。\nマイコンボード選びは以下の記事を確認いただくと良いですが、基本的には Wio Terminal がおすすめです。\n\n* [TinyGo 0.27 で遊べるマイコンボード一覧](https://sago35.hatenablog.com/entry/2023/02/13/220248)\n\n### wiokey : Wio Terminal 向けオプション\n\n![](./images/wiokey.jpg)\n\nwiokey は Wio Terminal に 6 キー追加するためのボードです。\n無くてもハンズオン可能ですが、wiokey があると自作キーボード気分が盛り上がると思います。\n\n以下で基板単体、ハンダ付け済み完成品 (Wio Terminal は付属しません) を購入できます。\n\n* https://sago35.booth.pm/\n\n\n### sgkey : XIAO RP2040 向けオプション\n\n![](./images/sgkey.jpg)\n\nsgkey は XIAO RP2040 などの XIAO 系ボードに 6 キーと液晶を追加するためのボードです。\n無くてもハンズオン可能ですが、 sgkey があると自作キーボード気分が盛り上がると思います。\n\n以下で基板単体、ハンダ付け済み完成品 (XIAO RP2040 は付属しません) を購入できます。\n\n* https://sago35.booth.pm/\n\n\n# TinyGo で自作キーボードを作る\n\n基本的には上記推奨マイコンボードを例として記載します。\nそれ以外の環境を使う場合は、適宜質問するなどしてください。\n\n## L チカ\n\n以下を実行します。\n以降では --target は wioterminal を例として記載します。\n\n```\n# Wio Terminal の場合\n$ tinygo flash --target wioterminal --size short examples/blinky1\n\n# XIAO RP2040 の場合\n$ tinygo flash --target xiao-rp2040 --size short examples/blinky1\n\n# Raspberry Pi Pico\n$ tinygo flash --target pico --size short examples/blinky1\n```\n\nなお、 xiao-rp2040 と pico については、 tinygo flash 時にうまくいかない場合は BOOTSEL を押したまま USB 接続してブートローダーに入れてから tinygo flash してください。\n一度書き込みに成功した後は tinygo flash が成功するようになります。\n\n## L チカ (その2)\n\n以下のソース (./01_blinky1) を適当な場所に作成してください。\nled を 100ms 毎に反転させるソースコードとなります。\n\n```go\npackage main\n\nimport (\n\t\"machine\"\n\t\"time\"\n)\n\nfunc main() {\n\tled := machine.LED\n\tled.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tfor {\n\t\tled.Low()\n\t\ttime.Sleep(time.Millisecond * 100)\n\t\tled.High()\n\t\ttime.Sleep(time.Millisecond * 100)\n\t}\n}\n```\n\nGo と同じく go mod init してから tinygo flash を実行することで書き込むことができます。\n\n```\n$ ls\nmain.go\n\n$ go mod init blinky1\n\n$ tinygo flash --target pico --size short .\n```\n\nうまく書き込めたら点滅周期を変えたり、 Wio Terminal の場合は `machine.LED` の代わりに `machine.LCD_BACKLIGHT` を使ってみてください。\n外付けの LED を持っている場合は、それらをポート操作で光らせてみてもよいでしょう。\n\n## USB CDCで Hello World\n\n今回のハンズオンで使用するマイコンは TinyGo から USB 機能を使うことができます。\nUSB CDC は Universal Serial Bus Communications Device Class の略で、雑な説明としてはパソコンとマイコン間で通信を行うためのものです。\n説明するよりも実際に試したほうが分かりやすいので、まずは以下を実行してみてください。\n`--monitor` というオプションを追加する必要があります。\n\n```\n$ tinygo flash --target wioterminal --size short --monitor examples/serial\n```\n\nWindows で実行すると以下のようになります。\n\n```\n$ tinygo flash --target wioterminal --size short --monitor examples/serial\n   code    data     bss |   flash     ram\n   7092     108    6672 |    7200    6780\nConnected to COM38. Press Ctrl-C to exit.\nhello world!\nhello world!\nhello world!\n(以下省略)\n```\n\nexamples/serial は以下のようなソース (./02_usbcdc-serial) です。\n`hello world!` を表示してから 1 秒待つ、を繰り返しています。\nこちらも待ち時間や、表示文字列の変更、あるいは fmt.Printf() を使った書き込み、などに変えてみてください。\n\n```\npackage main\n\nimport \"time\"\n\nfunc main() {\n\tfor {\n\t\tprintln(\"hello world!\")\n\t\ttime.Sleep(time.Second)\n\t}\n}\n```\n\n標準入力は以下のようなソース (./03_usbcdc-echo) で扱うことができます。\n\n```go\npackage main\n\nimport (\n\t\"bufio\"\n\t\"fmt\"\n\t\"os\"\n)\n\nfunc main() {\n\tscanner := bufio.NewScanner(os.Stdin)\n\tfor scanner.Scan() {\n\t\tfmt.Printf(\"you typed : %s\\n\", scanner.Text())\n\t}\n}\n```\n\n結果は以下のようになります。\nbufio.Scanner は改行文字を読み込む必要があるので、行の区切りとして `\u003cCtrl-J\u003e` を押す必要があります。\n\n```\n$ tinygo flash --target wioterminal --size short --monitor .\n   code    data     bss |   flash     ram\n  56652    1564    6676 |   58216    8240\nConnected to COM38. Press Ctrl-C to exit.\n(`hello` と入力した後、 \u003cCtrl-J\u003e を押す)\nyou typed : hello\n(`world` と入力した後、 \u003cCtrl-J\u003e を押す)\nyou typed : there\n```\n\n## USB HID を使う\n\nここではマイコンボードを USB HID Keyboard (いわゆる USB 接続のキーボード) として扱うために machine/usb/hid/keyboard を用いた例を実行します。\n以下のソース (./04_usbhid_keyboard) を書き込んでみてください。\n接続後 5 秒経過した後、 `tinygo version` を実行します。\n`keyboard.Port()` が存在しない、というエラーが出る場合は TinyGo の Version を上げるか、 `keyboard.New()` に変更してください。\n\n```go\npackage main\n\nimport (\n\t\"machine/usb/hid/keyboard\"\n\t\"time\"\n)\n\nfunc main() {\n\tkb := keyboard.Port()\n\n\ttime.Sleep(5 * time.Second)\n\tkb.Write([]byte(\"tinygo\")) // 指定したキー列を入力\n\ttime.Sleep(1 * time.Second)\n\tkb.Press(keyboard.KeySpace) // 単一キー入力\n\tkb.Press(keyboard.KeyV)\n\tkb.Press(keyboard.KeyE)\n\tkb.Press(keyboard.KeyR)\n\tkb.Press(keyboard.KeyS)\n\tkb.Press(keyboard.KeyI)\n\tkb.Press(keyboard.KeyO)\n\tkb.Press(keyboard.KeyN)\n\tkb.Down(keyboard.KeyEnter) // 押下\n\tkb.Up(keyboard.KeyEnter)   // 離す\n\n\tselect {}\n}\n```\n\n## Pin 入力を使った USB HID Keyboard\n\nTinyGo では、 Pin 入力を使ってボタン等の状態を取得します。\nここでは Pin 入力を用いてキーボードとして動作させます。\n以下のソース (./05_usbhid_keyboard2) を使うと、 `b1` で指定するボタンを押している時だけ `t` キーを押した状態となります。\nこれは最もシンプルな USB HID Keyboard の例になります。\n\n```go\npackage main\n\nimport (\n\t\"machine\"\n\t\"machine/usb/hid/keyboard\"\n\t\"time\"\n)\n\nfunc main() {\n\t// ボタンの定義はマイコン毎に変更する必要あり\n\tb1 := machine.BUTTON // wioterminal の場合\n\t//b1 := machine.D0 // xiao-rp2040 の場合\n\t// b1 := machine.GP0 // pico の場合\n\n\tb1.Configure(machine.PinConfig{Mode: machine.PinInputPullup})\n\n\tkb := keyboard.Port()\n\tfor {\n\t\tif b1.Get() {\n\t\t\tkb.Up(keyboard.KeyT)\n\t\t} else {\n\t\t\tkb.Down(keyboard.KeyT)\n\t\t}\n\n\t\ttime.Sleep(time.Millisecond * 10)\n\t}\n}\n```\n\nそれぞれのマイコンのボタン／ピン位置は以下になります。\nボタンはそのまま押せばよいですが、ピンについてはスイッチを経由して GND に接続してください。\nスイッチが無い場合は、ジャンプワイヤや針金等により該当ピンと GND を接続してください。\n\n* wioterminal : BUTTON\n  * 上面の一番右側 (中央側) のボタン\n* xiao-rp2040 : D0\n  * 左上のピン : https://wiki.seeedstudio.com/XIAO-RP2040/#hardware-overview\n* pico : GP0\n  * 左上のピン : https://www.raspberrypi.com/documentation/microcontrollers/raspberry-pi-pico.html#pinout-and-design-files\n\nこのサンプルは以下の回路を想定しています。\nPullup 抵抗 (R) は 1 ～ 10K ぐらいで設定すると良いですが、上記コードでは `machine.PinInputPullup` を使っていて内部プルアップが有効となっているため抵抗を省略しても問題ありません。\n\n![](./images/schema01.png)\n\nブレッドボードでの接続例は以下です。\n\n![](./images/schema01b.png)\n\n## Pin 入力を使った USB HID Keyboard (入力を増やす)\n\n続いて、入力を増やしてみましょう。\nここでは、 `Shift` キーと `t` キーを作ってみます。\n以下のソース (./06_usbhid_keyboard3) を使うと、 `t` と `T` を入力できるキーボードを作成することができます。\n前述のソースとの違いは、 b2 のコードの追加、となります。\n\n```go\npackage main\n\nimport (\n\t\"machine\"\n\t\"machine/usb/hid/keyboard\"\n\t\"time\"\n)\n\nfunc main() {\n\t// ボタンの定義はマイコン毎に変更する必要あり\n\tb1 := machine.BUTTON_1 // wioterminal の場合\n\tb2 := machine.BUTTON_2 // wioterminal の場合\n\t//b1 := machine.D0 // xiao-rp2040 の場合\n\t//b2 := machine.D1 // xiao-rp2040 の場合\n\t// b1 := machine.GP0 // pico の場合\n\t// b2 := machine.GP1 // pico の場合\n\n\tb1.Configure(machine.PinConfig{Mode: machine.PinInputPullup})\n\tb2.Configure(machine.PinConfig{Mode: machine.PinInputPullup})\n\n\tkb := keyboard.Port()\n\tfor {\n\t\tif b1.Get() {\n\t\t\tkb.Up(keyboard.KeyT)\n\t\t} else {\n\t\t\tkb.Down(keyboard.KeyT)\n\t\t}\n\t\tif b2.Get() {\n\t\t\tkb.Up(keyboard.KeyLeftShift)\n\t\t} else {\n\t\t\tkb.Down(keyboard.KeyLeftShift)\n\t\t}\n\n\t\ttime.Sleep(time.Millisecond * 10)\n\t}\n}\n```\n\nこのサンプルは以下の回路を想定しています。\n\n![](./images/schema02.png)\n\n## sago35/tinygo-keyboard を使う\n\n先ほどのコードのようなものを sago35/tinygo-keyboard を使って書いてみます。\nAddGpioKeyboard を使うことで同じ機能を実現できます。\n\nsago35/tinygo-keyboard を使うには `go get` が必要です。\n\n```\n$ go get -v github.com/sago35/tinygo-keyboard\n```\n\n以下のコード (./07_gpiokeyboard) は、 Wio Terminal 用です。\ngpioPins で指定されるそれぞれのボタンが、 `d.AddGpioKeyboard` 時の keyboard.Keycode で指定されるキーとなります。\ngpioPins で指定されるそれぞれのボタンは、すべて Pullup されていて、押下で Low、離すと High になります。\n\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"machine\"\n\n\tkeyboard \"github.com/sago35/tinygo-keyboard\"\n\t\"github.com/sago35/tinygo-keyboard/keycodes/jp\"\n)\n\nfunc main() {\n\td := keyboard.New()\n\n\tgpioPins := []machine.Pin{\n\t\tmachine.WIO_KEY_A,\n\t\tmachine.WIO_KEY_B,\n\t\tmachine.WIO_KEY_C,\n\t\tmachine.WIO_5S_UP,\n\t\tmachine.WIO_5S_LEFT,\n\t\tmachine.WIO_5S_RIGHT,\n\t\tmachine.WIO_5S_DOWN,\n\t\tmachine.WIO_5S_PRESS,\n\t}\n\n\tfor c := range gpioPins {\n\t\tgpioPins[c].Configure(machine.PinConfig{Mode: machine.PinInput})\n\t}\n\n\t// KeyMediaXXX will be supported starting with tinygo-0.28.\n\td.AddGpioKeyboard(gpioPins, [][][]keyboard.Keycode{\n\t\t{\n\t\t\t{\n\t\t\t\tjp.KeyA,\n\t\t\t\tjp.KeyB,\n\t\t\t\tjp.KeyC,\n\t\t\t\tjp.KeyMediaVolumeInc,\n\t\t\t\tjp.KeyLeft,\n\t\t\t\tjp.KeyRight,\n\t\t\t\tjp.KeyMediaVolumeDec,\n\t\t\t\tjp.KeyEnter,\n\t\t\t},\n\t\t},\n\t})\n\n\td.Loop(context.Background())\n}\n```\n\n## sago35/tinygo-keyboard のレイヤーキーを使う\n\n自作キーボードのファームウェアにはレイヤーと呼ばれる考え方があります。\n例えば特定のキーを押している時だけキー設定を切り替える事が出来ます。\n以下のソース (./08_gpiokeyboard_with_layer) では、 `jp.KeyMod1` を押していない時は `layer 0`、押しているときは `layer 1` のキーマップが有効となります。\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"machine\"\n\n\tkeyboard \"github.com/sago35/tinygo-keyboard\"\n\t\"github.com/sago35/tinygo-keyboard/keycodes/jp\"\n)\n\nfunc main() {\n\td := keyboard.New()\n\n\tgpioPins := []machine.Pin{\n\t\tmachine.WIO_KEY_A,\n\t\tmachine.WIO_KEY_B,\n\t\tmachine.WIO_KEY_C,\n\t\tmachine.WIO_5S_UP,\n\t\tmachine.WIO_5S_LEFT,\n\t\tmachine.WIO_5S_RIGHT,\n\t\tmachine.WIO_5S_DOWN,\n\t\tmachine.WIO_5S_PRESS,\n\t}\n\n\tfor c := range gpioPins {\n\t\tgpioPins[c].Configure(machine.PinConfig{Mode: machine.PinInput})\n\t}\n\n\t// KeyMediaXXX will be supported starting with tinygo-0.28.\n\td.AddGpioKeyboard(gpioPins, [][][]keyboard.Keycode{\n\t\t{\n\t\t\t// layer 0\n\t\t\t{\n\t\t\t\tjp.KeyA,\n\t\t\t\tjp.KeyB,\n\t\t\t\tjp.KeyMod1,\n\t\t\t\tjp.KeyUp,\n\t\t\t\tjp.KeyLeft,\n\t\t\t\tjp.KeyRight,\n\t\t\t\tjp.KeyDown,\n\t\t\t\tjp.KeyEnter,\n\t\t\t},\n\t\t},\n\n\t\t{\n\t\t\t// layer 1\n\t\t\t{\n\t\t\t\tjp.KeyX,\n\t\t\t\tjp.KeyY,\n\t\t\t\tjp.KeyMod1,\n\t\t\t\tjp.KeyMediaVolumeInc,\n\t\t\t\tjp.KeyLeft,\n\t\t\t\tjp.KeyRight,\n\t\t\t\tjp.KeyMediaVolumeDec,\n\t\t\t\tjp.KeyEnter,\n\t\t\t},\n\t\t},\n\t})\n\n\td.Loop(context.Background())\n}\n```\n\n## matrix keyboard を扱う\n\nwiokey および sgkey はマトリクス配線によりキースイッチを接続しています。\n詳細な説明は以下にあります。\n\n* [キーボードのマトリクス方式の分類 \u003e マトリクス](https://blog.ikejima.org/make/keyboard/2019/12/14/keyboard-circuit.html)\n  * wiokey : マトリクス+ダイオード逆向き(ROW2COL)\n  * sgkey : マトリクス+ダイオード(COL2ROW)\n\nここでは wiokey を題材として、単純な例を紹介します。\n手順としては以下の通りです。\n\n* SW1 / SW2 の読み込み\n  * r1 を H に、 r2 と r3 を L にして、 c1 を読み込むと SW1、 c2 を読み込むと SW2 の状態が取得できます\n* SW3 / SW4 の読み込み\n  * r2 を H に、 r1 と r3 を L にして、 c1 を読み込むと SW3、 c2 を読み込むと SW4 の状態が取得できます\n* SW5 / SW6 の読み込み\n  * r3 を H に、 r1 と r2 を L にして、 c1 を読み込むと SW5、 c2 を読み込むと SW6 の状態が取得できます\n\nsgkey の場合は以下の通りです。\n\n* SW1 / SW2 / SW3 の読み込み\n  * r1 を H に、 r2 を L にして、 c1 を読み込むと SW1、 c2 を読み込むと SW2、 c3 を読み込むと SW3 の状態が取得できます\n* SW4 / SW5 / SW6 の読み込み\n  * r2 を H に、 r1 を L にして、 c1 を読み込むと SW4、 c2 を読み込むと SW5、 c3 を読み込むと SW6 の状態が取得できます\n\n実際のソースコード例を以下 (./09_matrix_wiokey) に作成しました。\n出力ピンの電位を切り替えた後は、電位が落ち着くまで少し待つ必要があることに注意が必要です。\nsgkey 版のソースは後述します。\n\n\n```go\npackage main\n\nimport (\n\t\"machine\"\n\t\"machine/usb/hid/keyboard\"\n\t\"time\"\n)\n\nvar (\n\tc1 = machine.BCM5\n\tc2 = machine.BCM6\n\tr1 = machine.BCM13 // machine.PA04\n\tr2 = machine.BCM19\n\tr3 = machine.BCM26\n)\n\nfunc main() {\n\tkb := keyboard.Port()\n\n\tc1.Configure(machine.PinConfig{Mode: machine.PinInputPulldown})\n\tc2.Configure(machine.PinConfig{Mode: machine.PinInputPulldown})\n\tr1.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tr2.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tr3.Configure(machine.PinConfig{Mode: machine.PinOutput})\n\tfor {\n\t\t// SW1 / SW2 を読み込むため、 r1 を H、 r2 と r3 を L に\n\t\tr1.High()\n\t\tr2.Low()\n\t\tr3.Low()\n\t\ttime.Sleep(1 * time.Millisecond) // 少し待つ\n\n\t\t// SW1\n\t\tif c1.Get() {\n\t\t\tkb.Down(keyboard.KeyA)\n\t\t} else {\n\t\t\tkb.Up(keyboard.KeyA)\n\t\t}\n\n\t\t// SW2\n\t\tif c2.Get() {\n\t\t\tkb.Down(keyboard.KeyB)\n\t\t} else {\n\t\t\tkb.Up(keyboard.KeyB)\n\t\t}\n\n\t\t// SW3 / SW4 を読み込むため、 r2 を H、 r1 と r3 を L に\n\t\tr1.Low()\n\t\tr2.High()\n\t\tr3.Low()\n\t\ttime.Sleep(1 * time.Millisecond) // 少し待つ\n\n\t\t// SW3\n\t\tif c1.Get() {\n\t\t\tkb.Down(keyboard.KeyC)\n\t\t} else {\n\t\t\tkb.Up(keyboard.KeyC)\n\t\t}\n\n\t\t// SW4\n\t\tif c2.Get() {\n\t\t\tkb.Down(keyboard.KeyD)\n\t\t} else {\n\t\t\tkb.Up(keyboard.KeyD)\n\t\t}\n\n\t\t// SW5 / SW6 を読み込むため、 r3 を H、 r1 と r2 を L に\n\t\tr1.Low()\n\t\tr2.Low()\n\t\tr3.High()\n\t\ttime.Sleep(1 * time.Millisecond) // 少し待つ\n\n\t\t// SW5\n\t\tif c1.Get() {\n\t\t\tkb.Down(keyboard.KeyE)\n\t\t} else {\n\t\t\tkb.Up(keyboard.KeyE)\n\t\t}\n\n\t\t// SW6\n\t\tif c2.Get() {\n\t\t\tkb.Down(keyboard.KeyF)\n\t\t} else {\n\t\t\tkb.Up(keyboard.KeyF)\n\t\t}\n\n\t\ttime.Sleep(16 * time.Millisecond)\n\t}\n}\n```\n\nこのサンプルは以下の回路を想定しています。\n\n![](./images/schema03.png)\n\n\nsgkey 版のソースは以下になります。\n\n* [./09_matrix_sgkey/main.go](./09_matrix_sgkey/main.go) になります。\n\n## matrix keyboard を sago35/tinygo-keyboard から扱う\n\n先ほどの例は以下のソース (./10_matrixkeyboard_wiokey) になります。\nmatrix keyboard ぐらいになると、 sago35/tinygo-keyboard を使ったほうが簡単に書けます。\n\n```go\npackage main\n\nimport (\n\t\"context\"\n\t\"machine\"\n\n\tkeyboard \"github.com/sago35/tinygo-keyboard\"\n\t\"github.com/sago35/tinygo-keyboard/keycodes/jp\"\n)\n\nfunc main() {\n\td := keyboard.New()\n\n\tcolPins := []machine.Pin{\n\t\tmachine.BCM5,\n\t\tmachine.BCM6,\n\t}\n\n\trowPins := []machine.Pin{\n\t\tmachine.BCM13, // machine.PA04\n\t\tmachine.BCM19,\n\t\tmachine.BCM26,\n\t}\n\n\td.AddMatrixKeyboard(colPins, rowPins, [][][]keyboard.Keycode{\n\t\t{\n\t\t\t{jp.KeyT, jp.KeyI},\n\t\t\t{jp.KeyN, jp.KeyY},\n\t\t\t{jp.KeyG, jp.KeyO},\n\t\t},\n\t}, keyboard.InvertDiode(true))\n\n\td.Loop(context.Background())\n}\n```\n\n`d.AddMatrixKeyboard()` の引数の `keyboard.InvertDiode(true)` はダイオードの向きによって設定変更が必要です。\nwiokey は `マトリクス+ダイオード逆向き(ROW2COL)` のため true にする必要があります。\nsgkey は `マトリクス+ダイオード(COL2ROW)` のため false (default は false) にする必要があります。\n\n\n## duplex matrix keyboard を扱う\n\n以下にコード例があるので参考にしてください。\n\n* [github.com/sago35/tinygo-keyboard/targets/sgkb/left/main.go](https://github.com/sago35/tinygo-keyboard/blob/main/targets/sgkb/left/main.go)\n\n想定する回路は以下の通りです。\n\n![](./images/schema04.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsago35%2Ftinygo-workshop-keyboard","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsago35%2Ftinygo-workshop-keyboard","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsago35%2Ftinygo-workshop-keyboard/lists"}