2020年9月1日火曜日

STM32でDCC/DDCを作る方向で (48) 設計資料 audio data flow

告知です.
コミケ99にて当社のDDC/DACを頒布いたします.
  日付   2021年12月31日(金) 東地区 テ-40b  東5ホール
  サークル名    bangflat
コミケにお越しの際はお立ち寄りいただけますとありがたいです.
商品紹介ページを作りました.
ーーーー

ありゃ、9月だ.STM32でDCC/DDCを作ろう!            INDEXページへ

情報が間違っていても責任とらないし賠償とかしないです.

audio data flowを描写したく思います.始まりはUSB endpointの辺り、終着点はI2Sまで.

【endpoint 1の辺り】
USB EP1がaudio streamの入り口です.当deviceの最高レートは32bit384kHz2chですので、毎秒3.072MbytesがUSBを飛んできます.(4bytes x 2ch x 384k)

一方でUSB2.0のマイクロフレーム周期は125uSec=8kHzです.つまりpacketをなるべくせわしなく送ろうとしても毎秒8000個が上限だと言えます.

USBのpacketを観測すると、8000個のpacketに均等にバラかしてaudio streamが飛んでくるみたいです.だとすると、毎packetのaudio dataはどれだけかを計算できます.

    3072kbytes ÷ 8000 = 384bytes/packet
なんだか偶然の数字の一致ですが、384kHzのときは384bytesがpacket毎に飛んできます.48kHzならば48bytesです.

以上から、STM32のcodeはaudio data処理をこのようにする必要があります.
 ・packet毎に、すなわち125uSec毎に割り込みがかかる
 ・44.1~384bytesのaudio dataを処理する必要がある  @32bit
 ・このaudio dataはメモリ上のpacketバッファに格納されて引き渡される
 ・次の割り込みがかかるよりも速くaudio dataを何処かへコピーせにゃいかん

処理内容は何ですか?  コピー先は何処ですか?  などの疑問が浮かびます.

処理内容について
単純なコピーではなく、Little Endian→Big Endian変換しなくちゃいけません.ダラッとしたcodeだと384bytesの処理に125usecでは時間が足りないのですが、それはcodeの話題なのでここでは語りません.

なぜLEBE変換が必要なのか?
audio fileがwindowsのHDDの中に在る時、32bit整数はLittleEndianが主流です(WAVE formatはLEが主流だと思う).そのLEがUSBを経てSTM32まで辿り着いてもやはりLEのままです.ちなみにSTM32もLEです.
ところがI2SはMSB firstなのでSPIへaudio dataを渡す前にBigEndianに変更しておかないと砂の嵐になってしまう.
それでLE→BE変換がSTM32に必要なのです.

コピー先は何処ですか?
SPIへdataを送る前にリングバッファにaudio dataを蓄積します.そのリングバッファがコピー先です.
以上から、STM32はLEBE変換とリングバッファコピーを手際よく行う必要があります.
手際よくコピーするならDMAにやらせればよいのですが、ここではLEBE変換が伴うのでDMAが使えません.CPUのマシン語loopで処理しなくちゃいけません.

以上が、EndPoint1近傍での処理内容となります.


【リングバッファ】
リングバッファとは言ってもRAM上に確保されたリニア領域に過ぎません.アドレス操作によってリング状に見せかけているだけです.

リングバッファの容量は、現状のcodeでは、512x60=30720bytes確保してあります.512はdescriptorに記述したEP1の最大packetサイズです.

バッファと呼ぶからには何かからprotectするためのダムであるはずで、それはhostの動作が遅くなってレートが384bytes/Secよりも遅くなったりしたケースの緩衝役です.

挙動は、packet毎に384bytesがリングバッファに蓄積してゆきます.リングバッファが30720bytesですから、たかが80packetでリングバッファは満杯になってしまい、過去データを踏みつぶしてしまいます.どうするんだーっ?

その答えはSPIにさっさと読んでいただくのです.

SPIにどう読んでいただくのか?
SPI DMAでaudioサンプリングレートで読んでもらいます.SPIには専用のDMAが連結されています.

SPIの読みレートは何で決まるのか?
STM32の外部から供給される64Fsのbitclkです.bitclkは当device基板上に置かれたXTALです.DACがmaster clockだからです.

SPIが起動されるのはいつ?
再生先頭の蓄積データがリングバッファの半分に達した時にSPI DMAを起動します.こうするとhostのレート変動への耐性が最も強いはずだから.

384kHzの場合は40packetだけ再生が遅れるがそれでよいのか?
仕方ないです.レイテンシってやつです.40 x 125uSec=5mSecの再生遅延です.

リングバッファでもprotect出来ないほどhostレートが悪化したらどうするの?
そうならないようにfeedbackがあります.レート調整機構です.feedbackは別の投稿で説明します.ここではレートは概ね良好との仮定で先へ進みます.


【SPIの仕様】
STM32にはI2S peripheralも内蔵されているのですが、192kHzまでしか対応していないのです.384kHzは実現不能なのです.残念ですね.そこでいささか変則的ですが、似た信号仕様のSPIを流用します.

I2Sの信号仕様はこうなっていて、clkとdataだけでなくLRCKがあります.LRCKは32bit data区切りを表す信号です.

しかしSPIの信号仕様はclkとdataのみでLRCKが在りません.

なのでSPIが起動した先頭bitを検出して、そこから32bit毎にLRCKをON/OFFさせる回路を別途設ける必要があります.そのためにXC9536でbitカウントしてLRCKを生成しています.

なお、32bit384kHz2chのaudio伝送のためには、SPIのclkは24.576MHzが必要です.

SPIのバグかな
main()でSPIにこんな処理をやっています.STOP中はSPIをresetしています.
  while(HAL_SPI_DeInit(&hspi1)!=HAL_OK);
  __HAL_RCC_SPI1_FORCE_RESET();
  __HAL_RCC_SPI1_RELEASE_RESET();
  MX_SPI1_Init();
なぜresetしているのかというと、再生→停止→再生のように2曲目を再生した時にdataが化けて砂の嵐になってしまうからです.原因はSPI peripheralの中に1曲目の末尾が数bit残存していて、serial dataのword区切りが破綻してしまうんです.hardware的にSPIをresetするしかありませんでした.


以上で、USB EP~I2Sまでのデータの流れを説明できました.

かしこ

0 件のコメント:

コメントを投稿