ミニ・エレキーを解剖する-モールス符号データ編
2013-09-22
各種の小さなマイコンでエレキー製作されている方は沢山いらっしゃると思いますので、モールス符号のデータ化も千差万別でしょう。どなたかの役に立つかも知れませんので、今回のミニ・エレキーのモールス符号化に関わる部分をまとめておきます。
◆ まずはASCII文字として扱う
普段使っているパソコンもそうですが、半角のアルファベット表現に「ASCIIコード」を用いているものは非常に多く、今さら解説するほどでもないでしょう。このコード、元々はアメリカ生まれですから、アルファベットの大・小文字(と数字)の通信ができれば良かったために「7ビット」でコード化されたものです。7ビット・・・128通りの意思疎通が可能というわけですね。
このコードの0x00から0x1Fまでは、通信手段として「これから送信するぞ」「これで終わりだぞ」・・・といった意味のコードになっており、普通の人は専ら0x20から上のコードを使うわけですが、大体以下のようになっています。
0x20-0x2F : 特殊文字-1
0x30-0x39 : 数字の「0-9」
0x3A-0x40 : 特殊文字-2
0x41-0x5B : アルファベットの「A-Z」
(以下、略)
一方、アマチュア無線のモールス通信でも特殊な意味合いの通信用に「?」や「/」(スラッシュ)或いは表示上よく使う「 」(半角のスペース」は特殊文字の範囲にあります。例えば、「QRZ? JM1DPL K」という文字列を書いてみると判るように、特殊文字の「?」に加え、「?」の後ろと「L」の後ろには「 」(半角スペース)が入りますよね
実際のCW通信上は「7短点分空ける」という規則ですが、何れにせよこの「何もない部分」も「何もないんだぞ」というデータ化をする必要があるわけです。
こうなると、ASCIIコードをそのまま扱って「A」なら「・-」、「?」なら「・・--・・」、「 」(半角スペース)なら「(7短点分の時間)」といった変換を行えれば、何となくエレキーができそうだなぁ・・・となるでしょう。そこでとりあえず、大本の送信したい文字は「ASCIIコード」で表現する(扱う)ことにします。
◆ 短点と長点を符号化
マイコンの最小記憶単位はビットであり、1ビットは「0」か「1」の値になりますので、これを短点と長点に当て嵌めてしまうと、モールス符号が簡単に表現できます。1バイト=8ビットに右詰で表現してみます。
「A」 ⇒ 00000001
「B」 ⇒ 00001000
「C」 ⇒ 00001010
「D」 ⇒ 00000100
「E」 ⇒ 00000001
「F」 ⇒ 00000010
この辺で止めておきます
・・・が、よく見ると「A」と「E」が同じになってしまっていますね
これは上手くありません。そこで、そのコードがどこから始まるかを示す「スタートビット」を付けてみます。
同じ表現になってしまった「A」と「E」ですが、実は「A」の場合は右から2ビット分がデータ、「E」は右から1ビット分がデータですよね
ここに着目して、スタートビットを追加すると・・・。
「A」 ⇒ 00000101
「B」 ⇒ 00011000
「C」 ⇒ 00011010
「D」 ⇒ 00001100
「E」 ⇒ 00000011
「F」 ⇒ 00010010
ピンクの「1」がスタートビットです。こうすると、このビットの右側が「コード化された短点と長点」だということが判りますし、「A」と「E」もきちんと区別できます。
◆ スタートビットを探していざ送出
さぁ、この「スタートビットを探す論理」にも幾つかバリエーションがありますが、特にアセンブラで組む場合には「左シフトしてキャリーが立ったら見つけたことにする」という論理が簡単で高速な処理になります。即ち、以下のように処理を進めます。
1) キャリーが立つまで左シフト
2) キャリーが立ったらもう1ビットシフトし、またキャリーが立ったら「長点」、立たなかったら「短点」を送出
3) キャリー探しを含め8ビット分で終了
◆ コード化されたデータの配列を準備
上記の論理でコード化されたものを配列にします。そして、ASCIIコードの値をその配列を索引するインデックスに使えば、一発で「送出したい文字のコード化されたデータ」を持ってくることができます。ここで、0x20未満は不要ですから、下の表のようなデータを作りました。

