From c43db9d7c2c48cfd3e4923732682a79f991e596a Mon Sep 17 00:00:00 2001 From: ladyada Date: Tue, 7 Jan 2025 22:03:15 -0500 Subject: [PATCH 1/8] still need to doxy/clang --- Adafruit_BusIO_Register.cpp | 103 +++++++++++++++++++++--------------- Adafruit_BusIO_Register.h | 6 +++ Adafruit_GenericDevice.cpp | 45 ++++++++++++++++ Adafruit_GenericDevice.h | 37 +++++++++++++ 4 files changed, 148 insertions(+), 43 deletions(-) create mode 100644 Adafruit_GenericDevice.cpp create mode 100644 Adafruit_GenericDevice.h diff --git a/Adafruit_BusIO_Register.cpp b/Adafruit_BusIO_Register.cpp index a28193f..6099431 100644 --- a/Adafruit_BusIO_Register.cpp +++ b/Adafruit_BusIO_Register.cpp @@ -88,6 +88,29 @@ Adafruit_BusIO_Register::Adafruit_BusIO_Register( _width = width; } +/*! +* @brief Create a register we access over a GenericDevice +* @param genericdevice Generic device to use +* @param reg_addr Register address we will read/write +* @param width Width of the register in bytes (1-4) +* @param byteorder Byte order of register data (LSBFIRST or MSBFIRST) +* @param address_width Width of the register address in bytes (1 or 2) +*/ +Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_GenericDevice *genericdevice, + uint16_t reg_addr, + uint8_t width, + uint8_t byteorder, + uint8_t address_width) { + _i2cdevice = nullptr; + _spidevice = nullptr; + _genericdevice = genericdevice; + _addrwidth = address_width; + _address = reg_addr; + _byteorder = byteorder; + _width = width; +} + + /*! * @brief Write a buffer of data to the register location * @param buffer Pointer to data to write @@ -96,17 +119,14 @@ Adafruit_BusIO_Register::Adafruit_BusIO_Register( * uncheckable) */ bool Adafruit_BusIO_Register::write(uint8_t *buffer, uint8_t len) { - uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF), (uint8_t)(_address >> 8)}; - if (_i2cdevice) { return _i2cdevice->write(buffer, len, true, addrbuffer, _addrwidth); } if (_spidevice) { if (_spiregtype == ADDRESSED_OPCODE_BIT0_LOW_TO_WRITE) { // very special case! - // pass the special opcode address which we set as the high byte of the // regaddr addrbuffer[0] = @@ -116,7 +136,6 @@ bool Adafruit_BusIO_Register::write(uint8_t *buffer, uint8_t len) { // the address appears to be a byte longer return _spidevice->write(buffer, len, addrbuffer, _addrwidth + 1); } - if (_spiregtype == ADDRBIT8_HIGH_TOREAD) { addrbuffer[0] &= ~0x80; } @@ -129,6 +148,9 @@ bool Adafruit_BusIO_Register::write(uint8_t *buffer, uint8_t len) { } return _spidevice->write(buffer, len, addrbuffer, _addrwidth); } + if (_genericdevice) { + return _genericdevice->writeRegister(addrbuffer, _addrwidth, buffer, len); + } return false; } @@ -191,48 +213,43 @@ uint32_t Adafruit_BusIO_Register::read(void) { */ uint32_t Adafruit_BusIO_Register::readCached(void) { return _cached; } -/*! - * @brief Read a buffer of data from the register location - * @param buffer Pointer to data to read into - * @param len Number of bytes to read - * @return True on successful write (only really useful for I2C as SPI is - * uncheckable) - */ bool Adafruit_BusIO_Register::read(uint8_t *buffer, uint8_t len) { - uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF), - (uint8_t)(_address >> 8)}; - - if (_i2cdevice) { - return _i2cdevice->write_then_read(addrbuffer, _addrwidth, buffer, len); - } - if (_spidevice) { - if (_spiregtype == ADDRESSED_OPCODE_BIT0_LOW_TO_WRITE) { - // very special case! - - // pass the special opcode address which we set as the high byte of the - // regaddr - addrbuffer[0] = - (uint8_t)(_address >> 8) | 0x01; // set bottom bit high to read - // the 'actual' reg addr is the second byte then - addrbuffer[1] = (uint8_t)(_address & 0xFF); - // the address appears to be a byte longer - return _spidevice->write_then_read(addrbuffer, _addrwidth + 1, buffer, - len); - } - if (_spiregtype == ADDRBIT8_HIGH_TOREAD) { - addrbuffer[0] |= 0x80; - } - if (_spiregtype == ADDRBIT8_HIGH_TOWRITE) { - addrbuffer[0] &= ~0x80; - } - if (_spiregtype == AD8_HIGH_TOREAD_AD7_HIGH_TOINC) { - addrbuffer[0] |= 0x80 | 0x40; - } - return _spidevice->write_then_read(addrbuffer, _addrwidth, buffer, len); - } - return false; + uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF), + (uint8_t)(_address >> 8)}; + if (_i2cdevice) { + return _i2cdevice->write_then_read(addrbuffer, _addrwidth, buffer, len); + } + if (_spidevice) { + if (_spiregtype == ADDRESSED_OPCODE_BIT0_LOW_TO_WRITE) { + // very special case! + // pass the special opcode address which we set as the high byte of the + // regaddr + addrbuffer[0] = + (uint8_t)(_address >> 8) | 0x01; // set bottom bit high to read + // the 'actual' reg addr is the second byte then + addrbuffer[1] = (uint8_t)(_address & 0xFF); + // the address appears to be a byte longer + return _spidevice->write_then_read(addrbuffer, _addrwidth + 1, buffer, + len); + } + if (_spiregtype == ADDRBIT8_HIGH_TOREAD) { + addrbuffer[0] |= 0x80; + } + if (_spiregtype == ADDRBIT8_HIGH_TOWRITE) { + addrbuffer[0] &= ~0x80; + } + if (_spiregtype == AD8_HIGH_TOREAD_AD7_HIGH_TOINC) { + addrbuffer[0] |= 0x80 | 0x40; + } + return _spidevice->write_then_read(addrbuffer, _addrwidth, buffer, len); + } + if (_genericdevice) { + return _genericdevice->readRegister(addrbuffer, _addrwidth, buffer, len); + } + return false; } + /*! * @brief Read 2 bytes of data from the register location * @param value Pointer to uint16_t variable to read into diff --git a/Adafruit_BusIO_Register.h b/Adafruit_BusIO_Register.h index c6d58de..cd7f18a 100644 --- a/Adafruit_BusIO_Register.h +++ b/Adafruit_BusIO_Register.h @@ -8,6 +8,7 @@ #include #include +#include typedef enum _Adafruit_BusIO_SPIRegType { ADDRBIT8_HIGH_TOREAD = 0, @@ -57,6 +58,10 @@ class Adafruit_BusIO_Register { uint8_t width = 1, uint8_t byteorder = LSBFIRST, uint8_t address_width = 1); + Adafruit_BusIO_Register(Adafruit_GenericDevice *genericdevice, uint16_t reg_addr, + uint8_t width = 1, uint8_t byteorder = LSBFIRST, + uint8_t address_width = 1); + bool read(uint8_t *buffer, uint8_t len); bool read(uint8_t *value); bool read(uint16_t *value); @@ -77,6 +82,7 @@ class Adafruit_BusIO_Register { private: Adafruit_I2CDevice *_i2cdevice; Adafruit_SPIDevice *_spidevice; + Adafruit_GenericDevice *_genericdevice; Adafruit_BusIO_SPIRegType _spiregtype; uint16_t _address; uint8_t _width, _addrwidth, _byteorder; diff --git a/Adafruit_GenericDevice.cpp b/Adafruit_GenericDevice.cpp new file mode 100644 index 0000000..d41ec88 --- /dev/null +++ b/Adafruit_GenericDevice.cpp @@ -0,0 +1,45 @@ +#include "Adafruit_GenericDevice.h" + +Adafruit_GenericDevice::Adafruit_GenericDevice(busio_genericdevice_read_t read_func, + busio_genericdevice_write_t write_func, + busio_genericdevice_readreg_t readreg_func, + busio_genericdevice_writereg_t writereg_func) { + _read_func = read_func; + _write_func = write_func; + _readreg_func = readreg_func; + _writereg_func = writereg_func; + _begun = false; +} + +bool Adafruit_GenericDevice::begin(void) { + _begun = true; + return true; +} + +bool Adafruit_GenericDevice::write(const uint8_t *buffer, size_t len) { + if (!_begun) + return false; + + return _write_func(buffer, len); +} + +bool Adafruit_GenericDevice::read(uint8_t *buffer, size_t len) { + if (!_begun) + return false; + + return _read_func(buffer, len); +} + +bool Adafruit_GenericDevice::readRegister(uint8_t *addr_buf, uint8_t addrsiz, uint8_t *buf, uint16_t bufsiz) { + if (!_begun || !_readreg_func) + return false; + + return _readreg_func(addr_buf, addrsiz, buf, bufsiz); +} + +bool Adafruit_GenericDevice::writeRegister(uint8_t *addr_buf, uint8_t addrsiz, const uint8_t *buf, uint16_t bufsiz) { + if (!_begun || !_writereg_func) + return false; + + return _writereg_func(addr_buf, addrsiz, buf, bufsiz); +} diff --git a/Adafruit_GenericDevice.h b/Adafruit_GenericDevice.h new file mode 100644 index 0000000..ef84110 --- /dev/null +++ b/Adafruit_GenericDevice.h @@ -0,0 +1,37 @@ +#ifndef ADAFRUIT_GENERICDEVICE_H +#define ADAFRUIT_GENERICDEVICE_H + +#include + +typedef bool (*busio_genericdevice_read_t)(uint8_t *buffer, size_t len); +typedef bool (*busio_genericdevice_write_t)(const uint8_t *buffer, size_t len); +typedef bool (*busio_genericdevice_readreg_t)(uint8_t *addr_buf, uint8_t addrsiz, uint8_t *buf, uint16_t bufsiz); +typedef bool (*busio_genericdevice_writereg_t)(uint8_t *addr_buf, uint8_t addrsiz, const uint8_t *buf, uint16_t bufsiz); + +/*! + * @brief Class for communicating with a device via generic read/write functions + */ +class Adafruit_GenericDevice { +public: + Adafruit_GenericDevice(busio_genericdevice_read_t read_func, + busio_genericdevice_write_t write_func, + busio_genericdevice_readreg_t readreg_func = nullptr, + busio_genericdevice_writereg_t writereg_func = nullptr); + + bool begin(void); + + bool read(uint8_t *buffer, size_t len); + bool write(const uint8_t *buffer, size_t len); + bool readRegister(uint8_t *addr_buf, uint8_t addrsiz, uint8_t *buf, uint16_t bufsiz); + bool writeRegister(uint8_t *addr_buf, uint8_t addrsiz, const uint8_t *buf, uint16_t bufsiz); + +protected: + busio_genericdevice_read_t _read_func; + busio_genericdevice_write_t _write_func; + busio_genericdevice_readreg_t _readreg_func; + busio_genericdevice_writereg_t _writereg_func; + + bool _begun; +}; + +#endif // ADAFRUIT_GENERICDEVICE_H From 66448b37ecdebf48cdcb292c5398a83a9956121e Mon Sep 17 00:00:00 2001 From: ladyada Date: Tue, 7 Jan 2025 22:08:13 -0500 Subject: [PATCH 2/8] clang --- Adafruit_BusIO_Register.cpp | 104 +++++++++++++++++------------------- Adafruit_BusIO_Register.h | 7 +-- Adafruit_GenericDevice.cpp | 50 +++++++++-------- Adafruit_GenericDevice.h | 30 +++++++---- 4 files changed, 100 insertions(+), 91 deletions(-) diff --git a/Adafruit_BusIO_Register.cpp b/Adafruit_BusIO_Register.cpp index 6099431..86d13a9 100644 --- a/Adafruit_BusIO_Register.cpp +++ b/Adafruit_BusIO_Register.cpp @@ -89,28 +89,25 @@ Adafruit_BusIO_Register::Adafruit_BusIO_Register( } /*! -* @brief Create a register we access over a GenericDevice -* @param genericdevice Generic device to use -* @param reg_addr Register address we will read/write -* @param width Width of the register in bytes (1-4) -* @param byteorder Byte order of register data (LSBFIRST or MSBFIRST) -* @param address_width Width of the register address in bytes (1 or 2) -*/ -Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_GenericDevice *genericdevice, - uint16_t reg_addr, - uint8_t width, - uint8_t byteorder, - uint8_t address_width) { - _i2cdevice = nullptr; - _spidevice = nullptr; - _genericdevice = genericdevice; - _addrwidth = address_width; - _address = reg_addr; - _byteorder = byteorder; - _width = width; + * @brief Create a register we access over a GenericDevice + * @param genericdevice Generic device to use + * @param reg_addr Register address we will read/write + * @param width Width of the register in bytes (1-4) + * @param byteorder Byte order of register data (LSBFIRST or MSBFIRST) + * @param address_width Width of the register address in bytes (1 or 2) + */ +Adafruit_BusIO_Register::Adafruit_BusIO_Register( + Adafruit_GenericDevice *genericdevice, uint16_t reg_addr, uint8_t width, + uint8_t byteorder, uint8_t address_width) { + _i2cdevice = nullptr; + _spidevice = nullptr; + _genericdevice = genericdevice; + _addrwidth = address_width; + _address = reg_addr; + _byteorder = byteorder; + _width = width; } - /*! * @brief Write a buffer of data to the register location * @param buffer Pointer to data to write @@ -214,42 +211,41 @@ uint32_t Adafruit_BusIO_Register::read(void) { uint32_t Adafruit_BusIO_Register::readCached(void) { return _cached; } bool Adafruit_BusIO_Register::read(uint8_t *buffer, uint8_t len) { - uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF), - (uint8_t)(_address >> 8)}; - if (_i2cdevice) { - return _i2cdevice->write_then_read(addrbuffer, _addrwidth, buffer, len); - } - if (_spidevice) { - if (_spiregtype == ADDRESSED_OPCODE_BIT0_LOW_TO_WRITE) { - // very special case! - // pass the special opcode address which we set as the high byte of the - // regaddr - addrbuffer[0] = - (uint8_t)(_address >> 8) | 0x01; // set bottom bit high to read - // the 'actual' reg addr is the second byte then - addrbuffer[1] = (uint8_t)(_address & 0xFF); - // the address appears to be a byte longer - return _spidevice->write_then_read(addrbuffer, _addrwidth + 1, buffer, - len); - } - if (_spiregtype == ADDRBIT8_HIGH_TOREAD) { - addrbuffer[0] |= 0x80; - } - if (_spiregtype == ADDRBIT8_HIGH_TOWRITE) { - addrbuffer[0] &= ~0x80; - } - if (_spiregtype == AD8_HIGH_TOREAD_AD7_HIGH_TOINC) { - addrbuffer[0] |= 0x80 | 0x40; - } - return _spidevice->write_then_read(addrbuffer, _addrwidth, buffer, len); - } - if (_genericdevice) { - return _genericdevice->readRegister(addrbuffer, _addrwidth, buffer, len); - } - return false; + uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF), + (uint8_t)(_address >> 8)}; + if (_i2cdevice) { + return _i2cdevice->write_then_read(addrbuffer, _addrwidth, buffer, len); + } + if (_spidevice) { + if (_spiregtype == ADDRESSED_OPCODE_BIT0_LOW_TO_WRITE) { + // very special case! + // pass the special opcode address which we set as the high byte of the + // regaddr + addrbuffer[0] = + (uint8_t)(_address >> 8) | 0x01; // set bottom bit high to read + // the 'actual' reg addr is the second byte then + addrbuffer[1] = (uint8_t)(_address & 0xFF); + // the address appears to be a byte longer + return _spidevice->write_then_read(addrbuffer, _addrwidth + 1, buffer, + len); + } + if (_spiregtype == ADDRBIT8_HIGH_TOREAD) { + addrbuffer[0] |= 0x80; + } + if (_spiregtype == ADDRBIT8_HIGH_TOWRITE) { + addrbuffer[0] &= ~0x80; + } + if (_spiregtype == AD8_HIGH_TOREAD_AD7_HIGH_TOINC) { + addrbuffer[0] |= 0x80 | 0x40; + } + return _spidevice->write_then_read(addrbuffer, _addrwidth, buffer, len); + } + if (_genericdevice) { + return _genericdevice->readRegister(addrbuffer, _addrwidth, buffer, len); + } + return false; } - /*! * @brief Read 2 bytes of data from the register location * @param value Pointer to uint16_t variable to read into diff --git a/Adafruit_BusIO_Register.h b/Adafruit_BusIO_Register.h index cd7f18a..ee7a57e 100644 --- a/Adafruit_BusIO_Register.h +++ b/Adafruit_BusIO_Register.h @@ -6,9 +6,9 @@ #if !defined(SPI_INTERFACES_COUNT) || \ (defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0)) +#include #include #include -#include typedef enum _Adafruit_BusIO_SPIRegType { ADDRBIT8_HIGH_TOREAD = 0, @@ -58,8 +58,9 @@ class Adafruit_BusIO_Register { uint8_t width = 1, uint8_t byteorder = LSBFIRST, uint8_t address_width = 1); - Adafruit_BusIO_Register(Adafruit_GenericDevice *genericdevice, uint16_t reg_addr, - uint8_t width = 1, uint8_t byteorder = LSBFIRST, + Adafruit_BusIO_Register(Adafruit_GenericDevice *genericdevice, + uint16_t reg_addr, uint8_t width = 1, + uint8_t byteorder = LSBFIRST, uint8_t address_width = 1); bool read(uint8_t *buffer, uint8_t len); diff --git a/Adafruit_GenericDevice.cpp b/Adafruit_GenericDevice.cpp index d41ec88..917d96f 100644 --- a/Adafruit_GenericDevice.cpp +++ b/Adafruit_GenericDevice.cpp @@ -1,45 +1,49 @@ #include "Adafruit_GenericDevice.h" -Adafruit_GenericDevice::Adafruit_GenericDevice(busio_genericdevice_read_t read_func, - busio_genericdevice_write_t write_func, - busio_genericdevice_readreg_t readreg_func, - busio_genericdevice_writereg_t writereg_func) { - _read_func = read_func; - _write_func = write_func; - _readreg_func = readreg_func; - _writereg_func = writereg_func; - _begun = false; +Adafruit_GenericDevice::Adafruit_GenericDevice( + busio_genericdevice_read_t read_func, + busio_genericdevice_write_t write_func, + busio_genericdevice_readreg_t readreg_func, + busio_genericdevice_writereg_t writereg_func) { + _read_func = read_func; + _write_func = write_func; + _readreg_func = readreg_func; + _writereg_func = writereg_func; + _begun = false; } bool Adafruit_GenericDevice::begin(void) { - _begun = true; - return true; + _begun = true; + return true; } bool Adafruit_GenericDevice::write(const uint8_t *buffer, size_t len) { - if (!_begun) - return false; - - return _write_func(buffer, len); + if (!_begun) + return false; + + return _write_func(buffer, len); } bool Adafruit_GenericDevice::read(uint8_t *buffer, size_t len) { - if (!_begun) - return false; - - return _read_func(buffer, len); + if (!_begun) + return false; + + return _read_func(buffer, len); } -bool Adafruit_GenericDevice::readRegister(uint8_t *addr_buf, uint8_t addrsiz, uint8_t *buf, uint16_t bufsiz) { +bool Adafruit_GenericDevice::readRegister(uint8_t *addr_buf, uint8_t addrsiz, + uint8_t *buf, uint16_t bufsiz) { if (!_begun || !_readreg_func) return false; - + return _readreg_func(addr_buf, addrsiz, buf, bufsiz); } -bool Adafruit_GenericDevice::writeRegister(uint8_t *addr_buf, uint8_t addrsiz, const uint8_t *buf, uint16_t bufsiz) { +bool Adafruit_GenericDevice::writeRegister(uint8_t *addr_buf, uint8_t addrsiz, + const uint8_t *buf, + uint16_t bufsiz) { if (!_begun || !_writereg_func) return false; - + return _writereg_func(addr_buf, addrsiz, buf, bufsiz); } diff --git a/Adafruit_GenericDevice.h b/Adafruit_GenericDevice.h index ef84110..3cb8c5d 100644 --- a/Adafruit_GenericDevice.h +++ b/Adafruit_GenericDevice.h @@ -5,32 +5,40 @@ typedef bool (*busio_genericdevice_read_t)(uint8_t *buffer, size_t len); typedef bool (*busio_genericdevice_write_t)(const uint8_t *buffer, size_t len); -typedef bool (*busio_genericdevice_readreg_t)(uint8_t *addr_buf, uint8_t addrsiz, uint8_t *buf, uint16_t bufsiz); -typedef bool (*busio_genericdevice_writereg_t)(uint8_t *addr_buf, uint8_t addrsiz, const uint8_t *buf, uint16_t bufsiz); +typedef bool (*busio_genericdevice_readreg_t)(uint8_t *addr_buf, + uint8_t addrsiz, uint8_t *buf, + uint16_t bufsiz); +typedef bool (*busio_genericdevice_writereg_t)(uint8_t *addr_buf, + uint8_t addrsiz, + const uint8_t *buf, + uint16_t bufsiz); /*! * @brief Class for communicating with a device via generic read/write functions */ class Adafruit_GenericDevice { public: - Adafruit_GenericDevice(busio_genericdevice_read_t read_func, - busio_genericdevice_write_t write_func, - busio_genericdevice_readreg_t readreg_func = nullptr, - busio_genericdevice_writereg_t writereg_func = nullptr); - + Adafruit_GenericDevice( + busio_genericdevice_read_t read_func, + busio_genericdevice_write_t write_func, + busio_genericdevice_readreg_t readreg_func = nullptr, + busio_genericdevice_writereg_t writereg_func = nullptr); + bool begin(void); - + bool read(uint8_t *buffer, size_t len); bool write(const uint8_t *buffer, size_t len); - bool readRegister(uint8_t *addr_buf, uint8_t addrsiz, uint8_t *buf, uint16_t bufsiz); - bool writeRegister(uint8_t *addr_buf, uint8_t addrsiz, const uint8_t *buf, uint16_t bufsiz); + bool readRegister(uint8_t *addr_buf, uint8_t addrsiz, uint8_t *buf, + uint16_t bufsiz); + bool writeRegister(uint8_t *addr_buf, uint8_t addrsiz, const uint8_t *buf, + uint16_t bufsiz); protected: busio_genericdevice_read_t _read_func; busio_genericdevice_write_t _write_func; busio_genericdevice_readreg_t _readreg_func; busio_genericdevice_writereg_t _writereg_func; - + bool _begun; }; From c602ea03e00188d86f97b1315d00053b413373ba Mon Sep 17 00:00:00 2001 From: ladyada Date: Wed, 8 Jan 2025 09:29:49 -0500 Subject: [PATCH 3/8] doxyclanged! --- Adafruit_BusIO_Register.cpp | 6 ++++++ Adafruit_GenericDevice.cpp | 31 +++++++++++++++++++++++++++---- Adafruit_GenericDevice.h | 7 ++++++- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/Adafruit_BusIO_Register.cpp b/Adafruit_BusIO_Register.cpp index 86d13a9..f3e8187 100644 --- a/Adafruit_BusIO_Register.cpp +++ b/Adafruit_BusIO_Register.cpp @@ -210,6 +210,12 @@ uint32_t Adafruit_BusIO_Register::read(void) { */ uint32_t Adafruit_BusIO_Register::readCached(void) { return _cached; } +/*! + @brief Read a number of bytes from a register into a buffer + @param buffer Buffer to read data into + @param len Number of bytes to read into the buffer + @return true on successful read, otherwise false +*/ bool Adafruit_BusIO_Register::read(uint8_t *buffer, uint8_t len) { uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF), (uint8_t)(_address >> 8)}; diff --git a/Adafruit_GenericDevice.cpp b/Adafruit_GenericDevice.cpp index 917d96f..b0d8824 100644 --- a/Adafruit_GenericDevice.cpp +++ b/Adafruit_GenericDevice.cpp @@ -1,5 +1,10 @@ #include "Adafruit_GenericDevice.h" +/*! @brief Create a Generic device with the provided read/write functions + @param read_func Function pointer for reading raw data + @param write_func Function pointer for writing raw data + @param readreg_func Function pointer for reading registers (optional) + @param writereg_func Function pointer for writing registers (optional) */ Adafruit_GenericDevice::Adafruit_GenericDevice( busio_genericdevice_read_t read_func, busio_genericdevice_write_t write_func, @@ -12,38 +17,56 @@ Adafruit_GenericDevice::Adafruit_GenericDevice( _begun = false; } +/*! @brief Initializes the device + @return true if initialization was successful, otherwise false */ bool Adafruit_GenericDevice::begin(void) { _begun = true; return true; } +/*! @brief Write a buffer of data + @param buffer Pointer to buffer of data to write + @param len Number of bytes to write + @return true if write was successful, otherwise false */ bool Adafruit_GenericDevice::write(const uint8_t *buffer, size_t len) { if (!_begun) return false; - return _write_func(buffer, len); } +/*! @brief Read data into a buffer + @param buffer Pointer to buffer to read data into + @param len Number of bytes to read + @return true if read was successful, otherwise false */ bool Adafruit_GenericDevice::read(uint8_t *buffer, size_t len) { if (!_begun) return false; - return _read_func(buffer, len); } +/*! @brief Read from a register location + @param addr_buf Buffer containing register address + @param addrsiz Size of register address in bytes + @param buf Buffer to store read data + @param bufsiz Size of data to read in bytes + @return true if read was successful, otherwise false */ bool Adafruit_GenericDevice::readRegister(uint8_t *addr_buf, uint8_t addrsiz, uint8_t *buf, uint16_t bufsiz) { if (!_begun || !_readreg_func) return false; - return _readreg_func(addr_buf, addrsiz, buf, bufsiz); } +/*! @brief Write to a register location + @param addr_buf Buffer containing register address + @param addrsiz Size of register address in bytes + @param buf Buffer containing data to write + @param bufsiz Size of data to write in bytes + @return true if write was successful, otherwise false */ bool Adafruit_GenericDevice::writeRegister(uint8_t *addr_buf, uint8_t addrsiz, const uint8_t *buf, uint16_t bufsiz) { if (!_begun || !_writereg_func) return false; - return _writereg_func(addr_buf, addrsiz, buf, bufsiz); } diff --git a/Adafruit_GenericDevice.h b/Adafruit_GenericDevice.h index 3cb8c5d..7dd032f 100644 --- a/Adafruit_GenericDevice.h +++ b/Adafruit_GenericDevice.h @@ -34,12 +34,17 @@ class Adafruit_GenericDevice { uint16_t bufsiz); protected: + /*! @brief Function pointer for reading raw data from the device */ busio_genericdevice_read_t _read_func; + /*! @brief Function pointer for writing raw data to the device */ busio_genericdevice_write_t _write_func; + /*! @brief Function pointer for reading a 'register' from the device */ busio_genericdevice_readreg_t _readreg_func; + /*! @brief Function pointer for writing a 'register' to the device */ busio_genericdevice_writereg_t _writereg_func; - bool _begun; + bool _begun; ///< whether we have initialized yet (in case the function needs + ///< to do something) }; #endif // ADAFRUIT_GENERICDEVICE_H From 70ad31700abc20027e92756ff0b837c2700e5a07 Mon Sep 17 00:00:00 2001 From: ladyada Date: Wed, 8 Jan 2025 09:30:58 -0500 Subject: [PATCH 4/8] 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); } From fcc8dfaf6378c5b930078c92fda8bf19ff7e82d4 Mon Sep 17 00:00:00 2001 From: ladyada Date: Wed, 8 Jan 2025 09:31:54 -0500 Subject: [PATCH 5/8] bump --- README.md | 2 +- library.properties | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 1cc06a1..59712ff 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Adafruit Bus IO Library [![Build Status](https://github.com/adafruit/Adafruit_BusIO/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_BusIO/actions) -This is a helper library to abstract away I2C & SPI transactions and registers +This is a helper library to abstract away I2C, SPI, and 'generic transport' (e.g. UART) transactions and registers Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! diff --git a/library.properties b/library.properties index b2673fe..bdff9e1 100644 --- a/library.properties +++ b/library.properties @@ -1,9 +1,9 @@ name=Adafruit BusIO -version=1.16.2 +version=1.17.0 author=Adafruit maintainer=Adafruit -sentence=This is a library for abstracting away I2C and SPI interfacing -paragraph=This is a library for abstracting away I2C and SPI interfacing +sentence=This is a library for abstracting away UART, I2C and SPI interfacing +paragraph=This is a library for abstracting away UART, I2C and SPI interfacing category=Signal Input/Output url=https://github.com/adafruit/Adafruit_BusIO architectures=* From c0237922d3c883c8ba0dc7e2fc6ad30d0464203a Mon Sep 17 00:00:00 2001 From: ladyada Date: Wed, 8 Jan 2025 09:35:51 -0500 Subject: [PATCH 6/8] add claude credits! --- Adafruit_GenericDevice.cpp | 6 ++++++ .../genericdevice_uartregtest.ino | 9 +++++++++ .../genericdevice_uarttest/genericdevice_uarttest.ino | 8 ++++++++ 3 files changed, 23 insertions(+) diff --git a/Adafruit_GenericDevice.cpp b/Adafruit_GenericDevice.cpp index b0d8824..2fab4f0 100644 --- a/Adafruit_GenericDevice.cpp +++ b/Adafruit_GenericDevice.cpp @@ -1,3 +1,9 @@ +/* + Written with help by Claude! + https://claude.ai/chat/335f50b1-3dd8-435e-9139-57ec7ca26a3c (at this time + chats are not shareable :( +*/ + #include "Adafruit_GenericDevice.h" /*! @brief Create a Generic device with the provided read/write functions diff --git a/examples/genericdevice_uartregtest/genericdevice_uartregtest.ino b/examples/genericdevice_uartregtest/genericdevice_uartregtest.ino index b64389d..5e40c7f 100644 --- a/examples/genericdevice_uartregtest/genericdevice_uartregtest.ino +++ b/examples/genericdevice_uartregtest/genericdevice_uartregtest.ino @@ -1,3 +1,12 @@ +/* + Advanced example of using bstracted transport for reading and writing + register data from a UART-based device such as a TMC2209 + + Written with help by Claude! https://claude.ai/chat/335f50b1-3dd8-435e-9139-57ec7ca26a3c + (at this time chats are not shareable :( +*/ + + #include "Adafruit_BusIO_Register.h" #include "Adafruit_GenericDevice.h" diff --git a/examples/genericdevice_uarttest/genericdevice_uarttest.ino b/examples/genericdevice_uarttest/genericdevice_uarttest.ino index d943291..192081e 100644 --- a/examples/genericdevice_uarttest/genericdevice_uarttest.ino +++ b/examples/genericdevice_uarttest/genericdevice_uarttest.ino @@ -1,3 +1,11 @@ +/* + Abstracted transport for reading and writing data from a UART-based + device such as a TMC2209 + + Written with help by Claude! https://claude.ai/chat/335f50b1-3dd8-435e-9139-57ec7ca26a3c + (at this time chats are not shareable :( +*/ + #include "Adafruit_GenericDevice.h" Stream *uart_stream; // Will hold the pointer to our Stream object From 2663ca269f9cbffda79b7f5786ea34e5dbad18ed Mon Sep 17 00:00:00 2001 From: ladyada Date: Wed, 8 Jan 2025 10:15:09 -0500 Subject: [PATCH 7/8] woops fix serial --- .../genericdevice_uartregtest.ino | 492 +++++++++--------- .../genericdevice_uarttest.ino | 150 +++--- 2 files changed, 321 insertions(+), 321 deletions(-) diff --git a/examples/genericdevice_uartregtest/genericdevice_uartregtest.ino b/examples/genericdevice_uartregtest/genericdevice_uartregtest.ino index 5e40c7f..d9f3fab 100644 --- a/examples/genericdevice_uartregtest/genericdevice_uartregtest.ino +++ b/examples/genericdevice_uartregtest/genericdevice_uartregtest.ino @@ -1,246 +1,246 @@ -/* - Advanced example of using bstracted transport for reading and writing - register data from a UART-based device such as a TMC2209 - - Written with help by Claude! https://claude.ai/chat/335f50b1-3dd8-435e-9139-57ec7ca26a3c - (at this time chats are not shareable :( -*/ - - -#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); } +/* + Advanced example of using bstracted transport for reading and writing + register data from a UART-based device such as a TMC2209 + + Written with help by Claude! https://claude.ai/chat/335f50b1-3dd8-435e-9139-57ec7ca26a3c + (at this time chats are not shareable :( +*/ + + +#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!"); + + Serial1.begin(115200); + + TMC2209_UART uart(&Serial1, 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 index 192081e..bc4175c 100644 --- a/examples/genericdevice_uarttest/genericdevice_uarttest.ino +++ b/examples/genericdevice_uarttest/genericdevice_uarttest.ino @@ -1,75 +1,75 @@ -/* - Abstracted transport for reading and writing data from a UART-based - device such as a TMC2209 - - Written with help by Claude! https://claude.ai/chat/335f50b1-3dd8-435e-9139-57ec7ca26a3c - (at this time chats are not shareable :( -*/ - -#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); } +/* + Abstracted transport for reading and writing data from a UART-based + device such as a TMC2209 + + Written with help by Claude! https://claude.ai/chat/335f50b1-3dd8-435e-9139-57ec7ca26a3c + (at this time chats are not shareable :( +*/ + +#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!"); + + Serial1.begin(115200); + + Adafruit_GenericDevice *device = create_uart_device(&Serial1); + 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); } From 1a7e57883215809f1234c859916ec3f4659260cd Mon Sep 17 00:00:00 2001 From: ladyada Date: Wed, 8 Jan 2025 10:25:38 -0500 Subject: [PATCH 8/8] test skip for uart --- examples/genericdevice_uartregtest/.uno.test.skip | 0 examples/genericdevice_uarttest/.uno.test.skip | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 examples/genericdevice_uartregtest/.uno.test.skip create mode 100644 examples/genericdevice_uarttest/.uno.test.skip diff --git a/examples/genericdevice_uartregtest/.uno.test.skip b/examples/genericdevice_uartregtest/.uno.test.skip new file mode 100644 index 0000000..e69de29 diff --git a/examples/genericdevice_uarttest/.uno.test.skip b/examples/genericdevice_uarttest/.uno.test.skip new file mode 100644 index 0000000..e69de29