発振器を作る―第2回
発振器を作る―第2回
ATtiny85版を検討した。
4096×8bitのテーブル引きなのでポインタは12bit。位相アキュームレータとしては32bitを用意すれば良さげ。256ステップのタイマで割り込んだら、ポインタが指すデータをPWMに送りこみ、次の割込み時に備えて位相アキュームレータをアップデートしておいて、返る。これを256ステップ内で動作させられれば良い。
試してみたところではけっこうぎりぎりかも。ダメなら512ステップごとのレートでのデータ出力に替えよう*1。
位相アキュームレータのアップデートの量が周波数を決めることになる。
ATtiny85版ではアップデータの量すなわち周波数を外部から可変できるようにしておこうと考えている。I2Cに使えるポートがあるのでこれを使うことして、ATMELのアプリケーションノートから次のようなものを探し出してきた。
Cのコードも利用可能なのでありがたく使わせていただく*3。IARのAVRコンパイラ用のコードだったため、
- 割込みサービスルーチンの書き方
- AVR型番のdefine名
といったあたりでWinAVRとは差異がある。直す。
ついでにATtiny25/45/85用の部分に誤りがあった。直す。そしてシミュってみた。
AVR312のI2C slaveライブラリは、I2Cスタートコンディションを割り込みで検知したら、データ送受用のシフトレジスタのオーバーフローのたびに割り込んで状態を遷移しつつバッファ処理をしてI2Cのデータの授受を行っていた。受信時は裏でバッファに溜まるのだけど、バッファにデータがあるかどうかはメインループの中でポーリングしていた。まぁよくある実装。UARTでも良くやられるし。
しかしながら今回の用途にはこのポーリングが良くないようだ。1クロック命令と2クロック命令とのハザマで、タイマの割り込みが256ステップになったり257ステップになったり。
これは出力サンプルレートの揺らぎとなる。発振器としてどうよ、ってことになる。
さてどうしようかな…
(つづく)