右端の「0x??」が「送出したい文字のコード化されたデータ」です。黄色はスタートビットです。また、今回は制御データについては未使用として扱っています。将来、何か制御したいときに使うための「個人的な予約」です。
PICのC言語による実際のコーディングイメージは以下のようになっています。
実際にこのテーブルをインデックスする際は、先頭が0x20に当たるため、ASCIIコードから0x20を減算してインデックスすればOK・・・簡単ですね
◆ スペースと未使用領域
スペース(0x20)は、実際には短点も長点も出ませんから省いてもいいんですが、例えば送出中の文字をLCDに表示させたり、EEPROMにメッセージを格納するときなどには無いと困る文字でもあるため含んでいます。もしスペースが不要なら、もう少しテーブル自体を小さく(先頭を「/」にするなど)しても良いでしょう。
未使用領域には「#」「$」・・・が眠っているわけですが、中には「.」(ピリオド)など、ひょっとしたらCWで送信するかも知れないコードもありますから、その場合は該当する位置に「送出したい文字のコード化されたデータ」として定義すれば済みます。
◆ この方法の欠点
この方法は、送りたい文字の送出データを簡単に拾い出すことにはかなり長けていて、オマケに必要な短点・長点のデータを取り出す処理も簡単で比較的高速になると思いますが、各データに2ビットほど無駄があるのが欠点です。
アルファベットと数字、それに幾つかの特殊文字を合計すると大凡40文字あれば良く、これを管理するためには「6ビット」もあれば事足ります。この辺り、例えばエレキー専用のPICを用意するのではなく、「何かの序でにこのPICの空き部分に入れちゃおう」といった場合や、特にメモリが小さいPICの場合には「デカ過ぎ
」ということもあり得ます。
ただ、原理的には難易度が低いため、「そろそろ自作でエレキーを・・・」といった方なら、Mid Rangeの比較的容量のあるPICを採用すれば、少なくともASCII ⇒モールス符号データ変換は簡単に作れると思います
◆ まずはASCII文字として扱う
普段使っているパソコンもそうですが、半角のアルファベット表現に「ASCIIコード」を用いているものは非常に多く、今さら解説するほどでもないでしょう。このコード、元々はアメリカ生まれですから、アルファベットの大・小文字(と数字)の通信ができれば良かったために「7ビット」でコード化されたものです。7ビット・・・128通りの意思疎通が可能というわけですね。
このコードの0x00から0x1Fまでは、通信手段として「これから送信するぞ」「これで終わりだぞ」・・・といった意味のコードになっており、普通の人は専ら0x20から上のコードを使うわけですが、大体以下のようになっています。
0x20-0x2F : 特殊文字-1
0x30-0x39 : 数字の「0-9」
0x3A-0x40 : 特殊文字-2
0x41-0x5B : アルファベットの「A-Z」
(以下、略)
一方、アマチュア無線のモールス通信でも特殊な意味合いの通信用に「?」や「/」(スラッシュ)或いは表示上よく使う「 」(半角のスペース」は特殊文字の範囲にあります。例えば、「QRZ? JM1DPL K」という文字列を書いてみると判るように、特殊文字の「?」に加え、「?」の後ろと「L」の後ろには「 」(半角スペース)が入りますよね

こうなると、ASCIIコードをそのまま扱って「A」なら「・-」、「?」なら「・・--・・」、「 」(半角スペース)なら「(7短点分の時間)」といった変換を行えれば、何となくエレキーができそうだなぁ・・・となるでしょう。そこでとりあえず、大本の送信したい文字は「ASCIIコード」で表現する(扱う)ことにします。
◆ 短点と長点を符号化
マイコンの最小記憶単位はビットであり、1ビットは「0」か「1」の値になりますので、これを短点と長点に当て嵌めてしまうと、モールス符号が簡単に表現できます。1バイト=8ビットに右詰で表現してみます。
「A」 ⇒ 00000001
「B」 ⇒ 00001000
「C」 ⇒ 00001010
「D」 ⇒ 00000100
「E」 ⇒ 00000001
「F」 ⇒ 00000010
この辺で止めておきます


同じ表現になってしまった「A」と「E」ですが、実は「A」の場合は右から2ビット分がデータ、「E」は右から1ビット分がデータですよね

「A」 ⇒ 00000101
「B」 ⇒ 00011000
「C」 ⇒ 00011010
「D」 ⇒ 00001100
「E」 ⇒ 00000011
「F」 ⇒ 00010010
ピンクの「1」がスタートビットです。こうすると、このビットの右側が「コード化された短点と長点」だということが判りますし、「A」と「E」もきちんと区別できます。
◆ スタートビットを探していざ送出
さぁ、この「スタートビットを探す論理」にも幾つかバリエーションがありますが、特にアセンブラで組む場合には「左シフトしてキャリーが立ったら見つけたことにする」という論理が簡単で高速な処理になります。即ち、以下のように処理を進めます。
1) キャリーが立つまで左シフト
2) キャリーが立ったらもう1ビットシフトし、またキャリーが立ったら「長点」、立たなかったら「短点」を送出
3) キャリー探しを含め8ビット分で終了
◆ コード化されたデータの配列を準備
上記の論理でコード化されたものを配列にします。そして、ASCIIコードの値をその配列を索引するインデックスに使えば、一発で「送出したい文字のコード化されたデータ」を持ってくることができます。ここで、0x20未満は不要ですから、下の表のようなデータを作りました。

