From 70ad31700abc20027e92756ff0b837c2700e5a07 Mon Sep 17 00:00:00 2001 From: ladyada Date: Wed, 8 Jan 2025 09:30:58 -0500 Subject: [PATCH] some tests for uart mode --- .../genericdevice_uartregtest.ino | 237 ++++++++++++++++++ .../genericdevice_uarttest.ino | 67 +++++ 2 files changed, 304 insertions(+) create mode 100644 examples/genericdevice_uartregtest/genericdevice_uartregtest.ino create mode 100644 examples/genericdevice_uarttest/genericdevice_uarttest.ino diff --git a/examples/genericdevice_uartregtest/genericdevice_uartregtest.ino b/examples/genericdevice_uartregtest/genericdevice_uartregtest.ino new file mode 100644 index 0000000..b64389d --- /dev/null +++ b/examples/genericdevice_uartregtest/genericdevice_uartregtest.ino @@ -0,0 +1,237 @@ +#include "Adafruit_BusIO_Register.h" +#include "Adafruit_GenericDevice.h" + +// Debugging macros +//#define DEBUG_SERIAL Serial + +#ifdef DEBUG_SERIAL +#define DEBUG_PRINT(x) DEBUG_SERIAL.print(x) +#define DEBUG_PRINTLN(x) DEBUG_SERIAL.println(x) +#define DEBUG_PRINT_HEX(x) \ + do { \ + if (x < 0x10) \ + DEBUG_SERIAL.print('0'); \ + DEBUG_SERIAL.print(x, HEX); \ + DEBUG_SERIAL.print(' '); \ + } while (0) +#else +#define DEBUG_PRINT(x) +#define DEBUG_PRINTLN(x) +#define DEBUG_PRINT_HEX(x) +#endif + +// Add IOIN register definition +#define TMC2209_IOIN 0x06 + +class TMC2209_UART { +private: + static TMC2209_UART *_instance; + Stream *_uart_stream; + uint8_t _addr; + + static bool uart_read_impl(uint8_t *buffer, size_t len) { + return _instance->uart_read_fn(buffer, len); + } + + static bool uart_write_impl(const uint8_t *buffer, size_t len) { + return _instance->uart_write_fn(buffer, len); + } + + static bool uart_readreg_impl(uint8_t *addr_buf, uint8_t addrsiz, + uint8_t *data, uint16_t datalen) { + return _instance->uart_readreg_fn(addr_buf, addrsiz, data, datalen); + } + + static bool uart_writereg_impl(uint8_t *addr_buf, uint8_t addrsiz, + const uint8_t *data, uint16_t datalen) { + return _instance->uart_writereg_fn(addr_buf, addrsiz, data, datalen); + } + + bool uart_read_fn(uint8_t *buffer, size_t len) { + uint16_t timeout = 100; + while (_uart_stream->available() < len && timeout--) { + delay(1); + } + if (timeout == 0) { + DEBUG_PRINTLN("Read timeout!"); + return false; + } + + DEBUG_PRINT("Reading: "); + for (size_t i = 0; i < len; i++) { + buffer[i] = _uart_stream->read(); + DEBUG_PRINT_HEX(buffer[i]); + } + DEBUG_PRINTLN(""); + + return true; + } + + bool uart_write_fn(const uint8_t *buffer, size_t len) { + DEBUG_PRINT("Writing: "); + for (size_t i = 0; i < len; i++) { + DEBUG_PRINT_HEX(buffer[i]); + } + DEBUG_PRINTLN(""); + + _uart_stream->write(buffer, len); + return true; + } + + bool uart_readreg_fn(uint8_t *addr_buf, uint8_t addrsiz, uint8_t *data, + uint16_t datalen) { + while (_uart_stream->available()) + _uart_stream->read(); + + uint8_t packet[4] = {0x05, uint8_t(_addr << 1), addr_buf[0], 0x00}; + + packet[3] = calcCRC(packet, 3); + if (!uart_write_impl(packet, 4)) + return false; + + // Read back echo + uint8_t echo[4]; + if (!uart_read_impl(echo, 4)) + return false; + + // Verify echo + for (uint8_t i = 0; i < 4; i++) { + if (echo[i] != packet[i]) { + DEBUG_PRINTLN("Echo mismatch"); + return false; + } + } + + uint8_t response[8]; // sync + 0xFF + reg + 4 data bytes + CRC + if (!uart_read_impl(response, 8)) + return false; + + // Verify response + if (response[0] != 0x05) { + DEBUG_PRINTLN("Invalid sync byte"); + return false; + } + + // Verify 0xFF address byte + if (response[1] != 0xFF) { + DEBUG_PRINTLN("Invalid reply address"); + return false; + } + + // Verify register address matches our request + if (response[2] != addr_buf[0]) { + DEBUG_PRINTLN("Register mismatch"); + return false; + } + + // Verify CRC + uint8_t crc = calcCRC(response, 7); // Calculate CRC of all but last byte + if (crc != response[7]) { + DEBUG_PRINTLN("CRC mismatch"); + return false; + } + + // Copy the data bytes + memcpy(data, &response[3], 4); + + return true; + } + + bool uart_writereg_fn(uint8_t *addr_buf, uint8_t addrsiz, const uint8_t *data, + uint16_t datalen) { + while (_uart_stream->available()) + _uart_stream->read(); + + uint8_t packet[8] = {0x05, + uint8_t(_addr << 1), + uint8_t(addr_buf[0] | 0x80), + data[0], + data[1], + data[2], + data[3], + 0x00}; + + packet[7] = calcCRC(packet, 7); + if (!uart_write_impl(packet, 8)) + return false; + + // Read and verify echo + uint8_t echo[8]; + if (!uart_read_impl(echo, 8)) + return false; + + // Verify echo matches what we sent + for (uint8_t i = 0; i < 8; i++) { + if (echo[i] != packet[i]) { + DEBUG_PRINTLN("Write echo mismatch"); + return false; + } + } + + return true; + } + + static uint8_t calcCRC(uint8_t *data, uint8_t length) { + uint8_t crc = 0; + for (uint8_t i = 0; i < length; i++) { + uint8_t currentByte = data[i]; + for (uint8_t j = 0; j < 8; j++) { + if ((crc >> 7) ^ (currentByte & 0x01)) { + crc = (crc << 1) ^ 0x07; + } else { + crc = crc << 1; + } + currentByte = currentByte >> 1; + } + } + return crc; + } + +public: + TMC2209_UART(Stream *serial, uint8_t addr) + : _uart_stream(serial), _addr(addr) { + _instance = this; + } + + Adafruit_GenericDevice *createDevice() { + return new Adafruit_GenericDevice(uart_read_impl, uart_write_impl, + uart_readreg_impl, uart_writereg_impl); + } +}; + +TMC2209_UART *TMC2209_UART::_instance = nullptr; + +void setup() { + Serial.begin(115200); + while (!Serial) + ; + delay(100); + Serial.println("TMC2209 Generic Device register read/write test!"); + + Serial2.begin(115200); + + TMC2209_UART uart(&Serial2, 0); + Adafruit_GenericDevice *device = uart.createDevice(); + device->begin(); + + // Create register object for IOIN + Adafruit_BusIO_Register ioin_reg(device, + TMC2209_IOIN, // device and register address + 4, // width = 4 bytes + MSBFIRST, // byte order + 1); // address width = 1 byte + Serial.print("IOIN = 0x"); + Serial.println(ioin_reg.read(), HEX); + + // Create RegisterBits for VERSION field (bits 28:24) + Adafruit_BusIO_RegisterBits version_bits( + &ioin_reg, 8, 24); // 8 bits wide, starting at bit 24 + + Serial.println("Reading VERSION..."); + uint8_t version = version_bits.read(); + + Serial.print("VERSION = 0x"); + Serial.println(version, HEX); +} + +void loop() { delay(1000); } diff --git a/examples/genericdevice_uarttest/genericdevice_uarttest.ino b/examples/genericdevice_uarttest/genericdevice_uarttest.ino new file mode 100644 index 0000000..d943291 --- /dev/null +++ b/examples/genericdevice_uarttest/genericdevice_uarttest.ino @@ -0,0 +1,67 @@ +#include "Adafruit_GenericDevice.h" + +Stream *uart_stream; // Will hold the pointer to our Stream object + +Adafruit_GenericDevice *create_uart_device(Stream *serial_port) { + uart_stream = serial_port; // Store the Stream pointer + + auto uart_write = [](const uint8_t *buffer, size_t len) -> bool { + uart_stream->write(buffer, len); + return true; + }; + + auto uart_read = [](uint8_t *buffer, size_t len) -> bool { + uint16_t timeout = 100; + while (uart_stream->available() < len && timeout--) { + delay(1); + } + if (timeout == 0) { + return false; + } + for (size_t i = 0; i < len; i++) { + buffer[i] = uart_stream->read(); + } + return true; + }; + + return new Adafruit_GenericDevice(uart_read, uart_write); +} + +void setup() { + Serial.begin(115200); + while (!Serial) + ; + delay(100); + + Serial.println("Generic Device test!"); + + Serial2.begin(115200); + + Adafruit_GenericDevice *device = create_uart_device(&Serial2); + device->begin(); + + uint8_t write_buf[4] = {0x5, 0x0, 0x0, 0x48}; + uint8_t read_buf[8]; + + Serial.println("Writing data..."); + if (!device->write(write_buf, 4)) { + Serial.println("Write failed!"); + return; + } + + Serial.println("Reading response..."); + if (!device->read(read_buf, 8)) { + Serial.println("Read failed!"); + return; + } + + Serial.print("Got response: "); + for (int i = 0; i < 8; i++) { + Serial.print("0x"); + Serial.print(read_buf[i], HEX); + Serial.print(" "); + } + Serial.println(); +} + +void loop() { delay(1000); }