■大した話じゃないんですが、GPSロガーは根幹部ができあがり、あとはディテールを仕上げていくのみ。とりあえずは。細かいところの使い勝手を良くしていこうというわけです。使い勝手といってもそれほどいじれるところはないのですが、以前のバージョンからどうしようかとつねづね思っていたのが、インジケータの点滅パターンだった。ピカピカ、チカチカするあれです。
最初、明滅は主処理中のループの中で処理させていました。一回書き込んではチカ、二回書き込んではチカ、みたいな。ただ、書き込み処理にしろ、GPSからの読み込みにしろ、それぞれの処理時間は安定していない。だから、ちょっとみっともないチカチカになるわけです。それと、明滅のパターンのバリエーションを持つのが難しい。例えば●が点灯で○が消灯として、●○●○○○みたいな。できないことはないんですが明滅制御だけでロジックを喰うことになり、GPSモジュールからの読み込みとSDへの書き込みを1秒サイクルで処理しなければならないことを考えると、あんまり余計なことはしたくない。1秒って短いようだけど、ATmega128は内臓オシレータで8MHz動作だから結構余裕があるといえば、あるんですが。
明滅の間隔が不規則になるのは、主処理に押し込んでいるから。ということは、主処理とは別の規則正しいサイクルで動作するようにしてやればいいわけです。概ねそういう目的のためにタイマ割り込みというのが使われます。主処理で何をしていようと、定期的に割り込んで処理をしてくれるわけです。
タイマ割り込みによるチカチカというのは、いわば定番なんですが、できれば、チカチカではなく、チカチカ‥‥チカチカ‥‥、みたいなパターンを持たせたい。割り込み処理は本来の主処理を止めて脇道の処理をしていますから、あんまり重たい処理はさせられない。SDカードの書き込みそっちのけでチカチカやっているなんて、想像もしたくありません。
最初に考えたのは、明滅パターンを配列に収める方式ですが、ただ、チカチカさせるためだけにメモリを消費するのもコスト対効果としては考え物です。明滅パターンをビットに変換して格納する、というのもメモリ効率は高いですが、基本的に配列と同じだし、ヒトの目に明滅のパターンとして認識させるためには、(CPUとしては)結構長いサイクルを必要とします。つまり、ビット数もそれなりに確保しなければならないでしょう。
要はある割り込み回数に達した時に、点灯し、さらに次の所定回数に達した時に消灯してくれればいいわけです。ということは、「割り込み回数」そのものをパラメータとして利用できればいいのではないのか。
というわけで思いついたのが次のロジックです。
PATTERN=0b01010000; byte counter=0; time_interval(){ LED = ON; if((counter&PATTERN)!= 0) LED = OFF; LEDCONTROL(LED); counter++; }
実際に使っているコードではありません念のため。加算されるcounterの値とパターンマスク(PATTERN)の論理積をとって、どこかしらのビットがマッチした場合は消灯します。counterは足しっぱなしですが、実際にはbyte型なので255の次は256ではなくて、0に戻ります。
これで何がどうなるかというと、全体で256の長さ(0-255)を持つ点灯タイミングにおいて、PATTERNの8つのビットに対応する消灯タイミングが発生することになります。
これだけだとイメージが掴みにくいと思いますので、PATTERNが3ビットの場合を例示して終わりたいと思います。PATTERNが3ビットの場合、基本サイクル長は8になります。
で、PATTERNが0b001の場合。
●○●○●○●○
PATTERN=0b010の場合。
●●○○●●○○
PATTERN=0b101の場合。
●○●○○○○○
つまり、めまぐるしいチカチカから、普通のチカチカ、はたまたチカチカ‥‥チカチカ‥‥というパターンを同じロジックで、ただパターンマスクを変更するだけで発生させられます。仕掛け的に奇数回の点灯はできないのですが、個人的にはこの程度で十分。この程度のことなら誰しも思いついているような気がしますが、軽く検索した範囲では見当たらなかったもので。
アルゴリズム辞典というのを昔愛読した時期があったのですが、組み込み系の定番アルゴリズム辞典というのがあってもいいのかなという気がします。ただ、AVRのCの場合、コンパイラが微妙というか、ヘンなところで想定しない動作をすることがあるので、予防的コーディング(いわゆるバッドノウハウ)例の方が役に立つのかもしれません。