31-May-2025
[もっと手を入れてみた(どうしてこうなった)]

A1A Breakerから呼び出す文字列生成用の外部プログラム(MojiGene\MojiGeneConsole\MojiGene.exe)、使用する文字を任意に設定できるようにしたりUTF-8入出力とShift-JIS出力対応を入れたりしたものをGitHubに上げてしまいました

UCS-4→Shift-JIS変換を行う必要があるのと、PC-UNIX以外でUTF-8ロケールの処理を行えるかは不明なため、UTF-8のエンコード/デコードを自前で行っています(脆弱性を招く可能性があり、この手の処理は実績のあるライブラリを使用することが推奨されていることは知っています)。処理を行うコードがMITライセンスになっているのは、FUJIMI-IM/sj3のUTF-8対応版sj3(tty client)向けに書いたコードをちょっといじって載せたのが理由です。PC-UNIX上で使うことしか考えないのであれば<wchar.h>を使ってもう少しシンプルに書けるのですが、gcc/clangだけでなくOpenWatcomやLCC-Winでもビルドできるのでこれで良しとします。

今後機能を追加するとしたら、設定ファイル(MojiGene.ini)の切り替え機能くらいでしょうか。UTF-8ロケール以外のコマンドライン(Windows PowerShell等)で使用した場合は、一部のオプションでUS-ASCIIの範囲外の文字を正しく扱えません。これはMojiGene.iniに記述すれば回避できるという理由により、対応しないことにします。

仕事場の昼休みでちょっと受信練習ができたら良いなということでAndroid端末にMorseLearnProを入れ、人のいないときに練習しています。このソフトウェアでは速度の設定をCPM(character per minute)で設定するようになっているので90CPMにして聴いているのですが、妙に速いなーと思ったのでAudacity(PCMエディタ)を使って調べてみました。

簡単に測ってみると、50CPM時における長点の長さが250ms。PARIS 20WPM(100CPM)における短点は60msなので、その半分の速度である10WPM(50CPM)なら120ms→長点だったら3倍して360ms。MorseLearnProは1.44倍速い、ということになるのでしょうか。念のため問い合わせもしておりまして、25CPM時に短点240msとしているという回答を得ています…つまり50CPM時は短点120msになるはず(しかもPARIS WPM準拠)ということで、「妙に速い」という認識は間違いではないようです。

12500÷(MorseLearnProのCPM×3)が短点の長さ(ms)という公式が分かったのは良いとして、もう一つの疑問があります。トーン周波数の設定が600Hzの状態で、鳴っている周波数をWaveSpectraで調べてみたら652Hz。サンプリング周波数44100Hzで作ったデータを、48000Hzの設定で鳴らしている可能性があります(この件については報告済みです)。とはいえ、48000÷44100=1.088倍の再生速度の違いが送信速度の違いにどう結びついているのかが分かりません。単純な算数の問題なのか、あるいは別々の問題が絡んでそう見えるのか…

とりあえず、なかなか受信した文字が書き取れない(100文字のうち10文字は落としています)原因が分かったことと、これはこれで取れない文字は即座に捨てて次の文字に食らい付く練習にはなっているので、有益なのだと思います多分。55.5kg(21:50)

04-Jun-2025補足:MorseLearnPro他、FKT氏作成のモールス符号学習系ソフトウェアのアップデートが行われています。100CPMの設定で短点が60ms(PARIS 20WPM)になっていることと、600Hz設定で600Hzのトーンが出ていることをMorseLearnProで確認しました。CPMの上限が100→150に引き上げられているので、今まで90CPMに設定していたなら130CPMの設定で同様な練習が可能に…ってそんな速度で練習してたのか。

24-May-2025
[かなり手を入れてみた]

なんかコードいじりばっかりやっていて肝心の練習が進んでいません。どうしましょう。

