This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| tamiwiki:users:6r1d:diymall_esp32_s3_fixture [2025/10/18 22:19] – [ESP-IDF (+ history and PWM debug)] 6r1d | tamiwiki:users:6r1d:diymall_esp32_s3_fixture [2025/10/20 05:43] (current) – [ESP-IDF (+ history and PWM debug)] 6r1d | ||
|---|---|---|---|
| Line 53: | Line 53: | ||
| ====== Tracing code ====== | ====== Tracing code ====== | ||
| - | You may disagree with me and want to run a quick check. | + | You might disagree with me and want to double-check. |
| + | Grab your trusty 30-year-old LED soldered to a pair of DuPont sockets and start tracing. If you don’t have one handy (like me), grab your scope instead.((Marie Antoinette reference unintended.)) | ||
| + | |||
| + | For convenience, | ||
| ===== ESP-IDF (+ history and PWM debug) ===== | ===== ESP-IDF (+ history and PWM debug) ===== | ||
| Line 94: | Line 97: | ||
| </ | </ | ||
| - | <file cpp esp32_s3_pin_tracer.c> | + | As for using it, you should know the gist at this point. |
| - | #include < | + | |
| - | #include < | + | |
| - | #include < | + | |
| - | #include < | + | |
| - | #include " | + | <code bash> |
| - | #include " | + | mkdir pin_tracer && cd pin_tracer |
| + | idf.py create-project . && idf.py reconfigure && idf.py set-target esp32s3 | ||
| + | # fill the code | ||
| + | # update the CMake configs | ||
| + | idf.py build | ||
| + | idf.py flash monitor | ||
| + | </ | ||
| - | #include " | + | For your convenience, |
| - | #include " | + | |
| - | #include " | + | |
| - | #include " | + | |
| - | #include " | + | |
| - | #include " | + | |
| - | /* | + | Clone it like that: |
| - | * CONFIG | + | |
| - | */ | + | |
| - | // Defaults | + | |
| - | static uint32_t g_blink_delay_ms = 100; | + | |
| - | // Console config | + | |
| - | #define CLI_LINE_MAX 128 | + | |
| - | #define HIST_MAX | + | |
| - | // PWM configuration | + | <code bash> |
| - | #define LEDC_TIMER | + | git clone https://git.telavivmakers.space/6r1d/esp32_s3_pin_tracer_espidf.git esp32_s3_pin_tracer |
| - | #define LEDC_MODE | + | </code> |
| - | #define LEDC_CHANNEL | + | |
| - | #define LEDC_DUTY_RES | + | |
| - | #define LEDC_FREQUENCY | + | |
| - | + | ||
| - | // Conservative " | + | |
| - | static const gpio_num_t TEST_SAFE_GPIO[] = { | + | |
| - | 1, 2, | + | |
| - | 4, 5, 6, 7, | + | |
| - | 8, 9, 10, 11, 12, 13, 14, | + | |
| - | 15, 16, 17, 18, | + | |
| - | /* 19,20 excluded (USB D-/D+) */ | + | |
| - | 21, | + | |
| - | /* 22..34 not bonded on typical modules */ | + | |
| - | /* 35,36,37 excluded (PSRAM on some variants) */ | + | |
| - | 38, 39, 40, 41, 42, /* JTAG-capable if configured */ | + | |
| - | /* 43,44 excluded (UART0 console) */ | + | |
| - | 47, 48 /* may be 1.8 V on R16V */ | + | |
| - | }; | + | |
| - | static const size_t TEST_SAFE_GPIO_COUNT = sizeof(TEST_SAFE_GPIO) / sizeof(TEST_SAFE_GPIO[0]); | + | |
| - | + | ||
| - | // ====== RUNTIME STATE ====== | + | |
| - | static gpio_num_t g_current_pin = -1; | + | |
| - | static bool g_blinking = false; | + | |
| - | static bool g_pwm_mode = false; | + | |
| - | static uint8_t g_pwm_brightness = 50; // 0-99 scale | + | |
| - | static uint32_t g_pwm_frequency = LEDC_FREQUENCY; | + | |
| - | static TaskHandle_t g_blink_task = NULL; | + | |
| - | + | ||
| - | /* ================== GPIO HELPERS ================== */ | + | |
| - | + | ||
| - | static bool is_test_safe(gpio_num_t gpio) | + | |
| - | { | + | |
| - | for (size_t i = 0; i < TEST_SAFE_GPIO_COUNT; | + | |
| - | if (TEST_SAFE_GPIO[i] == gpio) return true; | + | |
| - | } | + | |
| - | return false; | + | |
| - | } | + | |
| - | + | ||
| - | static void print_test_safe_pins(void) | + | |
| - | { | + | |
| - | printf(" | + | |
| - | for (size_t i = 0; i < TEST_SAFE_GPIO_COUNT; | + | |
| - | printf(" | + | |
| - | } | + | |
| - | printf(" | + | |
| - | printf(" | + | |
| - | } | + | |
| - | + | ||
| - | static void release_pin(gpio_num_t pin) | + | |
| - | { | + | |
| - | if (pin >= 0) { | + | |
| - | | + | |
| - | gpio_reset_pin(pin); | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | static void stop_pwm(void) | + | |
| - | { | + | |
| - | if (g_pwm_mode) { | + | |
| - | ledc_stop(LEDC_MODE, | + | |
| - | g_pwm_mode = false; | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | static void stop_blink(void) | + | |
| - | { | + | |
| - | if (g_blink_task) { | + | |
| - | TaskHandle_t t = g_blink_task; | + | |
| - | g_blink_task = NULL; // signal task to exit | + | |
| - | for (int i = 0; i < 20 && eTaskGetState(t) != eDeleted; ++i) { | + | |
| - | vTaskDelay(pdMS_TO_TICKS(5)); | + | |
| - | } | + | |
| - | } | + | |
| - | g_blinking = false; | + | |
| - | } | + | |
| - | + | ||
| - | static void stop_all(void) | + | |
| - | { | + | |
| - | stop_blink(); | + | |
| - | stop_pwm(); | + | |
| - | release_pin(g_current_pin); | + | |
| - | g_current_pin = -1; | + | |
| - | printf(" | + | |
| - | } | + | |
| - | + | ||
| - | static void blink_task(void *arg) | + | |
| - | { | + | |
| - | gpio_num_t pin = (gpio_num_t)(intptr_t)arg; | + | |
| - | gpio_config_t io = { | + | |
| - | .pin_bit_mask = 1ULL << pin, | + | |
| - | .mode = GPIO_MODE_OUTPUT, | + | |
| - | .pull_up_en = GPIO_PULLUP_DISABLE, | + | |
| - | .pull_down_en = GPIO_PULLDOWN_DISABLE, | + | |
| - | .intr_type = GPIO_INTR_DISABLE | + | |
| - | }; | + | |
| - | gpio_config(& | + | |
| - | gpio_set_level(pin, | + | |
| - | + | ||
| - | while (g_blink_task == xTaskGetCurrentTaskHandle()) { | + | |
| - | gpio_set_level(pin, | + | |
| - | vTaskDelay(pdMS_TO_TICKS(g_blink_delay_ms)); | + | |
| - | gpio_set_level(pin, | + | |
| - | vTaskDelay(pdMS_TO_TICKS(g_blink_delay_ms)); | + | |
| - | } | + | |
| - | + | ||
| - | release_pin(pin); | + | |
| - | vTaskDelete(NULL); | + | |
| - | } | + | |
| - | + | ||
| - | static bool setup_pwm(gpio_num_t gpio) | + | |
| - | { | + | |
| - | // Stop previous PWM if any | + | |
| - | if (g_pwm_mode) { | + | |
| - | ledc_stop(LEDC_MODE, | + | |
| - | } | + | |
| - | + | ||
| - | // Configure LEDC timer | + | |
| - | ledc_timer_config_t ledc_timer = { | + | |
| - | .speed_mode | + | |
| - | .timer_num | + | |
| - | .duty_resolution | + | |
| - | .freq_hz | + | |
| - | .clk_cfg | + | |
| - | }; | + | |
| - | esp_err_t ret = ledc_timer_config(& | + | |
| - | if (ret != ESP_OK) { | + | |
| - | printf(" | + | |
| - | return false; | + | |
| - | } | + | |
| - | + | ||
| - | | + | |
| - | ledc_channel_config_t ledc_channel = { | + | |
| - | | + | |
| - | .channel | + | |
| - | .timer_sel | + | |
| - | .intr_type | + | |
| - | .gpio_num | + | |
| - | | + | |
| - | | + | |
| - | }; | + | |
| - | ret = ledc_channel_config(& | + | |
| - | if (ret != ESP_OK) { | + | |
| - | printf(" | + | |
| - | return false; | + | |
| - | } | + | |
| - | + | ||
| - | return true; | + | |
| - | } | + | |
| - | + | ||
| - | static void set_pwm_brightness(uint8_t level) | + | |
| - | { | + | |
| - | if (level > 99) level = 99; | + | |
| - | g_pwm_brightness = level; | + | |
| - | + | ||
| - | // Convert 0-99 scale to 0-255 duty cycle | + | |
| - | uint32_t duty = (level * 255) / 99; | + | |
| - | ledc_set_duty(LEDC_MODE, | + | |
| - | ledc_update_duty(LEDC_MODE, | + | |
| - | + | ||
| - | printf(" | + | |
| - | } | + | |
| - | + | ||
| - | static void set_pwm_frequency(uint32_t freq) | + | |
| - | { | + | |
| - | if (freq < 100) freq = 100; | + | |
| - | if (freq > 50000) freq = 50000; // Conservative max for LEDC | + | |
| - | + | ||
| - | g_pwm_frequency = freq; | + | |
| - | + | ||
| - | if (g_pwm_mode) { | + | |
| - | // Reconfigure PWM with new frequency | + | |
| - | ledc_timer_config_t ledc_timer = { | + | |
| - | .speed_mode | + | |
| - | .timer_num | + | |
| - | .duty_resolution | + | |
| - | .freq_hz | + | |
| - | .clk_cfg | + | |
| - | }; | + | |
| - | esp_err_t ret = ledc_timer_config(& | + | |
| - | if (ret == ESP_OK) { | + | |
| - | printf(" | + | |
| - | // Restore brightness | + | |
| - | set_pwm_brightness(g_pwm_brightness); | + | |
| - | } else { | + | |
| - | printf(" | + | |
| - | } | + | |
| - | } else { | + | |
| - | printf(" | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | static void start_blink(gpio_num_t gpio) | + | |
| - | { | + | |
| - | if (!is_test_safe(gpio)) { | + | |
| - | printf(" | + | |
| - | return; | + | |
| - | } | + | |
| - | + | ||
| - | stop_all(); // Stop any previous mode | + | |
| - | + | ||
| - | g_current_pin = gpio; | + | |
| - | g_blinking = true; | + | |
| - | + | ||
| - | if (xTaskCreatePinnedToCore(blink_task, | + | |
| - | tskIDLE_PRIORITY + 1, & | + | |
| - | printf(" | + | |
| - | g_blinking = false; | + | |
| - | g_current_pin = -1; | + | |
| - | return; | + | |
| - | } | + | |
| - | + | ||
| - | printf(" | + | |
| - | } | + | |
| - | + | ||
| - | static void start_pwm(gpio_num_t gpio, uint8_t brightness) | + | |
| - | { | + | |
| - | if (!is_test_safe(gpio)) { | + | |
| - | printf(" | + | |
| - | return; | + | |
| - | } | + | |
| - | + | ||
| - | stop_all(); // Stop any previous mode | + | |
| - | + | ||
| - | if (!setup_pwm(gpio)) { | + | |
| - | printf(" | + | |
| - | return; | + | |
| - | } | + | |
| - | + | ||
| - | g_current_pin = gpio; | + | |
| - | g_pwm_mode = true; | + | |
| - | set_pwm_brightness(brightness); | + | |
| - | + | ||
| - | printf(" | + | |
| - | } | + | |
| - | + | ||
| - | /* ================== COMMAND PARSER ================== */ | + | |
| - | + | ||
| - | static void trim(char *s) | + | |
| - | { | + | |
| - | size_t len = strlen(s); | + | |
| - | while (len && (s[len-1] == ' | + | |
| - | size_t i = 0; | + | |
| - | while (s[i] && isspace((unsigned char)s[i])) i++; | + | |
| - | if (i) memmove(s, s+i, strlen(s+i)+1); | + | |
| - | } | + | |
| - | + | ||
| - | static bool all_digits(const char *s) | + | |
| - | { | + | |
| - | if (!*s) return false; | + | |
| - | for (const char *p = s; *p; ++p) { | + | |
| - | if (!isdigit((unsigned char)*p)) return false; | + | |
| - | } | + | |
| - | return true; | + | |
| - | } | + | |
| - | + | ||
| - | static void handle_command(char *line) | + | |
| - | { | + | |
| - | trim(line); | + | |
| - | if (!*line) return; | + | |
| - | + | ||
| - | char cmd[64]; | + | |
| - | strncpy(cmd, | + | |
| - | cmd[sizeof(cmd)-1] = 0; | + | |
| - | for (char *p = cmd; *p; ++p) *p = (char)tolower((unsigned char)*p); | + | |
| - | + | ||
| - | if (strcmp(cmd, | + | |
| - | print_test_safe_pins(); | + | |
| - | return; | + | |
| - | } | + | |
| - | if (strcmp(cmd, | + | |
| - | printf(" | + | |
| - | | + | |
| - | if (g_blinking) { | + | |
| - | printf(" | + | |
| - | } else if (g_pwm_mode) { | + | |
| - | printf(" | + | |
| - | | + | |
| - | } else { | + | |
| - | printf(" | + | |
| - | } | + | |
| - | return; | + | |
| - | } | + | |
| - | if (strcmp(cmd, | + | |
| - | stop_all(); | + | |
| - | return; | + | |
| - | } | + | |
| - | if (strncmp(cmd, | + | |
| - | int gpio = atoi(line + 4); | + | |
| - | start_blink((gpio_num_t)gpio); | + | |
| - | return; | + | |
| - | } | + | |
| - | if (strncmp(cmd, | + | |
| - | int v = atoi(line + 6); | + | |
| - | if (v < 10) v = 10; | + | |
| - | g_blink_delay_ms = (uint32_t)v; | + | |
| - | printf(" | + | |
| - | return; | + | |
| - | } | + | |
| - | if (strncmp(cmd, | + | |
| - | // Parse "pwm <pin> < | + | |
| - | char *args = line + 4; | + | |
| - | trim(args); | + | |
| - | + | ||
| - | int gpio = -1, brightness = g_pwm_brightness; | + | |
| - | + | ||
| - | if (sscanf(args, | + | |
| - | if (brightness < 0) brightness = 0; | + | |
| - | if (brightness > 99) brightness = 99; | + | |
| - | start_pwm((gpio_num_t)gpio, | + | |
| - | } else { | + | |
| - | printf(" | + | |
| - | printf(" | + | |
| - | } | + | |
| - | return; | + | |
| - | } | + | |
| - | if (strncmp(cmd, | + | |
| - | // Allow both " | + | |
| - | char *arg = (cmd[6] == ' ') ? line + 7 : line + 11; | + | |
| - | int brightness = atoi(arg); | + | |
| - | if (brightness >= 0 && brightness <= 99) { | + | |
| - | if (g_pwm_mode) { | + | |
| - | set_pwm_brightness((uint8_t)brightness); | + | |
| - | } else { | + | |
| - | printf(" | + | |
| - | } | + | |
| - | } else { | + | |
| - | printf(" | + | |
| - | } | + | |
| - | return; | + | |
| - | } | + | |
| - | if (strncmp(cmd, | + | |
| - | char *arg = (cmd[4] == ' ') ? line + 5 : line + 10; | + | |
| - | int freq = atoi(arg); | + | |
| - | if (freq > 0) { | + | |
| - | set_pwm_frequency((uint32_t)freq); | + | |
| - | } else { | + | |
| - | printf(" | + | |
| - | } | + | |
| - | return; | + | |
| - | } | + | |
| - | if (strcmp(cmd, | + | |
| - | printf(" | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | " | + | |
| - | | + | |
| - | return; | + | |
| - | } | + | |
| - | if (all_digits(line)) { | + | |
| - | start_blink((gpio_num_t)atoi(line)); | + | |
| - | return; | + | |
| - | } | + | |
| - | + | ||
| - | printf(" | + | |
| - | } | + | |
| - | + | ||
| - | /* ================== CONSOLE ================== */ | + | |
| - | static void console_task(void *arg) | + | |
| - | { | + | |
| - | const uart_port_t uart_num = UART_NUM_0; | + | |
| - | + | ||
| - | char | + | |
| - | size_t pos = 0; // length of buffer | + | |
| - | size_t cursor = 0; // cursor index in [0..pos] | + | |
| - | + | ||
| - | char hist[HIST_MAX][CLI_LINE_MAX] = {{0}}; | + | |
| - | int hist_count = 0; // number of valid entries | + | |
| - | int hist_head | + | |
| - | int hist_view | + | |
| - | + | ||
| - | // helpers | + | |
| - | #define WRITE_STR(s) uart_write_bytes(uart_num, | + | |
| - | + | ||
| - | auto void prompt(void) { | + | |
| - | WRITE_STR(" | + | |
| - | fflush(stdout); | + | |
| - | } | + | |
| - | + | ||
| - | auto void redraw_line(void) { | + | |
| - | // Clear line, reprint prompt + buffer, then move cursor left if needed | + | |
| - | WRITE_STR(" | + | |
| - | if (pos) uart_write_bytes(uart_num, | + | |
| - | if (pos > cursor) { | + | |
| - | char seq[16]; int n = snprintf(seq, | + | |
| - | uart_write_bytes(uart_num, | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | auto void push_history(const char *cmd) { | + | |
| - | if (!cmd[0]) return; | + | |
| - | int last = (hist_head - 1 + HIST_MAX) % HIST_MAX; | + | |
| - | if (hist_count > 0 && strncmp(hist[last], | + | |
| - | strncpy(hist[hist_head], | + | |
| - | hist[hist_head][CLI_LINE_MAX - 1] = 0; | + | |
| - | hist_head = (hist_head + 1) % HIST_MAX; | + | |
| - | if (hist_count < HIST_MAX) hist_count++; | + | |
| - | } | + | |
| - | + | ||
| - | auto void load_history(int idx) { | + | |
| - | strncpy(line, | + | |
| - | line[CLI_LINE_MAX - 1] = 0; | + | |
| - | pos = cursor = strlen(line); | + | |
| - | redraw_line(); | + | |
| - | } | + | |
| - | + | ||
| - | auto bool in_history(void) { return hist_view != -1; } | + | |
| - | + | ||
| - | prompt(); | + | |
| - | + | ||
| - | enum { ESC_IDLE, ESC_ESC, ESC_CSI, ESC_TILDE } esc = ESC_IDLE; | + | |
| - | char csi_param_buf[4] = {0}; | + | |
| - | int csi_param_len = 0; | + | |
| - | + | ||
| - | while (1) { | + | |
| - | uint8_t ch; | + | |
| - | int got = uart_read_bytes(uart_num, | + | |
| - | if (got != 1) continue; | + | |
| - | + | ||
| - | // Escape handling (arrows/ | + | |
| - | if (esc == ESC_ESC) { | + | |
| - | if (ch == ' | + | |
| - | // Alt-b / Alt-f (word left/ | + | |
| - | if (ch == ' | + | |
| - | // word-left | + | |
| - | if (cursor > 0) { | + | |
| - | while (cursor > 0 && isspace((unsigned char)line[cursor-1])) cursor--; | + | |
| - | while (cursor > 0 && !isspace((unsigned char)line[cursor-1])) cursor--; | + | |
| - | redraw_line(); | + | |
| - | } | + | |
| - | esc = ESC_IDLE; continue; | + | |
| - | } | + | |
| - | if (ch == ' | + | |
| - | // word-right | + | |
| - | if (cursor < pos) { | + | |
| - | while (cursor < pos && !isspace((unsigned char)line[cursor])) cursor++; | + | |
| - | while (cursor < pos && | + | |
| - | redraw_line(); | + | |
| - | } | + | |
| - | esc = ESC_IDLE; continue; | + | |
| - | } | + | |
| - | // Unknown ESC seq -> ignore | + | |
| - | esc = ESC_IDLE; | + | |
| - | continue; | + | |
| - | } else if (esc == ESC_CSI) { | + | |
| - | if (ch >= ' | + | |
| - | if (csi_param_len < (int)sizeof(csi_param_buf)-1) csi_param_buf[csi_param_len++] = (char)ch; | + | |
| - | continue; | + | |
| - | } | + | |
| - | if (ch == ' | + | |
| - | // Handle [3~ delete, [1~ home, [4~ end | + | |
| - | int p = atoi(csi_param_buf); | + | |
| - | if (p == 3) { // Delete (forward) | + | |
| - | if (cursor < pos) { | + | |
| - | memmove(& | + | |
| - | pos--; | + | |
| - | line[pos] = 0; | + | |
| - | redraw_line(); | + | |
| - | } | + | |
| - | } else if (p == 1) { // Home | + | |
| - | cursor = 0; redraw_line(); | + | |
| - | } else if (p == 4) { // End | + | |
| - | cursor = pos; redraw_line(); | + | |
| - | } | + | |
| - | esc = ESC_IDLE; continue; | + | |
| - | } | + | |
| - | // Final byte for standard arrows/ | + | |
| - | if (ch == ' | + | |
| - | if (hist_count) { | + | |
| - | if (!in_history()) hist_view = (hist_head - 1 + HIST_MAX) % HIST_MAX; | + | |
| - | else { | + | |
| - | int oldest = (hist_head - hist_count + HIST_MAX) % HIST_MAX; | + | |
| - | if (hist_view != oldest) hist_view = (hist_view - 1 + HIST_MAX) % HIST_MAX; | + | |
| - | } | + | |
| - | load_history(hist_view); | + | |
| - | } | + | |
| - | } else if (ch == ' | + | |
| - | if (in_history()) { | + | |
| - | int newest = (hist_head - 1 + HIST_MAX) % HIST_MAX; | + | |
| - | if (hist_view != newest) { hist_view = (hist_view + 1) % HIST_MAX; load_history(hist_view); | + | |
| - | else { hist_view = -1; pos = cursor = 0; line[0] = 0; redraw_line(); | + | |
| - | } | + | |
| - | } else if (ch == ' | + | |
| - | if (cursor < pos) { cursor++; redraw_line(); | + | |
| - | } else if (ch == ' | + | |
| - | if (cursor > 0) { cursor--; redraw_line(); | + | |
| - | } else if (ch == ' | + | |
| - | cursor = 0; redraw_line(); | + | |
| - | } else if (ch == ' | + | |
| - | cursor = pos; redraw_line(); | + | |
| - | } | + | |
| - | esc = ESC_IDLE; | + | |
| - | continue; | + | |
| - | } | + | |
| - | + | ||
| - | // Start of escape? | + | |
| - | if (ch == 0x1B) { esc = ESC_ESC; continue; } | + | |
| - | + | ||
| - | // CR / LF -> execute | + | |
| - | if (ch == ' | + | |
| - | WRITE_STR(" | + | |
| - | line[pos] = 0; | + | |
| - | if (pos) { push_history(line); | + | |
| - | handle_command(line); | + | |
| - | pos = cursor = 0; line[0] = 0; | + | |
| - | prompt(); | + | |
| - | continue; | + | |
| - | } | + | |
| - | + | ||
| - | // Ctrl-A / Ctrl-E: home/end | + | |
| - | if (ch == 0x01) { cursor = 0; redraw_line(); | + | |
| - | if (ch == 0x05) { cursor = pos; redraw_line(); | + | |
| - | + | ||
| - | // Backspace / Delete-left | + | |
| - | if (ch == 0x08 || ch == 0x7F) { | + | |
| - | if (cursor > 0) { | + | |
| - | memmove(& | + | |
| - | cursor--; pos--; | + | |
| - | line[pos] = 0; | + | |
| - | redraw_line(); | + | |
| - | } | + | |
| - | continue; | + | |
| - | } | + | |
| - | + | ||
| - | // Ctrl-U: clear line | + | |
| - | if (ch == 0x15) { | + | |
| - | pos = cursor = 0; line[0] = 0; redraw_line(); | + | |
| - | continue; | + | |
| - | } | + | |
| - | + | ||
| - | // Ctrl-L: redraw | + | |
| - | if (ch == 0x0C) { redraw_line(); | + | |
| - | + | ||
| - | // Ctrl-W: delete previous word | + | |
| - | if (ch == 0x17) { | + | |
| - | size_t start = cursor; | + | |
| - | while (start > 0 && isspace((unsigned char)line[start - 1])) start--; | + | |
| - | while (start > 0 && !isspace((unsigned char)line[start - 1])) start--; | + | |
| - | if (start < cursor) { | + | |
| - | memmove(& | + | |
| - | pos -= (cursor - start); | + | |
| - | cursor = start; | + | |
| - | line[pos] = 0; | + | |
| - | redraw_line(); | + | |
| - | } | + | |
| - | continue; | + | |
| - | } | + | |
| - | + | ||
| - | // Printable ASCII: insert at cursor | + | |
| - | if (isprint(ch)) { | + | |
| - | if (pos + 1 < CLI_LINE_MAX) { | + | |
| - | if (in_history()) { hist_view = -1; /* keep text */ } | + | |
| - | memmove(& | + | |
| - | line[cursor++] = (char)ch; | + | |
| - | pos++; | + | |
| - | line[pos] = 0; | + | |
| - | redraw_line(); | + | |
| - | } | + | |
| - | continue; | + | |
| - | } | + | |
| - | + | ||
| - | // ignore other control bytes | + | |
| - | } | + | |
| - | + | ||
| - | // Prevent task from returning (FreeRTOS requirement) | + | |
| - | while (1) { | + | |
| - | vTaskDelay(pdMS_TO_TICKS(1000)); | + | |
| - | } | + | |
| - | } | + | |
| - | + | ||
| - | /* ================== APP ================== */ | + | |
| - | + | ||
| - | void app_main(void) | + | |
| - | { | + | |
| - | const int baud = 115200; | + | |
| - | const uart_port_t uart_num = UART_NUM_0; | + | |
| - | uart_config_t cfg = { | + | |
| - | .baud_rate = baud, | + | |
| - | .data_bits = UART_DATA_8_BITS, | + | |
| - | .parity | + | |
| - | .stop_bits = UART_STOP_BITS_1, | + | |
| - | .flow_ctrl = UART_HW_FLOWCTRL_DISABLE, | + | |
| - | .source_clk = UART_SCLK_DEFAULT, | + | |
| - | }; | + | |
| - | ESP_ERROR_CHECK(uart_driver_install(uart_num, | + | |
| - | ESP_ERROR_CHECK(uart_param_config(uart_num, | + | |
| - | uart_vfs_dev_use_driver(uart_num); | + | |
| - | uart_vfs_dev_port_set_rx_line_endings(uart_num, | + | |
| - | uart_vfs_dev_port_set_tx_line_endings(uart_num, | + | |
| - | + | ||
| - | vTaskDelay(pdMS_TO_TICKS(200)); | + | |
| - | + | ||
| - | printf(" | + | |
| - | printf(" | + | |
| - | print_test_safe_pins(); | + | |
| - | + | ||
| - | xTaskCreatePinnedToCore(console_task, | + | |
| - | tskIDLE_PRIORITY + 2, NULL, tskNO_AFFINITY); | + | |
| - | + | ||
| - | vTaskDelete(NULL); | + | |
| - | } | + | |
| - | </file> | + | |
| + | Also, you can use Minicom to interact with the tracing code if you'd like. It's just one of the default baudrates, 115200. | ||
| + | <code bash> | ||
| + | minicom -D / | ||
| + | </ | ||
| ===== Arduino (basic version) ===== | ===== Arduino (basic version) ===== | ||