1-chip LFO
(2006年?)凶器エフェクタの会・セミナで、ふふふさんから、「いろんな波形が出るLFOが欲しい。」という声があったのが発端。
マイコンには ATtiny45 を使用して、PWMにてCH0、CH1の2出力。内蔵A/Dコンバータ(ADC)で 周波数 / CH1のCH0に対する位相差 / 波形 を決定している。LFOの周波数は仕様では 7.5mHzから244Hz まで。
ATtiny45のメインクロックは内蔵PLL発振の16MHz。出力は 62.5kHz 8bit のPWMで、回路図では1~2kHz程度のRCフィルタで簡単に済ませている。このままの出力レンジは 0-5V。必要に応じてバファリング、電圧シフト、アクティブフィルタなどを試されたし。
また周波数と位相と波形は電圧ポテンショメータで指定するようになっているが、電圧制御も可能。ADCが10bitなので微妙に段階的な変化かも。しかも敷居の境目ではノイズによってこっちの波形になったりあっちの波形になったりということが起こってしまったが、これはこれで面白いのでそのまま採用。一応CH0に関しては波形が1周期変化したところで波形の切り替わりが行われるようにはしてある。
得られる波形はいろいろさまざま16種類。CVで波形選択できます(Doepfer的)。基本的には256アドレスの8bit語長のテーブルをいくつか持っていてそれを出力しているだけなので、ご興味のあるムキにはテーブルを書き換えればOK! http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=sine1.gif http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=rect.gif
http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=saw.gif http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=sawi.gif
http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=tri.gif
http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=sawpow20.gif http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=sawpow20i.gif
http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=sawlog10.gif http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=sawlog10i.gif
http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=tripow30.gif http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=tripow30i.gif
http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=trilog10.gif http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=trilog10i.gif
http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=asin.gif http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=asini.gif
http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=rand.gif
なんか見ていると、このLFOをカスケードにしても面白いような気がしてきた。そうなると16ステップの階段波形を入れなかったのが悔やまれる。矩形波をやめて階段波にしちゃおうかしら。 そうそう、当初案ではトリガで位相リセットという話があったけれど、それは止めて波形選択にしてしまった。リセットピンをポートに割り当てれば出来なくもないが、あとで波形とかを書き換えたりしようと思ったときに苦労するので見送りました。
8pinモノとしてはだいたい仕様をつっこんじゃったかなと思います。
LFO波形モーフィング
1-chip LFO完成後にRJBさんからコメントが寄せられた。
あと、たとえばCV変化で波形をシームレスに変化させられるというのはハードルが高そうですかね?
当初なかった素晴らしいアイディアで実装は難しくない。隣り合うふたつのテーブルの同一位相での比例配分で良ければ比較的簡単な実装です。10bit ADCの 上4bitで16波形を決定しているので、下6bitで64段階のモーフィングが可能です。チャネルあたり乗算2回と加算1回とビットシフト1回。
丸めを考慮しないでやってみた正弦波から鋸歯状歯(右肩上がり)への波形変化は以下のとおり。
http://www6.atwiki.jp/fx_geek/?plugin=ref&page=1-chip%20LFO&file=morph.gif
モーフィングを考慮した波形テーブル並びに変更するのが良さそう、ということで、当時、ブログならではのインタラクションで機能が追加されることになりました。
製作情報
回路図
http://www6.atwiki.jp/fx_geek?cmd=upload&act=open&pageid=52&file=LFO_8pin.gif
ソースコード
プログラムリスト
開発環境
AVR Studio 4.13 build 528 + WinAVR 20060421
fuse情報
no CK8DIV
CKSEL{3:0} = b0001
FAQ
参考文献
更新履歴
2017/10/20 記載完了
2017/10/20 Scrapboxにて記述開始
Appendix - 実現性検討
その0 8pin AVR LFO 机上検討
思考実験。
8pin AVRを使用した、
数mHz ~ 数100Hz の VC-LFO で、
位相をトリガでリセットする機能があって、
波形は256ポイントの正弦波(または256ポイントのテーブルデータ)を
ゼロ位相のもの と VCで位相を±πシフトしたもの の合わせて2波形を
PWM で出力する。
ざっと考えたところ、なんとか出来そうな感じ。
その1 8pin AVR LFO 机上検討
AVR LFO もその実現していないもののひとつ。半年ぶりに見直したらアルゴリズムを忘れていた。実装はもう3ヶ月先かもしれないが、またアルゴリズムを忘れてはなんなのでメモ。このアルゴリズムはEGを作るときにも使えるかもしれない。
前提
ATtiny45を使用し、64MHzのPWMでのLFO出力2系統
システムクロックは16MHzが使える
コントロールは周波数と位相
片系統の周波数を決め、もうひとつはテーブル参照位相をずらしてreadするだけ
コントロールを取得するA/D変換は10bit
LFO波形は1周期 256ポイントのテーブルを引く
LFOそのものに関しては、
レンジとして16オクターブ(出来高で良い)
周波数が低いところでは解像度が粗くてよい
システムクロックが16MHzなので、仮に256ポイントのテーブルをぶん回すと、$ \frac{16M}{256} = 62.5 (kHz)
256ckごとに割込んでテーブルポインタを更新する場合だと、$ \frac{16M}{256 \times 256} \simeq 244 (Hz)
512ckごとだと、$ \frac{16M}{256 \times 512} \simeq 122 (Hz)
1024ckごとだと、$ \frac{16M}{256 \times 1024} \simeq 61(Hz)
これを式にすると、$ f = \frac{16M}{256 \times 256 \times n}
となる。以下に $ n = 2^i (i=0,1,2,...,15)となる $ n と $ f の関係を表にする。
table:カウントと周波数の関係
i n f (Hz) 1/f (sec)
0 1 244
1 2 122
2 4 61.0
3 8 30.5
… … … …
13 8192 0.0298 33.6
14 16384 0.0149 67.1
15 32768 0.00745 134
その2 8pin AVR LFO 机上検討
ところでADC値は10bit(1024レベル)で、これが $ i = 0, 1, ... , 15 (すなわち $ n = 1, 2, 4, ..., 32768)にリニアにマッピングされることが望ましい。ADC{9:0} を {ADC{9:6}, ADC{5:0}} とビット分割し、上位4bit( ADC{9:0}÷64 の商 $ p)として $ i に対応する値を取り出し、同時に余り $ q = ADC{9:0} % 64 を得る。商$ pで256ckの割り込みが何回になるかを決め、余り$ qは補正する役を担う。
補正は直線補間でも良いが、ここでは $ i をパラメータとする補間関数 $ g_i(q) を定義する。
$ g_i(q) は、$ g_0(0)=0, $ g_0(64)=256, $ g_1(0)=0, $ g_1(64)=512 ...
といった境界条件を持つ。これより考えれば、$ iが1増えるとレンジが倍になるわけで、
$ g_1(q) = 2 g_0(p)、$ g_{i}(q) = 2 g_{i-1}(q)
すなわち、
$ g_i(q) = 2^i g_0(q)
となる。$ g_0(q)を(テーブル等で)定義すれば、これに定数を掛けることで補間関数$ g_i(q)を算出することができるとわかる。
なお現実的に$ g_0(q)の取りうる値は$ 0から$ 255である。
$ iに対応するADC値まで書き入れると次表のようになる。
table:ADC値とカウント値と周波数
ADC i n f (Hz) 1/f (sec)
0 0 1 244
64 1 2 122
128 2 4 61.0
192 3 8 30.5
… … … … …
896 14 16384 0.0149 67.1
960 15 32768 0.00745 134
その3 8pin AVR LFO 机上検討
ここで逆に、任意のADC値からLFOテーブルポインタを1進めるために必要な時間(総クロック数) を算出することを試みる。
仮にADC値が$ 64であるとき、$ 64=64 \times 1 + 0 なので、
総クロック数$ =256 \times 2^1 + g_1(0)
であり、すなわち総クロック数は 512ck となる。$ \frac{16M}{256 \times 512} \simeq 122(Hz) が得られる(検算)。
また、ADC値が$ 67であるとき、$ 67=64 \times 1 + 3 で、
総クロック数$ =256 \times 2^1 + g_1(3)
である。
一般化すると、ADC$ =64 \times p + qとして、
総クロック数$ =256 \times 2^p + g_p(q) = 256 \times 2^p + 2^p g_0(q) = 2^p \{256 + g_0(q) \}
となる。
さてここで、一般化して算出された総クロック数においては $ 2^p でくくり出されていることがわかる。これは、カウントに$ 2^pの分周クロックを使用すれば、カウントすべき値は常に $ 256 + g_0(q)であることを意味する。
$ g_0(q)を アドレス64個、データ値は0~255の2のべき乗に合うように整形したテーブルとして持つようにすれば、10bitのADC値から、周波数が低くなるほどに分解能が荒くなりつつ、0.00745Hz(134秒)~244Hz の LFOを実現することができる(はず)。変化カーブは逆ログ(のはず)。
タイマが8bitで256までしかカウントできない場合には、$ 256 + g_0(q)を$ (\frac{256 + g_0(q)}{2}) + (\frac{256 + g_0(q)}{2})のように二つに分けて、odd/even の組を作って LFOテーブルインクリメントすればよい。二つに分けるときに (256)+(残り) と分けると、残りのクロック数が小さいときに処理が間に合わず破綻するので注意。
なお ATtiny45 では1/1~1/16384の分周が使えるタイマがある。しかし64MHzのハイスピード PWM と排他かもしれないので、このあたりは実装フェーズで要確認。今回はとりあえずタイミング生成のアルゴリズムまで示して終了。
(おしまい)