右端の「0x??」が「送出したい文字のコード化されたデータ」です。黄色はスタートビットです。また、今回は制御データについては未使用として扱っています。将来、何か制御したいときに使うための「個人的な予約」です。
PICのC言語による実際のコーディングイメージは以下のようになっています。
static const uchar kcnv_t[59] = { 0x01,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x55,0x32, 0x3F,0x2F,0x27,0x23,0x21,0x20,0x30,0x38, 0x3C,0x3E,0xFF,0xFF,0xFF,0xFF,0xFF,0x4C, 0xFF,0x05,0x18,0x1A,0x0C,0x02,0x12,0x0E, 0x10,0x04,0x17,0x0D,0x14,0x07,0x06,0x0F, 0x16,0x1D,0x0A,0x08,0x03,0x09,0x11,0x0B, 0x19,0x1B,0x1C }; |
実際にこのテーブルをインデックスする際は、先頭が0x20に当たるため、ASCIIコードから0x20を減算してインデックスすればOK・・・簡単ですね

◆ スペースと未使用領域
スペース(0x20)は、実際には短点も長点も出ませんから省いてもいいんですが、例えば送出中の文字をLCDに表示させたり、EEPROMにメッセージを格納するときなどには無いと困る文字でもあるため含んでいます。もしスペースが不要なら、もう少しテーブル自体を小さく(先頭を「/」にするなど)しても良いでしょう。
未使用領域には「#」「$」・・・が眠っているわけですが、中には「.」(ピリオド)など、ひょっとしたらCWで送信するかも知れないコードもありますから、その場合は該当する位置に「送出したい文字のコード化されたデータ」として定義すれば済みます。
◆ この方法の欠点
この方法は、送りたい文字の送出データを簡単に拾い出すことにはかなり長けていて、オマケに必要な短点・長点のデータを取り出す処理も簡単で比較的高速になると思いますが、各データに2ビットほど無駄があるのが欠点です。
アルファベットと数字、それに幾つかの特殊文字を合計すると大凡40文字あれば良く、これを管理するためには「6ビット」もあれば事足ります。この辺り、例えばエレキー専用のPICを用意するのではなく、「何かの序でにこのPICの空き部分に入れちゃおう」といった場合や、特にメモリが小さいPICの場合には「デカ過ぎ

ただ、原理的には難易度が低いため、「そろそろ自作でエレキーを・・・」といった方なら、Mid Rangeの比較的容量のあるPICを採用すれば、少なくともASCII ⇒モールス符号データ変換は簡単に作れると思います

