| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219 |
- /*
- 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
- #define TMC2209_IOIN 0x06
- class TMC2209_UART {
- private:
- Stream *_uart_stream;
- uint8_t _addr;
- static bool uart_read(void *thiz, uint8_t *buffer, size_t len) {
- TMC2209_UART *dev = (TMC2209_UART *)thiz;
- uint16_t timeout = 100;
- while (dev->_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] = dev->_uart_stream->read();
- DEBUG_PRINT_HEX(buffer[i]);
- }
- DEBUG_PRINTLN("");
- return true;
- }
- static bool uart_write(void *thiz, const uint8_t *buffer, size_t len) {
- TMC2209_UART *dev = (TMC2209_UART *)thiz;
- DEBUG_PRINT("Writing: ");
- for (size_t i = 0; i < len; i++) {
- DEBUG_PRINT_HEX(buffer[i]);
- }
- DEBUG_PRINTLN("");
- dev->_uart_stream->write(buffer, len);
- return true;
- }
- static bool uart_readreg(void *thiz, uint8_t *addr_buf, uint8_t addrsiz,
- uint8_t *data, uint16_t datalen) {
- TMC2209_UART *dev = (TMC2209_UART *)thiz;
- while (dev->_uart_stream->available())
- dev->_uart_stream->read();
- uint8_t packet[4] = {0x05, uint8_t(dev->_addr << 1), addr_buf[0], 0x00};
- packet[3] = calcCRC(packet, 3);
- if (!uart_write(thiz, packet, 4))
- return false;
- // Read back echo
- uint8_t echo[4];
- if (!uart_read(thiz, 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(thiz, response, 8))
- return false;
- // Verify response
- if (response[0] != 0x05) {
- DEBUG_PRINTLN("Invalid sync byte");
- return false;
- }
- if (response[1] != 0xFF) {
- DEBUG_PRINTLN("Invalid reply address");
- return false;
- }
- if (response[2] != addr_buf[0]) {
- DEBUG_PRINTLN("Register mismatch");
- return false;
- }
- uint8_t crc = calcCRC(response, 7);
- if (crc != response[7]) {
- DEBUG_PRINTLN("CRC mismatch");
- return false;
- }
- memcpy(data, &response[3], 4);
- return true;
- }
- static bool uart_writereg(void *thiz, uint8_t *addr_buf, uint8_t addrsiz,
- const uint8_t *data, uint16_t datalen) {
- TMC2209_UART *dev = (TMC2209_UART *)thiz;
- while (dev->_uart_stream->available())
- dev->_uart_stream->read();
- uint8_t packet[8] = {0x05,
- uint8_t(dev->_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(thiz, packet, 8))
- return false;
- uint8_t echo[8];
- if (!uart_read(thiz, echo, 8))
- return false;
- 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) {}
- Adafruit_GenericDevice *createDevice() {
- return new Adafruit_GenericDevice(this, uart_read, uart_write, uart_readreg,
- uart_writereg);
- }
- };
- 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 31: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); }
|