2023年8月10日木曜日

BlackFinを使ってみるなり(9) DAC PCM5101動いたじょ~

九十九由基って呪術0に出てこなかったっけ? こんばんわ、ひらりんです.

ちょっとてこずりましたが、BlackFinにDAC PCM5101を接続できました.
手始めにノコギリ波を出しました.なんか直線性がちょっとおかしくないかこれ?
仕様:
96kHz32bit2ch
I2Sで接続(BlackFinのSPORTを利用)
Lch 上がりノコギリ波 100Hz
Rch 下がりノコギリ波 100Hz
BCK 100MHz/16=6.25MHz  BF706内部発生
LRCK BCK/64=97.656kHz  BF706内部発生

作業風景

project詰め合わせをこちらに置きます.

PCM5101付近の回路図(PCM5102でも同じ)

BF706評価ボードのコネクタからのシリアル信号取り出し.PCM5101へ接続する.

ーーーー
restdac.cの説明.

データバッファは256BYTES.32bit2chを納めるので、サンプリングクロック32発分を格納することになります.96kHzの32発だと333uSecで消費される計算かと.
#define SIZE_OF_TX_BUFFER  256

I2Sのparameter設定.上から、96kHz、32bit、BCK周波数、DAC出力周波数100Hz
#define I2S_FS  96000
#define I2S_BIT 32
#define I2S_BCK (2 * I2S_BIT * I2S_FS)    // 6.144MHz
#define I2S_AUDIO_FREQ   100

256Bytesのデータバッファを2本用意します.片方が送信中に、片方にdata setすりゃいいかなと思いまして.
uint8_t nBufferTx0[SIZE_OF_TX_BUFFER];
uint8_t nBufferTx1[SIZE_OF_TX_BUFFER];

ノコギリ波のdata変更step.
96kspsで100Hzですから、960回でloopです.
32bit fullを960回でloopするのですから、0x100000000/960がstepとなります.
uint64_t step = 0x100000000 / ( I2S_FS / I2S_AUDIO_FREQ ) ;

SPORTに何かあったら割り込みが発生し、このcallback()に入って来ます.送信バッファが空になるので長くても333uSec毎に飛んでくるはずだと思う.
void SportCallback(void* pHandle, uint32_t u32Arg, void* pArg)

callback関数の中にswitch-case文があり、これは送信し終えてバッファが空になったことを示しています.
case ADI_SPORT_EVENT_TX_BUFFER_PROCESSED:

送信し終えたのですから次の送信データを準備しときましょう.
TxBuffer0が終わったのなら、TxBuffer1を送信し、TxBuffer0を書き替えます.
TxBuffer1が終わったのなら、TxBuffer0を送信し、TxBuffer1を書き替えます.
やってみてこれで動くという条件です.
DACはsigned 32bitですから、LとRはintで宣言してあります.
問題は、これをbig endianで格納するべきなのか、little endianで格納するべきなのか?
結論はご覧の通りlittle endianでした.
Lを*nBufferTx0へ一発でドンッと書くように改良するべきだけどやってません.
LRの順でbufferに格納します.1サンプル辺り8BYTESになります.
nBufferTx0[i+0] = L;
nBufferTx0[i+1] = L>>8;
nBufferTx0[i+2] = L>>16;
nBufferTx0[i+3] = L>>24;
nBufferTx0[i+4] = R ;
nBufferTx0[i+5] = R>>8;
nBufferTx0[i+6] = R>>16;
nBufferTx0[i+7] = R>>24;

SPORTの設定関係はこれで全部.
SPORT0のAchをTXで使っています.
clockは、FB706内部のSCLK0 100MHzを源発振とし、適当に分周してます.
DMAを使いますが、この1文でDMAを接続できてしまうのは楽でいいや.
adi_sport_Open(1, ADI_HALF_SPORT_A,ADI_SPORT_DIR_TX, ADI_SPORT_I2S_MODE, DeviceMemory, ADI_SPORT_DMA_MEMORY_SIZE, &hDevice);
adi_sport_ConfigData(hDevice, ADI_SPORT_DTYPE_ZERO_FILL, 31u, false, false, false );
adi_sport_ConfigClock(hDevice, 15u, true, false, false);
adi_sport_ConfigFrameSync(hDevice, 31u, true, true, false, false, false, false);
adi_sport_EnableDMAMode(hDevice, true);
adi_sport_RegisterCallback(hDevice, SportCallback, NULL);
adi_sport_SubmitBuffer(hDevice, nBufferTx0, SIZE_OF_TX_BUFFER);
adi_sport_Enable(hDevice, true);

さて次は何をやろうか?

8へ    10へ

かしこ

0 件のコメント:

コメントを投稿