10-May-2025で作成した、A1A Breakerから呼び出す文字列生成用の外部プログラム(MojiGene\MojiGeneConsole\MojiGene.exe)、生成する文字列の条件を変えるのに再コンパイルするのも面倒なのでMojiGene.iniで設定できるようにしてみたのですが…どうにかできたとはいえ

  1. MojiGene.iniはA1ABreaker.exeと同じディレクトリに置く(MojiGene\MojiGeneConsoleではない)
  2. MojiGene.iniはUTF-8で記述する

という制約があります。

MojiGene.txtはMojiGene.exeと同じディレクトリに生成されるにも関わらず、MojiGene.iniはそこに置いても参照できません。しかもWindows PowerShellから実行する分にはこのような問題はなく、A1A Breakerから呼び出した場合に限って問題が起こるという…なんなんですかね、この挙動。

MojiGene.iniの文字コードについては、PowerShellからecho "Chars = 300" > MojiGene.iniとするとUTF-16でファイルを作成してしまうためにMojiGene.exeが解釈できなくなります。メモ帳や適当なテキストエディタでUTF-8(なりShift-JISなりUS-ASCIIなり)でMojiGene.iniを記述してください。

PC-UNIX上でbash等が動くコンソールから起動する場合は、MojiGene.iniがあればそれを読み込んだ上でコマンドラインオプションによる設定の上書きもできます。17-May-2025で作ったイマドキの流儀に合わせた練習用のコードと組み合わせることも、もちろん可能です。MojiGene -c 100 -n 8; ./a1a_gen -i MojiGene.txt -o - -p 22 | aucat -e s16le -i -; cat MojiGene.txt みたいな形で鳴らせます…というかこれを行うことが主たる目的なんですけど。

おまけとして、指定した秒数だけMojiGene.exe側で待つという機能も入れてあります。A1A Breakerからユーザ自作のプログラムを起動して文字列を生成させるといきなりモールス符号の再生が始まってしまい、ペンに持ち替える暇がないのでそれへの対策です(これに限らず、A1A Breakerのテキスト作成は作成終了後すぐに符号を鳴らし始める動作になっているようですが…皆さんどう対応しているのでしょう?)。57.7kg(23:40)

25-May-2025補足:MojiGene.iniを配置するディレクトリの問題、open-watcom-v2以外のコンパイラを使用した場合にどうなるかを確認する目的でlcc-win64も使ってみましたが、こちらもMojiGene.iniをA1ABreaker.exeと同じディレクトリに置く必要がありました。この問題はコンパイラに起因する問題ではないと判断します。

ソースコードは、lcc-win64でもビルドできるよう修正しました。lcc依存部分を#if defined(__LCC__)〜#endifで追加しただけであり、既に生成したバイナリへの影響は無いと考えられるため、ソースコードのみ変更した状態としています。

なお、lcc-win64を使う場合は

という点に注意が必要です。

17-May-2025
[黒歴史ってやつを]

晒してみます。MSX-BASIC向けに書いたモールス符号の練習プログラムで、当時はこれで練習していたはずです。はずです、というのは…タイムスタンプが1994年になっており、平成5(1993)年に一アマを取った後に多少手を入れたもののように見えるためです。これより古い版もあるにはありますが、1992年の物であり中身もかなり酷いのでここまでとしておきます。

コメントの内容やスペルミスに加え、単語間が5短点分ではなく7短点分の作りになっていることについて当時の自分に厳しくお説教しておく必要がありそうです(実際、練習していた時になんか単語間が長めだなーとは思っていました)。マシン語で記述した処理、ブザー出力のon/offに合わせたCapsLockランプのon/off制御と待ちについては、手作業で逆アセンブルすると


D000    F3              DI
D001    2A 9E FC        LD HL,(0FC9EH)  ; JIFFY
D004    ED 5B F8 F7     LD DE,(0F7F8H)  ; value from USR(x)
D008    19              ADD HL,DE
D009    FB              EI
D00A    ED 5B 9E FC     LD DE,(0FC9EH)
D00E    B7              OR A
D00F    E5              PUSH HL
D010    ED 52           SBC HL,DE
D012    EB              EX DE,HL
D013    E1              POP HL
D014    D8              RET C
D015    7A              LD A,D
D016    B3              OR E
D017    20 F1           JR NZ,0D00AH
D019    C9              RET
D01A    3A F8 F7        LD A,(0F7F8H)
D01D    3D              DEC A
D01E    CD 32 01        CALL 0132H      ; CHGCAP (A=0 off, else on)
D021    C9              RET

