diff --git a/grid_common/grid_ain.h b/grid_common/grid_ain.h index 833fac921..4e781f9e4 100644 --- a/grid_common/grid_ain.h +++ b/grid_common/grid_ain.h @@ -4,6 +4,8 @@ #include #include +#define GRID_MUX_UNUSED ((uint8_t)-1) + struct ain_chan_t { uint16_t capa; diff --git a/grid_common/grid_module.c b/grid_common/grid_module.c index 62b262c9c..59863c3f9 100644 --- a/grid_common/grid_module.c +++ b/grid_common/grid_module.c @@ -248,3 +248,36 @@ void grid_module_en16_ui_init(struct grid_ain_model* ain, struct grid_led_model* ui->lua_ui_init_callback = grid_lua_ui_init; } + +void grid_module_octv_ui_init(struct grid_ain_model* ain, struct grid_led_model* led, struct grid_ui_model* ui) { + + // 13 ADC channels for pressure-sensitive buttons (elements 8-20), depth of 4 for smoothing + grid_ain_init(ain, 13, 4); + + // 21 LEDs: 8 for encoders + 13 for buttons + grid_led_init(led, 21); + grid_led_lookup_alloc_identity(led, 0, 21); + + // 22 elements: 8 encoders + 13 buttons + 1 system + grid_ui_model_init(ui, 21 + 1); + + for (uint8_t j = 0; j < 21 + 1; j++) { + + struct grid_ui_element* ele = grid_ui_element_model_init(ui, j); + + if (j < 8) { + // Elements 0-7: Encoders (with push buttons integrated) + grid_ui_element_encoder_init(ele); + + } else if (j < 21) { + // Elements 8-20: Pressure-sensitive buttons + grid_ui_element_button_init(ele); + + } else { + // Element 21: System element + grid_ui_element_system_init(ele); + } + } + + ui->lua_ui_init_callback = grid_lua_ui_init; +} diff --git a/grid_common/grid_module.h b/grid_common/grid_module.h index c41a8f2b6..46b0b2ed4 100644 --- a/grid_common/grid_module.h +++ b/grid_common/grid_module.h @@ -12,6 +12,7 @@ void grid_module_bu16_ui_init(struct grid_ain_model* ain, struct grid_led_model* void grid_module_pbf4_ui_init(struct grid_ain_model* ain, struct grid_led_model* led, struct grid_ui_model* ui); void grid_module_en16_ui_init(struct grid_ain_model* ain, struct grid_led_model* led, struct grid_ui_model* ui); void grid_module_ef44_ui_init(struct grid_ain_model* ain, struct grid_led_model* led, struct grid_ui_model* ui); +void grid_module_octv_ui_init(struct grid_ain_model* ain, struct grid_led_model* led, struct grid_ui_model* ui); void grid_module_tek2_ui_init(struct grid_ain_model* ain, struct grid_led_model* led, struct grid_ui_model* ui); #endif /* GRID_MODULE_H */ diff --git a/grid_common/grid_protocol.h b/grid_common/grid_protocol.h index 59c621dfa..4701e8959 100644 --- a/grid_common/grid_protocol.h +++ b/grid_common/grid_protocol.h @@ -81,6 +81,9 @@ #define GRID_MODULE_EF44_ND_RevD 41 #define GRID_MODULE_EF44_ND_RevH 43 +#define GRID_MODULE_OCTV_RevH 211 +#define GRID_MODULE_OCTV_ND_RevH 219 + #define GRID_MODULE_TEK1_RevA 225 #define GRID_MODULE_TEK2_RevA 17 diff --git a/grid_common/grid_sys.c b/grid_common/grid_sys.c index 284d1b1e0..4d89c96da 100644 --- a/grid_common/grid_sys.c +++ b/grid_common/grid_sys.c @@ -224,6 +224,17 @@ int grid_hwcfg_module_is_en16(struct grid_sys_model* sys) { } } +int grid_hwcfg_module_is_octv(struct grid_sys_model* sys) { + + switch (grid_sys_get_hwcfg(sys)) { + case GRID_MODULE_OCTV_RevH: + case GRID_MODULE_OCTV_ND_RevH: + return 1; + default: + return 0; + } +} + int grid_hwcfg_module_is_pbf4(struct grid_sys_model* sys) { switch (grid_sys_get_hwcfg(sys)) { @@ -343,6 +354,8 @@ int grid_hwcfg_module_is_rev_h(struct grid_sys_model* sys) { case GRID_MODULE_EN16_ND_RevH: case GRID_MODULE_EF44_RevH: case GRID_MODULE_EF44_ND_RevH: + case GRID_MODULE_OCTV_RevH: + case GRID_MODULE_OCTV_ND_RevH: case GRID_MODULE_TEK2_RevH: case GRID_MODULE_VSN1L_RevH: case GRID_MODULE_VSN1R_RevH: @@ -362,6 +375,7 @@ int grid_hwcfg_module_encoder_is_detent(struct grid_sys_model* sys) { case GRID_MODULE_EN16_RevA: case GRID_MODULE_EN16_RevD: case GRID_MODULE_EN16_RevH: + case GRID_MODULE_OCTV_RevH: return 1; default: return 0; diff --git a/grid_common/grid_sys.h b/grid_common/grid_sys.h index 92225ea94..82be8ea86 100644 --- a/grid_common/grid_sys.h +++ b/grid_common/grid_sys.h @@ -89,6 +89,7 @@ uint32_t grid_sys_get_id(struct grid_sys_model* sys, uint32_t* return_array); int grid_hwcfg_module_is_bu16(struct grid_sys_model* sys); int grid_hwcfg_module_is_ef44(struct grid_sys_model* sys); int grid_hwcfg_module_is_en16(struct grid_sys_model* sys); +int grid_hwcfg_module_is_octv(struct grid_sys_model* sys); int grid_hwcfg_module_is_pbf4(struct grid_sys_model* sys); int grid_hwcfg_module_is_po16(struct grid_sys_model* sys); int grid_hwcfg_module_is_tek2(struct grid_sys_model* sys); diff --git a/grid_esp/bootloader/apps/blinky.uf2 b/grid_esp/bootloader/apps/blinky.uf2 new file mode 100644 index 000000000..92c34a12d Binary files /dev/null and b/grid_esp/bootloader/apps/blinky.uf2 differ diff --git a/grid_esp/bootloader/apps/update-tinyuf2.uf2 b/grid_esp/bootloader/apps/update-tinyuf2.uf2 new file mode 100644 index 000000000..e4cfac353 Binary files /dev/null and b/grid_esp/bootloader/apps/update-tinyuf2.uf2 differ diff --git a/grid_esp/bootloader/bootloader.bin b/grid_esp/bootloader/bootloader.bin index b726580ec..4b9027364 100644 Binary files a/grid_esp/bootloader/bootloader.bin and b/grid_esp/bootloader/bootloader.bin differ diff --git a/grid_esp/bootloader/combined.bin b/grid_esp/bootloader/combined.bin index 75f08d70f..394fd78dd 100644 Binary files a/grid_esp/bootloader/combined.bin and b/grid_esp/bootloader/combined.bin differ diff --git a/grid_esp/bootloader/flash_args b/grid_esp/bootloader/flash_args new file mode 100644 index 000000000..ef562d35f --- /dev/null +++ b/grid_esp/bootloader/flash_args @@ -0,0 +1,5 @@ +--flash_mode dio --flash_freq 80m --flash_size 8MB +0x0 bootloader/bootloader.bin +0x410000 tinyuf2.bin +0x8000 partition_table/partition-table.bin +0xe000 ota_data_initial.bin diff --git a/grid_esp/bootloader/tinyuf2.bin b/grid_esp/bootloader/tinyuf2.bin index 45ede8e96..7f40bd7ee 100644 Binary files a/grid_esp/bootloader/tinyuf2.bin and b/grid_esp/bootloader/tinyuf2.bin differ diff --git a/grid_esp/bootloader/update-tinyuf2.uf2 b/grid_esp/bootloader/update-tinyuf2.uf2 deleted file mode 100644 index 02b83daa4..000000000 Binary files a/grid_esp/bootloader/update-tinyuf2.uf2 and /dev/null differ diff --git a/grid_esp/components/grid_esp32_encoder/grid_esp32_encoder.c b/grid_esp/components/grid_esp32_encoder/grid_esp32_encoder.c index bf90f7770..e46877700 100644 --- a/grid_esp/components/grid_esp32_encoder/grid_esp32_encoder.c +++ b/grid_esp/components/grid_esp32_encoder/grid_esp32_encoder.c @@ -72,6 +72,6 @@ void grid_esp32_encoder_init(struct grid_esp32_encoder_model* encoder, uint32_t .on_send_q_ovf = NULL, }; ESP_ERROR_CHECK(i2s_channel_register_event_callback(encoder->rx_chan, &cbs, encoder)); - - ESP_ERROR_CHECK(i2s_channel_enable(encoder->rx_chan)); } + +void grid_esp32_encoder_start(struct grid_esp32_encoder_model* encoder) { ESP_ERROR_CHECK(i2s_channel_enable(encoder->rx_chan)); } diff --git a/grid_esp/components/grid_esp32_encoder/grid_esp32_encoder.h b/grid_esp/components/grid_esp32_encoder/grid_esp32_encoder.h index fd00f5c87..86d292ddf 100644 --- a/grid_esp/components/grid_esp32_encoder/grid_esp32_encoder.h +++ b/grid_esp/components/grid_esp32_encoder/grid_esp32_encoder.h @@ -55,6 +55,7 @@ struct grid_esp32_encoder_model { extern struct grid_esp32_encoder_model grid_esp32_encoder_state; void grid_esp32_encoder_init(struct grid_esp32_encoder_model* encoder, uint32_t divider, grid_process_encoder_t process_encoder); +void grid_esp32_encoder_start(struct grid_esp32_encoder_model* encoder); #ifdef __cplusplus } diff --git a/grid_esp/components/grid_esp32_module_ef44/grid_esp32_module_ef44.c b/grid_esp/components/grid_esp32_module_ef44/grid_esp32_module_ef44.c index 7f045dbb9..4c4e67f84 100644 --- a/grid_esp/components/grid_esp32_module_ef44/grid_esp32_module_ef44.c +++ b/grid_esp/components/grid_esp32_module_ef44/grid_esp32_module_ef44.c @@ -135,5 +135,7 @@ void grid_esp32_module_ef44_init(struct grid_sys_model* sys, struct grid_ui_mode grid_esp32_adc_init(adc, ef44_process_analog); grid_esp32_adc_mux_init(adc, 2); uint8_t mux_dependent = !grid_hwcfg_module_is_rev_h(sys); + + grid_esp32_encoder_start(enc); grid_esp32_adc_start(adc, mux_dependent); } diff --git a/grid_esp/components/grid_esp32_module_en16/grid_esp32_module_en16.c b/grid_esp/components/grid_esp32_module_en16/grid_esp32_module_en16.c index 2107fa556..e2946ffe2 100644 --- a/grid_esp/components/grid_esp32_module_en16/grid_esp32_module_en16.c +++ b/grid_esp/components/grid_esp32_module_en16/grid_esp32_module_en16.c @@ -70,4 +70,6 @@ void grid_esp32_module_en16_init(struct grid_sys_model* sys, struct grid_ui_mode for (uint8_t i = 0; i < GRID_MODULE_EN16_ENC_NUM; i++) { grid_ui_encoder_state_init(&ui_encoder_state[i], detent, direction); } + + grid_esp32_encoder_start(enc); } diff --git a/grid_esp/components/grid_esp32_module_octv/CMakeLists.txt b/grid_esp/components/grid_esp32_module_octv/CMakeLists.txt new file mode 100644 index 000000000..1ebaf3aba --- /dev/null +++ b/grid_esp/components/grid_esp32_module_octv/CMakeLists.txt @@ -0,0 +1,8 @@ +idf_component_register( + SRCS + "grid_esp32_module_octv.c" + INCLUDE_DIRS + "." + REQUIRES + "grid_esp32_adc" "grid_esp32_encoder" "grid_common" +) diff --git a/grid_esp/components/grid_esp32_module_octv/grid_esp32_module_octv.c b/grid_esp/components/grid_esp32_module_octv/grid_esp32_module_octv.c new file mode 100644 index 000000000..1dd5082b9 --- /dev/null +++ b/grid_esp/components/grid_esp32_module_octv/grid_esp32_module_octv.c @@ -0,0 +1,139 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "grid_esp32_module_octv.h" + +#include + +#include "grid_ain.h" +#include "grid_asc.h" +#include "grid_cal.h" +#include "grid_config.h" +#include "grid_module.h" + +#include "grid_ui.h" + +#include "grid_ui_button.h" +#include "grid_ui_encoder.h" +#include "grid_ui_system.h" + +#include "grid_platform.h" +#include "grid_sys.h" + +#include "grid_esp32_adc.h" +#include "grid_esp32_encoder.h" + +// static const char* TAG = "module_octv"; + +#define GRID_MODULE_OCTV_BUT_NUM 21 + +#define GRID_MODULE_OCTV_ENC_NUM 8 + +static struct grid_ui_button_state* DRAM_ATTR ui_button_state = NULL; +static struct grid_ui_encoder_state* DRAM_ATTR ui_encoder_state = NULL; +static struct grid_asc* DRAM_ATTR asc_state = NULL; +static struct grid_ui_element* DRAM_ATTR elements = NULL; + +void IRAM_ATTR octv_process_analog(void* user) { + +#define X GRID_MUX_UNUSED + static DRAM_ATTR const uint8_t multiplexer_lookup[16] = {15, 8, 16, 9, 17, 10, 18, 11, 19, 12, 20, 13, X, 14, X, X}; +#undef X + + assert(user); + + struct grid_esp32_adc_result* result = (struct grid_esp32_adc_result*)user; + + uint8_t lookup_index = result->mux_state * 2 + result->channel; + uint8_t element_index = multiplexer_lookup[lookup_index]; + + if (element_index == GRID_MUX_UNUSED) { + return; + } + + assert(element_index < GRID_MODULE_OCTV_BUT_NUM); + + struct grid_ui_element* ele = &elements[element_index]; + + if (!grid_asc_process(&asc_state[lookup_index], result->value, &result->value)) { + return; + } + + grid_ui_button_store_input(ele, &ui_button_state[element_index], result->value, 12); +} + +void IRAM_ATTR octv_process_encoder(void* dma_buf) { + + static DRAM_ATTR uint8_t encoder_lookup[GRID_MODULE_OCTV_ENC_NUM] = {6, 7, 4, 5, 2, 3, 0, 1}; + + // Skip hwcfg byte + uint8_t* bytes = &((uint8_t*)dma_buf)[1]; + + for (uint8_t j = 0; j < GRID_MODULE_OCTV_ENC_NUM; ++j) { + + uint8_t value = (bytes[j / 2] >> (4 * (j % 2))) & 0x0F; + uint8_t idx = encoder_lookup[j]; + struct grid_ui_element* ele = &elements[idx]; + + grid_ui_encoder_store_input(ele, &ui_encoder_state[idx], value); + + uint8_t button_value = value & 0b00000100; + + grid_ui_button_store_input(ele, &ui_button_state[idx], button_value, 1); + } +} + +void grid_esp32_module_octv_init(struct grid_sys_model* sys, struct grid_ui_model* ui, struct grid_esp32_adc_model* adc, struct grid_esp32_encoder_model* enc, struct grid_config_model* conf, + struct grid_cal_model* cal) { + + ui_button_state = grid_platform_allocate_volatile(GRID_MODULE_OCTV_BUT_NUM * sizeof(struct grid_ui_button_state)); + ui_encoder_state = grid_platform_allocate_volatile(GRID_MODULE_OCTV_ENC_NUM * sizeof(struct grid_ui_encoder_state)); + asc_state = grid_platform_allocate_volatile(16 * sizeof(struct grid_asc)); + memset(ui_button_state, 0, GRID_MODULE_OCTV_BUT_NUM * sizeof(struct grid_ui_button_state)); + memset(ui_encoder_state, 0, GRID_MODULE_OCTV_ENC_NUM * sizeof(struct grid_ui_encoder_state)); + memset(asc_state, 0, 16 * sizeof(struct grid_asc)); + + for (int i = 0; i < GRID_MODULE_OCTV_ENC_NUM; ++i) { + grid_ui_button_state_init(&ui_button_state[i], 1, 0.5, 0.2); + } + + for (int i = GRID_MODULE_OCTV_ENC_NUM; i < GRID_MODULE_OCTV_BUT_NUM; ++i) { + grid_ui_button_state_init(&ui_button_state[i], 12, 0.5, 0.2); + } + + grid_asc_array_set_factors(asc_state, 16, 0, 16, 1); + + elements = grid_ui_model_get_elements(ui); + + grid_config_init(conf, cal); + grid_cal_init(cal, ui->element_list_length, 12); + + for (int i = 8; i < 21; ++i) { + assert(grid_cal_set(cal, i, GRID_CAL_LIMITS, &ui_button_state[i].limits) == 0); + } + + while (grid_ui_bulk_conf_init(ui, GRID_UI_BULK_CONFREAD_PROGRESS, 0, NULL)) { + vTaskDelay(1); + } + + while (grid_ui_bulk_is_in_progress(ui, GRID_UI_BULK_CONFREAD_PROGRESS)) { + vTaskDelay(1); + } + + grid_esp32_encoder_init(enc, 1, octv_process_encoder); + uint8_t detent = grid_hwcfg_module_encoder_is_detent(&grid_sys_state); + int8_t direction = grid_hwcfg_module_encoder_dir(sys); + for (uint8_t i = 0; i < GRID_MODULE_OCTV_ENC_NUM; i++) { + grid_ui_encoder_state_init(&ui_encoder_state[i], detent, direction); + } + + grid_esp32_adc_init(adc, octv_process_analog); + grid_esp32_adc_mux_init(adc, 7); + uint8_t mux_dependent = !grid_hwcfg_module_is_rev_h(sys); + + grid_esp32_encoder_start(enc); + grid_esp32_adc_start(adc, mux_dependent); +} diff --git a/grid_esp/components/grid_esp32_module_octv/grid_esp32_module_octv.h b/grid_esp/components/grid_esp32_module_octv/grid_esp32_module_octv.h new file mode 100644 index 000000000..e9df2b40c --- /dev/null +++ b/grid_esp/components/grid_esp32_module_octv/grid_esp32_module_octv.h @@ -0,0 +1,25 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include "grid_cal.h" +#include "grid_config.h" +#include "grid_sys.h" +#include "grid_ui.h" + +#include "grid_esp32_adc.h" +#include "grid_esp32_encoder.h" + +void grid_esp32_module_octv_init(struct grid_sys_model* sys, struct grid_ui_model* ui, struct grid_esp32_adc_model* adc, struct grid_esp32_encoder_model* enc, struct grid_config_model* conf, + struct grid_cal_model* cal); + +#ifdef __cplusplus +} +#endif diff --git a/grid_esp/components/grid_esp32_module_tek1/grid_esp32_module_tek1.c b/grid_esp/components/grid_esp32_module_tek1/grid_esp32_module_tek1.c index 30c1bb75a..cf4dc2a69 100644 --- a/grid_esp/components/grid_esp32_module_tek1/grid_esp32_module_tek1.c +++ b/grid_esp/components/grid_esp32_module_tek1/grid_esp32_module_tek1.c @@ -345,6 +345,7 @@ void grid_esp32_module_tek1_init(struct grid_sys_model* sys, struct grid_ui_mode if (!is_vsn_rev_h_8bit_hwcfg) { grid_esp32_encoder_init(&grid_esp32_encoder_state, 10, process_encoder); + grid_esp32_encoder_start(&grid_esp32_encoder_state); } grid_esp32_adc_mux_init(adc, 8); diff --git a/grid_esp/main/grid_fw.c b/grid_esp/main/grid_fw.c index f6d8eb619..cf3456c8e 100644 --- a/grid_esp/main/grid_fw.c +++ b/grid_esp/main/grid_fw.c @@ -43,6 +43,7 @@ #include "grid_esp32_module_bu16.h" #include "grid_esp32_module_ef44.h" #include "grid_esp32_module_en16.h" +#include "grid_esp32_module_octv.h" #include "grid_esp32_module_pbf4.h" #include "grid_esp32_module_po16.h" #include "grid_esp32_module_tek1.h" @@ -423,6 +424,8 @@ void app_main(void) { grid_module_en16_ui_init(&grid_ain_state, &grid_led_state, &grid_ui_state); } else if (grid_hwcfg_module_is_ef44(&grid_sys_state)) { grid_module_ef44_ui_init(&grid_ain_state, &grid_led_state, &grid_ui_state); + } else if (grid_hwcfg_module_is_octv(&grid_sys_state)) { + grid_module_octv_ui_init(&grid_ain_state, &grid_led_state, &grid_ui_state); } else if (grid_hwcfg_module_is_tek2(&grid_sys_state)) { grid_module_tek2_ui_init(&grid_ain_state, &grid_led_state, &grid_ui_state); } else if (grid_hwcfg_module_is_vsnx(&grid_sys_state)) { @@ -537,6 +540,8 @@ void app_main(void) { grid_esp32_module_en16_init(&grid_sys_state, &grid_ui_state, &grid_esp32_encoder_state); } else if (grid_hwcfg_module_is_ef44(&grid_sys_state)) { grid_esp32_module_ef44_init(&grid_sys_state, &grid_ui_state, &grid_esp32_adc_state, &grid_esp32_encoder_state, &grid_config_state, &grid_cal_state); + } else if (grid_hwcfg_module_is_octv(&grid_sys_state)) { + grid_esp32_module_octv_init(&grid_sys_state, &grid_ui_state, &grid_esp32_adc_state, &grid_esp32_encoder_state, &grid_config_state, &grid_cal_state); } else if (grid_hwcfg_module_is_tek2(&grid_sys_state)) { grid_esp32_module_tek2_init(&grid_sys_state, &grid_ui_state, &grid_esp32_adc_state, &grid_config_state, &grid_cal_state); } else if (grid_hwcfg_module_is_vsnx(&grid_sys_state)) {