pcnt_config_t pcnt_config = { .pulse_gpio_num = PIN_MONITOR, // Input BCK; MCLK would exceed PCNT capability .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, // Negative edge disabled to avoid count ambiguity .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){ // Simply raise a “do it” flag every 1 ms if (g_app_started) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; vTaskNotifyGiveFromISR(g_monitor_task_handle, &xHigherPriorityTaskWoken); if (xHigherPriorityTaskWoken) { portYIELD_FROM_ISR(); // Run the task immediately after ISR } //g_monitor_tick = true; } return true;}
void monitor_task_gpt(void *param){ ESP_LOGI(TAG, "monitor_task_gpt enter"); // Wait until the system is fully started while (!g_app_started) { vTaskDelay(pdMS_TO_TICKS(1)); } while (1) { // Wait for notification from GPTimer ISR (infinite wait) // → One notification = 1 ms of processing ulTaskNotifyTake(pdTRUE, portMAX_DELAY); // Do nothing until all IO is active 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 reset workaround } uac_send_feedback(fb_to_send, 0); } }}