STM32CubeIDE: Version 1.5.1
Target board: Nucleo-F446RE
Target board: Nucleo-F446RE
32bit/48kHz動作
まず、DMAを利用して32bit/48kHzでサイン波を出力させてみます。16bit/48kHzのプログラムを32bitに変更します。
参考
配線
16bitの場合と同様です。
System Core
GPIO
PC5:
GPIO mode: Output Push Pull
User Label: CK_PERIOD
PC6:
GPIO mode: Output Push Pull
User Label: CK_CPLT
PC8:
GPIO mode: Output Push Pull
User Label: CK_HALF_CPLT
Multimedia
I2S2
Mode
Mode: Half-Duplex Master
Configuration
Parameter Settings
Generic Parameters
Data and Frame Format: 32Bits Data 32Bits Frame
Selected Audio Frequency: 48KHz
DMA Settings
SPI2_TX
DMA Request Settings
Mode: Circular
Peripheral: Data Width: Half Word
Memory : Data Width: Half Word
Data and Frame Formatを32Bits Data 32Bits Frameにしています。
main.cにコードを追加
/* Private includes ----------------------------------------------------------*/ /* USER CODE BEGIN Includes */ #include <math.h> /* USER CODE END Includes */ <中略> /* Private define ------------------------------------------------------------*/ /* USER CODE BEGIN PD */ #define PI_F (3.1415926f) /* USER CODE END PD */ <中略> /* USER CODE BEGIN PV */ float sampling_rate = 48000.0f; float frequency = 1000.0f; float phi = 0.0f; float delta; int32_t tx_buffer[2] = { 0, 0 }; /* USER CODE END PV */ <中略> int main(void) { /* USER CODE BEGIN 1 */ delta = (2.0f * PI_F * frequency) / sampling_rate; /* USER CODE END 1 */ <中略> /* USER CODE BEGIN 2 */ HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t *)tx_buffer, 2); /* USER CODE END 2 */ <中略> /* USER CODE BEGIN 4 */ static int32_t swap16(int32_t x) { return ((uint32_t)x << 16) | ((uint32_t)x >> 16); } void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s) { HAL_GPIO_WritePin(GPIOC, CK_HALF_CPLT_Pin, GPIO_PIN_SET); // Generate Sine wave float fv = sinf(phi); int32_t v = fv * 0x7fffffff; tx_buffer[0] = swap16(v); HAL_GPIO_WritePin(GPIOC, CK_HALF_CPLT_Pin, GPIO_PIN_RESET); } void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s) { HAL_GPIO_WritePin(GPIOC, CK_CPLT_Pin, GPIO_PIN_SET); // Generate Sawtooth wave float fv = phi / PI_F; int32_t v = fv * 0x7fffffff; tx_buffer[1] = swap16(v); // Advance in phase phi += delta; if (phi > PI_F) { phi -= 2.0f * PI_F; HAL_GPIO_TogglePin(GPIOC, CK_PERIOD_Pin); } HAL_GPIO_WritePin(GPIOC, CK_CPLT_Pin, GPIO_PIN_RESET); } /* USER CODE END 4 */
出力波形を観測
16bitの場合とノコギリ波で比較するとほとんど変わらないようです。
スペクトラム
Lch(サイン波) 500kHzレンジ
Lch(サイン波) 100kHzレンジ
Rch(ノコギリ波) 500kHzレンジ
32bit/192kHz動作
サンプリング周波数を上げてみます。STM32F446Eでは32bit/192kHzが最高のレートです。I2Sのクロック周波数Fclkは
Fclk = 2 * 32bit * 192kHz = 12.288MHz
となります。
MXの設定 - Pinout & Configuration
System Core
GPIO
PC5:
GPIO mode: Output Push Pull
User Label: CK_PERIOD
PC6:
GPIO mode: Output Push Pull
User Label: CK_CPLT
PC8:
GPIO mode: Output Push Pull
User Label: CK_HALF_CPLT
Multimedia
I2S2
Mode
Mode: Half-Duplex Master
Configuration
Parameter Settings
Generic Parameters
Data and Frame Format: 32Bits Data 32Bits Frame
Selected Audio Frequency: 192KHz
DMA Settings
SPI2_TX
DMA Request Settings
Mode: Circular
Peripheral: Data Width: Half Word
Memory : Data Width: Half Word
Selected Audio Frequencyを192KHzに変更しています。
MXの設定 - Clock Configuration
STM32F446REのデフォルトのクロック周波数(84MHz)で、I2Sのサンプリング周波数を192kHzで動作させると処理が間に合わないので、STM32F446REを180MHz動作させます。
PLL Source Mux: HSE
HCLK(MHz): 180
コンパイラで速度優先最適化を指定
最適化しないと処理が間に合わないので、速度優先で最適化を指定します。階層が深いので迷いますw
Project > Properties > C/C++ Build > Settings
Tool Settings > MCU GCC Compiler > Optimization
Optimization level: Optimization for speed (-Ofast)
main.cにコードを追加
32bit/48kHzのコードのサンプリング周波数の定義を変更します。
float sampling_rate = 48000.0f;↓float sampling_rate = 195312.0f;
MXでSelected Audio Frequencyに192kHzを指定すると、Real Audio Frequencyが195.312kHzとなるので、これを使って出力波形の周波数を補正します。
出力波形を観測
32bit/48kHzの場合と比べるとノコギリ波のエッジの部分の振動が細かくなっています。過渡特性はかなり向上します。
スペクトラム
Lch(サイン波) 500kHzレンジ
Lch(サイン波) 100kHzレンジ
サイン波のスペクトラムを32bit/48kHzの場合と比較するとノイズフロアが15dBぐらい下がりますが、ところどころピークが現れています。いやですねw
Rch(ノコギリ波) 50kHzレンジ
Rch(ノコギリ波) 500kHzレンジ
※ノコギリ波のスペクトラムは変動が激しいのでLinear RMS Averageにして平均値を表示しています。
ノコギリ波のスペクトラムを32bit/48kHzの場合と比較するとナイキスト周波数の96kHz付近までノコギリ波らしい高調波が見られます。平均値をとっているので単純には比較できませんが、高調波の間のピークが残っています。ノコギリ波の綺麗さではやはりアナログ発振器に分がありそうです。
こういう歪んだ(?)ノコギリ波のほうが味がある場合もあるので、音源としてはいろいろなビット数/サンプリング周波数で出力できるようにすると面白いかもしれません。
PCM5102Aのハードウェア設定
32bit/192kHzの場合もFLTとDEMPの設定による出力の変化を見てみました。
FLT: H
上側の振動がなくなり下側の振動が増えてますね。
DEMP: H
32bit/192kHzではDEMPによる変化はないようです。PCM5102Aのデータシートには以下の記述があります。
De-emphasis control for 44.1-kHz sampling rate(1): Off (Low) / On (High)(1) Failsafe LVCMOS Schmitt trigger input
0 件のコメント:
コメントを投稿