製作モジュール一覧

ラベル PCM5102A の投稿を表示しています。 すべての投稿を表示
ラベル PCM5102A の投稿を表示しています。 すべての投稿を表示

2021年3月24日水曜日

STM32CubeIDE: I2S DACのPCM5102Aを32bitで使う

STM32CubeIDE: Version 1.5.1
Target board: Nucleo-F446RE

32bit/48kHz動作


まず、DMAを利用して32bit/48kHzでサイン波を出力させてみます。16bit/48kHzのプログラムを32bitに変更します。

参考

配線


16bitの場合と同様です。


MXの設定


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(ノコギリ波) 50kHzレンジ

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

 

2021年3月19日金曜日

STM32CubeIDE: I2S DACのPCM5102Aを16bitで使う

PCM5102Aは表面実装パッケージですが、秋月からDIP化キットが販売されていてブレッドボードやユニバーサル基板でも実験しやすいDACです。

外付け回路が必要な電流出力ではなく電圧出力で、内蔵電源によりGNDを中心としたAC波形が得られます。また内蔵PLLによりマスタークロックなしの3線(BCK/DIN/LRCK)で使用可能です。

電源電圧が3.3Vで、絶対定格が-0.3V~3.9Vな点は十分注意する必要があります。私は実験中に間違えて5Vを掛けて壊してしまいました。ほんの数秒でアウトです。

秋月ではIC単体ではなくDIP化基板のみの販売です。近年TIがIC単体の販売を絞っているためでしょうか。どういう意図があるんでしょうね?


PCM5102Aは32bit/384kHzまで対応してますが16bitでも使えます。今回は16bit/48kHzで動作させてみます。

STM32CubeIDE: Version 1.5.1
Target board: Nucleo-F446RE

回路図

データシートに載っているTypical Applicationの回路から、出力にかかっているCR LPFを削除しています。SCKは使わずBCKを利用するためGNDに落としています。

配線図



実験のようす

3.3V電源はNucleoからも供給可能ですがPCM5102Aは結構電源にシビアなので、別の電源からとっています。今回は3.3Vのリニアレギュレータを使った電池電源を使用しています。

STM32のプログラムは「STM32CubeIDE: I2S DACのTDA1543を使う - サイン波を出力」のものと同じです。

MXの設定


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
        Selected Audio Frequency: 48KHz
    DMA Settings
      SPI2_TX
        DMA Request Settings
          Mode: Circular
          Peripheral: Data Width: Half Word
          Memory   : Data Width: Half Word

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 */
uint32_t sampling_rate = 48000u;
float frequency = 1000.0f;
float phi = 0.0f;
float delta;
uint16_t tx_buffer[2] = { 0, 0 };
/* USER CODE END PV *

  /* 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, tx_buffer, 2);
  /* USER CODE END 2 */

/* USER CODE BEGIN 4 */
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);
	int16_t v = fv * 0x7fff;
	tx_buffer[0] = (uint16_t)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;
	int16_t v = fv * 0x7fff;
	tx_buffer[1] = (uint16_t)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 */

出力波形を観測


C1:Lch C2:Rch

NOSのTDA1503の場合と比べるとオーバーサンプリングとデジタルフィルタが効いているため、同じ16bit/48kHzのデータでもサイン波にガタガタがほとんど見られません。

ノコギリ波もガタガタは無くなっていますが、上下のエッジに振動が見られます。内蔵のデジタル補間フィルタの特性ですね。

サイン波ではあまりわかりませんが、ノコギリ波だと過渡特性がよくわかります。

スペクトラム


Lch(サイン波) 500kHzレンジ

Lch(サイン波) 100kHzレンジ

48kHz動作ですが、TDA1543を192kHzで動作させた場合と比較して歪が少なくなっています。

Rch(ノコギリ波) 50kHzレンジ

Rch(ノコギリ波) 500kHzレンジ

ノコギリ波では25kHz付近で一旦高調波がカットされ、その後放物線状のカーブが現れ350kHz~400kHzでは帯状のピークが出ています。面白いですね。

PCM5102Aのハードウェア設定


PCM5102AのFLTピンとDEMPピンはH/Lさせることにより特性が変わります。

FLT: H

FLTピンをHレベルにすると補間フィルタがLow Latencyになります。ノコギリ波の波形がNormalとは異なります。

PCM5102Aのデータシートのインパルス応答を見るとNormalがFIR、Low LatencyがIIRっぽいです。IIRのほうがアナログフィルタに近い特性で次数が少なくて済むようですがどうなんでしょうね。

DEMP: H

DEMPピンをHレベルにするとDe-emphasisがONになります。この機能はよく知らないのですがレコードのRIAAのように録音時に高音を強め、再生時に高音を弱めるのでしょうか。ノコギリ波の出力波形を見るとLPFを通したような感じです。

