diff --git a/src/main/esp32_eurorack_generic.c b/src/main/esp32_eurorack_generic.c index 7b66f33..80bbb5a 100644 --- a/src/main/esp32_eurorack_generic.c +++ b/src/main/esp32_eurorack_generic.c @@ -1,6 +1,156 @@ #include +#include + +#include "esp_attr.h" +#include "esp_err.h" +#include "esp_log.h" +#include "esp_adc/adc_cali.h" +#include "esp_adc/adc_cali_scheme.h" +#include "esp_adc/adc_continuous.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/portmacro.h" +#include "hal/adc_types.h" +#include "soc/soc_caps.h" + +/* ADC input pins */ +#define ADC_INPUT_1_PIN 4 +#define ADC_INPUT_2_PIN 6 +#define ADC_INPUT_3_PIN 9 /* TODO Reroute from pin 46 to 9 on schematic, cant do ADC */ +#define ADC_INPUT_4_PIN 10 + +#define ADC_READ_LEN 16 + +/* ADC channels */ +static adc_channel_t channel[4] = {ADC_CHANNEL_3, ADC_CHANNEL_5, ADC_CHANNEL_8, ADC_CHANNEL_9}; + +/* ADC handles */ +static adc_continuous_handle_t adc_handle; +static adc_cali_handle_t adc_cali_handle; +static TaskHandle_t adc_task_handle; + +static const char *TAG = "EERG"; + +/* ADC continuous read task */ +static void adc_read_task(void *pvParameter) +{ + ESP_LOGI(TAG, "Starting adc read task"); + esp_err_t adc_ret; + uint32_t ret_num = 0; + uint8_t result[ADC_READ_LEN] = {0}; + /* Fill result with 0xcc */ + memset(result, 0xcc, ADC_READ_LEN); + + while (1) { + /* Wait here until notified that the conversion is done */ + ulTaskNotifyTake(pdTRUE, portMAX_DELAY); + + /* Perform a read */ + adc_ret = adc_continuous_read(adc_handle, result, ADC_READ_LEN, &ret_num, 0); + if (adc_ret == ESP_OK) { + ESP_LOGI("adc", "Got a reading"); + for (int i = 0; i < ret_num; i+= SOC_ADC_DIGI_RESULT_BYTES) { + /* Grab the data and channel number */ + adc_digi_output_data_t *p_data = (void*)&result[i]; + uint32_t chan = ((p_data)->type2.channel); + uint32_t data = ((p_data)->type2.data); + /* Check channel number to see if data is bogus */ + if (chan < SOC_ADC_CHANNEL_NUM(ADC_UNIT_1)) { + ESP_LOGI("adc", "ADC_1_%"PRIu32" value: %"PRIx32, chan, data); + } else { + ESP_LOGW("adc", "Invalid data from ADC_1_%"PRIu32, chan); + } + } + } + vTaskDelay(1000 / portTICK_PERIOD_MS); + } +} + +/* ADC conversion finished callback */ +static bool IRAM_ATTR adc_conv_cb(adc_continuous_handle_t handle, const adc_continuous_evt_data_t *edata, void *user_data) +{ + BaseType_t mustYield = pdFALSE; + /* Send notification to handler task */ + vTaskNotifyGiveFromISR(adc_task_handle, &mustYield); + return (mustYield == pdTRUE); +} + +/* Deinitializes ADC handles */ +static void adc_cleanup(void) +{ + ESP_LOGI(TAG, "Cleaning up ADC"); + ESP_ERROR_CHECK(adc_continuous_stop(adc_handle)); + ESP_ERROR_CHECK(adc_continuous_deinit(adc_handle)); + ESP_ERROR_CHECK(adc_cali_delete_scheme_curve_fitting(adc_cali_handle)); +} + +/* Initializes calibration driver of internal 12bit ADC */ +static void adc_cali_init(void) +{ + ESP_LOGI(TAG, "Initializing ADC calibration driver"); + /* Create and apply calibration driver configuration */ + adc_cali_curve_fitting_config_t cali_config = { + .unit_id = ADC_UNIT_1, + .atten = ADC_ATTEN_DB_0, + .bitwidth = ADC_BITWIDTH_DEFAULT + }; + ESP_ERROR_CHECK(adc_cali_create_scheme_curve_fitting(&cali_config, &adc_cali_handle)); +} + +/* Initializes internal 12bit ADC */ +static void adc_cont_init(void) +{ + ESP_LOGI(TAG, "Initializing ADC continuous mode driver"); + + /* Create continuous mode driver handle */ + adc_continuous_handle_cfg_t adc_handle_config = { + .max_store_buf_size = ADC_READ_LEN, + .conv_frame_size = ADC_READ_LEN + }; + ESP_ERROR_CHECK(adc_continuous_new_handle(&adc_handle_config, &adc_handle)); + + /* Configure continuous driver */ + adc_continuous_config_t adc_config = { + .sample_freq_hz = 20 * 1000, /* 20kHz TODO calculate proper sampling rate */ + .conv_mode = ADC_CONV_SINGLE_UNIT_1, + .format = ADC_DIGI_OUTPUT_FORMAT_TYPE2, + .pattern_num = 4 + }; + + /* Loop through channels for their configs */ + adc_digi_pattern_config_t adc_pattern[4] = {0}; + for (int i = 0; i < 4; i++){ + adc_pattern[i].atten = ADC_ATTEN_DB_0; + adc_pattern[i].channel = channel[i]; + adc_pattern[i].unit = ADC_UNIT_1; + adc_pattern[i].bit_width = ADC_BITWIDTH_12; + } + adc_config.adc_pattern = adc_pattern; + ESP_ERROR_CHECK(adc_continuous_config(adc_handle, & adc_config)); + + /* Configure callbacks */ + adc_continuous_evt_cbs_t cbs = { + .on_conv_done = adc_conv_cb + }; + ESP_ERROR_CHECK(adc_continuous_register_event_callbacks(adc_handle, &cbs, NULL)); +} void app_main(void) { + /* Initialize internal ADC */ + /* Initialize calibration driver */ + adc_cali_init(); + /* Initialize continuous driver */ + adc_cont_init(); + /* Start the continuous driver */ + ESP_ERROR_CHECK(adc_continuous_start(adc_handle)); + xTaskCreate(adc_read_task, "adc read", 4096, NULL, 0, &adc_task_handle); + + while (1) { + + } + + /* Cleanup ADC */ + adc_cleanup(); }