続いてPCMの設定です。
FRAME_SIZEを32bitにして、32bit分まるごとch1に割り当てます。
PCM_FSはMasterにしないとFS待ちで止まってしまうのでMasterに設定します。
PCMCLKはexternal_clkのinputに設定します。
これで、GPIOCLKで作った38kHzでサンプリングしてFIFOに取り込まれるようになります。
DMAはユーザーランドからはPhysicalAddressが取れないのと、連続メモリの割当が出来ないのでポーリング動作で取り込んでエラーが発生していないことだけを監視しています。
一緒にRXFIFOのレベルを監視してギリギリになっていないことを見られるようにしています。
今のところエラーなく取り込めているようですが、エラーが多発するようならば、linuxの使用メモリをちょっと小さくして後ろ側のメモリを固定でDMAバッファにしてしのごうかと思います。
-----
int PCMRead(unsigned int *buf, int size) { // ret = maxfifo level, ret < 0 error
pcm[PCMMODE] = PCMMODECLKDIS | PCMMODECLKM | (31 << SHIFT_PCMMODEFLEN) | (1 << SHIFT_PCMMODEFSLEN); // PCMCLK stop
pcm[PCMRXC] = PCMRXCCH1WEX | PCMRXCCH1EN | (0 << SHIFT_PCMRXCCH1POS) | (8 << SHIFT_PCMRXCCH1WID);
pcm[PCMMODE] = PCMMODECLKM | (31 << SHIFT_PCMMODEFLEN) | (1 << SHIFT_PCMMODEFSLEN); // PCMCLK start
pcm[PCMCS] = PCMCSSTBY | PCMCSRXERR | PCMCSRXCLR| PCMCSEN; // RXERR RXFIFO Clear
usleep(120); // 120us (> PCMCLK 26us x 4clk)
pcm[PCMCS] = PCMCSSTBY | PCMCSRXON | PCMCSEN; // RXON
unsigned int d1 = 0xffffffff;
unsigned int d2 = 0xffffffff;
int maxfifo = 0;int error = 0;
do {
d1 = d2;
while(!(pcm[PCMCS] & PCMCSRXR));
d2 = pcm[PCMFIFO];
} while(d2);
buf[0] = d1;
buf[1] = d2;
for(int i = 2; i < size; i++) {
while(!(pcm[PCMCS] & PCMCSRXR));
buf[i] = pcm[PCMFIFO];
if(pcm[PCMCS] & PCMCSRXERR) error = 1;
int fifo = (pcm[PCMGRAY] >> 16) & 0x3f;
if(fifo > maxfifo) maxfifo = fifo;
}
pcm[PCMCS] = PCMCSSTBY | PCMCSEN; // RXoff
if(error) return -1;
return maxfifo;
}
0 件のコメント:
コメントを投稿