2020年10月30日金曜日

PCM5102Aの出力に8次多重帰還LPF(ベッセル特性/96kHz/10dB)をかけてみる その2

PCM5102A_FGの出力と8th MFB LPFを直結すると信号波形が歪むため、間にバッファとしてOPアンプのボルテージフォロアを入れて測定し直しました。


OPアンプは、アクティブフィルタ、バッファ、仮想GNDともNJM4580DDを使用しました。

ノコギリ波


100Hz

1kHz

10kHz

44kHz

入力波形の崩れがなくなり出力波形もきれいになっています。10kHzからはノコギリ波の立ち下がりの遅れがはっきりしてきます。44kHzでは1波形ごとに参照するテーブルの要素が異なるため、出力にうねりが現れています。

スペクトラム


PCM5102A_FGから44kHzの正弦波を出力し、Analog Discovery 2 + WaveFormsのSpectam機能でTHD、THD+Nを計測しました。

バッファなし

バッファあり

バッファを入れることにより歪率(正弦波)も改善するようです。

OPアンプの品種を変えてみる


OPアンプの品種を変えて、歪率が改善されるか見てみました。

アクティブフィルタ、バッファに使うOPアンプを変更し、仮想GND用のOPアンプはNJM4580DDです。

NJM4580DD

NJM072D

OPA2134PA

OPアンプの品種による歪率はあまり変わりません。44kHzあたりになるとOPアンプの性能より、PCM5102Aから出力される波形のガタガタとDDSのテーブル参照によるの出力波形の周期性などの方が問題になるようです。

2020年10月26日月曜日

PCM5102Aの出力に8次多重帰還LPF(ベッセル特性/96kHz/10dB)をかけてみる

以前作ったオーディオ用DACのPCM5102Aを使ったファンクションジェネレーター(PCM5102A_FG)の出力に8次多重帰還LPFをかけてみました。

PCM5102A_FG

設計


PCM5102A_FGは32bit/384kHzですが、出力波形はもろにデジタルのガタガタが現れています。


PCM5102A_FGは波形テーブルを使っているので、正弦波だけではなくプログラム次第で任意の波形を出力できます。過渡特性を良くして波形を崩さないようにベッセル特性で設計しました。

サンプリングレートが384kHzなので半分の192kHzより上を遮断域にすればよいのですが、ベッセル特性は次数を上げてもカットオフ周波数付近のキレが悪いので、今回は様子見としてカットオフ周波数96kHzにしました。

また、PCM5102Aの出力振幅は2.1[VRMS]ですので、使いやすいように利得を10dBとしました。単純計算では6.3[VRMS]の出力となります。

シミュレーション回路図

周波数特性

192kHzでは約-17dBの減衰です。(利得10dBから見て)

ステップ応答

特性の実測


製作した基板

仮想GNDを使って単三電池x6の9Vの単電源を電源としています。OPアンプはNJM4580DDを使用しています。

周波数特性

ステップ応答

PCM5102A_FGの出力にかける



フィルターに10dBの利得があるため、直結すると電源電圧の制限で出力がクリップしてしまうので、途中に10kΩのPOTを入れて出力を減衰させました。

フィルターを通したあともPCM5102A_FGの出力と同じ振幅になるようにPOTを調節しています。

また、今まで使っていた4次VCVS LPF(バターワース特性)も同じ条件で測定しました。

出力周波数は少し意地悪して44kHzとしています。

PCM5102Aの生の出力

4次VCVS LPF

8次MFB LPF


8次MFB LPFでは4次VCVS LPFと比較しても歪さが取れてきれいな正弦波になっています。

スペクトラム


PCM5102Aの生の出力

4次VCVS LPF

8次MFB LPF

高周波数でのピークがかなり取れています。Measure機能でTHDとTHD+Nを%表示させていますが、8次MFB_LPFでは

THD:     0.0843%
THD+N: 1.313%

とかなり良好だと思います。デジタル歪は高調波歪(基本周波数の整数倍)とは限らないのでTHD+Nの値も重要です。

今回はカットオフ周波数96kHzとしましたが、100kHz付近にまだピークがみられます。これは高調波歪のようです。

ノコギリ波


100Hz、1kHz、10kHz、44kHzのノコギリ波を出力して8次MFB LPFを通してみました。

100Hz


1kHz

10kHz

44kHz


ノコギリ波の底の部分で波形が歪んでいます。入力側も歪んでいるのでフィルターに入力する前にバッファを入れれば改善するかも知れません。(←淡い期待)

いずれにせよ、高周波数になると素の波形がはっきりと階段状になってくるので、ノコギリ波では10kHzぐらいが上限だと思います。

この点、アナログ発振器は小細工しなくてもきれいなノコギリ波を得られるので有利だと思います。