ソースコード
#include <project.h>
#define TABLE_LENGTH 128
/* Defines for DMA_1 */
#define DMA_1_BYTES_PER_BURST 1
#define DMA_1_REQUEST_PER_BURST 1
#define DMA_1_SRC_BASE (CYDEV_SRAM_BASE)
#define DMA_1_DST_BASE (CYDEV_PERIPH_BASE)
/* Variable declarations for DMA_1 */
/* Move these variable declarations to the top of the function */
uint8 DMA_1_Chan;
uint8 DMA_1_TD[1];
int8 sineTable[TABLE_LENGTH*2];
const uint8 sineTable8[TABLE_LENGTH] =
{
128, 134, 140, 147, 153, 159, 165, 171,
177, 183, 188, 194, 199, 204, 209, 214,
218, 223, 227, 231, 234, 238, 241, 244,
246, 248, 250, 252, 253, 254, 255, 255,
255, 255, 255, 254, 253, 252, 250, 248,
246, 244, 241, 238, 234, 231, 227, 223,
218, 214, 209, 204, 199, 194, 188, 183,
177, 171, 165, 159, 153, 147, 140, 134,
128, 122, 115, 109, 103, 97, 91, 85,
79, 73, 68, 62, 57, 52, 47, 42,
37, 33, 29, 25, 22, 18, 15, 12,
10, 7, 6, 4, 2, 1, 1, 0,
0, 0, 1, 1, 2, 4, 6, 7,
10, 12, 15, 18, 22, 25, 29, 33,
37, 42, 47, 52, 57, 62, 68, 73,
79, 85, 91, 97, 103, 109, 115, 122
};
int main()
{
int i;
// 符号付き16bit sineTableの生成
for (i = 0; i < TABLE_LENGTH; i++) {
sineTable[i*2] = (int)sineTable8[i] - 128;
sineTable[i*2+1] = 0;
}
CyGlobalIntEnable; /* Enable global interrupts. */
/* Place your initialization/startup code here (e.g. MyInst_Start()) */
I2S_1_Start();
/* DMA Configuration for DMA_1 */
DMA_1_Chan = DMA_1_DmaInitialize(DMA_1_BYTES_PER_BURST, DMA_1_REQUEST_PER_BURST,
HI16(DMA_1_SRC_BASE), HI16(DMA_1_DST_BASE));
DMA_1_TD[0] = CyDmaTdAllocate();
CyDmaTdSetConfiguration(DMA_1_TD[0], (TABLE_LENGTH*2), DMA_1_TD[0], TD_INC_SRC_ADR);
CyDmaTdSetAddress(DMA_1_TD[0], LO16((uint32)sineTable), LO16((uint32)I2S_1_TX_CH0_F0_PTR));
CyDmaChSetInitialTd(DMA_1_Chan, DMA_1_TD[0]);
CyDmaChEnable(DMA_1_Chan, 1);
while(0u != (I2S_1_ReadTxStatus() & I2S_1_TX_FIFO_0_NOT_FULL))
{
/* Wait for TxDMA to fill Tx FIFO */
}
CyDelayUs(1);
I2S_1_EnableTx();
for(;;)
{
/* Place your application code here. */
}
}
/* [] END OF FILE */
DMAの設定
16bitデータなので1度に2Byte送るつもりで「DMA_1_BYTES_PER_BURST」を2に設定していたが、よくわからないので1に戻した。要求1回で1度に1Byte送る。「DMA Wizard」ではDestinationをI2Sコンポーネントに設定すると「Byptes per Burst:」の項が1しか選択できなくなるのでこういう仕様なんだろう。I2Sのデータは符号付き
WindowsのWavフォーマットも16bitPCMは符号付きだが、TDA1543の受け取るデータも符号付きらしい。サイン波形の配列がたまたま符号なし8bitのものしかなかったので(作るのがめんどくさい)プログラムで// 符号付き16bit sineTableの生成として符号付き16bitのデータを作った。
for (i = 0; i < TABLE_LENGTH; i++) {
sineTable[i*2] = (int)sineTable8[i] - 128;
sineTable[i*2+1] = 0;
}
インターリーブなので左右のチャンネルで代わりばんこにデータが送られる。
I-V変換
配線抵抗一本で電流電圧変換しているが、ここの抵抗値を決めるのがなかなか難しい。値を変えて出力波形を見てみた。
2.2kΩ
上側がつぶれている
1.5kΩ
上下とも少しずつつぶれている。
1.2kΩ
下側がつぶれている。
上側のつぶれは電源電圧を上げれば改善された。PSoC 5LPは5.5VまでなのでTDA1543のVDDだけ自作の電流/電圧計付可変両電源を使って電源電圧を上げてみた。
I/V変換用抵抗:2kΩ
電源電圧:5.51V
電源電圧:6.00V
電源電圧:6.49V
電源電圧:6.99V
2kΩの抵抗だとVDD:6V程度でフルスケール出力できるようだ。
電圧を変更しても消費電流は43mA程度だった。
拡大
2kΩだとまだ下側つぶれているようなのでもう少し抵抗値を上げたほうがよさそうだ。
周波数のチェック
今回はI2Sコンポーネントに12MHzのクロックを入力したので、I2Sのクロックは1/2の6MHzになる。16bitの2chなのでサンプルリング周波数は6MHz / (16 * 2) = 187.5kHzサンプルデータの周期は128/2=64なので
187.5kHz / 64 ≒ 2.93kHzオシロでの計測値も2.9kHz程度になっているのでこれでだいたいOK。
メモ:
TDA1543の7PinはVrefとなっていて電圧を測ると2.13V程度。波形の中点としてはちょっとずれてる?(オシロの計測値だと3.35V程度)1.5kΩの抵抗を入れているが、このRを取り去ると波形が出力されなくなる。音楽の再生ではなくてDDSで波形を生成するならサンプリング周波数はきっちり48kHzとか96kHzにしなくてもいい?安定度を上げるためには外付けの水晶を使う必要はありそう。
TDA1543である程度ファンクションジェネレータとしてテストしてみてからDACをPCM5102Aに変更
Github
https://github.com/ryood/TDA1543
0 件のコメント:
コメントを投稿