- 関連記事
-
- LFタイプの検証と回路直しのオマケ
- ミニ・エレキーを解剖する-モールス符号複合化編
- ミニ・エレキーを解剖する-モールス符号データ編
- ミニ・エレキーを解剖する-C言語処理編
- ミニ・エレキーのバージョンアップ完了!
コメントの投稿
2mCWRCたまには出ましょ
こんばんは。朝晩だいぶ涼しくなってきましたね。
今日は用事で外出以外はキーヤーのスリープ機能の実装とEEPROMの読み書き作法を勉強していました。あとはメッセージの保存形式をどうしたら効率よくなるだろうかとつらつら考えていました。
その折に、先の記事のコメントへのレスにもありましたけど文字コードを6ビットに圧縮するというお話をいただき少し思いついたことがあります。
残りの2ビット(1ビットでもOK)をレタースペース(3短点分)とワードスペース(7短点分)の判別に使うということです。考えてみると各キャラクターの間には必ずレタースペースかワードスペースがひとつ入るので、キャラクターとスペースセットで丁度1バイトにしてやると情報量はキャラクター個数分のバイト数で済むし、バイト単位で処理できるので都合が良いのではないかと思います。
一方長短点の情報(2ビット)をそのまま記録するとなると、1キャラクターの長短点個数が最短1つ(TとかEとか)最長6つ(ピリオド、カンマとか)と大きな幅があることやスペースの分の個数を含めるとかえって情報量が大きくなってしまうことがあります。
今週もちまちま実装していきます(^-^)/
今日は用事で外出以外はキーヤーのスリープ機能の実装とEEPROMの読み書き作法を勉強していました。あとはメッセージの保存形式をどうしたら効率よくなるだろうかとつらつら考えていました。
その折に、先の記事のコメントへのレスにもありましたけど文字コードを6ビットに圧縮するというお話をいただき少し思いついたことがあります。
残りの2ビット(1ビットでもOK)をレタースペース(3短点分)とワードスペース(7短点分)の判別に使うということです。考えてみると各キャラクターの間には必ずレタースペースかワードスペースがひとつ入るので、キャラクターとスペースセットで丁度1バイトにしてやると情報量はキャラクター個数分のバイト数で済むし、バイト単位で処理できるので都合が良いのではないかと思います。
一方長短点の情報(2ビット)をそのまま記録するとなると、1キャラクターの長短点個数が最短1つ(TとかEとか)最長6つ(ピリオド、カンマとか)と大きな幅があることやスペースの分の個数を含めるとかえって情報量が大きくなってしまうことがあります。
今週もちまちま実装していきます(^-^)/
だって、免許が・・・
ぶんさん、蝉の声が聞こえなくなり、ちょっと寂しい気もしています。
残り2ビット活用案・・・いいアイディアですね(^^)v
今回作ったエレキーでは、短・長点の後の短点1つは固定的に付与し、さらに文字間に必要な2短点と完全なスペースに必要な残り4短点を、状態に合わせて付加しています。これは大いに「次回作」のLCD表示を意識して作り始めたことから、「スペース」を何とかしてデータ化したかった部分・・・このように落ち着けていますが、ぶんさんの言う通り、この部分がデータ化できると、特にスペース部分は1文字分不要になるため、CQ送出メッセージの効率化などには結構有効でしょう。
SLEEPからの起き上がりも様々考えられますから、頑張ってくださいね(^^)b
残り2ビット活用案・・・いいアイディアですね(^^)v
今回作ったエレキーでは、短・長点の後の短点1つは固定的に付与し、さらに文字間に必要な2短点と完全なスペースに必要な残り4短点を、状態に合わせて付加しています。これは大いに「次回作」のLCD表示を意識して作り始めたことから、「スペース」を何とかしてデータ化したかった部分・・・このように落ち着けていますが、ぶんさんの言う通り、この部分がデータ化できると、特にスペース部分は1文字分不要になるため、CQ送出メッセージの効率化などには結構有効でしょう。
SLEEPからの起き上がりも様々考えられますから、頑張ってくださいね(^^)b