K3NG Keyer を STM32F103C(BluePill) で製作
[和文&日本語キーボード対応]

7M4MON

2020/8/1 初版
2021/5/1 和文対応追加
2021/6/1 操作説明書追加
2023/7/1 回路図を追加




前置きが長いので、制作過程まで飛ばすリンクを貼っておきます。
BluePillで作る
和文&日本語キーボード対応

1.前置き

およそ20年前のコンテスト運用ではZLOGを使っていました。
ZLOGではパラレルポート付きのPCとWindows9x/MEとの組み合わせで
プリンタポートにつないだパドル(当時は カツミ KM-23 を愛用)でキーイングが可能でした。
その後、OSはWindows 2000/XPが主流になりましたが、ZLOG+NT系の組み合わせは、
シリアルポートのDTR線でキーイングは可能なものの、パラレルポートでのパドル操作はできなくなりました。
USBIF4CW がサポートされていましたが、パラレルポートI/Fと比較すれば微妙に高価で、なんとなく手が出せずにいました。
という訳で、熱があるうちはWindows98とパラレルポート付きのノートPCを使用し、
熱が冷めてからはDTR線でのキーイング+外付けキーヤー(OIKey-F675等)でのパドル操作で参戦していました。
外付けのキーヤーではロギングソフト側と速度の同期が取れないので、パラレルポートでのパドル操作と比べるとイマイチ不便でした。

時は流れて21世紀となり、ZLOGの開発が終了し、国内コンテストロギングソフトの主流はCtestWinに移りました。
CtestWinでもシリアルポートのフロー制御線でキー操作は可能でしたので、しばらくそれで参加していたのですが、
あるとき、CWポート設定に WinKeyer があることに気づきました。



調べてみると、オリジナルの WinKeyer は USBIF4CW と同じくらいの値段でしたが、
K3NG CW Keyerというオープンソースで開発されているキーヤーには「WinKeyer Emulation Mode」というものがあり
CtestWinとの組み合わせで、ロギングソフトと連動したパドル操作が可能ということが分かりました。

2.Arduino nano (ATMega328P)バージョンの製作

まずはArduino nano (ATMega328P)で試してみることに。
K3NG Keyerには様々な機能がありますが、keyer_features_and_options.h の該当機能の行のコメントアウトを外すと
任意の機能を有効にすることができます。

せっかくだから液晶を付けたいよね。と、とりあえず
FEATURE_LCD_YDv1, FEATURE_POTENTIOMETER, FEATURE_COMMAND_BUTTONS, FEATURE_WINKEY_EMULATION
あたりでビルドしてみると、[スケッチが大きすぎます]となり全然入りません。
色々オプションを試してみましたが、どうやら表示器をつけた時点で入らないっぽいです。
ということで、液晶は諦めて
FEATURE_COMMAND_BUTTONS, FEATURE_MEMORIES, FEATURE_WINKEY_EMULATION, FEATURE_POTENTIOMETER
のオプションを有効にして作りました。

出来上がった写真が

です。
内部は2階建てで、1階部分は Mumble-Funk用に製作した、
『絶縁型オーディオインターフェース&シリアル(リグ)コントロール&フロー制御PTT/CWインターフェース』です。



2階部分にはPICマイコンを使用したキーヤーがついていたのですが取り外してK3NG Keyerを設置しました。



微妙に高さが入らなかったのでUSBコネクタ部は超音波カッターで取り除いてあります。
これでCtestWinと同期してパドル操作できるようになりました。

3.BluePillで作る

Arduino nano版を使ってみると絶好調で、そうなると液晶付きの K3NG Keyerを作ってみたくなるのが人情です。
Arduino Mega 2560を使った作例が多いようでしたが、ATmega2560はマイコンボード単体でも結構な大きさです。
keyer_hardware.h を覗いてみると HARDWARE_GENERIC_STM32F103C が存在しています。
ということで、別のプロジェクト の検討用に購入した STM32F103 (BluePill)を使ってみることにしました。
ATmega328と比較すると下表の通り、Flash容量4倍、クロック4.5倍、SRAM容量10倍です。



ターゲットをSTM32F103CB にして試しにビルドしてみると、
エラー[call of overloaded 'noTone(<anonymous enum>)' is ambiguous]
と出てビルドできませんでした。
調べてみると、これは hardwareフォルダにある [tone.h] と、 [keyer_stm32duino.h] で定義されている
tone関数および noTone 関数の型定義が不一致であることが原因でした。
修正後に焼いてみて1602の液晶を付け、ブレッドボード上で動作確認ができたので、
勇気を出して人生初の Pull Request をかけました。
Fixed error : call of overloaded 'noTone()' is ambiguous #94



しばらくして無事にMargeされました。


どうせ作るなら、液晶は20x4行で送信機切り替え機能もほしいと欲が出て↓のようになりました。







主要部材は

などで、かかった費用は3500円くらいでした。

で、作ったものの、コマンドボタン 1〜3 が動きません。("Button - 0" だけは動作する)
調べてみると ボタンを読み込む analogRead()の範囲が異なっていることが原因と判明。
再度 Pull Request をかけて、こちらもマージされました。
Command buttons 1-3 are not working with ARDUINO_GENERIC_STM32F103C. #100

素晴らしいソフトを公開し、メンテナンスを継続されているK3NG [Anthony Good] OM、ならびに、
Arduinoやライブラリを開発しているオープンソースコミュニティの皆様に感謝します。



4.和文&日本語キーボード対応 (2021/5/1)

