Refactor: beat tempo now works off of a timer instead of manual delay

main
rkcf 2023-02-05 13:57:45 -06:00
parent d1ac219547
commit f7559f71d4
1 changed files with 90 additions and 35 deletions

View File

@ -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);
}