Refactor: beat tempo now works off of a timer instead of manual delay
parent
d1ac219547
commit
f7559f71d4
|
|
@ -77,6 +77,7 @@ static QueueHandle_t control_event_queue = NULL;
|
||||||
/* Timers */
|
/* Timers */
|
||||||
static gptimer_handle_t tap_tempo_timer = NULL;
|
static gptimer_handle_t tap_tempo_timer = NULL;
|
||||||
static gptimer_handle_t gate_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 const uint16_t DEBOUNCE_TIMEOUT = 10; /* polling period length when debouncing in ms */
|
||||||
static uint64_t debounce_time = 0; /* system time of last intterupt */
|
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;
|
static uint16_t current_bpm = DEFAULT_BPM;
|
||||||
lv_obj_t * bpm_label = NULL;
|
lv_obj_t * bpm_label = NULL;
|
||||||
|
|
||||||
|
TaskHandle_t tempo_handle;
|
||||||
|
|
||||||
#define SEQ_MAX_LEN 8
|
#define SEQ_MAX_LEN 8
|
||||||
static uint8_t sequence[SEQ_MAX_LEN] = {0};
|
static uint8_t sequence[SEQ_MAX_LEN] = {0};
|
||||||
static uint8_t seq_len = SEQ_MAX_LEN;
|
static uint8_t seq_len = SEQ_MAX_LEN;
|
||||||
|
uint8_t current_step = 0;
|
||||||
lv_obj_t * sequence_label = NULL;
|
lv_obj_t * sequence_label = NULL;
|
||||||
lv_obj_t * sequence_tracker = NULL;
|
lv_obj_t * sequence_tracker = NULL;
|
||||||
|
|
||||||
|
|
@ -105,8 +109,26 @@ uint32_t ms_to_bpm(uint32_t ms) {
|
||||||
return 60000 / 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) {
|
static void update_bpm(void) {
|
||||||
lv_label_set_text_fmt(bpm_label, "BPM: %d", current_bpm);
|
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 */
|
/* 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) {
|
static void IRAM_ATTR gpio_isr_handler(void* arg) {
|
||||||
uint32_t gpio_num = (uint32_t)arg;
|
uint32_t gpio_num = (uint32_t)arg;
|
||||||
portENTER_CRITICAL_ISR(&mux);
|
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) {
|
void app_main(void) {
|
||||||
/* Initialize Peripherals */
|
/* Initialize Peripherals */
|
||||||
/* Initialize GPIO */
|
/* Initialize GPIO */
|
||||||
|
|
@ -498,28 +572,9 @@ void app_main(void) {
|
||||||
/* Initialize sequence */
|
/* Initialize sequence */
|
||||||
randomize_seq(sequence);
|
randomize_seq(sequence);
|
||||||
|
|
||||||
/* Main Loop */
|
/* Initialize tempo timer */
|
||||||
while (1) {
|
tempo_init();
|
||||||
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] = '_';
|
|
||||||
|
|
||||||
/* set the new sequence label */
|
/* start main beat tempo loop task */
|
||||||
lv_label_set_text(sequence_tracker, tracker_str);
|
xTaskCreate(tempo_task, "tempo", 2048, NULL, 0, &tempo_handle);
|
||||||
|
|
||||||
/* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Reference in New Issue