「100人のプロが選んだソフトウェア開発の名著」に寄稿させていただきました。
100人のプロが選んだソフトウェア開発の名著に寄稿させていただきました。
デブサミで先行発売されるそうです。しかも割引ありとのことなのでデブサミに行ける方は、現地で購入されるのがよろしいかと。またこの本の中で紹介されている書籍も、デブサミで販売されるそうです。
blogでも、取り上げてくださいとのことなので私の原稿を公開します。
「コンピュータの気持ちが分かりますか?」
ruimoがコンピュータを仕事としたい新卒の人に贈りたい1冊
30日でできる! OS自作入門
川合秀実 著
毎日コミュニケーションズ, 2006年
コンピュータの調子が悪いので見てくれと言われて調べていると、まわりの人達が突然笑い出しました。その時私は、コンピュータ本体に耳をあて、じっと音を聞いていたのです。コンピュータが発する音を聞いて診断するというのが、エスパーか何かのように見えたのでしょう。しかし、これはトリックでもハッタリでもなく、割と有効な診断方法なのです。HDDの音を聞けば、シリンドルモータが回っているのか、エラーリトライしていないか、軸受が劣化していないかが分かりますし、冷却ファンの音を聞けば、ちゃんと冷却できているのかが分かります。そして無音状態のコンピュータのスピーカの音からは、CPUの動作状況が良く分かります。嘘だと思ったらヘッドフォンを付け、ボリュームを上げた状態でCPUに負荷のかかる作業をしてみてください。特徴的なノイズの音が様々に変化し、慣れれば愛機のCPU使用率がだいたい判断できるようになるはずです。CPUや周辺回路の出すノイズがオーディオ回路に入り込んで聞こえるため、そうした回路の動作状況が音から判断できるのです。
私がコンピュータを始めた頃は、パソコン(当時はマイコンと呼ばれていました)一式揃えると100万近くかかり、よほど裕福な人以外は自分でパーツを買ってきて回路を設計し、半田付けして作るのが当たり前でした。初めて作ったコンピュータはメモリが256バイト(256Mでも256Kでもありませんよ!)で、バスリクエストという機構を使ってCPUを停止状態にし、2進数でメモリに命令を書き込んでから、停止を解除して計算を実行。終わってからまた停止してメモリの内容を確認するという感じでした。
会社に入ったのはDOS/Vが日本で流行りだした、16bit全盛の時代です。この頃はDMAとか、割り込み、メモリといったものを意識して構成ファイルを書く必要があり、否が応にもハードウェアのことを少なからず意識 しなければなりませんでした。その後OSはどんどん高度化され、今BIOSが無くなろうとしています。必要とされるハードウェアの知識は今後もどんどん減っていくでしょう。コモディティ化の中では避けられないことですし、大部分の人にとっては好ましいことでしょう。
仕事で、特に障害の解析をしていると「なんでそんなことが分かったんですか?」と聞かれることがあります。こういう場合、聞かれた本人でも、あらためて「なぜ」と聞かれると良く分からなかったりします。しかし最近、原始的なハードウェアやOSをいじっていた頃の知識が少なからず役に立っていることが分かってきました。例えばハードウェアを設計する時はタイミングチャートを書き、信号がぶつかったりしないか何度も検証しますが、これはマルチスレッドプログラミングの設計に通じるところがあります。DOSのようなメモリ保護のないOSの下で、プログラムが暴走(OSも含めてコンピュータのメモリ内容を破壊してしまう現象)して原因がなかなか分からず苦労した経験があれば、Cのような「危険と隣り合わせの」言語を使う時に細心の注意を払うようになります。
パソコンの進歩は、低レベルの動作を学ぶ機会を奪いました。これは不幸なことかもしれません。今回挙げたのは、OSを1から作る本です。フロッピーディスクを使って16bitのリアルモードでブートローダを書くところから始まり(フロッピーディスクを知らない若い人がいたりして戦慄を覚えますが、実際入手は困難なので、この本の内容を実際に試すのに残された時間は長くありません)、最終的にはマルチタスクの可能なOSを書き上げてしまいます。この本を読んで試してみれば、きっとこれまでよりも「コンピュータの気持ち」が分かるようになるはずです。
もう1つハードウェア寄りの実践知識を手に入れる方法をご紹介しておきましょう。秋月電子は私が秋葉原の中でもっとも好きなお店の1つですが、ここには様々な組み込み用のマイコンが売られています。最近は非常に敷居が下がったので10k円くらいあれば一式揃います。これを使ってアセンブラ、割込を使ったプログラミングを経験してみてください。色々と得るものがあるはずです。
JINSでルーペを作る。
普段、細かい作業ではこの手の両手が使えるルーペを使っていた。まぁそれなりに役には立つのだけど、レンズの収差が結構大きかったり、レンズ交換できるとはいえ、自分にとっての最適な倍率にはなかなかうまく適合しなかったりと今ひとつなところも目立ってきた。何より画面に回路図を出して配線すると、ルーペを付けたままでは離れた画面にはピントが合わず、しょっちゅうルーペを外したり付けたりでまどろっこしい。
こういうタイプが割と人気があると聞いたけど結構なお値段。要はルーペって老眼鏡と同じなんだから眼鏡屋で自分専用に作ってしまえばいいのではないか?
有楽町阪急のJINSに行って見てみると、遠近両用でも+5000円で作成できるとのこと。一番安いタイプなら3980+5000円で作成できる。というわけで画面と手元両方が見えるようなルーペを作ってもらうことにした。
こういうレンズは累進レンズというそうで、用途的には中近両用という区分なのだそうだ(中近とか近近というタイプがあるのだそう)。昔みたいに一見してすぐに遠近両用と分かるような境がなくて、見ためにはどちらか分からない。要望を伝えたところ、かなり特殊なユースケースなんで、店員に「目が疲れますよ」と何度も念をおされたけど、まぁそういう用途だし1-2時間くらいしかつけないのでこれで構わない。特殊な要望なんで2週間かかると言われたけど、5日ほどで完成。昨日取りに行ってきた。
早速使ってみた。まだこう首を動かしてレンズを切り替えるというのに慣れていないけど、これなら画面を見ながら配線という作業が眼鏡を外さずに行える。あとは傍らに凸レンズを置いて(自分はヒモ付けて首から下げている)おけばバッチリ。ここまで眼鏡が安くなったらルーペもオーダーメードで良いのではないか。
テスト駆動JavaScriptを献本いただきました。
献本いただきました。JavaScriptでTDDを進めるためのコツが満載。第2部は一転してJavaScriptの落とし穴の解説が盛り沢山で「はて、何の本だっけ?」という感じになるけど、このあたりのことが理解できていないと、後のテクニックの解説も消化不良になりそう。というか自分も1回読んだだけでは消化不良だし。何度も読み返さないと。TDDに限らず生JavaScriptでプログラミングするなら間違いなく必携の書。静的言語ばかりの人も、動的言語でのTDDというのは色々参考になると思うので読んでおいて損は無いと思う。
しかしなんというかJavaScriptは難儀な言語だ。今後ECMAScript仕様が何度か改訂されて改善されていくのだろうけど。
年賀状
インクジェットプリンタを持っていても使うのは年賀状印刷くらいで、そうすると間がやたらあくのでノズルが詰まっていて、そのクリーニングでインクタンクが空になってと、お財布にも精神衛生上も最悪なので、カラー印刷は外に頼むようにしている。ハガキサイズの印刷も、昔はL判などに比べると妙に高かったのが、最近は1枚10円を切るのが当たり前になってきた。それなのに年賀状印刷がいまだに妙に高いのはなぜなんだろう。
モノクロ印刷だけはA4レーザプリンタが残してある。正直セブンイレブンの印刷サービスでほとんど用は足りているんだけど、年賀状の宛名をシールに印刷する必要があり、残念ながら宛名印刷を安価でやってくれるサービスが、まだ見当たらないので。
おまけ。大昔の夢久の写真。最近、肥満をこじらせていてデブ猫化がやばい。
赤外線取り込みができた。
赤外線取り込み部分ができたので表にしてみた。東芝のビデオのリモコンの「1」を押した時の信号。単位はμ秒で、10μ秒の桁を四捨五入している。
| 点灯 | 9,000 |
| 消灯 | 4,500 |
| 点灯 | 600 |
| 消灯 | 1,700 |
| 点灯 | 700 |
| 消灯 | 400 |
| 点灯 | 600 |
| 消灯 | 1,700 |
| 点灯 | 600 |
| 消灯 | 500 |
| 点灯 | 600 |
| 消灯 | 500 |
| 点灯 | 600 |
| 消灯 | 500 |
| 点灯 | 600 |
| 消灯 | 1,700 |
| 点灯 | 600 |
| 消灯 | 500 |
| 点灯 | 600 |
| 消灯 | 500 |
| 点灯 | 600 |
| 消灯 | 500 |
| 点灯 | 600 |
| 消灯 | 1,700 |
| 点灯 | 600 |
| 消灯 | 1,700 |
| 点灯 | 600 |
| 消灯 | 1,700 |
| 点灯 | 600 |
| 消灯 | 1,700 |
| 点灯 | 600 |
| 消灯 | 500 |
| 点灯 | 600 |
| 消灯 | 1,700 |
| 点灯 | 600 |
| 消灯 | 1,700 |
| 点灯 | 600 |
| 消灯 | 500 |
| 点灯 | 700 |
| 消灯 | 500 |
| 点灯 | 600 |
| 消灯 | 500 |
| 点灯 | 600 |
| 消灯 | 500 |
| 点灯 | 600 |
| 消灯 | 500 |
| 点灯 | 600 |
| 消灯 | 500 |
| 点灯 | 600 |
| 消灯 | 500 |
| 点灯 | 600 |
| 消灯 | 500 |
| 点灯 | 700 |
| 消灯 | 1,700 |
| 点灯 | 600 |
| 消灯 | 1,700 |
| 点灯 | 600 |
| 消灯 | 1,700 |
| 点灯 | 600 |
| 消灯 | 1,700 |
| 点灯 | 600 |
| 消灯 | 1,700 |
| 点灯 | 600 |
| 消灯 | 1,700 |
| 点灯 | 600 |
| 消灯 | 1,700 |
| 点灯 | 600 |
| 消灯 | 39,800 |
| 点灯 | 9,000 |
| 消灯 | 2,200 |
| 点灯 | 600 |
最後の39,800μ秒以降がトレーラのようなんだけど、何回か取り込んでみると、ここが出力されない時がある。プログラム側のバグかと思ってオシロで観察してみたところ、実際に出ていないようだ。多分リモコンの受光側が、40,000μ秒近く変化無ければ、そこでおしまいというロジックで、特にトレーラ部が無くてもいいんだろう。
このデータは、たかだか70個くらいなんだけど、日立のエアコンだと、これが1000個くらい出ている。何しろメモリが少なくてバッファが取れないんで、なんとか圧縮かけて256バイトに(ヘッダとかあるので、もう少し小さめに)したい。オーソドックスにハフマン圧縮かな。PICは高速だからハフマン符号の解凍くらいなら十分に間に合うんじゃないかと見ているが、さて。
PICのUSB割込の優先度を変更。
リコモンの赤外線信号をPCに転送するのに、PIC18Fシリーズの18F14K50でコードを書いてみた。赤外線受信モジュールをPICの入力端子に接続して、端子の状態変化に対して高優先度割込みを設定。状態変化が起きるごとにタイマをリセットして、タイマ値から時間経過を測定して、リングバッファを経由して同時並行でUSBを介してPCに転送という感じ。しかしオシロの結果と比較すると妙に誤差が大きい。考えてみたらUSBもフレームワークで高優先度割込に設定されていたのだった。USBの処理って結構重そうだから、これが原因かも。
試しに赤外線受信中にUSB転送をするのをやめて、一通り受信し終わってからUSBに転送するようにしてみたところ、誤差が大幅に改善された。とはいえ、このPICはRAMが768バイトしかなく、USBのバッファとかランタイム用で512バイト近く持っていかれてしまい、スタックにも128バイトくらいは欲しい(USBフレームワークからアプリのエントリに来た時点で64バイトくらい消費されてしまっている)ので、アプリには128バイトくらいしか残されていない。しかも最初に実験に使っていた東芝のリモコンは割と信号長が短かくて、これなら頑張れば行けるかもと思っていたのが、ふと日立のエアコンのリモコンを試したら、その10倍くらいデータ量が多くてびっくり。流石に無理かもしれない。赤外線受信だけならまだしも、このあとXBeeという無線モジュールを介して別の場所にあるリモコン対応機器を制御したいなと思っているので。PIC24の24F64GB002のカタログを横目で見つつ、他に手はないかと悪あがき。そもそもUSB割込を高優先度にしなければ良いような気がしてきた。USBのところはバッファもふんだんに割り当てられているし、そもそもフレームワークではポーリングという選択肢も用意されている。それならUSBを低優先度割込にして、高優先度割込の処理をなるべく軽くしておいてやればいいのではないか。
とはいえUSBフレームワークのソースを見ても、優先度設定のオプションが見当たらない。仕方がないのでパッチを当てることにした。USBのフレームワークのMicrochip/Include/USB/usb_hal_pic18.hというファイルの383行あたり。
# if defined USB_INTERRUPT_PRIORITY_LOW (追加)
#define USBEnableInterrupts() {RCONbits.IPEN = 1;IPR2bits.USBIP = 0;PIE2bits.USBIE = 1;INTCONbits.GIEH = 1;} (追加)
# else (追加)
#define USBEnableInterrupts() {RCONbits.IPEN = 1;IPR2bits.USBIP = 1;PIE2bits.USBIE = 1;INTCONbits.GIEH = 1;}
# endif (追加)
あとは自分のアプリケーションのusb_config.hの中に、USB_INTERRUPT_PRIORITY_LOWのdefineを追加してやる。
//#define USB_POLLING #define USB_INTERRUPT #define USB_INTERRUPT_PRIORITY_LOW
とりあえず、これで動いているようだ。
リモコン信号を見てみた。
オシロスコープを新調したので、赤外線リモコンの信号を見てみた。実際は38kHzの点滅信号らしいのだけど、こういった専用の受光モジュールが市販されていて、これを使うと検波は不要。Single shotに設定したら、きれいに信号を取得できた。
この素子は負論理なので、5V出ているところが消灯で、0Vのところが点灯を意味する。記入した時間は実測値なので規格値とは誤差があるようだ。このあたりで解説されている内容によると、先頭にある9000μ秒と4500μ秒のセットがリーダ信号と呼ばれる開始の合図、その後からはデータで500μ秒の点灯と1700μ秒の消灯のセットで1を、500μ秒点灯、消灯のセットで0を表わすらしい。
この信号をリモコンから受けるのであれば、100μ秒くらいの精度のタイマで時間を測り、50msも信号が変化しなければ終了と判定してしまえば良さそう。逆に機器に伝える場合、このタイミングで38kHzの点滅が必要なので、PWMを持ったマイコンを使うのが簡単そう。
Java Communications API
Java Communications APIが10年以上ぶりくらいに必要になったので探す。なんかRXTXというのを使えという記事が見つかるものの、飛び先がリンク切ればかりで、twitterでぼやいたところ、さくらばさんから場所を教えていただきました。もっともこのRXTXというのは、パッケージ名がgnu.orgになっていてJava Communications APIとは別物のよう。まぁUSBモデムデバイスが制御できれば良いので、これを使うことにする。
Linux amd64というマイナー環境なので、ソースからコンパイルすることにする。zipで置いてあるやつは、UTS_RELEASEという識別子が無いよ〜というエラーでコンパイルできないので、CVSから最新版を取る。
で、これだと/dev/ttyACMnデバイスが見つからないのでソースを修正する。src/gnu/io/RXTXCommDriver.javaを開き、
if(osName.equals("Linux"))
{
String[] Temp = {
"ttyS", // linux Serial Ports
"ttySA", // for the IPAQs
"ttyUSB", // for USB frobs
"ttyACM",// linux CDC ACM devices <<= ここを追加。
"rfcomm", // bluetooth serial device
"ttyircomm", // linux IrCommdevices (IrDA serial emu)
};
CandidatePortPrefixes=Temp;
}
あとは、定石通りconfigure/make/make installでok。あ、export JAVA_HOME=の指定が必要。
ここにあるデバイス列挙のサンプルを動かしてみると、列挙された。
shanai@desktop:/tmp$ java Test
WARNING: RXTX Version mismatch
Jar version = RXTX-2.2
native lib Version = RXTX-2.2pre2
/dev/ttyACM0 - Serial
/dev/ttyS0 - Serial
月食
丁度玄関先から見えたので月食を観察。うちの機材は望遠側は300mmまでしかないので、画角的にはこんな感じ。

撮影条件は、1/60s f10 ISO320あたり。以降はトリミング。
22:02頃
22:25頃
22:33頃
22:53頃
23:00頃
23:03頃ほぼ隠れてきて、暗い部分はノイズが厳しいのでシャッタ速度を1s近辺まで落とす。
23:32頃
23:34頃相当暗い。ss 3.2s f10 ISO1600。薄い雲が流れていて、シャッター速度があまり遅いと結構不鮮明。折り返し地点も過ぎたんで退散。寒かった。





