219 lines
5.9 KiB
C++
219 lines
5.9 KiB
C++
/*
|
|
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); } |