2012年12月30日日曜日

RaspberryPiでIRリモコンを読む(PCMの設定)


続いて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[PCMCS] = PCMCSSTBY | PCMCSEN;
  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 件のコメント:

コメントを投稿