こうでしょうか。おそらくturboR対策として、(NTSC版なので)1/60秒毎に増えるカウンタを監視して待たせる意図があったのでしょう。CapsLockランプの点灯については、完全にお遊びでしょうね。

とりあえず、イマドキの流儀に合わせた練習用のコードを書いてみました。とはいえ、与えられた文字列に対するraw形式のPCMデータを作るだけなので、問題文とPCM再生部分については別途用意する必要があります。PCMの再生はaucatなりaplayなりを使えば良いとして、問題文の生成はこの前作ったアレを使うことにしましょう。56.9kg(24:15)

18-May-2025補足:Z80マシン語部分、ちょっと手直しできますね。


D000    F3              DI
D001    2A 9E FC        LD HL,(0FC9EH)  ; JIFFY
D004    ED 5B F8 F7     LD DE,(0F7F8H)  ; value from USR(x)
D008    19              ADD HL,DE
D009    EB              EX DE,HL
D00A    FB              EI
D00B    2A 9E FC        LD HL,(0FC9EH)
D00E    B7              OR A
D00F    ED 52           SBC HL,DE
D011    7D              LD A,L
D012    B4              OR H
D013    20 F6           JR NZ,0D00BH
D015    C9              RET
D016    00              NOP
D017    00              NOP
D018    00              NOP
D019    00              NOP
D01A    3A F8 F7        LD A,(0F7F8H)
D01D    3D              DEC A
D01E    CD 32 01        CALL 0132H      ; CHGCAP (A=0 off, else on)
D021    C9              RET

4byte節約できましたが、CapsLock LED操作部分はいじりたくないので結局NOPで埋めます。その他細かい部分を直したものを置いておくことにしましょう(一応MSXPen上で簡単に動作確認はしています)。

10-May-2025
[まだまだですね…]

LCWO.net、character speed 24WPM/effective speed 22WPMでの練習を始めたところなのですが、Koch Method CW Courseばかりやっていると練習量が偏るということに今更気付きました。必ずK, M, U, R, … D, 6, 0, Xの順番になるため、これを繰り返すとKやMに反応できても、DやXが来た場合は一瞬「ん?」となってしまい、その間に数文字落としてしまうのです。

なので、Change CW settingsからX, D, C, H, Qと逆順に設定してCode Groupsを試しています。XとDだけとか、これはこれで本当にキツいですね。符号も最後に-が付いてるか付いてないかの違いなだけなので。あとは、「ん?」となった場合は考え込まずにその文字だけさくっと捨てて即座に次の文字を拾いにいく動きができないといけないのですが、これはもう1分よりも長い量で受信練習を繰り返さないとダメかも。

A1A Breakerも触っています。その筋では超定番のソフトウェアなのでどこかの時点でこれを使うことにはなるのですが、受信力(と書いてスタミナと読んでほしい)のまだ低い身に5文字暗語・500文字は流石に辛いです。まずはお手柔らかに300文字くらいでお願いしたいのですが、500/1000/2000文字の三段階からしか選べないのはどうしたものかと。

A1A Breakerから文字列生成用の外部プログラムを呼び出すことができるらしいので、OpenBSD上でopen-watcom-v2を使ってWin32のコンソールアプリを作る実験をしてみました。必須となる条件をA1A Breaker JPN Helpから引用すると(原文ママ)

この程度なら、こんな感じですかね?あとは、A1ABreaker.iniのConsoleMenuItemVisible=1とし、コンソールプログラムから実行すれば

t20250510.png

