Skip to content

Commit

Permalink
SUKU components updated
Browse files Browse the repository at this point in the history
  • Loading branch information
SukuWc committed Oct 16, 2024
1 parent a09f4c6 commit 3033cb5
Show file tree
Hide file tree
Showing 6 changed files with 589 additions and 118 deletions.
3 changes: 2 additions & 1 deletion Firmware/.vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
"bitset": "c",
"initializer_list": "c",
"utility": "c",
"knot_midi_usb.h": "c"
"knot_midi_usb.h": "c",
"grid_lua.h": "c"
},
"actionButtons": {
"defaultColor": "#ff0034",
Expand Down
1 change: 1 addition & 0 deletions Firmware/components/knot_midi_usb/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ idf_component_register(
"knot_midi_uart"
"knot_midi_queue"
"driver"
"esp_timer"
"usb"
"grid_common"
"grid_esp32_led"
Expand Down
58 changes: 52 additions & 6 deletions Firmware/components/knot_midi_usb/knot_midi_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
#include "knot_midi_usb.h"

#include "esp_log.h"

#include "esp_timer.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "grid_led.h"
Expand Down Expand Up @@ -211,20 +213,63 @@ static usb_transfer_t* out_transfer;

static usb_transfer_t* in_transfer;

static void in_transfer_cb(usb_transfer_t* in_transfer) {
// This is function is called from within usb_host_client_handle_events(). Don't block and try to keep it short
struct class_driver_t* class_driver_obj = (struct class_driver_t*)in_transfer->context;
// printf("IN: Transfer status %d, actual number of bytes transferred %d\n", in_transfer->status, in_transfer->actual_num_bytes);
static bool is_transfer_completed(usb_transfer_t* transfer) {
bool completed = false;

switch (transfer->status) {
case USB_TRANSFER_STATUS_COMPLETED:
completed = true;
break;
case USB_TRANSFER_STATUS_NO_DEVICE: // User is notified about device disconnection from usb_event_cb
case USB_TRANSFER_STATUS_CANCELED:
break;
case USB_TRANSFER_STATUS_ERROR:
case USB_TRANSFER_STATUS_TIMED_OUT:
case USB_TRANSFER_STATUS_STALL:
case USB_TRANSFER_STATUS_OVERFLOW:
case USB_TRANSFER_STATUS_SKIPPED:
default:
}
return completed;
}

volatile uint8_t DRAM_ATTR usb_in_ready = 0;

static portMUX_TYPE in_mutex = portMUX_INITIALIZER_UNLOCKED;
#define CDC_ACM_ENTER_CRITICAL() portENTER_CRITICAL(&in_mutex)
#define CDC_ACM_EXIT_CRITICAL() portEXIT_CRITICAL(&in_mutex)
esp_err_t try_start_in_transfer(void) {
CDC_ACM_ENTER_CRITICAL();

// printf("IN: %d %d %d %d", in_transfer->data_buffer[0], in_transfer->data_buffer[1], in_transfer->data_buffer[2], in_transfer->data_buffer[3]);
if (usb_in_ready == 0) {

CDC_ACM_EXIT_CRITICAL();
return -1;
}

esp_err_t err = usb_host_transfer_submit(in_transfer);
usb_in_ready = 0;
CDC_ACM_EXIT_CRITICAL();

// printf("S\n");
return err;
}

static void in_transfer_cb(usb_transfer_t* in_transfer) {
// CDC_ACM_ENTER_CRITICAL();
printf("TIME: %lld IN: Transfer status %d, actual number of bytes transferred %d\n", esp_timer_get_time(), in_transfer->status, in_transfer->actual_num_bytes);

struct usb_midi_event_packet usb_ev = {.byte0 = in_transfer->data_buffer[0], .byte1 = in_transfer->data_buffer[1], .byte2 = in_transfer->data_buffer[2], .byte3 = in_transfer->data_buffer[3]};

struct uart_midi_event_packet uart_ev = usb_midi_to_uart(usb_ev);

knot_midi_queue_trsout_push(uart_ev);

// usb_in_ready = 1;
// CDC_ACM_EXIT_CRITICAL();
usb_host_transfer_submit(in_transfer);

ets_printf("IN: %d %d %d %d\n", esp_timer_get_time(), in_transfer->status, in_transfer->data_buffer[0], in_transfer->data_buffer[1], in_transfer->data_buffer[2], in_transfer->data_buffer[3]);
}

volatile uint8_t DRAM_ATTR usb_out_ready = 1;
Expand Down Expand Up @@ -313,10 +358,11 @@ static void action_get_config_desc(class_driver_t* driver_obj) {
if (in_transfer == NULL) {
usb_host_transfer_alloc(USB_EP_DESC_GET_MPS(in_ep), 0, &in_transfer);
}
memset(in_transfer->data_buffer, 0xAA, 4);
memset(in_transfer->data_buffer, 0, 4);
in_transfer->num_bytes = USB_EP_DESC_GET_MPS(in_ep);
in_transfer->device_handle = driver_obj->dev_hdl;
in_transfer->bEndpointAddress = in_ep->bEndpointAddress;
in_transfer->timeout_ms = 5000;
in_transfer->callback = in_transfer_cb;
in_transfer->context = (void*)&driver_obj;

Expand Down
3 changes: 2 additions & 1 deletion Firmware/main/idf_component.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## IDF Component Manager Manifest File
dependencies:
sukuwc/grid_common: "^2024.5.211458"
espressif/usb_host_cdc_acm: "^2.0.4"
sukuwc/grid_common: "*"
sukuwc/grid_esp32_led: "*"
sukuwc/grid_esp32_nvm: "*"
joltwallet/littlefs: "*"
Expand Down
202 changes: 197 additions & 5 deletions Firmware/main/midi_host_fw.c
Original file line number Diff line number Diff line change
@@ -1,18 +1,204 @@
#ifdef TEST_CDC_SERIAL

/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: CC0-1.0
*/

#include "esp_err.h"
#include "esp_log.h"
#include "esp_system.h"
#include <inttypes.h>
#include <stdio.h>
#include <string.h>

#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/task.h"

#include "usb/cdc_acm_host.h"
#include "usb/usb_host.h"

#define EXAMPLE_USB_HOST_PRIORITY (20)
#define EXAMPLE_USB_DEVICE_VID (0x303A)
#define EXAMPLE_USB_DEVICE_PID (0x8123) // 0x303A:0x4001 (TinyUSB CDC device)
#define EXAMPLE_USB_DEVICE_DUAL_PID (0x4002) // 0x303A:0x4002 (TinyUSB Dual CDC device)
#define EXAMPLE_TX_STRING ("CDC test string!")
#define EXAMPLE_TX_TIMEOUT_MS (1000)

static const char* TAG = "USB-CDC";
static SemaphoreHandle_t device_disconnected_sem;

/**
* @brief Data received callback
*
* @param[in] data Pointer to received data
* @param[in] data_len Length of received data in bytes
* @param[in] arg Argument we passed to the device open function
* @return
* true: We have processed the received data
* false: We expect more data
*/
static bool handle_rx(const uint8_t* data, size_t data_len, void* arg) {
ESP_LOGI(TAG, "Data received");
ESP_LOG_BUFFER_HEXDUMP(TAG, data, data_len, ESP_LOG_INFO);
return true;
}

/**
* @brief Device event callback
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
* Apart from handling device disconnection it doesn't do anything useful
*
* @param[in] event Device event type and data
* @param[in] user_ctx Argument we passed to the device open function
*/
static void handle_event(const cdc_acm_host_dev_event_data_t* event, void* user_ctx) {
switch (event->type) {
case CDC_ACM_HOST_ERROR:
ESP_LOGE(TAG, "CDC-ACM error has occurred, err_no = %i", event->data.error);
break;
case CDC_ACM_HOST_DEVICE_DISCONNECTED:
ESP_LOGI(TAG, "Device suddenly disconnected");
ESP_ERROR_CHECK(cdc_acm_host_close(event->data.cdc_hdl));
xSemaphoreGive(device_disconnected_sem);
break;
case CDC_ACM_HOST_SERIAL_STATE:
ESP_LOGI(TAG, "Serial state notif 0x%04X", event->data.serial_state.val);
break;
case CDC_ACM_HOST_NETWORK_CONNECTION:
default:
ESP_LOGW(TAG, "Unsupported CDC event: %i", event->type);
break;
}
}

/**
* @brief USB Host library handling task
*
* @param arg Unused
*/
static void usb_lib_task(void* arg) {
while (1) {
// Start handling system events
uint32_t event_flags;
usb_host_lib_handle_events(portMAX_DELAY, &event_flags);
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_NO_CLIENTS) {
ESP_ERROR_CHECK(usb_host_device_free_all());
}
if (event_flags & USB_HOST_LIB_EVENT_FLAGS_ALL_FREE) {
ESP_LOGI(TAG, "USB: All devices freed");
// Continue handling USB events to allow device reconnection
}
}
}

/**
* @brief Main application
*
* Here we open a USB CDC device and send some data to it
*/

#include "driver/gpio.h"

void app_main(void) {

#define USB_NATIVE_SELECT_PIN 11
#define USB_SOFT_SELECT_PIN 12

gpio_set_direction(USB_NATIVE_SELECT_PIN, GPIO_MODE_OUTPUT);
gpio_set_direction(USB_SOFT_SELECT_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(USB_NATIVE_SELECT_PIN, 1);
gpio_set_level(USB_SOFT_SELECT_PIN, 1);

#define PMIC_EN_PIN 48

gpio_set_direction(PMIC_EN_PIN, GPIO_MODE_OUTPUT);
gpio_set_level(PMIC_EN_PIN, 1);

device_disconnected_sem = xSemaphoreCreateBinary();
assert(device_disconnected_sem);

// Install USB Host driver. Should only be called once in entire application
ESP_LOGI(TAG, "Installing USB Host");
const usb_host_config_t host_config = {
.skip_phy_setup = false,
.intr_flags = ESP_INTR_FLAG_LEVEL1,
};
ESP_ERROR_CHECK(usb_host_install(&host_config));

// Create a task that will handle USB library events
BaseType_t task_created = xTaskCreate(usb_lib_task, "usb_lib", 4096, xTaskGetCurrentTaskHandle(), EXAMPLE_USB_HOST_PRIORITY, NULL);
assert(task_created == pdTRUE);

ESP_LOGI(TAG, "Installing CDC-ACM driver");
ESP_ERROR_CHECK(cdc_acm_host_install(NULL));

const cdc_acm_host_device_config_t dev_config = {.connection_timeout_ms = 1000, .out_buffer_size = 512, .in_buffer_size = 512, .user_arg = NULL, .event_cb = handle_event, .data_cb = handle_rx};

while (true) {
cdc_acm_dev_hdl_t cdc_dev = NULL;

// Open USB device from tusb_serial_device example example. Either single or dual port configuration.
ESP_LOGI(TAG, "Opening CDC ACM device 0x%04X:0x%04X...", EXAMPLE_USB_DEVICE_VID, EXAMPLE_USB_DEVICE_PID);
esp_err_t err = cdc_acm_host_open(EXAMPLE_USB_DEVICE_VID, EXAMPLE_USB_DEVICE_PID, 0, &dev_config, &cdc_dev);
if (ESP_OK != err) {
ESP_LOGI(TAG, "Opening CDC ACM device 0x%04X:0x%04X...", EXAMPLE_USB_DEVICE_VID, EXAMPLE_USB_DEVICE_DUAL_PID);
err = cdc_acm_host_open(EXAMPLE_USB_DEVICE_VID, EXAMPLE_USB_DEVICE_DUAL_PID, 0, &dev_config, &cdc_dev);
if (ESP_OK != err) {
ESP_LOGI(TAG, "Failed to open device");
continue;
}
}
cdc_acm_host_desc_print(cdc_dev);
vTaskDelay(pdMS_TO_TICKS(100));

// Test sending and receiving: responses are handled in handle_rx callback
ESP_ERROR_CHECK(cdc_acm_host_data_tx_blocking(cdc_dev, (const uint8_t*)EXAMPLE_TX_STRING, strlen(EXAMPLE_TX_STRING), EXAMPLE_TX_TIMEOUT_MS));
vTaskDelay(pdMS_TO_TICKS(100));

// Test Line Coding commands: Get current line coding, change it 9600 7N1 and read again
ESP_LOGI(TAG, "Setting up line coding");

cdc_acm_line_coding_t line_coding;
ESP_ERROR_CHECK(cdc_acm_host_line_coding_get(cdc_dev, &line_coding));
ESP_LOGI(TAG, "Line Get: Rate: %" PRIu32 ", Stop bits: %" PRIu8 ", Parity: %" PRIu8 ", Databits: %" PRIu8 "", line_coding.dwDTERate, line_coding.bCharFormat, line_coding.bParityType,
line_coding.bDataBits);

line_coding.dwDTERate = 9600;
line_coding.bDataBits = 7;
line_coding.bParityType = 1;
line_coding.bCharFormat = 1;
ESP_ERROR_CHECK(cdc_acm_host_line_coding_set(cdc_dev, &line_coding));
ESP_LOGI(TAG, "Line Set: Rate: %" PRIu32 ", Stop bits: %" PRIu8 ", Parity: %" PRIu8 ", Databits: %" PRIu8 "", line_coding.dwDTERate, line_coding.bCharFormat, line_coding.bParityType,
line_coding.bDataBits);

ESP_ERROR_CHECK(cdc_acm_host_line_coding_get(cdc_dev, &line_coding));
ESP_LOGI(TAG, "Line Get: Rate: %" PRIu32 ", Stop bits: %" PRIu8 ", Parity: %" PRIu8 ", Databits: %" PRIu8 "", line_coding.dwDTERate, line_coding.bCharFormat, line_coding.bParityType,
line_coding.bDataBits);

ESP_ERROR_CHECK(cdc_acm_host_set_control_line_state(cdc_dev, true, false));

// We are done. Wait for device disconnection and start over
ESP_LOGI(TAG, "Example finished successfully! You can reconnect the device to run again.");
xSemaphoreTake(device_disconnected_sem, portMAX_DELAY);
}
}

#else

#include "esp_intr_alloc.h"
#include "esp_log.h"

#include "esp_freertos_hooks.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "freertos/task.h"
#include "usb/usb_host.h"

// must be last freertos relevant header to avoid #error
#include "esp_freertos_hooks.h"

#include <string.h>

#include "knot_midi_queue.h"
Expand Down Expand Up @@ -156,7 +342,7 @@ uint8_t grid_platform_get_adc_bit_depth(void) { return 12; }

#include "grid_ain.h"
#include "grid_led.h"
#include "grid_lua_api.h"
#include "grid_lua.h"
#include "grid_ui.h"
#include "grid_ui_system.h"

Expand Down Expand Up @@ -201,8 +387,12 @@ void knot_lua_ui_init_knot(struct grid_lua_model* mod) {
grid_lua_dostring(mod, "setmetatable(" GRID_LUA_KW_ELEMENT_short "[0], system_meta)");
}

extern esp_err_t try_start_in_transfer(void);

bool idle_hook(void) {

try_start_in_transfer();

struct uart_midi_event_packet uart_midi_ev = {0};
while (0 == knot_midi_queue_trsout_pop(&uart_midi_ev)) {
// ets_printf("TRS OUT: %d %d %d %d\n", uart_midi_ev.length, uart_midi_ev.byte1, uart_midi_ev.byte2, uart_midi_ev.byte3);
Expand Down Expand Up @@ -287,7 +477,7 @@ void app_main(void) {
xSemaphoreGive(nvm_or_port);

ESP_LOGI(TAG, "===== LUA INIT =====");
grid_lua_init(&grid_lua_state);
grid_lua_init(&grid_lua_state, NULL, NULL);
grid_lua_set_memory_target(&grid_lua_state, 80); // 80kb
grid_lua_start_vm(&grid_lua_state);
grid_lua_dostring(&grid_lua_state, "foo = 123");
Expand Down Expand Up @@ -370,3 +560,5 @@ void app_main(void) {
last_button_state = current_button_state;
}
}

#endif
Loading

0 comments on commit 3033cb5

Please sign in to comment.