モールス信号発生器

友達が撮った飛行機の中に、エンジンの写真が含まれていたそうな。その写真を見た 友人は、ふと飛行機、ジェットストリームの連想で、i-tunesから、「ジェットストリーム」 のCDを購入して、聞いているとか。

曲の合間に効果音で、管制塔とのやり取りとか、モールス信号で発せられるビーコン 信号が使われていたそうな。そのモールス信号を聞くとはなく聞いてみると 「JFK:ケネディ空港」だったとか。

いいなあ、私もたまには聞いてみたいよ。今から40年も前にモールスを覚えた事が あるけど、今、どれぐらい取れるかなあ?

モールス信号を聞く

早速、Vectorへ 行って、A1A Breaker というのを落としてきた。モールスコードの半分ぐらいは、頭から 蒸発してたよ。BGMとして、暫く聞いてみようかな。そのうちに、思い出してくるか。

BGMと言えば、先の友人に教えてもらった 標準周波数報時シミュレータ STEMU と言うソフトも楽しい。NCITが、アナウンサーの声を提供するなんて、なかなか味な事を するわい。

で、昨日から A1A Breakerを聞いているんだけど、つい悪い癖が出てしまった。自分で、 これと同等のものを作ってみたくなった。

まずは、資料集めですね。 世界の百科辞典 を引いて、ここを基点に モールス信号へのお誘いを経由して 初心者向けエレクトロニックキーヤ-の使い方 に、やさしい説明を見つけた。

モールス信号発生器

ハムフェア2009へ行けば 「オリジナルモールス練習機(会場価格2,500円)」等と言う楽しい工作が出来るようだ が、もう、こても部品もすっかり処分してしまっているので、パソコンでやってみる。

えっと、まずブザーを鳴らすんだな。それからちょっとお休みしろと言う命令があれば 何とかなりそう。私の部品箱 へ行って、適当に調べればいい。

今回は、音を鳴らすんだから、beep かなあ。お休みだから、sleepかなあと当たりを つけたら、ぴったんこのやつがヒットした。

後は、発生器をどういう構成にするかだな。発生して欲しいモールス信号を、コマンド引数か 何かから、"CQCQ DE 8J1A" とかするか。これじゃ、RTTYみたいで面白みに欠ける。

もっと単純に、ト・ツー・ツーみたいに与えたほうが、何となく、モールスっぽくて 面白い。もう一つ考えておかないとならないのは、文字区切り(やワード区切り)を どうするかだ。一文字づつ、発生器を呼び出すのもオーバーヘッドが大きそうだ。 一文(1行)単位ぐらいで呼ぶのが良さそう。

そうなると、文字区切りのマークとワード区切りのマークも定義しておいて、ト・ツーも 含めて、モールス記号となるな。まとめると、

s
ト(短点)を表わす、1単位分の発声、これに続き、必ず1単位の停止あり
l
ツー(長点)を表わす、3単位分の発声、これに続き、必ず1単位の停止あり
c
文字区切りを表わす、3単位分の発声停止
w
ワード区切りを表わす、7単位分の発声停止

"I AM A" ならば、"sswslcllwsl" と言う文字列を、モールス発信器に送る事になる。これ 私が今決めた、文字列は、別アプリにより発生させる事にしよう。

後は、お好みだけど、発生スピードと、発生周波数も指定出来るようにしておこう。 これらはオプション扱いにする。指定しなかった場合は、発生スピード、短点の長さが 100ms、周波数は、440Hzとしよう。

原始的モールス発生器

一応、Windows限定って事で

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>

long freq = 440;  // beep freq in  [Hz]
long t    = 100;  // dot length in [MS]
long t3   = 300;  // dash length in [MS]
long t2   = 200;  // between char break length in [MS]
long t6   = 600;  // between word break length in [MS]

sett(long t){
  t3 = t * 3;
  t2 = t * 2;
  t6 = t * 6;
}

osc(char *str){
  int c;
  while ( (c = *str++) ){
    switch (c) {
    case 's':
    case 'S':
      Beep(freq, t);
      Sleep(t);
      break;
    case 'l':
    case 'L':
      Beep(freq, t3);
      Sleep(t);
      break;
    case 'c':
    case 'C':
      Sleep(t2);
      break;
    case 'w':
    case 'W':
      Sleep(t6);
      break;
    default:
      exit(2);        // Bad char, soon exit
    }
 }
}

main(int argc, char *argv[]){
    if (argc > 3){ freq = atol(argv[3]); }
    if (argc > 2){ t    = atol(argv[2]); sett(t); }
    if (argc > 1){ osc(argv[1]); }
    if (argc == 1){
        printf("Usage: mosc.exe \"slcw\" [speed freq]\n");
        exit(1);
    }
    exit(0);
}

既定した文字以外が発見された場合、実行は即座に終了する。

実行例

c:\borland\work\beep\Debug>mosc.exe
Usage: mosc.exe "slcw" [speed freq]
c:\borland\work\beep\Debug>mosc.exe slclsss
c:\borland\work\beep\Debug>mosc.exe sssClllCsss 80
c:\borland\work\beep\Debug>mosc.exe lslscllslwlsscs 120 880
c:\borland\work\beep\Debug>mosc.exe sssXsssclll

最後の例では、"sss"の後、例外文字があったので、実行は、打ち切りとなった。 なお、一度動き出したプログラムは、CTRL+Cで停止するか、全コードを発声し終わるまでは、 終了しない。