入力
バスドラム・スネアドラム・ハイハットの三つのチューン入力は、ボリューム基板から CV としてマイクロプロセッサへ ADC 入力として入っています。チューン制御をするには、まず ADC を使って CV を読み取る必要があります。
出力
バスドラム・スネアドラムのチューンは CV としてマイクロプロセッサの PWM 出力から回路に入っています。オリジナル回路でも同じなのですが、制御電圧の範囲について注意が必要です。ハイハットのチューンはオリジナルになかった機能ですが、PCM のクロック周波数を変えることで制御します。
ATMega64 での AD 変換
ATMega64 には備え付けの ADC が入っていますから、これをそのまま使います。AD 変換器は一個だけですが、アナログマルチプレクサを使って 8 チャネルまでの入力が可能です。909 クローンでは、このうち 0-2 の 3 チャネルをチューン入力に使っています。
AD 変換の手順は、以下のように行います
- AD チャネルを切り替える
- 切り替えが完了するまで少し待つ。チャネルを切り替えていきなりアナログ値を読むと読み取り値が不安定になる
- AD変換制御レジスタの「AD変換中フラグ」を立てて AD 変換を開始する
- AD 変換が完了するとプロセッサが「AD変換中フラグ」を落とす
- フラグが落ちるのを待ってAD変換値を読み取る
このように、AD 変換はちょいちょい「待ち」を入れないといけないので、メインルーチンのループの中で定期的に AD 変換部に戻ってきて以下を繰り返します
- AD チャネルを切り替える
- AD 変換を開始する
- AD 変換が終了したか確認する。終了していなければこのステップを繰り返す
- AD 変換値を読み取る。読み取った値を処理する
以前電圧制御エンベロープジェネレータを AVR で作った時に同じことをしているので、そのコードを参考にしました。その時には、上記ステップの間隔を 10ms に取ったのですが、今回は少しのんびり 16ms にしました。ボリューム値の読み取りなので遅すぎることはないでしょう。
AD 値の処理
バスドラムへのチューン入力が一番単純でした。ADC の値をチューン PWM に送りました。8 ビット 256 ステップなので、0 から 255 の PWM 値に割り当て、それをそのままバスドラムのチューン CV として送ります
スネアドラムも同様ですが、CV 範囲に少し配慮が必要でした。以下はオリジナルの回路のスネアドラムのチューン入力部ですが、電源電圧 12V を分圧して 1V – 2V の範囲に CV が収まるようになっています。これに対して、クローンの PWM 出力は分圧することなくそのままオシレータに直結しているので、 0V – 5V の範囲の CV を入れることができてしまいます。
これでは出せる音の高さの範囲が広すぎるので、ADC の値から PWM 値に変換する部分を調整して CV の範囲を制限しました。ここは、音を聴いて使いやすそうな範囲を決めたのですが、結果 CV の範囲は約 0.74V – 2V となったので、良いんじゃないかと思います。
最後にハイハットのチューンコントロールですが、これは、PCM のタイマのオーバーフロー割り込みの処理の際にカウンタの値を 0 より進めることで実装しました。一番音の低いところでは 0、そこから ADC 値の増加に応じてカウンタを進めると、早くオーバーフローするのでチューンが上がることになります。実際の実装では使いやすい範囲に収めるために ADC = 0 でも開始カウンタ値は 0 よりも大きくしました。これで狙い通りハイハットのチューン調整が可能になりました。でももともとの PCM クロック (約30kHz) より高くするのはあまりうまく行かず、もっぱら下げる方に範囲は割かれました。なぜなのかはまだ解析していませんが、PCM 回路はもともと 30kHz 程度をサンプリング周波数にするように設計されていて、そこから高くすると、PCM 出力のエイリアジングを除去する LPF が音を削りすぎてしまうのかもしれません。
LPF は固定なので本来はサンプリング周波数は変えるべきではなく、その代わりにファームウェア側でアップサンプリング・ダウンサンプリングするのが正しそうですが、それをするには少し処理速度がこころもとなく、まだ MIDI 入力処理やシーケンサなどタイミングに厳しい処理が実装されていないこともあり、とりあえず今はこのままにしておきます。そういうわけで、ハイハットのチューンを落とすとエイジアリングらしきジャリジャリしたノイズも聞こえます。