動いているみたいです。WindowsNT(Win32)向けという今となっては古いバイナリ形式であり、将来性については疑問符が付くとはいえ、ちょっとした目的ならこれで十分対応できるのはありがたいものです。56.7kg(23:35)

14-May-2025補足:生成される乱文の、数字の出現率がなんとなく高い気がしたので修正しました。A1A Breakerの「数字と記号の出現割合」、低(1/3倍)に合わせようと書いたコードが…数字1に対して英文字2になっていました。これを、数字1に対し英文字3となるようにしています。

06-May-2025
[うーん]

dpboxもtntも、一旦白紙(なるべく手を入れない状態かつ32bit環境での動作)からやり直した方が良いのかもって気がしてきました…

time_tが32bit、本当にここが一番厄介な気がします。Slackware(i686)に限らず、Debian/i386も「過去のx86バイナリとの互換性を保つため32bit time_tのままとする」決定をしているようで。きちんと手間をかければ直せるのでしょうが(64bit OSなら自動的にtime_tは64bitになりますし、32bit OSでも-DTIME_BITS=64で64bit化しますけどね)、単なる表示だけの問題ではなくtime_tを含んだ構造体をディスク上に保存しているとなると…既に保存されているデータとの互換性を一体どうするのかという問題も首をもたげてきます。単に64bit化すりゃいーじゃんという話ではないです、決して。

また、構造体である以上paddingの問題もあります。__attribute__((packed))等で押し込もうものなら、x86系以外の機種ではunaligned-accessによるSIGBUS等に悩まされることになるでしょう。この辺りの問題をよーーっく考えて手を付けないとダメな気がします←と書いている時点で、何も考えずにやっていることがバレバレです:-p

対処については、組込み機器開発における2038年問題への対応事例(デジタルプラクティス Vol.10 No.3 (July 2019))のようなラッパー関数を使用して32bit time_tを維持する方法や、ディスク上に記録するエントリのみ32bit形式とし(1970/Jan/01 00:00:00〜2004/Jan/10 13:37:03に対応する0x00000000〜0x3fffffffを2038/Jan/19 03:14:08〜に割り当てる)それ以外は全て64bit time_tで処理する方法もありそうです。どのような方法が使えるかはdpboxを動かせれば分かりそうですが、まだ動かせていないので全く見当がつきません。

netbsd-tntのビルドについては、pkgsrc(NetBSD)版はnbmakeを使っているらしいと聞いています。自分はOpenBSDの民なので、CMakeLists.txtを作ってCMakeでのビルドを行えるようにしてしまいました。CMakeによるconfigureによるconfig.h生成の真似事、意外とできてしまうものなのですね…非常に面倒ですが。56.3kg(22:05)

04-May-2025
[とりあえず…では全然ないです]

30-May-2018dpboxをOpenBSD対応してみたなんて書いてますけど…単にwarningを黙らせただけでマトモに動く代物じゃないです、GitHubに上げてるやつ。実はkq6up/netbsd-dpboxをベースに全てを見直してみたというのをどうにか作ってみたんですが、これがちゃんと動くかどうかも謎なんですよね。前のよりは動く確率高いんじゃね?くらいの可能性で。

コードを見てみるに、

64bit環境でのビルドができても、きちんと手を入れないと動きませんよというニオイがそこら中に漂っているという。

とはいえ、dpboxはまだマシで、問題はnetbsd-tnt/tnt-openbsdです。configureが古いのかSlackware-15.0(i686)ですらビルドができず、autoreconfも通りません。Vine-2.5の仮想マシンでも(こちらはこちらで違う理由になるのですが)configureが通らず…どうしたものでしょうかね、これ。単にビルドするだけならともかく、多数のファイルをインストールする指示もあるのでconfigure.inもずいぶん複雑です。どうにかしてこれをメンテナンスするしか道はなさそうです。

Pure Pascalで検索していたら、Atari TOS向けに書かれた表計算ソフト(Texel)のソースコードに辿り着きました。Atari ST…全く知らない世界なので、時間があればもう少し調べてみたいのですが今は脇に置いておきます。56.3kg(23:15)