From 9d42fc106150526c354b75aea5db1aabdb10a88d Mon Sep 17 00:00:00 2001 From: Sassa NF Date: Sat, 19 Oct 2024 20:51:43 +0100 Subject: [PATCH] Use onEvent instead of periodic polling --- lib/comms/comms.cpp | 83 ++++++++++++++++++++++++++-------- spectrum_scan.c | 107 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 171 insertions(+), 19 deletions(-) create mode 100644 spectrum_scan.c diff --git a/lib/comms/comms.cpp b/lib/comms/comms.cpp index c350efc..2576f81 100644 --- a/lib/comms/comms.cpp +++ b/lib/comms/comms.cpp @@ -2,25 +2,12 @@ #include #include +#include #include #include Comms *Comms0; -TaskHandle_t monitorSerial = NULL; - -void _onReceive0(); - -void monitorSerialTask(void *) -{ - Serial.println("Spawned a task to monitor Serial.available()"); - for (;;) - { - vTaskDelay(pdMS_TO_TICKS(10)); - _onReceive0(); - } -} - void _onReceive0() { if (Comms0 == NULL) @@ -31,16 +18,27 @@ void _onReceive0() Comms0->_onReceive(); } +void _onUsbEvent0(void *arg, esp_event_base_t event_base, int32_t event_id, + void *event_data) +{ + if (event_base == ARDUINO_HW_CDC_EVENTS) + { + // arduino_hw_cdc_event_data_t *data = (arduino_hw_cdc_event_data_t *)event_data; + if (event_id == ARDUINO_HW_CDC_RX_EVENT) + { + _onReceive0(/*data->rx.len*/); + } + } +} + bool Comms::initComms(Config &c) { if (c.listen_on_usb.equalsIgnoreCase("readline")) { // comms using readline plaintext protocol Comms0 = new ReadlineComms(Serial); - // Serial.onEvent(_onUsbEvent0); - // Serial.begin(); - xTaskCreate(monitorSerialTask, "CHECK_SERIAL_PROCESS", 2048, NULL, 1, - &monitorSerial); + Serial.onEvent(ARDUINO_HW_CDC_RX_EVENT, _onUsbEvent0); + Serial.begin(); Serial.println("Initialized communications on Serial using readline protocol"); @@ -155,7 +153,54 @@ bool ReadlineComms::send(Message &m) p = _scan_result_str(m.payload.dump); break; } - serial.println(p); + + const char *cstr = p.c_str(); + size_t cstr_len = strlen(cstr); + + int loops = 0; + uint64_t t0 = millis(); + uint64_t idle_started = 0; + + for (size_t a = serial.availableForWrite(); a < cstr_len; + a = serial.availableForWrite(), loops++) + { + uint64_t now = millis(); + if (now - t0 > 1000) + { + Serial.printf("Unable to make progress after %d loops; %d bytes available " + "for write, %d chars still to write\n", + loops, a, cstr_len); + break; + } + + if (a == 0) + { + if (idle_started == 0) + { + idle_started = now; + } + + if (now - idle_started > 2) + { + vTaskDelay(pdMS_TO_TICKS(2)); + } + else + { + yield(); + } + continue; + } + + idle_started = 0; + + serial.write(cstr, a); + cstr += a; + cstr_len -= a; + } + serial.println(cstr); + + uint64_t dt = millis() - t0; + Serial.printf("Wrote stuff in %d iterations and %" PRIu64 " ms.\n", loops, dt); return true; } diff --git a/spectrum_scan.c b/spectrum_scan.c new file mode 100644 index 0000000..4cadba6 --- /dev/null +++ b/spectrum_scan.c @@ -0,0 +1,107 @@ +#include +#include +#include +#include +#include + +#define BUFSIZE 102400 +#define LOOPS 200 +int main(int argc, char** argv) +{ + char *port = "/dev/ttyACM0"; + + int device = open(port, O_RDWR | O_NOCTTY | O_SYNC); + + char *scan_ln = "SCAN -1 -1\n"; + char *buffer = malloc(BUFSIZE + 1); + + write(device, scan_ln, strlen(scan_ln)); + + int lines = 0; + int errors = 0; + + int pos = 0; + int progress = 0; + int progress_ln = 0; + + while(lines - errors < LOOPS) + { + if (pos == BUFSIZE) + { + buffer[pos] = 0; + printf("Something went completely wrong: %s\n", buffer); + break; + } + + int n = read(device, buffer + pos, BUFSIZE - pos); + + if (n > 0) + { + n += pos; + buffer[n] = 0; + + char *nl = strchr(buffer + pos, '\n'); + while (nl != NULL) + { + lines++; + + // assert: n points at the first unused byte in buffer + pos = (nl - buffer) + 1; + + char *scan_result = "SCAN_RESULT "; + char is_scan_result = strncmp(buffer, scan_result, strlen(scan_result)) == 0; + + if (is_scan_result) { + if ( + !(buffer[pos-2] == ']' || // that's where it should "normally" appear + buffer[pos-3] == ']') // that's where it actually appears - because HWCDC.println produces \r\n + ) + { + errors++; + } + // assert: pos points at the first byte of the next line + write(1, buffer, pos); + // printf("Last char is: %c\n", buffer[pos-3]); - wow, HWCDC.println ends up producing \r\n + } else if (strncmp(buffer, "Wrote stuff in ", 15) == 0) { + lines--; + write(1, buffer, pos); + } else if (strncmp(buffer, "Unable to make ", 15) == 0) { + lines--; + write(1, buffer, pos); + } else { + errors++; + } + + if (lines > progress_ln) + { + progress_ln = lines + 10; + if (lines - errors > progress) + { + progress = lines - errors; + } + else + { + printf("D'oh! %d lines read, %d errors - no progress\n", lines, errors); + } + } + + n -= pos; + memmove(buffer, nl + 1, n + 1); + // assert: n points at the first unused byte after moving out the parsed line + nl = strchr(buffer, '\n'); + } + + pos = n; + } + } + + char *stop_scan_ln = "SCAN 0 -1\n"; + write(device, stop_scan_ln, strlen(stop_scan_ln)); + close(device); + + free(buffer); + + printf("Read %d lines, got %d errors. Success rate: %.2f\n", + lines, errors, + lines == 0 ? 0.0: 100 - 100.0 * errors / lines); +}