トップ «前の日記(2008年03月13日) 最新 次の日記(2008年03月22日)» 編集
2003|01|02|03|04|05|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|10|12|
2009|02|03|06|07|10|11|12|
2010|01|02|03|04|07|09|10|11|12|
2011|01|03|04|05|06|07|08|10|
2012|01|06|08|09|10|12|
2013|01|02|03|04|07|09|11|12|
2014|01|03|04|05|06|09|
2015|04|
2016|01|08|
ここは旧えびめもです。えびめも2に移行します(2016/12/1)

2008年03月14日

音声コーデックできた

以前設計して中断していた音声コーデック基板のハード試作とドライバ試作ができた。コーデックは Phillips製でたぶん量産CDプレイヤー用だと思われる。

SH4 LinuxマイコンボードCAT760(MB760)用の、録音再生基板。試作1号機。勢いで作ったので超空中配線だ。SMTの水晶に足をつけて立ってる(笑)

SH7760のSSI(シリアルサウンドインターフェース)が録音もしくは再生どちらかしか使えないので外部に3stateバッファを入れて半二重とした。サンプリングレートはCD互換の44.1KHzがよかったのだけど水晶が手に入らなかったのでDVD互換の48KHzとした。時期リビジョンまでに44.1K用の水晶(44.1KHz * 256 = 11.2896MHz)を手配しよう。
    /dev/ssi_play
    /dev/ssi_rec
のデバイスとした。で、大方の予想通り
  # cat /dev/ssi_rec > data.bin       で録音ができ
  # cat data.bin > /dev/ssi_play      で再生ができる
う〜ん。こいうのが簡単にできるのがLinuxのいいところだなぁ。
  # cat dancingqueen48K.pcm > /dev/ssi_play
とかして遊んでみた。ノイズ対策を全くしていない基板だが意外と音がよくて驚いた。48KHz,16bit,Stereoデータ(=データレートは192KByte/secだね)の再生時に、気になるロードアベレージは 0.22くらい。ドライバを工夫したらもちっと下げれるかも。以外と低負荷だ。

低負荷達成

ほぼ測定限界以下のロードアベレージ 0.00 まで下がった。DMAと自動リングバッファのアイディアが活きた。
# time cat dancingqueen48K.pcm > /dev/ssi_play
real    3m49.402s
user    0m0.000s
sys     0m0.030s
スプールバッファ256Kバイト/一回の転送サイズ8Kバイトの条件で、3分49秒のPCMデータを鳴らして、ドライバ動作時間+CFからのファイル読み込み時間の累計はたったの30msec。

44.1KHz→48KHz変換

この試作基板のサンプリングレートは48KHzなのでCDからリッピングした44.1KHzのPCMデータはそのままでは再生できない。試しにやってみたら1音以上音が高くなって気持ち悪かった。変換ツールはヤマハさんが出しているフリーのものが便利に使えた。

http://www.yamaha.co.jp/ にいって検索窓に twe と入れると出てくる。2001年のものだけどVISTAでも動いたし、機能も十分だった。

SSI DMAドライバメモ

SH7760の DMA にはハーフ転送完了割り込みと全転送完了割り込みがある。マニュアル読んでみると AB 2面バッファ方式を意図していると読み取れる。しかし DMAには自動リピート機能もあるので、これをつかうと自動リングバッファと考えることもできると思われる。そう考えるたほうが半々なんて制約せずに確保した全バッファ分スプールできる。
んでリングバッファになるようにコードを作ったのだけど受信ですごくノイズが乗る。
#define RX_INP	(RX_SIZE-*DMAARXTCNT0)
while(RX_INP == RX_OUTP){
	// 受信リングバッファが空から少し待つ
	;
}
rx_inp = RX_INP;	// RX_INPは動いてしまうのでテンポラリ変数に控える
if(rx_inp > RX_OUTP){
	length = rx_inp - RX_OUTP;
}else{
	length = RX_SIZE - RX_OUTP;
}
とやるとノイズだらけ。どうやら DMAARXTCNT0 (受信DMA残りバイト数)が示す値よりも実際にメモリに書き込まれた情報が少ないようである。ここから先はマニュアルにも書いていないので憶測だけど、SDRAMへの転送ストアキューに入っているデータが数ライン分あって、それはSDRAMには到達していないように思う。仮に
while(RX_INP == RX_OUTP){
	// 受信リングバッファが空から少し待つ
	;
}
rx_inp = RX_INP;	// RX_INPは動いてしまうのでテンポラリ変数に控える
mdelay(1);   // 1msec待つ
以下同じ
とやって DMAからメモリに書き込まれただろうと適当に1msec待ちを挟むとノイズがない。む。