From f7559f71d4905b339a439944c5653e0b4b977271 Mon Sep 17 00:00:00 2001 From: rkcf Date: Sun, 5 Feb 2023 13:57:45 -0600 Subject: [PATCH] Refactor: beat tempo now works off of a timer instead of manual delay --- main/esp32-sequencer.c | 125 +++++++++++++++++++++++++++++------------ 1 file changed, 90 insertions(+), 35 deletions(-) diff --git a/main/esp32-sequencer.c b/main/esp32-sequencer.c index c6a445f..93513bd 100644 --- a/main/esp32-sequencer.c +++ b/main/esp32-sequencer.c @@ -77,6 +77,7 @@ static QueueHandle_t control_event_queue = NULL; /* Timers */ static gptimer_handle_t tap_tempo_timer = NULL; static gptimer_handle_t gate_timer = NULL; +static gptimer_handle_t tempo_timer = NULL; static const uint16_t DEBOUNCE_TIMEOUT = 10; /* polling period length when debouncing in ms */ static uint64_t debounce_time = 0; /* system time of last intterupt */ @@ -88,9 +89,12 @@ static const uint32_t DEFAULT_BPM = 120; static uint16_t current_bpm = DEFAULT_BPM; lv_obj_t * bpm_label = NULL; +TaskHandle_t tempo_handle; + #define SEQ_MAX_LEN 8 static uint8_t sequence[SEQ_MAX_LEN] = {0}; static uint8_t seq_len = SEQ_MAX_LEN; +uint8_t current_step = 0; lv_obj_t * sequence_label = NULL; lv_obj_t * sequence_tracker = NULL; @@ -105,8 +109,26 @@ uint32_t ms_to_bpm(uint32_t ms) { return 60000 / ms; } +static void pulse_cv(bool triggered) { + ESP_ERROR_CHECK(gptimer_start(gate_timer)); + ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 4095)); + ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0)); + gpio_set_level(GPIO_CLK_OUT, 1); + if (triggered) { + gpio_set_level(GPIO_GATE_OUT, 1); + ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1, 4095)); + ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1)); + } +} + static void update_bpm(void) { lv_label_set_text_fmt(bpm_label, "BPM: %d", current_bpm); + gptimer_alarm_config_t tempo_alarm_config = { + .reload_count = 0, + .flags.auto_reload_on_alarm = true, + .alarm_count = bpm_to_ms(current_bpm) * 1000 + }; + ESP_ERROR_CHECK(gptimer_set_alarm_action(tempo_timer, &tempo_alarm_config)); } /* updates the sequence for the GUI display */ @@ -159,6 +181,70 @@ static void tap_tempo_handler(){ } } +/* Essentially the Main Loop. Runs the tempo timer to trigger beat related events */ +static void tempo_task(void *pvParameter) { + /* Start the timer */ + ESP_ERROR_CHECK(gptimer_start(tempo_timer)); + uint32_t ulInterruptStatus; + + /* Loop that waits for notification of beat end */ + while (1) { + xTaskNotifyWait(0, ULONG_MAX, &ulInterruptStatus , portMAX_DELAY); + + /* Pulse outputs if step is active */ + if (sequence[current_step] == 1) { + pulse_cv(true); + } else { + pulse_cv(false); + } + + /* Construct a string for the sequence tracker display */ + char tracker_str[] = " "; + tracker_str[current_step] = '_'; + + /* set the new sequence label */ + lv_label_set_text(sequence_tracker, tracker_str); + + /* Advance the Step */ + if (current_step == seq_len - 1) { + current_step = 0; + } else { + current_step++; + } + } +} + +/* Handler that runs when the tempo timer goes off */ +static void tempo_timer_cb(void * arg) { + BaseType_t xHigherPriorityTaskWoken; + xTaskNotifyFromISR(tempo_handle , 0, eSetBits, &xHigherPriorityTaskWoken); +} + +/* Initialize tempo timer */ +static void tempo_init(void) { + /* Setup timer */ + gptimer_config_t tempo_timer_config = { + .clk_src = GPTIMER_CLK_SRC_DEFAULT, + .direction = GPTIMER_COUNT_UP, + .resolution_hz = 1 * 1000 * 1000 /* 1MHz; 1 tick = 1µs */ + }; + ESP_ERROR_CHECK(gptimer_new_timer(&tempo_timer_config, &tempo_timer)); + + /* Configure alarm to go off based on BPM */ + gptimer_alarm_config_t tempo_alarm_config = { + .reload_count = 0, + .flags.auto_reload_on_alarm = true, + .alarm_count = bpm_to_ms(current_bpm) * 1000}; + ESP_ERROR_CHECK(gptimer_set_alarm_action(tempo_timer, &tempo_alarm_config)); + + /* Setup tempo callback */ + gptimer_event_callbacks_t cb_config = { + .on_alarm = tempo_timer_cb + }; + ESP_ERROR_CHECK(gptimer_register_event_callbacks(tempo_timer, &cb_config, NULL)); + ESP_ERROR_CHECK(gptimer_enable(tempo_timer)); +} + static void IRAM_ATTR gpio_isr_handler(void* arg) { uint32_t gpio_num = (uint32_t)arg; portENTER_CRITICAL_ISR(&mux); @@ -466,18 +552,6 @@ static void gui_task(void *pvParameter) { } } -static void pulse_cv(bool triggered) { - ESP_ERROR_CHECK(gptimer_start(gate_timer)); - ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0, 4095)); - ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_0)); - gpio_set_level(GPIO_CLK_OUT, 1); - if (triggered) { - gpio_set_level(GPIO_GATE_OUT, 1); - ESP_ERROR_CHECK(ledc_set_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1, 4095)); - ESP_ERROR_CHECK(ledc_update_duty(LEDC_LOW_SPEED_MODE, LEDC_CHANNEL_1)); - } -} - void app_main(void) { /* Initialize Peripherals */ /* Initialize GPIO */ @@ -498,28 +572,9 @@ void app_main(void) { /* Initialize sequence */ randomize_seq(sequence); - /* Main Loop */ - while (1) { - char tracker_str[seq_len]; - for (uint8_t step = 0; step < seq_len; step++) { - /* advance step tracker */ - if (step == 0) { - tracker_str[seq_len - 1] = ' '; - } else { - tracker_str[step - 1] = ' '; - } - tracker_str[step] = '_'; + /* Initialize tempo timer */ + tempo_init(); - /* set the new sequence label */ - lv_label_set_text(sequence_tracker, tracker_str); - - /* if step has been set for sequence */ - if (sequence[step] == 1) { - pulse_cv(true); - } else { - pulse_cv(false); - } - vTaskDelay(bpm_to_ms(current_bpm)/ portTICK_PERIOD_MS); - } - } + /* start main beat tempo loop task */ + xTaskCreate(tempo_task, "tempo", 2048, NULL, 0, &tempo_handle); }