Module 2: Real Time Sensor(リアルタイム観測)Module 3: Timeline Adjuster(時間軸補正)Module 4: Feedback Uplinker(フィードバック上りリンク)
pcnt_config_t pcnt_config = { .pulse_gpio_num = PIN_MONITOR, // BCKを入力、MCLKだとちょいともたない .ctrl_gpio_num = PCNT_PIN_NOT_USED, .channel = PCNT_CHANNEL_0, .unit = SYNCLK_PCNT_UNIT, .pos_mode = PCNT_COUNT_INC, .neg_mode = /*PCNT_COUNT_INC*/PCNT_COUNT_DIS, // ネガティブ側もカウントする(カウント開始がPかNかでカウント数に誤差がでるため) .lctrl_mode = PCNT_MODE_KEEP, .hctrl_mode = PCNT_MODE_KEEP, .counter_h_lim = INT16_MAX, .counter_l_lim = 0, };
bool IRAM_ATTR monitor_task_gpt_isr(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void *user_ctx){ // 1ms ごとに「やれ」のフラグを立てるだけ if (g_app_started) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; vTaskNotifyGiveFromISR(g_monitor_task_handle, &xHigherPriorityTaskWoken); if (xHigherPriorityTaskWoken) { portYIELD_FROM_ISR(); // ISR終了直後にタスク実行 } //g_monitor_tick = true; } return true;}
void monitor_task_gpt(void *param){ ESP_LOGI(TAG, "monitor_task_gpt enter"); // 起動完了まで適当に待つ while (!g_app_started) { vTaskDelay(pdMS_TO_TICKS(1)); } while (1) { // GPTimer ISR からの通知を待つ(無限待ち) // → 1 回の通知 = 1ms 分の処理 ulTaskNotifyTake(pdTRUE, portMAX_DELAY); // 全IOが稼働し始めるまでは何もしない if (g_app_started) { // RTS実施 g_ddc.counter_warmup_rollout = get_fscount(&g_cnt_ideal); // TLA(デルタ算出) fscount_to_fb_q(&g_ddc, &g_cnt_ideal); // FB Lock if (g_ddc.uac_fb_start_pending) { g_ddc.uac_fb_started = true; g_ddc.uac_fb_start_pending = false; } // FUL uint32_t fb_to_send = g_cnt_ideal.last_fb; if (!g_ddc.uac_fb_locked) { fb_to_send = ((g_ddc.uac_quality.sample_rate * (1u << 14) 500) / 1000); // ← VLCのリセット甘さ対応、嘘通知 } uac_send_feedback(fb_to_send, 0); } }}