typedef struct { // audio stream 設定 audio_quality_t uac_quality; // USB 側の状態管理 bool usb_mounted; // USBマウント状態 bool uac_alt1_active; // Out EP開閉(SPEAKERストリーム) uint8_t uac_alt1_muted; // ミュート有無 int16_t uac_alt1_volume; // ボリューム // Feedbackプリロール、立ち上がりのドリフトをFB軽減 int16_t uac_fb_inverval_count; /* 送信間隔を(1 << (UAC_EXPLICIT_FB_INTERVAL-1)ms間隔に合わせる */ bool uac_fb_started; // FB発射開始シグナル bool uac_fb_start_pending; // FB発射準備シグナル bool uac_fb_locked; // FBロック状態 int16_t uac_fb_lockcount; // FB 未ロックカウント int32_t uac_long_err_mHz; // 長期誤差蓄積(mHz 単位) // I2Sプリロール、ALT1立ち上がり直後のドリフト吸収 bool i2s_starting; // I2S発射準備シグナル uint32_t i2s_start_ms; // I2S発射カウントダウンタイマー // I2S ASRCコントロ-ラ(SRC & Killer) bool i2s_src_enabled; // ASRC 有効/無効(デバッグ用) bool i2s_src_inited; // SRC Preroll済みフラグ bool i2s_src_locked; // SRC ロック済み int16_t i2s_src_lockcount; // SRC 未ロックカウント int32_t i2s_pcnt_delta_hz; // SRCに渡す側のデルタHz //float i2s_src_clock_ratio; // 制御ループ >> CLOCK側に移動 float i2s_src_phase_ratio; // resampler 用(USB/I2S) float i2s_src_smooth_ratio; // SRC補正レート float i2s_src_phase; // ASRC の位相(補間器の内部状態) int i2s_src_in_idx; // 補間器の入力サンプル位置 // カウンタープリロール bool counter_warmup_rollout; // カウンター初動完了 // 監視 健康状態のモニタリング int16_t ddc_ring_looses; // DDC ringの渇水、量子化ノイズ、ジッタノイズ源 float ddc_ring_wl; // DDC ring water level int16_t ddc_rx_size; // UAC受信バッファサイズ int16_t ddc_tx_size; // I2S送信バッファサイズ} ddc_control_t;
typedef struct { int32_t sample_rate; int8_t channels; int8_t resolution_bits; int8_t sample_bytes; int16_t frame_size; int16_t mclk_multi; float rms_max;} audio_quality_t;
typedef struct { int src; int mclk; int16_t mclk_multiple; int16_t lrck; int bclk; int bclk_divn; // 整数部= mclk / bclk int bclk_divi; // 端数部= mclk % bclk // 以下はカウンタ int16_t pcnt_diff; int16_t pcnt_cur; int16_t pcnt_last; int32_t pcnt_fs; int16_t pcnt_warmup; int32_t pcnt_fs_history[3]; // 3点中央値フィルタ int16_t pcnt_fs_factor; // 以下はASRC用 uint32_t last_fb; // Q14 int32_t acc_q14; // fractional 累積用 Q14 int32_t delta_fb_q; float source_clock_ratio;} clock_counter_t;
typedef struct { bool uac_fb_started; // UAC FB開始後 bool uac_fb_locked; // UAC FBロック中 bool i2s_inited; // I2S初期化 bool i2s_locked; // I2Sロック中 bool pcnt_countdown; // 立上げカウントダウン bool pcnt_rollupped; // カウンター実運転中 int16_t delta_fb_q; // UAC Feedback用(10.14) int32_t delta_hz; // ASRC入力用 int16_t pcnt_diff; // PCNT生値 int32_t pcnt_fs; // PCNT Hz int32_t fs_raw; // PCNT生→Hz生 int32_t long_err_mHz; // FB長期誤差 float ratio_clock; // 制御ループ用(I2S/USB) float ratio_phase; // resampler 用(USB/I2S) float ratio_smooth; // ASRC内部補正 float i2s_src_phase; // ASRC の位相(補間器の内部状態) int i2s_src_in_idx; // 補間器の入力サンプル位置 uint64_t tick_us; // ★ 追加:ログ時刻(マイクロ秒) call_position_e call_position; // 呼び出し元} log_entry_t;
int32_t ddc_log_print_detail(ddc_control_t *ddc, int32_t start, int32_t count){ if (start >= MAX_DDC_LOG) return 0; // Header if (start == 0) { ESP_LOGI(TAG, "DDC cfg rate=%u bits=%d ch=%d mclk_multi=%d", ddc->uac_quality.sample_rate, ddc->uac_quality.resolution_bits, ddc->uac_quality.channels, ddc->uac_quality.mclk_multi ); } int tail = start count; if (tail > MAX_DDC_LOG) tail = MAX_DDC_LOG; for (int i = start; i < tail; i ) { log_entry_t *L = &g_ddc_log[i]; // ---- フェーズ判定 ---- const char *phase = (!L->i2s_locked) ? "PHASE0(I2S_INIT)" : (!L->pcnt_rollupped) ? "PHASE1(PCNT_WARMUP)" : (!L->uac_fb_started) ? "PHASE2(FB_WAIT_START)" : (!L->uac_fb_locked) ? "PHASE3(FB_WAIT_LOCK)" : "PHASE4(LOCKED)"; // ---- STUCK 判定 ---- bool fs_stuck = (L->fs_raw == ddc->uac_quality.sample_rate); bool pcntfs_stuck = (L->pcnt_fs == ddc->uac_quality.sample_rate); bool dhz_stuck = (L->delta_hz == 0); bool dfb_stuck = (L->delta_fb_q == 0); ESP_LOGI(TAG, "idx=%d tick=%u part=%d %s\n" " I2S: init=%d lock=%d\n" " PCNT: warm=%d up=%d diff=%d fs_raw=%ld%s fs=%d%s dhz=%ld%s\n" " FB: start=%d lock=%d dfb=%d%s long=%ld ratio clock=%.6f\n" " SRC: ratio phase=%.6f smooth=%.6f", i, (uint32_t)(L->tick_us & 0xFFFFFFFF), L->call_position, phase, // I2S L->i2s_inited, L->i2s_locked, // PCNT L->pcnt_countdown, L->pcnt_rollupped, L->pcnt_diff, L->fs_raw, fs_stuck ? " (STUCK)" : "", L->pcnt_fs, pcntfs_stuck ? " (STUCK)" : "", L->delta_hz, dhz_stuck ? " (NO-MOVE)" : "", // FB L->uac_fb_started, L->uac_fb_locked, L->delta_fb_q, dfb_stuck ? " (NO-MOVE)" : "", L->long_err_mHz, L->ratio_clock, // SRC L->ratio_clock, L->ratio_smooth ); } return tail - start;}