2020年7月26日日曜日

STM32でDCC/DDCを作る方向で (31) まだ続くfeedbackの研究

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

ーーーー
STM32でDDCを作ろう! (DCCじゃなくてDDCが正解らしく...)   INDEXページへ

feedbackがまだ動かない.

HOSTはちゃんと動いているのだろうか?
feedback値を手動ツマミで可変できるようにしてHOSTが感知しているのかどうかを確かめたのがこの動画です.確かにHOSTはfeedbackに反応しています.
2つの波形が見えています.bufferにwriteするサイクル(上)とbufferをreadするサイクル(下)を示しています.
動画の始まりでは両者が流れているので、writeがbufferを破壊しまくっている状況です.NGです.
動画の後半で流れが止まります.これが求めている挙動です.feedback値を手動のrotary encoderで可変してこの結果を得ています.
条件はwindows10、usbaudio2.sys、48kHz、32bit ってところ.

HOSTは期待通りに反応しているので、やれば出来そうな手掛かりは掴めているのですが、どうにもfixできない問題があるんです.
・動画では、feedback値に2%ぐらいの偏差を与えて波形の流れが止まった
・ところが、feedback値の定義通りに測定すると、HOSTレートとDAC masterレートの偏差は数10ppmしかない
この2%と10ppmの違いにズーッと悩んでいます.そして解決していません.妥当なのは後者なんです.HOSTレートとDACレートの誤差は水晶振動子の周波数偏差に帰着するので数10ppmの誤差なのがフツーですから.なので2%というのが謎なのです.

というわけでfeedbackの研究はまだ続きます.

-----
前回の連載で、feedback値測定のSOF割り込みがブレブレだと書きました.  →こちら
hardware的にSOF割り込みが発生した時刻と、software的にSOF割り込みroutineに入れた時刻は別物です.後者は何個もの割り込みの順番待ちの後ですから遅れてブレブレになるのはさもありなん.

SOFブレブレの反省から、feedback値を測定するためにsoftware処理が介在しては上手くいかないので、タイマでhardwareでfeedback値測定させたく、タイマにやらせたいのはこうゆうことです.
  1)24.576MHzを外部CLK端子へ入力する
  2)SOFパルスをTRIGGER端子へ入力する
  3)TRIGGERエッジでcounter値をレジスタに退避
  4)TRIGGER割り込みで退避値をゆっくりと読み処理する
123はhardware処理、4はsoft処理ってことになりんす.これなら無問題.

それは判っちゃいるけどどうやったらSTM32のタイマで実装できるのかが判らない.タイマへのclockとtriggerのダブル外部入力ってどうやったらできるんだよ?というのがdatasheetをチャラっと読んだだけだと判らないのだ.

仕方ないのでdatasheetをまじめに読んでみた.できました.

【外部clock1と2は何か?】
External clock source mode 1: TIMx_CH1またはTIMx_CH2へclockを入力する
External clock source mode 2: ETRへclockを入力する
mode2を使うべきなのかな?

【STM32CubeMXの設定】
mode1/mode2という文言はCubeMXには出てこないみたいなので忘れます.わたしはこんな設定にしました.

上から順に説明すると、
Trigger Modeとは、SOFパルスedgeでCNTをCCRにsaveするために必要な設定.

TI1_EDとは、TIM3_CH1へSOFパルスを入力し、それをedge detectしたものをsaveに使う.

ETR2とは、外部CLK入力端子の指定.
(TIM3_CH1とETR2を逆には出来ないらしい)

Input Capture triggerd by TRCとは、TIM3_CH1をCapture回路に導くために必要だと思う.

スクショには写ってない下の方にあるParameter Settings →Counter Period(Autoreload Regsiter)には65535を入れておく.

あと割り込みはONにしときます.

【main()】
初期化はこれを書いときます.
  HAL_TIM_Base_Start(&htim3);
  HAL_TIM_IC_Start(&htim3, TIM_CHANNEL_1);

【TIM3 IRQ】
SOFパルスedgeでTIM3は割り込みを発生させます.(もはやSOF割り込みは使わない)
TIM3のCCR1レジスタにsave値が入っているのでおごそかに読みます.TIM3は16bitです.
void TIM3_IRQHandler(void) {
uint16_t x;
x = htim3->Instance->CCR1;
}

これにて、feedback値を正しく採取できるようになりました.

しかし、2%と10ppmの謎は残っています.

かしこ

0 件のコメント:

コメントを投稿