YM2203をNucleo F401REで鳴らす話 (1)
前回: YM2203をNucleo F401REで鳴らす話 (序) - 頼りないニモニック
マスタークロックと発声周波数
YM2203のφMピン(38番)にはマスタークロックとして0.7〜4.2[MHz]を与えなければなりません。
PSG音源、FM音源で生成される波形の周波数は、このマスタークロックに依存します。
参考:
YM2203 データシート(Datasheet) 8 Page - List of Unclassifed Manufacturers
YM2203のピン機能 - 滴了庵日録
計算式より、マスタークロックφMが
- 1.0 [MHz]のとき、
- PSG音源は 3.81 〜 15625 [Hz]
- FM音源は 0.00 〜 867.63 [Hz]
- 4.0 [MHz]のとき、
- PSG音源は 15.3 〜 62500 [Hz]
- FM音源は 0.00 〜 3470.53 [Hz]
のように発声できる音程が決まります。FM音源は基本周波数(正弦波)です。
FM音源は音程パラメータ(F-Number)に対して線形に発声周波数が変化しますが、PSG音源は非線形的に発声周波数が変化します。
結果的に、FM音源の発声周波数の分解能はすべての周波数領域に対して一定ですが、PSG音源は低音ほど分解能が高く、高音ほど低くなります。
なお、FM音源の音程はオペレータ毎に倍率が指定できる(0.5〜15倍)ため、最終的な発声周波数は、
- 1.0 [MHz]のとき、0.00 〜 13014.48 [Hz]
- 4.0 [MHz]のとき、0.00 〜 52057.90 [Hz]
となります。
F401REは最高動作クロックが84[MHz]ですが、84[MHz]そのものを取り出すには少々難があるようです。
YM2203で用いることのできるクロックは、現実的には以下の2種類の生成方法があります。
- PWMを用いてクロック生成 (〜1.0[MHz])
- 内部クロックを分周して出力(3.2〜16[MHz])
PWMでクロック生成
最も簡単と思われる方法です。
ただしmbedのライブラリの仕様上、1.0[MHz]が限界です。精度は高めです。
#include "mbed.h" PwmOut pwm(D3); int main() { pwm.period_us(2); pwm.pulsewidth_us(1); while (1) wait(1); }
このほか FastPWM も使えると思われますが、私の環境では 80[tick] 未満のパルス長は指定ができませんでした。
内部クロックを分周して出力
こちらの記事を発見しました。以下は必要に応じて改変したものです。
F401RE内部で使われているクロックを分周して特定のピンに出力させます。分周比1で16[MHz]、分周比は1〜5まで指定ができます。
精度はあまりよくありません。4分周、室温19[℃]で 4.062±0.005[MHz] ほどです。
#include "mbed.h" int main() { HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSI, RCC_MCODIV_4); /* RCC_MCODIV_x が分周比 */ GPIO_InitTypeDef GPIO_InitStruct; GPIO_InitStruct.Pin = GPIO_PIN_8; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; GPIO_InitStruct.Alternate = GPIO_AF0_MCO; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); while (1) wait(1); }
MCO2もありますが、私の環境ではこれまた出力できませんでした。要検証。
精度に問題があるものの、外部Xtal無しで無事4[MHz]が出力できます。
定格クロック周波数4.2[MHz]を超えることはまずないと思われるため、私は内部クロックを分周して用いることとしました。
次回はYM2203に書き込むデータについてまとめてみます。