K3NG Keyerで使用した液晶のコントローラ(ST7066U, HD44780互換)は、カタカナのフォントを内蔵してます。
となれば、K3NG Keyerに和文符号を対応させるのは、Contributorである私の役目だろうと自任して(笑)実装を行いました。

4.1 和文符号対応

とはいえ、私は和文はさっぱりで、ホレ / ラタ くらいしか知らないので調べてみると…

というようなルールとなっていることがわかりました。今回は、
という方針としました。

トンツー符号から文字コードに変換している関数は、k3ng_keyer.ino の 15800行目付近
int convert_cw_number_to_ascii (long number_in)
です。
この関数の内部では、例えば "A" は 12 というように、 短点 が 1, 長点 が 2 と表現されています。
和文に対応させるため関数内に static で mode_wabun と tmp_eng という変数を設け、
mode_wabun が 真 かつ tmp_eng が 偽 であるときにJISコードを返す関数(新たに作成)を呼び出すようにしました。
(例えば、22122 がきたら、177 = 0xB1 = 「ア」を返す)
LCDのフォントの都合で、ヰは「イ」、ヱは「エ」と表示します。

ここまでで、パドル操作で液晶にカタカナが表示されるようになりました。
逆に、メモリやキーボードからモールス符号を送出する関数は、9200行目付近
void send_char(byte cw_char, byte omit_letterspace)
です。
この関数は、1バイトの文字コードを受け取り、send_the_dits_and_dahs関数に長点と短点の組み合わせを渡します。
例えば、case 'A': send_the_dits_and_dahs(".-");  といった具合です。
これに和文に対応させるには、例えば "ア" だったら、JISコードは 0xB1 = 177 なので、
case 177  : send_the_dits_and_dahs("--.--");
という case文を追加します。
これを、50音+拗音、促音、長音、段落、区切点、ホレ、ラタ、下向き括弧、上向き括弧 で行えば実装完了です。
ラタは 訂正にも使うのですが、キーヤー側では和文終了なのか訂正なのか区別がつきません。
今回は、「和文終了」として実装を行いました。

和文に対応したところまでのブランチは
https://github.com/7m4mon/k3ng_cw_keyer/tree/wabun_code
です。

4.2 日本語キーボード対応

4.2.1 STM32 に対応する。

「keyer_features_and_options_generic_STM32F103C.h」には "#define FEATURE_PS2_KEYBOARD" があり
とりあえず有効にしてビルドしてみましたが、あえなく失敗してしまいました。
原因は、私のボードが STM32 を使用しているのに対し、K3NG がカスタマイズしたライブラリ(後述)は
AVR向けに書かれているからです。
ちょっと検索したところ、STM32 向けの PS2Keyboard ライブラリは既に存在していて (Tamakichi/Arduino_PS2Keyboard)
これをありがたく利用させてもらいます。なんと日本語キーボード対応済です。(オープンソース万歳!)

K3NG Keyer は標準の PS2Keyboard ライブラリではなく、K3NG が独自にカスタマイズした K3NG_PS2Keyboard を使用しています。
(CTRL や ALT の組み合わせで、送信機切替などの機能を実現している)
これを STM32 へ対応させるには、上記ライブラリの #if defined (__STM32F1__) 以下を数カ所コピペするだけです。

STM32F1に対応した K3NG_PS2Keyboard は下記プルリクエストに反映されています。
https://github.com/k3ng/k3ng_cw_keyer/pull/114

4.2.2 JIS配列キーボード対応

JISキーボード配列は、ひらがなと英数字が同じキーに刻印されていて、モードを切り替えて使用します。
触ってみながら実装して、以下のような形にしました。
STM32対応版の PS2Keyboardライブラリは、かな入力時にキーマップのポインタを切り替えるようになっていて
比較的簡単にキーマップを変えられますが、K3NG_PS2Keyboardはキーのテーブルそのものを読みに行く処理なので、
キーマップの切り替えはひと手間必要です。
どちらをベースとしても変更量は大差なさそうですが、今回は STM32対応版のPS2Keyboardライブラリ に K3NG の
変更を盛り込む形としました。
前述の通り、K3NG のカスタマイズでは、CTRL や ALT の組み合わせで送信機切替などの機能を盛り込んでいて、
それらのキーストロークを送るのに、 162(0xA2)〜211(0xD3) を使用しています。
対して、8ビットJISのカナは 0xA1〜0xDF を使用しますので、キーコードが競合します。
(ASCIIコードで使用していない 0x80〜0x9F は ファンクションキーや矢印、BackSpaceなどに割当済)
カナの領域を確保すると残りは32バイトで、悩んだ結果、Ctrl+A から Ctrl+Z までの 26バイトと、
Ctrl+F1〜F3 の3バイトと Alt+F1〜F3 の3バイトを割り当てました。(私が制作したK3NG Keyerに合わせました。)
メインプログラム側も変更が必要で、3700行目付近の void check_ps2_keyboard() について
Alt+F4〜F12, Ctrl+F4〜F12の処理を #ifndef マクロで飛ばすようにしました。

和文と日本語キーボードに対応したブランチは
https://github.com/7m4mon/k3ng_cw_keyer/tree/wabun_jis-keyboard
です。設定ファイルは私が使っているものに差し替えてあります。

4.3 操作説明書の作成

ハムフェアの自作品コンテストに応募するにあたり、操作説明書を作成しました。(Wordファイル 約30kBytes)
K3NG Keyer [和文&日本語キーボード対応] 操作説明書
原稿のWordファイルをアップしておきますのでご自由にご利用ください。

5.その他