From 94c348b88b6638db74143a889b466f630e9aa301 Mon Sep 17 00:00:00 2001 From: Andrey G Date: Sat, 3 Dec 2022 01:08:11 +0300 Subject: [PATCH] Jdy33 (#171) * tunerstudio: support JDY33 BT module init on UART * tunerstudio: BT: try most popular baudrates first * tunerstudio: BT: protect from overflow * tunerstudio: BT: limit retries * tunerstudio: BT: directly do chprintf() to SD device * TS: serial: make BT setup optional --- .../boards/f1_dual/wideband_board_config.h | 5 + firmware/console/binary/tunerstudio_io.h | 10 +- .../console/binary/tunerstudio_io_serial.cpp | 184 +++++++++++++++++- 3 files changed, 193 insertions(+), 6 deletions(-) diff --git a/firmware/boards/f1_dual/wideband_board_config.h b/firmware/boards/f1_dual/wideband_board_config.h index 590350f..fadd12a 100644 --- a/firmware/boards/f1_dual/wideband_board_config.h +++ b/firmware/boards/f1_dual/wideband_board_config.h @@ -65,3 +65,8 @@ // MAX31855 spi port // ******************************* #define EGT_SPI_DRIVER (&SPID1) + +// Serial connection over BT module +// enable BT module setup attempt +#define BT_SERIAL_OVER_JDY33 TRUE +#define BT_BROADCAST_NAME "RusEFI WBO x2" diff --git a/firmware/console/binary/tunerstudio_io.h b/firmware/console/binary/tunerstudio_io.h index 421171b..85fdb84 100644 --- a/firmware/console/binary/tunerstudio_io.h +++ b/firmware/console/binary/tunerstudio_io.h @@ -136,7 +136,7 @@ class SerialTsChannelBase : public TsChannelBase { public: SerialTsChannelBase(const char *name) : TsChannelBase(name) {}; // Open the serial port with the specified baud rate - virtual void start(uint32_t baud) = 0; + virtual int start(uint32_t baud) = 0; }; #if HAL_USE_SERIAL @@ -145,13 +145,17 @@ class SerialTsChannel : public SerialTsChannelBase { public: SerialTsChannel(SerialDriver& driver) : SerialTsChannelBase("Serial"), m_driver(&driver) { } - void start(uint32_t baud) override; + int start(uint32_t baud) override; void stop() override; void write(const uint8_t* buffer, size_t size, bool isEndOfPacket) override; size_t readTimeout(uint8_t* buffer, size_t size, int timeout) override; private: + int bt_read_line(char *str, size_t max_len); + int bt_wait_ok(void); + int bt_disconnect(void); + SerialDriver* const m_driver; }; #endif // HAL_USE_SERIAL @@ -162,7 +166,7 @@ class UartTsChannel : public SerialTsChannelBase { public: UartTsChannel(UARTDriver& driver) : SerialTsChannelBase("UART"), m_driver(&driver) { } - void start(uint32_t baud) override; + int start(uint32_t baud) override; void stop() override; void write(const uint8_t* buffer, size_t size, bool isEndOfPacket) override; diff --git a/firmware/console/binary/tunerstudio_io_serial.cpp b/firmware/console/binary/tunerstudio_io_serial.cpp index 777c3a6..1e8fc6d 100644 --- a/firmware/console/binary/tunerstudio_io_serial.cpp +++ b/firmware/console/binary/tunerstudio_io_serial.cpp @@ -2,11 +2,63 @@ * Implementation for hardware-serial TunerStudio ports */ +#include + #include "tunerstudio_io.h" #include "hal.h" +#include "chprintf.h" +#include "wideband_config.h" #if HAL_USE_SERIAL -void SerialTsChannel::start(uint32_t baud) { + +#ifndef BT_SERIAL_OVER_JDY33 + #define BT_SERIAL_OVER_JDY33 FALSE +#endif + +#ifndef BT_BROADCAST_NAME + #define BT_BROADCAST_NAME "RusEFI WBO" +#endif + +// JDY-33 has 9: 128000 which we do not +static const unsigned int baudRates[] = { 115200, 9600, 38400, 2400, 4800, 19200, 57600 }; +static const unsigned int baudRateCodes[] = { 8, 4, 6, 2, 3, 5, 7 }; +static const unsigned int btModuleTimeout = TIME_MS2I(100); + +int SerialTsChannel::bt_read_line(char *str, size_t max_len) +{ + size_t i = 0; + + /* read until end of line */ + do { + if (i >= max_len) + return -1; + if (readTimeout((uint8_t *)&str[i], 1, btModuleTimeout) != 1) + return -1; + } while (str[i++] != '\n'); + + return i; +} + +int SerialTsChannel::bt_wait_ok(void) +{ + /* wait for '+OK\r\n' */ + char tmp[6]; + if (readTimeout((uint8_t *)tmp, 5, btModuleTimeout) == 5) { + if (strncmp(tmp, "+OK\r\n", 5) == 0) + return 0; + } + + return -1; +} + +int SerialTsChannel::bt_disconnect(void) +{ + chprintf((BaseSequentialStream *)m_driver, "AT+DISC\r\n"); + + return bt_wait_ok(); +} + +int SerialTsChannel::start(uint32_t baud) { SerialConfig cfg = { .speed = baud, .cr1 = 0, @@ -14,7 +66,131 @@ void SerialTsChannel::start(uint32_t baud) { .cr3 = 0 }; - sdStart(m_driver, &cfg); + if (BT_SERIAL_OVER_JDY33) { + /* try BT setup */ + int retry = 3; + bool done = false; + size_t baudIdx = 0; + + do { + for (baudIdx = 0; baudIdx < 8 && !done; baudIdx++) { + cfg.speed = baudRates[baudIdx]; + baudIdx++; + if (baudIdx == 8) + baudIdx = 0; + sdStart(m_driver, &cfg); + + chprintf((BaseSequentialStream *)m_driver, "AT\r\n"); + if (bt_wait_ok() != 0) { + /* try to diconnect in case device already configured and in silence mode */ + if (bt_disconnect() != 0) { + /* try next baud rate */ + sdStop(m_driver); + continue; + } + } + done = true; + break; + } + } while ((!done) && (--retry)); + + if (retry <= 0) { + return -1; + } + + /* find expected baudrate */ + for (baudIdx = 0; baudIdx < 8; baudIdx++) { + if (baud == baudRates[baudIdx]) { + break; + } + } + if (baudIdx == 8) { + /* unknown baudrate */ + return -1; + } + + int len; + char tmp[64]; + /* setup */ + done = false; + do { + /* just a curious */ + chprintf((BaseSequentialStream *)m_driver, "AT+VERSION\r\n"); + len = bt_read_line(tmp, sizeof(tmp)); + if (len < 0) { + /* retrty */ + continue; + } + + /* Reset settings to defaults */ + chprintf((BaseSequentialStream *)m_driver, "AT+DEFAULT\r\n"); + if (bt_wait_ok() != 0) { + /* retrty */ + continue; + } + + /* SPP Broadcast name: up to 18 bytes */ + chprintf((BaseSequentialStream *)m_driver, "AT+NAME%s\r\n", BT_BROADCAST_NAME); + if (bt_wait_ok() != 0) { + /* retrty */ + continue; + } + + /* BLE Broadcast name: up to 18 bytes */ + chprintf((BaseSequentialStream *)m_driver, "AT+NAMB%s\r\n", BT_BROADCAST_NAME " BLE"); + if (bt_wait_ok() != 0) { + /* retrty */ + continue; + } + + /* SPP connection with no password */ + chprintf((BaseSequentialStream *)m_driver, "AT+TYPE%d\r\n", 0); + if (bt_wait_ok() != 0) { + /* retrty */ + continue; + } + + /* Disable serial port status output */ + chprintf((BaseSequentialStream *)m_driver, "AT+ENLOG%d\r\n", 0); + if (bt_wait_ok() != 0) { + /* retrty */ + continue; + } + + chprintf((BaseSequentialStream *)m_driver, "AT+BAUD%d\r\n", baudRateCodes[baudIdx]); + if (bt_wait_ok() != 0) { + /* retrty */ + continue; + } + + /* BT module changes baud rate here */ + done = true; + } while ((!done) && (--retry)); + + if (retry <= 0) { + return -1; + } + + /* switch baudrate */ + sdStop(m_driver); + cfg.speed = baud; + sdStart(m_driver, &cfg); + + chThdSleepMilliseconds(10); + + /* now reset BT to apply new settings */ + chprintf((BaseSequentialStream *)m_driver, "AT+RESET\r\n", baudRateCodes[baudIdx]); + if (bt_wait_ok() != 0) { + return -1; + } + + /* ready to roll */ + } else { + /* Direct uart connetion */ + sdStart(m_driver, &cfg); + } + + return 0; } void SerialTsChannel::stop() { @@ -31,7 +207,7 @@ size_t SerialTsChannel::readTimeout(uint8_t* buffer, size_t size, int timeout) { #endif // HAL_USE_SERIAL #if (HAL_USE_UART == TRUE) && (UART_USE_WAIT == TRUE) -void UartTsChannel::start(uint32_t baud) { +int UartTsChannel::start(uint32_t baud) { m_config.txend1_cb = NULL; m_config.txend2_cb = NULL; m_config.rxend_cb = NULL; @@ -44,6 +220,8 @@ void UartTsChannel::start(uint32_t baud) { m_config.cr3 = 0; uartStart(m_driver, &m_config); + + return 0; } void UartTsChannel::stop() {