Raspberry Pi PicoでVGA出力をテストしたので、次は音をテストをしました。
Raspberry Pi Picoには音を出力するための仕組みが(たぶん)ないため、そのまま使用できるGPIO、PWM、外部に部品を取り付ける必要があるDAC(PCM)、PSG(AY-3-8910)、FM音源などを試そうと思います。
外部に別の部品を取り付けようとした場合、DACはSPIのものがあるので問題ないが、PSGはピン数が多いためI/Oエキスパンダが必須となり面倒、FM音源は秋月で売っているYMF825がSPIなので買ってくれば良いが、値段高い+私が音楽のことが分からないためもったいないということで今回は試しません。
10bitのDACなら、SN76489をエミュレートすることが十分できると思いますが、部品が手持ちにないためこちらも今回は試しません。
今回は抵抗だけで、簡単に使用することができるPWMとGPIO(+タイマー)を使用して音を鳴らしてみました。
AY-3-8910音源を追加(libvga/pcm/ay-3-8910.c)しました。
ソースコードはdownloadにあります。
AY-3-8910音源をlibvdmgrのソースから作成していたら、実機の波形はこんなのだった?と詳細が思い出せない。
以前AY-3-8910の動作を確認する時にRL78/G13を使用したが、たしか開発環境が無駄にでかくコンパイラが使い物にならなかった記憶があるため、実機確認はまた後で行う
(今ならRL78/G13を使用する必要はなく、PIOが使用できるRaspberry Pi Picoで確認した方が便利)。
ついでにAY-3-8910+SCCも鳴らしてみました。
NAMCOT-163音源を追加(libvga/pcm/namcot163.c)しました。
ついでにVRC6の音源も適当に作成(libvga/pcm/vrc6.c)しました。
今回試していて気が付いたのが、矩形波などが出せず、低い周波数を鳴らすことができない。
抵抗やコンデンサなどを正しく繋げる必要があると思いますが、現状はテストのため音が出れば良いとしています(低音が出ないため、ノコギリ波が厳しい)。
正しい回路の作成など分かる方がいるなら、教えていただきたいです。
また、以下の音楽はVRC6音源部のみ、内蔵音源は再現していません
秋月でSPIのDAC(MCP4911)を買ってきたので、とりあえずSN76789(libvga/pcm/sn76489.c)とSCC音源(libvga/pcm/scc.c)を再現してみました。
適当に作成したものでも、それなりに聞こえました。
結線図 |
今回は、SN76489の周波数などのレジスタ値が使用できるようにしており、トーンをPWM、ノイズをGPIOで実現しています。
PWMとGPIOだけでは音量の変更ができないため、PWMの音量はDuty比の変更、ノイズは音量変更不可としました。
さすがにPWMはDuty比を変更するだけでは音が変わってしまいますが、適当な値を設定しただけでも思っていた良い音が出ました。
今回はDuty比は適当に調整しているので変な音が混ざっていますが、初めからPWMを意識して音を作れば、それなりの音を出せそうです、
※今回試して思ったのは、音量を変える仕組みを用意できれば、PWM(Duty比50%)とGPIOだけでSN76489を簡単にエミュレートでき、CPUパワーも全然必要としない。
サンプルでは、VSync割り込み内で設定していますが、PWMの設定だけなので特に制限はないはずです。
sound_setTone(0, (8<<12)|288) ; // トーン0:音量8 + 周波数レジスタ288 sound_setTone(1, (7<<12)|363) ; // トーン1:音量7 + 周波数レジスタ363 sound_setTone(2, (8<<12)|363) ; // トーン2:音量8 + 周波数レジスタ288 sound_setNoise( 1<<12 ) ; // ノイズ:ホワイトノイズ
結線図 |
今回はMCP4911を使用しましたが、MCP4901/MCP4921でも動作すると思います(未確認)。
PWM時と異なり、36us周期のタイマーで処理を行っているため、少し処理負荷が掛かります。
現在、サンプリング周波数が50KHz以上になっているため、もう少し割り込み間隔を長くすることがで、もう少し軽く動作することが可能です。
また、SN76489はオリジナルから以下を追加・変更しています。