Testprogram for TMC2209-Library. Uses Speed-Control via VACTUAL instead of Step/Dir

Dependencies:   TMCStepper mRotaryEncoder-os

Files at this revision

API Documentation at this revision

Comitter:
charly
Date:
Thu Feb 04 19:46:56 2021 +0000
Child:
1:60419aa0c030
Commit message:
Working Version with TMC2209

Changed in this revision

.gitignore Show annotated file Show diff for this revision Revisions of this file
TMCStepper.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
mbed-os.lib Show annotated file Show diff for this revision Revisions of this file
source/CHOPCONF.cpp Show annotated file Show diff for this revision Revisions of this file
source/DRV_STATUS.cpp Show annotated file Show diff for this revision Revisions of this file
source/GCONF.cpp Show annotated file Show diff for this revision Revisions of this file
source/IHOLD_IRUN.cpp Show annotated file Show diff for this revision Revisions of this file
source/PWMCONF.cpp Show annotated file Show diff for this revision Revisions of this file
source/TMC2130_bitfields.h Show annotated file Show diff for this revision Revisions of this file
source/TMC2160_bitfields.h Show annotated file Show diff for this revision Revisions of this file
source/TMC2208Stepper.cpp Show annotated file Show diff for this revision Revisions of this file
source/TMC2208_bitfields.h Show annotated file Show diff for this revision Revisions of this file
source/TMC2209Stepper.cpp Show annotated file Show diff for this revision Revisions of this file
source/TMC2209_bitfields.h Show annotated file Show diff for this revision Revisions of this file
source/TMC2660_bitfields.h Show annotated file Show diff for this revision Revisions of this file
source/TMC5130_bitfields.h Show annotated file Show diff for this revision Revisions of this file
source/TMC5160_bitfields.h Show annotated file Show diff for this revision Revisions of this file
source/TMCStepper.cpp Show annotated file Show diff for this revision Revisions of this file
source/TMC_MACROS.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/.gitignore	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,4 @@
+.build
+.mbed
+projectfiles
+*.py*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/TMCStepper.h	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,383 @@
+#pragma once
+
+//#define TMCDEBUG
+
+#include "mbed.h"
+
+#define SW_CAPABLE_PLATFORM true
+
+#include "source/TMC2130_bitfields.h"
+#include "source/TMC2160_bitfields.h"
+#include "source/TMC5130_bitfields.h"
+#include "source/TMC5160_bitfields.h"
+#include "source/TMC2208_bitfields.h"
+#include "source/TMC2209_bitfields.h"
+#include "source/TMC2660_bitfields.h"
+
+#define INIT_REGISTER(REG) REG##_t REG##_register = REG##_t
+#define INIT2130_REGISTER(REG) TMC2130_n::REG##_t REG##_register = TMC2130_n::REG##_t
+#define INIT2160_REGISTER(REG) TMC2160_n::REG##_t REG##_register = TMC2160_n::REG##_t
+#define INIT5130_REGISTER(REG) TMC5130_n::REG##_t REG##_register = TMC5130_n::REG##_t
+#define INIT5160_REGISTER(REG) TMC5160_n::REG##_t REG##_register = TMC5160_n::REG##_t
+#define INIT2660_REGISTER(REG) TMC2660_n::REG##_t REG##_register = TMC2660_n::REG##_t
+#define INIT2208_REGISTER(REG) TMC2208_n::REG##_t REG##_register = TMC2208_n::REG##_t
+#define INIT2224_REGISTER(REG) TMC2224_n::REG##_t REG##_register = TMC2224_n::REG##_t
+#define SET_ALIAS(TYPE, DRIVER, NEW, ARG, OLD) TYPE (DRIVER::*NEW)(ARG) = &DRIVER::OLD
+
+#define TMCSTEPPER_VERSION 0x000701 // v0.7.1
+
+#if SW_CAPABLE_PLATFORM
+    #include <BufferedSerial.h>
+    #include <Stream.h>
+#endif
+class TMCStepper {
+    public:
+        uint16_t cs2rms(uint8_t CS);
+        void rms_current(uint16_t mA);
+        void rms_current(uint16_t mA, float mult);
+        uint16_t rms_current();
+        void hold_multiplier(float val) { holdMultiplier = val; }
+        float hold_multiplier() { return holdMultiplier; }
+        uint8_t test_connection();
+
+        // Helper functions
+        void microsteps(uint16_t ms);
+        uint16_t microsteps();
+        void blank_time(uint8_t value);
+        uint8_t blank_time();
+        void hysteresis_end(int8_t value);
+        int8_t hysteresis_end();
+        void hysteresis_start(uint8_t value);
+        uint8_t hysteresis_start();
+
+        // R+WC: GSTAT
+        void    GSTAT(                          uint8_t input);
+        uint8_t GSTAT();
+        bool    reset();
+        bool    drv_err();
+        bool    uv_cp();
+
+        // W: IHOLD_IRUN
+        void IHOLD_IRUN(                    uint32_t input);
+        uint32_t IHOLD_IRUN();
+        void    ihold(                          uint8_t B);
+        void    irun(                               uint8_t B);
+        void    iholddelay(                 uint8_t B);
+        uint8_t ihold();
+        uint8_t irun();
+        uint8_t iholddelay();
+
+        // W: TPOWERDOWN
+        uint8_t TPOWERDOWN();
+        void TPOWERDOWN(                    uint8_t input);
+
+        // R: TSTEP
+        uint32_t TSTEP();
+
+        // W: TPWMTHRS
+        uint32_t TPWMTHRS();
+        void TPWMTHRS(                      uint32_t input);
+
+        // R: MSCNT
+        uint16_t MSCNT();
+
+        // R: MSCURACT
+        uint32_t MSCURACT();
+        int16_t cur_a();
+        int16_t cur_b();
+
+    protected:
+        TMCStepper(float RS) : Rsense(RS) {};
+        INIT_REGISTER(IHOLD_IRUN){{.sr=0}}; // 32b
+        INIT_REGISTER(TPOWERDOWN){.sr=0};       // 8b
+        INIT_REGISTER(TPWMTHRS){.sr=0};         // 32b
+
+        static constexpr uint8_t TMC_READ = 0x00,
+                                                        TMC_WRITE = 0x80;
+
+        struct TSTEP_t { constexpr static uint8_t address = 0x12; };
+        struct MSCNT_t { constexpr static uint8_t address = 0x6A; };
+
+        virtual void write(uint8_t, uint32_t) = 0;
+        virtual uint32_t read(uint8_t) = 0;
+        virtual void vsense(bool) = 0;
+        virtual bool vsense(void) = 0;
+        virtual uint32_t DRV_STATUS() = 0;
+        virtual void hend(uint8_t) = 0;
+        virtual uint8_t hend() = 0;
+        virtual void hstrt(uint8_t) = 0;
+        virtual uint8_t hstrt() = 0;
+        virtual void mres(uint8_t) = 0;
+        virtual uint8_t mres() = 0;
+        virtual void tbl(uint8_t) = 0;
+        virtual uint8_t tbl() = 0;
+
+        const float Rsense;
+        float holdMultiplier = 0.5;
+};
+
+
+class TMC2208Stepper : public TMCStepper {
+    public:
+        TMC2208Stepper(Stream * SerialPort, float RS, uint8_t addr, uint16_t mul_pin1, uint16_t mul_pin2);
+        TMC2208Stepper(Stream * SerialPort, float RS) :
+            TMC2208Stepper(SerialPort, RS, TMC2208_SLAVE_ADDR)
+            {}
+        #if SW_CAPABLE_PLATFORM
+            TMC2208Stepper(PinName SW_RX_pin, PinName SW_TX_pin, float RS) :
+                TMC2208Stepper(SW_RX_pin, SW_TX_pin, RS, TMC2208_SLAVE_ADDR)
+                {}
+
+            __attribute__((deprecated("Boolean argument has been deprecated and does nothing")))
+            TMC2208Stepper(PinName SW_RX_pin, PinName SW_TX_pin, float RS, bool) :
+                TMC2208Stepper(SW_RX_pin, SW_TX_pin, RS, TMC2208_SLAVE_ADDR)
+                {};
+        #else
+            TMC2208Stepper(PinName, PinName, float) = delete; // Your platform does not currently support Software Serial
+        #endif
+        void defaults();
+        void push();
+        void begin();
+        #if SW_CAPABLE_PLATFORM
+            void beginSerial(uint32_t baudrate) __attribute__((weak));
+        #else
+            void beginSerial(uint32_t) = delete; // Your platform does not currently support Software Serial
+        #endif
+        bool isEnabled();
+
+        // RW: GCONF
+        void GCONF(uint32_t input);
+        void I_scale_analog(bool B);
+        void internal_Rsense(bool B);
+        void en_spreadCycle(bool B);
+        void shaft(bool B);
+        void index_otpw(bool B);
+        void index_step(bool B);
+        void pdn_disable(bool B);
+        void mstep_reg_select(bool B);
+        void multistep_filt(bool B);
+        uint32_t GCONF();
+        bool I_scale_analog();
+        bool internal_Rsense();
+        bool en_spreadCycle();
+        bool shaft();
+        bool index_otpw();
+        bool index_step();
+        bool pdn_disable();
+        bool mstep_reg_select();
+        bool multistep_filt();
+
+        // R: IFCNT
+        uint8_t IFCNT();
+
+        // W: SLAVECONF
+        void SLAVECONF(uint16_t input);
+        uint16_t SLAVECONF();
+        void senddelay(uint8_t B);
+        uint8_t senddelay();
+
+        // W: OTP_PROG
+        void OTP_PROG(uint16_t input);
+
+        // R: OTP_READ
+        uint32_t OTP_READ();
+
+        // R: IOIN
+        uint32_t IOIN();
+        bool enn();
+        bool ms1();
+        bool ms2();
+        bool diag();
+        bool pdn_uart();
+        bool step();
+        bool sel_a();
+        bool dir();
+        uint8_t version();
+
+        // RW: FACTORY_CONF
+        void FACTORY_CONF(uint16_t input);
+        uint16_t FACTORY_CONF();
+        void fclktrim(uint8_t B);
+        void ottrim(uint8_t B);
+        uint8_t fclktrim();
+        uint8_t ottrim();
+
+        // W: VACTUAL
+        void VACTUAL(uint32_t input);
+        uint32_t VACTUAL();
+
+        // RW: CHOPCONF
+        void CHOPCONF(uint32_t input);
+        void toff(uint8_t B);
+        void hstrt(uint8_t B);
+        void hend(uint8_t B);
+        void tbl(uint8_t B);
+        void vsense(bool B);
+        void mres(uint8_t B);
+        void intpol(bool B);
+        void dedge(bool B);
+        void diss2g(bool B);
+        void diss2vs(bool B);
+        uint32_t CHOPCONF();
+        uint8_t toff();
+        uint8_t hstrt();
+        uint8_t hend();
+        uint8_t tbl();
+        bool vsense();
+        uint8_t mres();
+        bool intpol();
+        bool dedge();
+        bool diss2g();
+        bool diss2vs();
+
+        // R: DRV_STATUS
+        uint32_t DRV_STATUS();
+        bool otpw();
+        bool ot();
+        bool s2ga();
+        bool s2gb();
+        bool s2vsa();
+        bool s2vsb();
+        bool ola();
+        bool olb();
+        bool t120();
+        bool t143();
+        bool t150();
+        bool t157();
+        uint16_t cs_actual();
+        bool stealth();
+        bool stst();
+
+        // RW: PWMCONF
+        void PWMCONF(uint32_t input);
+        void pwm_ofs(uint8_t B);
+        void pwm_grad(uint8_t B);
+        void pwm_freq(uint8_t B);
+        void pwm_autoscale(bool B);
+        void pwm_autograd(bool B);
+        void freewheel(uint8_t B);
+        void pwm_reg(uint8_t B);
+        void pwm_lim(uint8_t B);
+        uint32_t PWMCONF();
+        uint8_t pwm_ofs();
+        uint8_t pwm_grad();
+        uint8_t pwm_freq();
+        bool pwm_autoscale();
+        bool pwm_autograd();
+        uint8_t freewheel();
+        uint8_t pwm_reg();
+        uint8_t pwm_lim();
+
+        // R: PWM_SCALE
+        uint32_t PWM_SCALE();
+        uint8_t pwm_scale_sum();
+        int16_t pwm_scale_auto();
+
+        // R: PWM_AUTO (0x72)
+        uint32_t PWM_AUTO();
+        uint8_t pwm_ofs_auto();
+        uint8_t pwm_grad_auto();
+
+        uint16_t bytesWritten = 0;
+        float Rsense = 0.11;
+        bool CRCerror = false;
+    protected:
+        INIT2208_REGISTER(GCONF)            {{.sr=0}};
+        INIT_REGISTER(SLAVECONF)            {{.sr=0}};
+        INIT_REGISTER(FACTORY_CONF)     {{.sr=0}};
+        INIT2208_REGISTER(VACTUAL)      {.sr=0};
+        INIT2208_REGISTER(CHOPCONF)     {{.sr=0}};
+        INIT2208_REGISTER(PWMCONF)      {{.sr=0}};
+
+        struct IFCNT_t      { constexpr static uint8_t address = 0x02; };
+        struct OTP_PROG_t   { constexpr static uint8_t address = 0x04; };
+        struct OTP_READ_t   { constexpr static uint8_t address = 0x05; };
+
+        TMC2208Stepper(Stream * SerialPort, float RS, uint8_t addr);
+        #if SW_CAPABLE_PLATFORM
+            TMC2208Stepper(PinName SW_RX_pin, PinName SW_TX_pin, float RS, uint8_t addr);
+        #endif
+
+        Stream * HWSerial = nullptr;
+        #if SW_CAPABLE_PLATFORM
+            BufferedSerial * SWSerial = nullptr;
+            const uint16_t RXTX_pin = 0; // Half duplex
+        #endif
+
+//        SSwitch *sswitch = nullptr;
+
+        int available();
+        void preWriteCommunication();
+        void preReadCommunication();
+        int16_t serial_read();
+        uint8_t serial_write(const uint8_t data);
+        void postWriteCommunication();
+        void postReadCommunication();
+        void write(uint8_t, uint32_t);
+        uint32_t read(uint8_t);
+        const uint8_t slave_address;
+        uint8_t calcCRC(uint8_t datagram[], uint8_t len);
+        static constexpr uint8_t  TMC2208_SYNC = 0x05,
+                                  TMC2208_SLAVE_ADDR = 0x00;
+        static constexpr uint8_t replyDelay = 2;  //ms
+        static constexpr uint8_t abort_window = 5;
+        static constexpr uint8_t max_retries = 2;
+
+        uint64_t _sendDatagram(uint8_t [], const uint8_t, uint16_t);
+};
+
+class TMC2209Stepper : public TMC2208Stepper {
+    public:
+        TMC2209Stepper(Stream * SerialPort, float RS, uint8_t addr) :
+            TMC2208Stepper(SerialPort, RS, addr) {}
+
+        #if SW_CAPABLE_PLATFORM
+            TMC2209Stepper(PinName SW_RX_pin, PinName SW_TX_pin, float RS, uint8_t addr) :
+                TMC2208Stepper(SW_RX_pin, SW_TX_pin, RS, addr) {}
+        #else
+            TMC2209Stepper(PinName, PinName, float, uint8_t) = delete; // Your platform does not currently support Software Serial
+        #endif
+        void push();
+
+        // R: IOIN
+        uint32_t IOIN();
+        bool enn();
+        bool ms1();
+        bool ms2();
+        bool diag();
+        bool pdn_uart();
+        bool step();
+        bool spread_en();
+        bool dir();
+        uint8_t version();
+
+        // W: TCOOLTHRS
+        uint32_t TCOOLTHRS();
+        void TCOOLTHRS(uint32_t input);
+
+        // W: SGTHRS
+        void SGTHRS(uint8_t B);
+        uint8_t SGTHRS();
+
+        // R: SG_RESULT
+        uint16_t SG_RESULT();
+
+        // W: COOLCONF
+        void COOLCONF(uint16_t B);
+        uint16_t COOLCONF();
+        void semin(uint8_t B);
+        void seup(uint8_t B);
+        void semax(uint8_t B);
+        void sedn(uint8_t B);
+        void seimin(bool B);
+        uint8_t semin();
+        uint8_t seup();
+        uint8_t semax();
+        uint8_t sedn();
+        bool seimin();
+
+    protected:
+        INIT_REGISTER(TCOOLTHRS){.sr=0};
+        TMC2209_n::SGTHRS_t SGTHRS_register{.sr=0};
+        TMC2209_n::COOLCONF_t COOLCONF_register{{.sr=0}};
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,93 @@
+/* mbed Microcontroller Library
+ * Copyright (c) 2019 ARM Limited
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "mbed.h"
+#include "platform/mbed_thread.h"
+
+
+DigitalOut ledDir(LED2);
+//Virtual serial port over USB with 15200 baud 8N1
+static BufferedSerial host(USBTX, USBRX,115200);
+
+
+// apply number of steps, direction, speed and 
+// a linear acceleration/deceleration to a Stepper Motor Controller
+
+#include "TMCStepper.h"
+ 
+// MOTOR Steps per Revolution ( 1/8 Microsteps, 200Steps per Rev / 1.8 degrees per FullStep)
+#define MSPR 1600
+// Gear Ratio
+#define GR 288
+
+#define DRIVER_ADDRESS 0b00 // TMC2209 Driver address according to MS1 and MS2
+#define R_SENSE 0.11f // Match to your driver
+#define MICROSTEPS 64
+
+//RX, TX, RS, Addr 
+TMC2209Stepper stepper(p14, p13, R_SENSE, DRIVER_ADDRESS);
+
+// Assumes little endian
+void printBits(size_t const size, void const * const ptr)
+{
+    unsigned char *b = (unsigned char*) ptr;
+    unsigned char byte;
+    int i, j;
+//    puts("#");
+    for (i = size-1; i >= 0; i--) {
+        for (j = 7; j >= 0; j--) {
+            byte = (b[i] >> j) & 1;
+            printf("%u", byte);
+        }
+    }
+//    puts("#");
+}
+ 
+ int main()
+ {
+    printf("\r\nConnected to mbed\r\n");
+    stepper.begin();                  // UART: Init SW UART (if selected) with default baudrate
+    stepper.toff(5);                  // Enables driver in software
+    stepper.rms_current(600);         // Set motor RMS current in mA
+    stepper.microsteps(MICROSTEPS);   // Set microsteps to 1:Fullstep ... 256: 1/256th
+    stepper.en_spreadCycle(false);    // Toggle spreadCycle on TMC2208/2209/2224
+    stepper.pwm_autoscale(true);      // Needed for stealthChop
+    printf("TMC-Version: %02X\r\n",stepper.version());
+    
+    while(1) {
+//        printf("TSTEP(): %i\r\n", stepper.TSTEP());
+        uint32_t status = stepper.DRV_STATUS();
+        printf("DRV_STATUS(): "); printBits(sizeof(status),&status);printf("\r\n");
+        uint32_t ioin = stepper.IOIN();        
+        printf("IOIN(): "); printBits(sizeof(ioin),&ioin);printf("\r\n");
+//        uint32_t otp = stepper.OTP_READ();
+//        printf("OTP_READ(): ");printBits(sizeof(otp),&otp);printf("\r\n");
+      
+/*        printf("VACTUAL(): %zu \r\n", stepper.VACTUAL());
+        // increase
+        int maxspeed = 1600;
+        int actspeed = 0;
+        while (actspeed < maxspeed) {
+            actspeed += 200;
+            printf("actspeed: %i",actspeed);
+            stepper.VACTUAL(actspeed*MICROSTEPS);// Set Speed to value
+            ThisThread::sleep_for(20ms); //wait
+        }
+        printf("VACTUAL(): %zu \r\n", stepper.VACTUAL());
+        ThisThread::sleep_for(10s); 
+        // decrease
+        maxspeed = 0;
+        while (actspeed > maxspeed) {
+            actspeed -= 200;
+            printf("actspeed: %i",actspeed);
+            stepper.VACTUAL(actspeed*MICROSTEPS);// Set Speed to value
+            ThisThread::sleep_for(20ms); //wait
+        }
+*/
+        stepper.VACTUAL(400*MICROSTEPS);// Set Speed to value
+        ThisThread::sleep_for(5s); //wait 
+        printf("loop...\r\n");
+   }
+ }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-os.lib	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,1 @@
+https://github.com/ARMmbed/mbed-os/#890f0562dc2efb7cf76a5f010b535c2b94bce849
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/CHOPCONF.cpp	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,110 @@
+#include "TMCStepper.h"
+#include "TMC_MACROS.h"
+
+#define SET_REG(SETTING) CHOPCONF_register.SETTING = B; write(CHOPCONF_register.address, CHOPCONF_register.sr)
+
+// CHOPCONF
+/*
+uint32_t TMC2130Stepper::CHOPCONF() {
+    return read(CHOPCONF_register.address);
+}
+void TMC2130Stepper::CHOPCONF(uint32_t input) {
+    CHOPCONF_register.sr = input;
+    write(CHOPCONF_register.address, CHOPCONF_register.sr);
+}
+
+void TMC2130Stepper::toff(      uint8_t B ) { SET_REG(toff);    }
+void TMC2130Stepper::hstrt(     uint8_t B ) { SET_REG(hstrt);   }
+void TMC2130Stepper::hend(      uint8_t B ) { SET_REG(hend);    }
+//void TMC2130Stepper::fd(      uint8_t B ) { SET_REG(fd);      }
+void TMC2130Stepper::disfdcc(   bool    B ) { SET_REG(disfdcc); }
+void TMC2130Stepper::rndtf(     bool    B ) { SET_REG(rndtf);   }
+void TMC2130Stepper::chm(       bool    B ) { SET_REG(chm);     }
+void TMC2130Stepper::tbl(       uint8_t B ) { SET_REG(tbl);     }
+void TMC2130Stepper::vsense(    bool    B ) { SET_REG(vsense);  }
+void TMC2130Stepper::vhighfs(   bool    B ) { SET_REG(vhighfs); }
+void TMC2130Stepper::vhighchm(  bool    B ) { SET_REG(vhighchm);}
+void TMC2130Stepper::sync(      uint8_t B ) { SET_REG(sync);    }
+void TMC2130Stepper::mres(      uint8_t B ) { SET_REG(mres);    }
+void TMC2130Stepper::intpol(    bool    B ) { SET_REG(intpol);  }
+void TMC2130Stepper::dedge(     bool    B ) { SET_REG(dedge);   }
+void TMC2130Stepper::diss2g(    bool    B ) { SET_REG(diss2g);  }
+
+uint8_t TMC2130Stepper::toff()      { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.toff;    }
+uint8_t TMC2130Stepper::hstrt()     { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.hstrt;   }
+uint8_t TMC2130Stepper::hend()      { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.hend;    }
+//uint8_t TMC2130Stepper::fd()      { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.fd;      }
+bool    TMC2130Stepper::disfdcc()   { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.disfdcc; }
+bool    TMC2130Stepper::rndtf()     { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.rndtf;   }
+bool    TMC2130Stepper::chm()       { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.chm;     }
+uint8_t TMC2130Stepper::tbl()       { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.tbl;     }
+bool    TMC2130Stepper::vsense()    { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.vsense;  }
+bool    TMC2130Stepper::vhighfs()   { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.vhighfs; }
+bool    TMC2130Stepper::vhighchm()  { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.vhighchm;}
+uint8_t TMC2130Stepper::sync()      { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.sync;    }
+uint8_t TMC2130Stepper::mres()      { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.mres;    }
+bool    TMC2130Stepper::intpol()    { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.intpol;  }
+bool    TMC2130Stepper::dedge()     { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.dedge;   }
+bool    TMC2130Stepper::diss2g()    { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.diss2g;  }
+
+void TMC5160Stepper::diss2vs(bool B){ SET_REG(diss2vs); }
+void TMC5160Stepper::tpfd(uint8_t B){ SET_REG(tpfd);    }
+bool TMC5160Stepper::diss2vs()      { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.diss2vs; }
+uint8_t TMC5160Stepper::tpfd()      { CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.tpfd;    }
+*/
+void TMC2208Stepper::CHOPCONF(uint32_t input) {
+    CHOPCONF_register.sr = input;
+    write(CHOPCONF_register.address, CHOPCONF_register.sr);
+}
+uint32_t TMC2208Stepper::CHOPCONF() {
+    return read(CHOPCONF_register.address);
+}
+void TMC2208Stepper::toff   ( uint8_t  B )  { SET_REG(toff);    }
+void TMC2208Stepper::hstrt  ( uint8_t  B )  { SET_REG(hstrt);   }
+void TMC2208Stepper::hend   ( uint8_t  B )  { SET_REG(hend);    }
+void TMC2208Stepper::tbl    ( uint8_t  B )  { SET_REG(tbl);     }
+void TMC2208Stepper::vsense ( bool     B )  { SET_REG(vsense);  }
+void TMC2208Stepper::mres   ( uint8_t  B )  { SET_REG(mres);    }
+void TMC2208Stepper::intpol ( bool     B )  { SET_REG(intpol);  }
+void TMC2208Stepper::dedge  ( bool     B )  { SET_REG(dedge);   }
+void TMC2208Stepper::diss2g ( bool     B )  { SET_REG(diss2g);  }
+void TMC2208Stepper::diss2vs( bool     B )  { SET_REG(diss2vs); }
+
+uint8_t TMC2208Stepper::toff()      { TMC2208_n::CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.toff;     }
+uint8_t TMC2208Stepper::hstrt()     { TMC2208_n::CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.hstrt;    }
+uint8_t TMC2208Stepper::hend()      { TMC2208_n::CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.hend;     }
+uint8_t TMC2208Stepper::tbl()       { TMC2208_n::CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.tbl;      }
+bool    TMC2208Stepper::vsense()    { TMC2208_n::CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.vsense;   }
+uint8_t TMC2208Stepper::mres()      { TMC2208_n::CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.mres;     }
+bool    TMC2208Stepper::intpol()    { TMC2208_n::CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.intpol;   }
+bool    TMC2208Stepper::dedge()     { TMC2208_n::CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.dedge;    }
+bool    TMC2208Stepper::diss2g()    { TMC2208_n::CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.diss2g;   }
+bool    TMC2208Stepper::diss2vs()   { TMC2208_n::CHOPCONF_t r{0}; r.sr = CHOPCONF(); return r.diss2vs;  }
+/*
+#define GET_REG_2660(SETTING) return CHOPCONF_register.SETTING;
+
+uint32_t TMC2660Stepper::CHOPCONF() { return CHOPCONF_register.sr; }
+void TMC2660Stepper::CHOPCONF(uint32_t data) {
+  CHOPCONF_register.sr = data;
+  write(CHOPCONF_register.address, CHOPCONF_register.sr);
+}
+
+void TMC2660Stepper::toff(uint8_t B)    {
+    SET_REG(toff);
+    if (B>0) _savedToff = B;
+}
+void TMC2660Stepper::hstrt(uint8_t B)   { SET_REG(hstrt);   }
+void TMC2660Stepper::hend(uint8_t B)    { SET_REG(hend);    }
+void TMC2660Stepper::hdec(uint8_t B)    { SET_REG(hdec);    }
+void TMC2660Stepper::rndtf(bool B)  { SET_REG(rndtf);   }
+void TMC2660Stepper::chm(bool B)    { SET_REG(chm); }
+void TMC2660Stepper::tbl(uint8_t B)     { SET_REG(tbl); }
+
+uint8_t TMC2660Stepper::toff()  { GET_REG_2660(toff);   }
+uint8_t TMC2660Stepper::hstrt()     { GET_REG_2660(hstrt);  }
+uint8_t TMC2660Stepper::hend() { GET_REG_2660(hend);    }
+uint8_t TMC2660Stepper::hdec()  { GET_REG_2660(hdec);   }
+bool TMC2660Stepper::rndtf() { GET_REG_2660(rndtf); }
+bool TMC2660Stepper::chm()  { GET_REG_2660(chm);    }
+uint8_t TMC2660Stepper::tbl() { GET_REG_2660(tbl);  }
+*/
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/DRV_STATUS.cpp	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,38 @@
+#include "TMCStepper.h"
+#include "TMC_MACROS.h"
+
+#define GET_REG(NS, SETTING) NS::DRV_STATUS_t r{0}; r.sr = DRV_STATUS(); return r.SETTING
+/*
+uint32_t TMC2130Stepper::DRV_STATUS() { return read(DRV_STATUS_t::address); }
+
+uint16_t TMC2130Stepper::sg_result(){ GET_REG(TMC2130_n, sg_result);    }
+bool TMC2130Stepper::fsactive()     { GET_REG(TMC2130_n, fsactive);     }
+uint8_t TMC2130Stepper::cs_actual() { GET_REG(TMC2130_n, cs_actual);    }
+bool TMC2130Stepper::stallguard()   { GET_REG(TMC2130_n, stallGuard);   }
+bool TMC2130Stepper::ot()           { GET_REG(TMC2130_n, ot);           }
+bool TMC2130Stepper::otpw()         { GET_REG(TMC2130_n, otpw);         }
+bool TMC2130Stepper::s2ga()         { GET_REG(TMC2130_n, s2ga);         }
+bool TMC2130Stepper::s2gb()         { GET_REG(TMC2130_n, s2gb);         }
+bool TMC2130Stepper::ola()          { GET_REG(TMC2130_n, ola);          }
+bool TMC2130Stepper::olb()          { GET_REG(TMC2130_n, olb);          }
+bool TMC2130Stepper::stst()         { GET_REG(TMC2130_n, stst);         }
+*/
+uint32_t TMC2208Stepper::DRV_STATUS() {
+    return read(TMC2208_n::DRV_STATUS_t::address);
+}
+
+bool        TMC2208Stepper::otpw()      { GET_REG(TMC2208_n, otpw);         }
+bool        TMC2208Stepper::ot()        { GET_REG(TMC2208_n, ot);           }
+bool        TMC2208Stepper::s2ga()      { GET_REG(TMC2208_n, s2ga);         }
+bool        TMC2208Stepper::s2gb()      { GET_REG(TMC2208_n, s2gb);         }
+bool        TMC2208Stepper::s2vsa()     { GET_REG(TMC2208_n, s2vsa);        }
+bool        TMC2208Stepper::s2vsb()     { GET_REG(TMC2208_n, s2vsb);        }
+bool        TMC2208Stepper::ola()       { GET_REG(TMC2208_n, ola);          }
+bool        TMC2208Stepper::olb()       { GET_REG(TMC2208_n, olb);          }
+bool        TMC2208Stepper::t120()      { GET_REG(TMC2208_n, t120);         }
+bool        TMC2208Stepper::t143()      { GET_REG(TMC2208_n, t143);         }
+bool        TMC2208Stepper::t150()      { GET_REG(TMC2208_n, t150);         }
+bool        TMC2208Stepper::t157()      { GET_REG(TMC2208_n, t157);         }
+uint16_t    TMC2208Stepper::cs_actual() { GET_REG(TMC2208_n, cs_actual);    }
+bool        TMC2208Stepper::stealth()   { GET_REG(TMC2208_n, stealth);      }
+bool        TMC2208Stepper::stst()      { GET_REG(TMC2208_n, stst);         }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/GCONF.cpp	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,94 @@
+#include "TMCStepper.h"
+#include "TMC_MACROS.h"
+
+#define SET_REG(SETTING) GCONF_register.SETTING = B; write(GCONF_register.address, GCONF_register.sr)
+
+// GCONF
+/*
+uint32_t TMC2130Stepper::GCONF() {
+    return read(GCONF_register.address);
+}
+void TMC2130Stepper::GCONF(uint32_t input) {
+    GCONF_register.sr = input;
+    write(GCONF_register.address, GCONF_register.sr);
+}
+
+void TMC2130Stepper::I_scale_analog(bool B)         { SET_REG(i_scale_analog);          }
+void TMC2130Stepper::internal_Rsense(bool B)        { SET_REG(internal_rsense);         }
+void TMC2130Stepper::en_pwm_mode(bool B)            { SET_REG(en_pwm_mode);             }
+void TMC2130Stepper::enc_commutation(bool B)        { SET_REG(enc_commutation);         }
+void TMC2130Stepper::shaft(bool B)                  { SET_REG(shaft);                   }
+void TMC2130Stepper::diag0_error(bool B)            { SET_REG(diag0_error);             }
+void TMC2130Stepper::diag0_otpw(bool B)             { SET_REG(diag0_otpw);              }
+void TMC2130Stepper::diag0_stall(bool B)            { SET_REG(diag0_stall);             }
+void TMC2130Stepper::diag1_stall(bool B)            { SET_REG(diag1_stall);             }
+void TMC2130Stepper::diag1_index(bool B)            { SET_REG(diag1_index);             }
+void TMC2130Stepper::diag1_onstate(bool B)          { SET_REG(diag1_onstate);           }
+void TMC2130Stepper::diag1_steps_skipped(bool B)    { SET_REG(diag1_steps_skipped);     }
+void TMC2130Stepper::diag0_int_pushpull(bool B)     { SET_REG(diag0_int_pushpull);      }
+void TMC2130Stepper::diag1_pushpull(bool B)         { SET_REG(diag1_poscomp_pushpull);  }
+void TMC2130Stepper::small_hysteresis(bool B)       { SET_REG(small_hysteresis);        }
+void TMC2130Stepper::stop_enable(bool B)            { SET_REG(stop_enable);             }
+void TMC2130Stepper::direct_mode(bool B)            { SET_REG(direct_mode);             }
+
+bool TMC2130Stepper::I_scale_analog()               { GCONF_t r{0}; r.sr = GCONF(); return r.i_scale_analog;        }
+bool TMC2130Stepper::internal_Rsense()              { GCONF_t r{0}; r.sr = GCONF(); return r.internal_rsense;       }
+bool TMC2130Stepper::en_pwm_mode()                  { GCONF_t r{0}; r.sr = GCONF(); return r.en_pwm_mode;           }
+bool TMC2130Stepper::enc_commutation()              { GCONF_t r{0}; r.sr = GCONF(); return r.enc_commutation;       }
+bool TMC2130Stepper::shaft()                        { GCONF_t r{0}; r.sr = GCONF(); return r.shaft;                 }
+bool TMC2130Stepper::diag0_error()                  { GCONF_t r{0}; r.sr = GCONF(); return r.diag0_error;           }
+bool TMC2130Stepper::diag0_otpw()                   { GCONF_t r{0}; r.sr = GCONF(); return r.diag0_otpw;            }
+bool TMC2130Stepper::diag0_stall()                  { GCONF_t r{0}; r.sr = GCONF(); return r.diag0_stall;           }
+bool TMC2130Stepper::diag1_stall()                  { GCONF_t r{0}; r.sr = GCONF(); return r.diag1_stall;           }
+bool TMC2130Stepper::diag1_index()                  { GCONF_t r{0}; r.sr = GCONF(); return r.diag1_index;           }
+bool TMC2130Stepper::diag1_onstate()                { GCONF_t r{0}; r.sr = GCONF(); return r.diag1_onstate;         }
+bool TMC2130Stepper::diag1_steps_skipped()          { GCONF_t r{0}; r.sr = GCONF(); return r.diag1_steps_skipped;   }
+bool TMC2130Stepper::diag0_int_pushpull()           { GCONF_t r{0}; r.sr = GCONF(); return r.diag0_int_pushpull;    }
+bool TMC2130Stepper::diag1_pushpull()               { GCONF_t r{0}; r.sr = GCONF(); return r.diag1_poscomp_pushpull;}
+bool TMC2130Stepper::small_hysteresis()             { GCONF_t r{0}; r.sr = GCONF(); return r.small_hysteresis;      }
+bool TMC2130Stepper::stop_enable()                  { GCONF_t r{0}; r.sr = GCONF(); return r.stop_enable;           }
+bool TMC2130Stepper::direct_mode()                  { GCONF_t r{0}; r.sr = GCONF(); return r.direct_mode;           }
+*/
+/*
+bit 18 not implemented:
+test_mode 0:
+Normal operation 1:
+Enable analog test output on pin DCO. IHOLD[1..0] selects the function of DCO:
+0…2: T120, DAC, VDDH Attention:
+Not for user, set to 0 for normal operation!
+*/
+/*
+void TMC5160Stepper::recalibrate(bool B)            { SET_REG(recalibrate);             }
+void TMC5160Stepper::faststandstill(bool B)         { SET_REG(faststandstill);          }
+void TMC5160Stepper::multistep_filt(bool B)         { SET_REG(multistep_filt);          }
+bool TMC5160Stepper::recalibrate()                  { GCONF_t r{0}; r.sr = GCONF(); return r.recalibrate;   }
+bool TMC5160Stepper::faststandstill()               { GCONF_t r{0}; r.sr = GCONF(); return r.faststandstill;    }
+bool TMC5160Stepper::multistep_filt()               { GCONF_t r{0}; r.sr = GCONF(); return r.multistep_filt;    }
+*/
+uint32_t TMC2208Stepper::GCONF() {
+    return read(GCONF_register.address);
+}
+void TMC2208Stepper::GCONF(uint32_t input) {
+    GCONF_register.sr = input;
+    write(GCONF_register.address, GCONF_register.sr);
+}
+
+void TMC2208Stepper::I_scale_analog(bool B)     { SET_REG(i_scale_analog);  }
+void TMC2208Stepper::internal_Rsense(bool B)    { SET_REG(internal_rsense); }
+void TMC2208Stepper::en_spreadCycle(bool B)     { SET_REG(en_spreadcycle);  }
+void TMC2208Stepper::shaft(bool B)              { SET_REG(shaft);           }
+void TMC2208Stepper::index_otpw(bool B)         { SET_REG(index_otpw);      }
+void TMC2208Stepper::index_step(bool B)         { SET_REG(index_step);      }
+void TMC2208Stepper::pdn_disable(bool B)        { SET_REG(pdn_disable);     }
+void TMC2208Stepper::mstep_reg_select(bool B)   { SET_REG(mstep_reg_select);}
+void TMC2208Stepper::multistep_filt(bool B)     { SET_REG(multistep_filt);  }
+
+bool TMC2208Stepper::I_scale_analog()   { TMC2208_n::GCONF_t r{0}; r.sr = GCONF(); return r.i_scale_analog;     }
+bool TMC2208Stepper::internal_Rsense()  { TMC2208_n::GCONF_t r{0}; r.sr = GCONF(); return r.internal_rsense;    }
+bool TMC2208Stepper::en_spreadCycle()   { TMC2208_n::GCONF_t r{0}; r.sr = GCONF(); return r.en_spreadcycle;     }
+bool TMC2208Stepper::shaft()            { TMC2208_n::GCONF_t r{0}; r.sr = GCONF(); return r.shaft;              }
+bool TMC2208Stepper::index_otpw()       { TMC2208_n::GCONF_t r{0}; r.sr = GCONF(); return r.index_otpw;         }
+bool TMC2208Stepper::index_step()       { TMC2208_n::GCONF_t r{0}; r.sr = GCONF(); return r.index_step;         }
+bool TMC2208Stepper::pdn_disable()      { TMC2208_n::GCONF_t r{0}; r.sr = GCONF(); return r.pdn_disable;        }
+bool TMC2208Stepper::mstep_reg_select() { TMC2208_n::GCONF_t r{0}; r.sr = GCONF(); return r.mstep_reg_select;   }
+bool TMC2208Stepper::multistep_filt()   { TMC2208_n::GCONF_t r{0}; r.sr = GCONF(); return r.multistep_filt;     }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/IHOLD_IRUN.cpp	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,20 @@
+#include "TMCStepper.h"
+#include "TMC_MACROS.h"
+
+#define SET_REG(SETTING) IHOLD_IRUN_register.SETTING = B; write(IHOLD_IRUN_register.address, IHOLD_IRUN_register.sr);
+#define GET_REG(SETTING) return IHOLD_IRUN_register.SETTING;
+
+// IHOLD_IRUN
+uint32_t TMCStepper::IHOLD_IRUN() { return IHOLD_IRUN_register.sr; }
+void TMCStepper::IHOLD_IRUN(uint32_t input) {
+    IHOLD_IRUN_register.sr = input;
+    write(IHOLD_IRUN_register.address, IHOLD_IRUN_register.sr);
+}
+
+void    TMCStepper::ihold(uint8_t B)        { SET_REG(ihold);       }
+void    TMCStepper::irun(uint8_t B)         { SET_REG(irun);        }
+void    TMCStepper::iholddelay(uint8_t B)   { SET_REG(iholddelay);  }
+
+uint8_t TMCStepper::ihold()                 { GET_REG(ihold);       }
+uint8_t TMCStepper::irun()                  { GET_REG(irun);        }
+uint8_t TMCStepper::iholddelay()            { GET_REG(iholddelay);  }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/PWMCONF.cpp	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,80 @@
+#include "TMCStepper.h"
+#include "TMC_MACROS.h"
+
+#define SET_REG(SETTING) PWMCONF_register.SETTING = B; write(PWMCONF_register.address, PWMCONF_register.sr)
+#define GET_REG(SETTING) return PWMCONF_register.SETTING
+
+// PWMCONF
+/*
+uint32_t TMC2130Stepper::PWMCONF() { return PWMCONF_register.sr; }
+void TMC2130Stepper::PWMCONF(uint32_t input) {
+	PWMCONF_register.sr = input;
+	write(PWMCONF_register.address, PWMCONF_register.sr);
+}
+
+void TMC2130Stepper::pwm_ampl(		uint8_t B )	{ SET_REG(pwm_ampl);		}
+void TMC2130Stepper::pwm_grad(		uint8_t B )	{ SET_REG(pwm_grad);		}
+void TMC2130Stepper::pwm_freq(		uint8_t B )	{ SET_REG(pwm_freq);		}
+void TMC2130Stepper::pwm_autoscale(	bool 	B )	{ SET_REG(pwm_autoscale);	}
+void TMC2130Stepper::pwm_symmetric(	bool 	B )	{ SET_REG(pwm_symmetric);	}
+void TMC2130Stepper::freewheel(		uint8_t B )	{ SET_REG(freewheel);		}
+
+uint8_t TMC2130Stepper::pwm_ampl()		{ GET_REG(pwm_ampl);		}
+uint8_t TMC2130Stepper::pwm_grad()		{ GET_REG(pwm_grad);		}
+uint8_t TMC2130Stepper::pwm_freq()		{ GET_REG(pwm_freq);		}
+bool 	TMC2130Stepper::pwm_autoscale()	{ GET_REG(pwm_autoscale);	}
+bool 	TMC2130Stepper::pwm_symmetric()	{ GET_REG(pwm_symmetric);	}
+uint8_t TMC2130Stepper::freewheel()		{ GET_REG(freewheel);		}
+
+uint32_t TMC2160Stepper::PWMCONF() {
+	return PWMCONF_register.sr;
+}
+void TMC2160Stepper::PWMCONF(uint32_t input) {
+	PWMCONF_register.sr = input;
+	write(PWMCONF_register.address, PWMCONF_register.sr);
+}
+
+void TMC2160Stepper::pwm_ofs		( uint8_t B ) { PWMCONF_register.pwm_ofs = B; 		write(PWMCONF_register.address, PWMCONF_register.sr); }
+void TMC2160Stepper::pwm_grad		( uint8_t B ) { PWMCONF_register.pwm_grad = B; 		write(PWMCONF_register.address, PWMCONF_register.sr); }
+void TMC2160Stepper::pwm_freq		( uint8_t B ) { PWMCONF_register.pwm_freq = B; 		write(PWMCONF_register.address, PWMCONF_register.sr); }
+void TMC2160Stepper::pwm_autoscale	( bool 	  B ) { PWMCONF_register.pwm_autoscale = B; write(PWMCONF_register.address, PWMCONF_register.sr); }
+void TMC2160Stepper::pwm_autograd	( bool    B ) { PWMCONF_register.pwm_autograd = B; 	write(PWMCONF_register.address, PWMCONF_register.sr); }
+void TMC2160Stepper::freewheel		( uint8_t B ) { PWMCONF_register.freewheel = B; 	write(PWMCONF_register.address, PWMCONF_register.sr); }
+void TMC2160Stepper::pwm_reg		( uint8_t B ) { PWMCONF_register.pwm_reg = B; 		write(PWMCONF_register.address, PWMCONF_register.sr); }
+void TMC2160Stepper::pwm_lim		( uint8_t B ) { PWMCONF_register.pwm_lim = B; 		write(PWMCONF_register.address, PWMCONF_register.sr); }
+
+uint8_t TMC2160Stepper::pwm_ofs()		{ return PWMCONF_register.pwm_ofs;		}
+uint8_t TMC2160Stepper::pwm_grad()		{ return PWMCONF_register.pwm_grad;		}
+uint8_t TMC2160Stepper::pwm_freq()		{ return PWMCONF_register.pwm_freq;		}
+bool 	TMC2160Stepper::pwm_autoscale()	{ return PWMCONF_register.pwm_autoscale;}
+bool 	TMC2160Stepper::pwm_autograd()	{ return PWMCONF_register.pwm_autograd;	}
+uint8_t TMC2160Stepper::freewheel()		{ return PWMCONF_register.freewheel;	}
+uint8_t TMC2160Stepper::pwm_reg()		{ return PWMCONF_register.pwm_reg;		}
+uint8_t TMC2160Stepper::pwm_lim()		{ return PWMCONF_register.pwm_lim;		}
+*/
+uint32_t TMC2208Stepper::PWMCONF() {
+	return read(PWMCONF_register.address);
+}
+void TMC2208Stepper::PWMCONF(uint32_t input) {
+	PWMCONF_register.sr = input;
+	write(PWMCONF_register.address, PWMCONF_register.sr);
+}
+
+void TMC2208Stepper::pwm_ofs		( uint8_t B ) { PWMCONF_register.pwm_ofs = B; write(PWMCONF_register.address, PWMCONF_register.sr); }
+void TMC2208Stepper::pwm_grad		( uint8_t B ) { PWMCONF_register.pwm_grad = B; write(PWMCONF_register.address, PWMCONF_register.sr); }
+void TMC2208Stepper::pwm_freq		( uint8_t B ) { PWMCONF_register.pwm_freq = B; write(PWMCONF_register.address, PWMCONF_register.sr); }
+void TMC2208Stepper::pwm_autoscale	( bool 	  B ) { PWMCONF_register.pwm_autoscale = B; write(PWMCONF_register.address, PWMCONF_register.sr); }
+void TMC2208Stepper::pwm_autograd	( bool    B ) { PWMCONF_register.pwm_autograd = B; write(PWMCONF_register.address, PWMCONF_register.sr); }
+void TMC2208Stepper::freewheel		( uint8_t B ) { PWMCONF_register.freewheel = B; write(PWMCONF_register.address, PWMCONF_register.sr); }
+void TMC2208Stepper::pwm_reg		( uint8_t B ) { PWMCONF_register.pwm_reg = B; write(PWMCONF_register.address, PWMCONF_register.sr); }
+void TMC2208Stepper::pwm_lim		( uint8_t B ) { PWMCONF_register.pwm_lim = B; write(PWMCONF_register.address, PWMCONF_register.sr); }
+
+uint8_t TMC2208Stepper::pwm_ofs()		{ TMC2208_n::PWMCONF_t r{0}; r.sr = PWMCONF(); return r.pwm_ofs;		}
+uint8_t TMC2208Stepper::pwm_grad()		{ TMC2208_n::PWMCONF_t r{0}; r.sr = PWMCONF(); return r.pwm_grad;		}
+uint8_t TMC2208Stepper::pwm_freq()		{ TMC2208_n::PWMCONF_t r{0}; r.sr = PWMCONF(); return r.pwm_freq;		}
+bool 	TMC2208Stepper::pwm_autoscale()	{ TMC2208_n::PWMCONF_t r{0}; r.sr = PWMCONF(); return r.pwm_autoscale;	}
+bool 	TMC2208Stepper::pwm_autograd()	{ TMC2208_n::PWMCONF_t r{0}; r.sr = PWMCONF(); return r.pwm_autograd;	}
+uint8_t TMC2208Stepper::freewheel()		{ TMC2208_n::PWMCONF_t r{0}; r.sr = PWMCONF(); return r.freewheel;		}
+uint8_t TMC2208Stepper::pwm_reg()		{ TMC2208_n::PWMCONF_t r{0}; r.sr = PWMCONF(); return r.pwm_reg;		}
+uint8_t TMC2208Stepper::pwm_lim()		{ TMC2208_n::PWMCONF_t r{0}; r.sr = PWMCONF(); return r.pwm_lim;		}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/TMC2130_bitfields.h	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,235 @@
+#pragma once
+#pragma pack(push, 1)
+
+struct GCONF_t {
+  constexpr static uint8_t address = 0x00;
+  union {
+    uint32_t sr : 18;
+    struct {
+      bool  i_scale_analog : 1, // 2130, 5130
+            internal_rsense : 1, // 2130, 5130
+            en_pwm_mode : 1,
+            enc_commutation : 1, // 2130, 5130
+            shaft : 1,
+            diag0_error : 1,
+            diag0_otpw : 1,
+            diag0_stall : 1,
+            diag1_stall : 1,
+            diag1_index : 1,
+            diag1_onstate : 1,
+            diag1_steps_skipped : 1,
+            diag0_int_pushpull : 1,
+            diag1_pushpull : 1,
+            small_hysteresis : 1,
+            stop_enable : 1,
+            direct_mode : 1;
+    };
+    struct { // TMC5160
+      bool recalibrate : 1,
+           faststandstill : 1,
+                          : 1,
+           multistep_filt : 1,
+                    : 3,
+           diag0_step : 1,
+           diag1_dir : 1,
+                 : 4,
+           diag1_poscomp_pushpull : 1;
+    };
+  };
+};
+
+struct IHOLD_IRUN_t {
+  constexpr static uint8_t address = 0x10;
+  union {
+    uint32_t sr : 20;
+    struct {
+      uint8_t ihold : 5,
+                    : 3,
+              irun : 5,
+                   : 3,
+              iholddelay : 4;
+    };
+  };
+};
+
+struct GSTAT_t {
+  constexpr static uint8_t address = 0x01;
+  union {
+    uint8_t sr : 3;
+    struct {
+      bool  reset : 1,
+            drv_err : 1,
+            uv_cp : 1;
+    };
+  };
+};
+
+struct IOIN_t {
+  constexpr static uint8_t address = 0x04;
+  union {
+    uint32_t sr;
+    struct {
+      bool  step : 1,
+            dir : 1,
+            dcen_cfg4 : 1,
+            dcin_cfg5 : 1,
+            drv_enn_cfg6 : 1,
+            dco : 1,
+            : 2;
+      uint16_t : 16;
+      uint8_t version : 8;
+    };
+  };
+};
+
+struct TPOWERDOWN_t {
+  constexpr static uint8_t address = 0x11;
+  uint8_t sr : 8;
+};
+
+struct TPWMTHRS_t {
+  constexpr static uint8_t address = 0x13;
+  uint32_t sr : 20;
+};
+
+struct TCOOLTHRS_t {
+  constexpr static uint8_t address = 0x14;
+  uint32_t sr : 20;
+};
+
+struct THIGH_t {
+  constexpr static uint8_t address = 0x15;
+  uint32_t sr : 20;
+};
+
+struct XDIRECT_t {
+  constexpr static uint8_t address = 0x2D;
+  union {
+    uint32_t sr : 25;
+    struct {
+      int16_t coil_A : 9;
+      int8_t         : 7;
+      int16_t coil_B : 9;
+    };
+  };
+};
+
+struct VDCMIN_t {
+  constexpr static uint8_t address = 0x33;
+  uint32_t sr : 23;
+};
+
+struct CHOPCONF_t {
+  constexpr static uint8_t address = 0x6C;
+  union {
+    uint32_t sr : 32;
+    struct {
+      uint8_t toff : 4,
+              hstrt : 3,
+              hend : 4,
+                   : 1;
+      bool    disfdcc : 1,
+              rndtf : 1,
+              chm : 1;
+      uint8_t tbl : 2;
+      bool    vsense : 1,
+              vhighfs : 1,
+              vhighchm : 1;
+      uint8_t sync : 4, // 2130, 5130
+              mres : 4;
+      bool    intpol : 1,
+              dedge : 1,
+              diss2g : 1;
+    };
+    struct { // TMC5160
+      uint32_t     : 20;
+      uint8_t tpfd : 4; // 5160
+      uint16_t     : 7;
+      bool diss2vs : 1; // TMC5160 only
+    };
+  };
+};
+
+struct COOLCONF_t {
+  constexpr static uint8_t address = 0x6D;
+  union {
+    uint32_t sr : 25;
+    struct {
+      uint8_t semin : 4,
+                    : 1,
+              seup : 2,
+                    : 1,
+              semax : 4,
+                    : 1,
+              sedn : 2;
+      bool    seimin : 1;
+      int8_t  sgt : 7,
+                  : 1;
+      bool    sfilt : 1;
+    };
+  };
+};
+
+struct DCCTRL_t {
+    constexpr static uint8_t address = 0x6E;
+    union {
+        uint32_t sr : 24;
+        struct {
+            uint16_t dc_time : 10,
+                : 6;
+            uint8_t dc_sg : 8;
+        };
+    };
+};
+
+namespace TMC2130_n {
+  struct DRV_STATUS_t {
+    constexpr static uint8_t address = 0x6F;
+    union {
+      uint32_t sr;
+      struct {
+        uint16_t sg_result : 10;
+        uint8_t            : 5;
+        bool fsactive : 1;
+        uint8_t cs_actual : 5,
+                          : 3;
+        bool  stallGuard : 1,
+              ot : 1,
+              otpw : 1,
+              s2ga : 1,
+              s2gb : 1,
+              ola : 1,
+              olb : 1,
+              stst : 1;
+      };
+    };
+  };
+}
+
+struct PWMCONF_t {
+  constexpr static uint8_t address = 0x70;
+  union {
+    uint32_t sr : 22;
+    struct {
+      uint8_t pwm_ampl : 8,
+              pwm_grad : 8,
+              pwm_freq : 2;
+      bool pwm_autoscale : 1,
+           pwm_symmetric : 1;
+      uint8_t freewheel : 2;
+    };
+  };
+};
+
+struct ENCM_CTRL_t {
+  constexpr static uint8_t address = 0x72;
+  union {
+    uint8_t sr : 2;
+    struct {
+      bool  inv : 1,
+            maxspeed : 1;
+    };
+  };
+};
+
+#pragma pack(pop)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/TMC2160_bitfields.h	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,54 @@
+#pragma once
+#pragma pack(push, 1)
+
+namespace TMC2160_n {
+  struct IOIN_t {
+    constexpr static uint8_t address = 0x04;
+    union {
+      uint32_t sr;
+      struct {
+        bool  refl_step : 1,
+              refr_dir : 1,
+              encb_dcen_cfg4 : 1,
+              enca_dcin_cfg5 : 1,
+              drv_enn : 1,
+              dco_cfg6 : 1,
+              : 2;
+        uint16_t : 16;
+        uint8_t version : 8;
+      };
+    };
+  };
+
+  struct PWMCONF_t {
+    constexpr static uint8_t address = 0x70;
+    union {
+      uint32_t sr;
+      struct {
+        uint8_t pwm_ofs : 8,
+                pwm_grad : 8,
+                pwm_freq : 2;
+        bool pwm_autoscale : 1,
+             pwm_autograd : 1;
+        uint8_t freewheel : 2,
+                          : 2,
+                pwm_reg : 4,
+                pwm_lim : 4;
+      };
+    };
+  };
+
+  struct PWM_SCALE_t {
+    constexpr static uint8_t address = 0x71;
+    union {
+      uint32_t sr : 25;
+      struct {
+        uint8_t pwm_scale_sum : 8,
+                              : 8;
+        uint16_t pwm_scale_auto : 9;
+      };
+    };
+  };
+}
+
+#pragma pack(pop)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/TMC2208Stepper.cpp	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,459 @@
+#include "TMCStepper.h"
+#include "TMC_MACROS.h"
+//#include "SERIAL_SWITCH.h"
+
+// Protected
+// addr needed for TMC2209
+TMC2208Stepper::TMC2208Stepper(Stream * SerialPort, float RS, uint8_t addr) :
+    TMCStepper(RS),
+    slave_address(addr)
+    {
+        HWSerial = SerialPort;
+        defaults();
+    }
+
+TMC2208Stepper::TMC2208Stepper(Stream * SerialPort, float RS, uint8_t addr, uint16_t mul_pin1, uint16_t mul_pin2) :
+    TMC2208Stepper(SerialPort, RS)
+    {
+//        SSwitch *SMulObj = new SSwitch(mul_pin1, mul_pin2, addr);
+//        sswitch = SMulObj;
+    }
+
+#if SW_CAPABLE_PLATFORM
+    // Protected
+    // addr needed for TMC2209
+    TMC2208Stepper::TMC2208Stepper(PinName SW_RX_pin, PinName SW_TX_pin, float RS, uint8_t addr) :
+        TMCStepper(RS),
+        RXTX_pin(SW_RX_pin == SW_TX_pin ? SW_RX_pin : 0),
+        slave_address(addr)
+        {
+            BufferedSerial *SWSerialObj = new BufferedSerial(SW_TX_pin, SW_RX_pin);
+            SWSerial = SWSerialObj;
+            defaults();
+        }
+
+    void TMC2208Stepper::beginSerial(uint32_t baudrate) {
+        if (SWSerial != nullptr)
+        {
+            //SWSerial->begin(baudrate);
+            //SWSerial->end();
+            SWSerial->set_baud(baudrate);
+            SWSerial->set_format(
+                        /* bits */ 8,
+                        /* parity */ BufferedSerial::None,
+                        /* stop bit */ 1
+                    );
+            SWSerial->set_blocking(true);
+        }
+//        #if defined(ARDUINO_ARCH_AVR)
+//            if (RXTX_pin > 0) {
+//                digitalWrite(RXTX_pin, HIGH);
+//                pinMode(RXTX_pin, OUTPUT);
+//           }
+//        #endif
+    }
+#endif
+
+void TMC2208Stepper::begin() {
+    #if SW_CAPABLE_PLATFORM
+        beginSerial(115200);
+        //beginSerial(9600);
+    #endif
+    pdn_disable(true);
+    mstep_reg_select(true);
+    //Wait to initialize
+    wait_us(replyDelay*1000);
+
+}
+
+void TMC2208Stepper::defaults() {
+    GCONF_register.i_scale_analog = 1;
+    GCONF_register.internal_rsense = 0; // OTP
+    GCONF_register.en_spreadcycle = 0; // OTP
+    GCONF_register.multistep_filt = 1; // OTP
+    IHOLD_IRUN_register.iholddelay = 1; // OTP
+    TPOWERDOWN_register.sr = 20;
+    CHOPCONF_register.sr = 0x10000053;
+    PWMCONF_register.sr = 0xC10D0024;
+  //MSLUT0_register.sr = ???;
+  //MSLUT1_register.sr = ???;
+  //MSLUT2_register.sr = ???;
+  //MSLUT3_register.sr = ???;
+  //MSLUT4_register.sr = ???;
+  //MSLUT5_register.sr = ???;
+  //MSLUT6_register.sr = ???;
+  //MSLUT7_register.sr = ???;
+  //MSLUTSTART_register.start_sin90 = 247;
+}
+
+void TMC2208Stepper::push() {
+    GCONF(GCONF_register.sr);
+    IHOLD_IRUN(IHOLD_IRUN_register.sr);
+    SLAVECONF(SLAVECONF_register.sr);
+    TPOWERDOWN(TPOWERDOWN_register.sr);
+    TPWMTHRS(TPWMTHRS_register.sr);
+    VACTUAL(VACTUAL_register.sr);
+    CHOPCONF(CHOPCONF_register.sr);
+    PWMCONF(PWMCONF_register.sr);
+}
+
+bool TMC2208Stepper::isEnabled() { return !enn() && toff(); }
+
+uint8_t TMC2208Stepper::calcCRC(uint8_t datagram[], uint8_t len) {
+    uint8_t crc = 0;
+    for (uint8_t i = 0; i < len; i++) {
+        uint8_t currentByte = datagram[i];
+        for (uint8_t j = 0; j < 8; j++) {
+            if ((crc >> 7) ^ (currentByte & 0x01)) {
+                crc = (crc << 1) ^ 0x07;
+            } else {
+                crc = (crc << 1);
+            }
+            crc &= 0xff;
+            currentByte = currentByte >> 1;
+        }
+    }
+    return crc;
+}
+
+__attribute__((weak))
+int TMC2208Stepper::available() {
+    int out = 0;
+    #if SW_CAPABLE_PLATFORM
+        if (SWSerial != nullptr) {
+//            out = SWSerial->available();
+out = 1;
+        } else
+    #endif
+        if (HWSerial != nullptr) {
+//            out = HWSerial->available();
+out = 1;
+        }
+
+    return out;
+}
+
+__attribute__((weak))
+void TMC2208Stepper::preWriteCommunication() {
+    if (HWSerial != nullptr) {
+//        if (sswitch != nullptr)
+//            sswitch->active();
+    }
+}
+
+__attribute__((weak))
+void TMC2208Stepper::preReadCommunication() {
+    #if SW_CAPABLE_PLATFORM
+        if (SWSerial != nullptr) {
+//            SWSerial->listen();
+        } else
+    #endif
+        if (HWSerial != nullptr) {
+//            if (sswitch != nullptr)
+//                sswitch->active();
+        }
+}
+
+__attribute__((weak))
+int16_t TMC2208Stepper::serial_read() {
+    int16_t out = 0;
+    int16_t count = 0;
+     
+    #if SW_CAPABLE_PLATFORM
+        if (SWSerial != nullptr) {
+//            out = SWSerial->read();
+            count = SWSerial->read(&out, 1); // read one character
+//            if (SWSerial->readable()) {
+//                SWSerial->read(&out, 1); // read one character
+//            }
+
+        } else
+    #endif
+        if (HWSerial != nullptr) {
+//            out = HWSerial->read();
+            HWSerial->read(&out, 1); // read one character
+        }
+    if (count >= 1) {
+//       printf("<%02X|",out);
+       return out;
+    } else {
+        return -1;
+    }
+}
+
+__attribute__((weak))
+uint8_t TMC2208Stepper::serial_write(const uint8_t data) {
+    int out = 0;
+    #if SW_CAPABLE_PLATFORM
+        if (SWSerial != nullptr) {
+//            printf(">%02X|",data);
+            return SWSerial->write(&data,1);
+        } else
+    #endif
+        if (HWSerial != nullptr) {
+            return HWSerial->write(&data,1);
+        }
+
+    return out;
+}
+
+__attribute__((weak))
+void TMC2208Stepper::postWriteCommunication() {}
+
+__attribute__((weak))
+void TMC2208Stepper::postReadCommunication() {
+    #if SW_CAPABLE_PLATFORM
+//        if (SWSerial != nullptr) {
+//            SWSerial->end();
+//        }
+    #endif
+}
+
+void TMC2208Stepper::write(uint8_t addr, uint32_t regVal) {
+    uint8_t len = 7;
+    addr |= TMC_WRITE;
+    uint8_t datagram[] = {TMC2208_SYNC, slave_address, addr, (uint8_t)(regVal>>24), (uint8_t)(regVal>>16), (uint8_t)(regVal>>8), (uint8_t)(regVal>>0), 0x00};
+
+    datagram[len] = calcCRC(datagram, len);
+
+    preWriteCommunication();
+
+    for(uint8_t i=0; i<=len; i++) {
+        bytesWritten += serial_write(datagram[i]);
+    }
+    postWriteCommunication();
+
+    //delay(replyDelay);
+    wait_us(replyDelay*1000);
+}
+
+uint64_t TMC2208Stepper::_sendDatagram(uint8_t datagram[], const uint8_t len, uint16_t timeout) {
+
+//  while (available() > 0) serial_read(); // Flush
+    SWSerial->sync();
+/*    uint8_t dummy;
+    while (SWSerial->readable()) {
+        SWSerial->read(&dummy, 1); // read one character
+    }
+*/    
+/*    uint8_t dummy;
+    while (SWSerial->read(&dummy, 1) >= 0) {
+        ;
+    }    
+*/
+
+    #if defined(ARDUINO_ARCH_AVR)
+        if (RXTX_pin > 0) {
+            digitalWrite(RXTX_pin, HIGH);
+            pinMode(RXTX_pin, OUTPUT);
+        }
+    #endif
+
+    for(int i=0; i<=len; i++) serial_write(datagram[i]);
+
+    #if defined(ARDUINO_ARCH_AVR)
+        if (RXTX_pin > 0) {
+            pinMode(RXTX_pin, INPUT_PULLUP);
+        }
+    #endif
+
+    //delay(this->replyDelay);
+    wait_us(this->replyDelay*1000*2);
+
+    // scan for the rx frame and read it
+
+//    uint32_t ms = millis();
+    uint32_t sync_target = (static_cast<uint32_t>(datagram[0])<<16) | 0xFF00 | datagram[2];
+    uint32_t sync = 0;
+
+
+    do {
+/*        uint32_t ms2 = millis();
+        if (ms2 != ms) {
+            // 1ms tick
+            ms = ms2;
+            timeout--;
+        }
+        if (!timeout) return 0;
+*/
+        int16_t res = serial_read();
+        if (res < 0) continue;
+
+        sync <<= 8;
+        sync |= res & 0xFF;
+        sync &= 0xFFFFFF;
+
+    } while (sync != sync_target);
+
+    uint64_t out = sync;
+ //   ms = millis();
+ //   timeout = this->abort_window;
+
+    for(uint8_t i=0; i<5;) {
+/*        uint32_t ms2 = millis();
+        if (ms2 != ms) {
+            // 1ms tick
+            ms = ms2;
+            timeout--;
+        }
+        if (!timeout) return 0;
+*/
+        int16_t res = serial_read();
+        if (res < 0) continue;
+
+        out <<= 8;
+        out |= res & 0xFF;
+
+        i++;
+    }
+
+    #if defined(ARDUINO_ARCH_AVR)
+        if (RXTX_pin > 0) {
+            digitalWrite(RXTX_pin, HIGH);
+            pinMode(RXTX_pin, OUTPUT);
+        }
+    #endif
+
+//    while (available() > 0) serial_read(); // Flush
+    SWSerial->sync();
+
+    return out;
+
+
+}
+
+uint32_t TMC2208Stepper::read(uint8_t addr) {
+    constexpr uint8_t len = 3;
+    addr |= TMC_READ;
+    uint8_t datagram[] = {TMC2208_SYNC, slave_address, addr, 0x00};
+    datagram[len] = calcCRC(datagram, len);
+    uint64_t out = 0x00000000UL;
+
+    for (uint8_t i = 0; i < max_retries; i++) {
+        preReadCommunication();
+        out = _sendDatagram(datagram, len, abort_window);
+        postReadCommunication();
+
+//        delay(replyDelay);
+//        wait_us(replyDelay*1000);
+
+        CRCerror = false;
+        uint8_t out_datagram[] = {
+            static_cast<uint8_t>(out>>56),
+            static_cast<uint8_t>(out>>48),
+            static_cast<uint8_t>(out>>40),
+            static_cast<uint8_t>(out>>32),
+            static_cast<uint8_t>(out>>24),
+            static_cast<uint8_t>(out>>16),
+            static_cast<uint8_t>(out>> 8),
+            static_cast<uint8_t>(out>> 0)
+        };
+        uint8_t crc = calcCRC(out_datagram, 7);
+        if ((crc != static_cast<uint8_t>(out)) || crc == 0 ) {
+            CRCerror = true;
+            out = 0;
+        } else {
+            break;
+        }
+    }
+
+    return out>>8;
+}
+
+uint8_t TMC2208Stepper::IFCNT() {
+    return read(IFCNT_t::address);
+}
+
+void TMC2208Stepper::SLAVECONF(uint16_t input) {
+    SLAVECONF_register.sr = input&0xF00;
+    write(SLAVECONF_register.address, SLAVECONF_register.sr);
+}
+uint16_t TMC2208Stepper::SLAVECONF() {
+    return SLAVECONF_register.sr;
+}
+void TMC2208Stepper::senddelay(uint8_t B)   { SLAVECONF_register.senddelay = B; write(SLAVECONF_register.address, SLAVECONF_register.sr); }
+uint8_t TMC2208Stepper::senddelay()         { return SLAVECONF_register.senddelay; }
+
+void TMC2208Stepper::OTP_PROG(uint16_t input) {
+    write(OTP_PROG_t::address, input);
+}
+
+uint32_t TMC2208Stepper::OTP_READ() {
+    return read(OTP_READ_t::address);
+}
+
+uint32_t TMC2208Stepper::IOIN() {
+    return read(TMC2208_n::IOIN_t::address);
+}
+bool TMC2208Stepper::enn()          { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.enn;      }
+bool TMC2208Stepper::ms1()          { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.ms1;      }
+bool TMC2208Stepper::ms2()          { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.ms2;      }
+bool TMC2208Stepper::diag()         { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.diag;     }
+bool TMC2208Stepper::pdn_uart()     { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.pdn_uart; }
+bool TMC2208Stepper::step()         { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.step;     }
+bool TMC2208Stepper::sel_a()        { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.sel_a;    }
+bool TMC2208Stepper::dir()          { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.dir;      }
+uint8_t TMC2208Stepper::version()   { TMC2208_n::IOIN_t r{0}; r.sr = IOIN(); return r.version;  }
+
+/*
+uint32_t TMC2224Stepper::IOIN() {
+    return read(TMC2224_n::IOIN_t::address);
+}
+bool TMC2224Stepper::enn()          { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.enn;      }
+bool TMC2224Stepper::ms1()          { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.ms1;      }
+bool TMC2224Stepper::ms2()          { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.ms2;      }
+bool TMC2224Stepper::pdn_uart()     { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.pdn_uart; }
+bool TMC2224Stepper::spread()       { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.spread;   }
+bool TMC2224Stepper::step()         { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.step;     }
+bool TMC2224Stepper::sel_a()        { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.sel_a;    }
+bool TMC2224Stepper::dir()          { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.dir;      }
+uint8_t TMC2224Stepper::version()   { TMC2224_n::IOIN_t r{0}; r.sr = IOIN(); return r.version;  }
+*/
+uint16_t TMC2208Stepper::FACTORY_CONF() {
+    return read(FACTORY_CONF_register.address);
+}
+void TMC2208Stepper::FACTORY_CONF(uint16_t input) {
+    FACTORY_CONF_register.sr = input;
+    write(FACTORY_CONF_register.address, FACTORY_CONF_register.sr);
+}
+void TMC2208Stepper::fclktrim(uint8_t B){ FACTORY_CONF_register.fclktrim = B; write(FACTORY_CONF_register.address, FACTORY_CONF_register.sr); }
+void TMC2208Stepper::ottrim(uint8_t B)  { FACTORY_CONF_register.ottrim = B; write(FACTORY_CONF_register.address, FACTORY_CONF_register.sr); }
+uint8_t TMC2208Stepper::fclktrim()      { FACTORY_CONF_t r{0}; r.sr = FACTORY_CONF(); return r.fclktrim; }
+uint8_t TMC2208Stepper::ottrim()        { FACTORY_CONF_t r{0}; r.sr = FACTORY_CONF(); return r.ottrim; }
+
+void TMC2208Stepper::VACTUAL(uint32_t input) {
+    VACTUAL_register.sr = input;
+    write(VACTUAL_register.address, VACTUAL_register.sr);
+}
+uint32_t TMC2208Stepper::VACTUAL() {
+    return VACTUAL_register.sr;
+}
+
+uint32_t TMC2208Stepper::PWM_SCALE() {
+    return read(TMC2208_n::PWM_SCALE_t::address);
+}
+uint8_t TMC2208Stepper::pwm_scale_sum() {
+    TMC2208_n::PWM_SCALE_t r{0};
+    r.sr = PWM_SCALE();
+    return r.pwm_scale_sum;
+}
+
+int16_t TMC2208Stepper::pwm_scale_auto() {
+    TMC2208_n::PWM_SCALE_t r{0};
+    r.sr = PWM_SCALE();
+    return r.pwm_scale_auto;
+    // Not two's complement? 9nth bit determines sign
+    /*
+    uint32_t d = PWM_SCALE();
+    int16_t response = (d>>PWM_SCALE_AUTO_bp)&0xFF;
+    if (((d&PWM_SCALE_AUTO_bm) >> 24) & 0x1) return -response;
+    else return response;
+    */
+}
+
+// R: PWM_AUTO
+uint32_t TMC2208Stepper::PWM_AUTO() {
+    return read(PWM_AUTO_t::address);
+}
+uint8_t TMC2208Stepper::pwm_ofs_auto()  { PWM_AUTO_t r{0}; r.sr = PWM_AUTO(); return r.pwm_ofs_auto; }
+uint8_t TMC2208Stepper::pwm_grad_auto() { PWM_AUTO_t r{0}; r.sr = PWM_AUTO(); return r.pwm_grad_auto; }
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/TMC2208_bitfields.h	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,181 @@
+#pragma once
+#pragma pack(push, 1)
+
+namespace TMC2208_n {
+  struct GCONF_t {
+    constexpr static uint8_t address = 0x00;
+    union {
+      uint16_t sr : 10;
+      struct {
+        bool  i_scale_analog : 1,
+              internal_rsense : 1,
+              en_spreadcycle : 1,
+              shaft : 1,
+              index_otpw : 1,
+              index_step : 1,
+              pdn_disable : 1,
+              mstep_reg_select : 1,
+              multistep_filt : 1,
+              test_mode : 1;
+      };
+    };
+  };
+}
+
+namespace TMC2208_n {
+  struct IOIN_t {
+    constexpr static uint8_t address = 0x06;
+    union {
+      uint32_t sr;
+      struct {
+        bool  enn : 1,
+              : 1,
+              ms1 : 1,
+              ms2 : 1,
+              diag : 1,
+              : 1,
+              pdn_uart : 1,
+              step : 1,
+              sel_a : 1,
+              dir : 1;
+        uint16_t : 14;
+        uint8_t version : 8;
+      };
+    };
+  };
+}
+
+namespace TMC2224_n {
+  struct IOIN_t {
+    constexpr static uint8_t address = 0x06;
+    union {
+      uint32_t sr;
+      struct {
+        bool  : 1,
+              pdn_uart : 1,
+              spread : 1,
+              dir : 1,
+              enn : 1,
+              step : 1,
+              ms1 : 1,
+              ms2 : 1,
+              sel_a : 1;
+        uint16_t : 15;
+        uint8_t version : 8;
+      };
+    };
+  };
+}
+
+struct FACTORY_CONF_t {
+  constexpr static uint8_t address = 0x07;
+  union {
+    uint16_t sr;
+    struct {
+        uint8_t fclktrim : 5,
+                         : 3,
+                ottrim : 2;
+    };
+  };
+};
+
+namespace TMC2208_n {
+  struct VACTUAL_t {
+    constexpr static uint8_t address = 0x22;
+    uint32_t sr;
+  };
+}
+
+struct MSCURACT_t {
+  constexpr static uint8_t address = 0x6B;
+  union {
+    uint32_t sr : 25;
+    struct {
+      int16_t cur_a : 9,
+                    : 7,
+              cur_b : 9;
+    };
+  };
+};
+
+namespace TMC2208_n {
+  struct CHOPCONF_t {
+    constexpr static uint8_t address = 0x6C;
+    union {
+      uint32_t sr;
+      struct {
+        uint8_t toff : 4,
+                hstrt : 3,
+                hend : 4,
+                     : 4,
+                tbl : 2;
+        bool    vsense : 1;
+        uint8_t : 6,
+                mres : 4;
+        bool    intpol : 1,
+                dedge : 1,
+                diss2g : 1,
+                diss2vs : 1;
+      };
+    };
+  };
+
+  struct PWMCONF_t {
+    constexpr static uint8_t address = 0x70;
+    union {
+      uint32_t sr;
+      struct {
+        uint8_t pwm_ofs : 8,
+                pwm_grad : 8,
+                pwm_freq : 2;
+        bool pwm_autoscale : 1,
+             pwm_autograd : 1;
+        uint8_t freewheel : 2,
+                          : 2,
+                pwm_reg : 4,
+                pwm_lim : 4;
+      };
+    };
+  };
+
+  struct DRV_STATUS_t {
+    constexpr static uint8_t address = 0x6F;
+    union {
+      uint32_t sr;
+      struct {
+        bool otpw : 1,
+             ot : 1,
+             s2ga : 1,
+             s2gb : 1,
+             s2vsa : 1,
+             s2vsb : 1,
+             ola : 1,
+             olb : 1,
+             t120 : 1,
+             t143 : 1,
+             t150 : 1,
+             t157 : 1;
+        uint8_t : 4,
+                cs_actual : 5,
+                : 3,
+                : 6;
+        bool stealth : 1,
+             stst : 1;
+      };
+    };
+  };
+
+  struct PWM_SCALE_t {
+    constexpr static uint8_t address = 0x71;
+    union {
+      uint32_t sr;
+      struct {
+        uint8_t pwm_scale_sum : 8,
+                : 8;
+        int16_t pwm_scale_auto : 9;
+      };
+    };
+  };
+}
+
+#pragma pack(pop)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/TMC2209Stepper.cpp	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,45 @@
+#include "TMCStepper.h"
+
+uint32_t TMC2209Stepper::IOIN() {
+    return read(TMC2209_n::IOIN_t::address);
+}
+bool TMC2209Stepper::enn()          { TMC2209_n::IOIN_t r{0}; r.sr = IOIN(); return r.enn;      }
+bool TMC2209Stepper::ms1()          { TMC2209_n::IOIN_t r{0}; r.sr = IOIN(); return r.ms1;      }
+bool TMC2209Stepper::ms2()          { TMC2209_n::IOIN_t r{0}; r.sr = IOIN(); return r.ms2;      }
+bool TMC2209Stepper::diag()         { TMC2209_n::IOIN_t r{0}; r.sr = IOIN(); return r.diag;     }
+bool TMC2209Stepper::pdn_uart()     { TMC2209_n::IOIN_t r{0}; r.sr = IOIN(); return r.pdn_uart; }
+bool TMC2209Stepper::step()         { TMC2209_n::IOIN_t r{0}; r.sr = IOIN(); return r.step;     }
+bool TMC2209Stepper::spread_en()    { TMC2209_n::IOIN_t r{0}; r.sr = IOIN(); return r.spread_en;}
+bool TMC2209Stepper::dir()          { TMC2209_n::IOIN_t r{0}; r.sr = IOIN(); return r.dir;      }
+uint8_t TMC2209Stepper::version()   { TMC2209_n::IOIN_t r{0}; r.sr = IOIN(); return r.version;  }
+
+void TMC2209Stepper::push() {
+    IHOLD_IRUN(IHOLD_IRUN_register.sr);
+    TPOWERDOWN(TPOWERDOWN_register.sr);
+    TPWMTHRS(TPWMTHRS_register.sr);
+    GCONF(GCONF_register.sr);
+    SLAVECONF(SLAVECONF_register.sr);
+    VACTUAL(VACTUAL_register.sr);
+    CHOPCONF(CHOPCONF_register.sr);
+    PWMCONF(PWMCONF_register.sr);
+    TCOOLTHRS(TCOOLTHRS_register.sr);
+}
+
+void TMC2209Stepper::SGTHRS(uint8_t input) {
+    SGTHRS_register.sr = input;
+    write(SGTHRS_register.address, SGTHRS_register.sr);
+}
+uint8_t TMC2209Stepper::SGTHRS() {
+    return SGTHRS_register.sr;
+}
+
+// W: TCOOLTHRS
+uint32_t TMC2209Stepper::TCOOLTHRS() { return TCOOLTHRS_register.sr; }
+void TMC2209Stepper::TCOOLTHRS(uint32_t input) {
+  TCOOLTHRS_register.sr = input;
+  write(TCOOLTHRS_register.address, TCOOLTHRS_register.sr);
+}
+
+uint16_t TMC2209Stepper::SG_RESULT() {
+    return read(TMC2209_n::SG_RESULT_t::address);
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/TMC2209_bitfields.h	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,54 @@
+#pragma once
+#pragma pack(push, 1)
+
+namespace TMC2209_n {
+  struct IOIN_t {
+    constexpr static uint8_t address = 0x06;
+    union {
+      uint32_t sr;
+      struct {
+        bool  enn : 1,
+                  : 1,
+              ms1 : 1,
+              ms2 : 1,
+              diag : 1,
+                   : 1,
+              pdn_uart : 1,
+              step : 1,
+              spread_en : 1,
+              dir : 1;
+        uint16_t : 14;
+        uint8_t version : 8;
+      };
+    };
+  };
+
+  struct SGTHRS_t {
+    constexpr static uint8_t address = 0x40;
+    uint8_t sr : 8;
+  };
+
+  struct SG_RESULT_t {
+    constexpr static uint8_t address = 0x41;
+    uint16_t sr : 10;
+  };
+
+  struct COOLCONF_t {
+    constexpr static uint8_t address = 0x42;
+    union {
+      uint16_t sr;
+      struct {
+        uint8_t semin : 4,
+                      : 1,
+                seup : 2,
+                      : 1,
+                semax : 4,
+                      : 1,
+                sedn : 2;
+        bool    seimin : 1;
+      };
+    };
+  };
+}
+
+#pragma pack(pop)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/TMC2660_bitfields.h	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,153 @@
+#pragma once
+#pragma pack(push, 1)
+/*
+struct DRVCTRL_1_t {
+  constexpr static uint8_t address = 0b00;
+  union {
+    uint32_t sr;
+    struct {
+      uint8_t cb : 8;
+      bool phb : 1;
+      uint8_t ca : 8;
+      bool pha : 1;
+    };
+  };
+};
+
+struct DRVCTRL_0_t {
+  constexpr static uint8_t address = 0b00;
+  union {
+    uint32_t sr;
+    struct {
+      uint8_t mres : 4;
+      uint8_t : 4;
+      bool dedge : 1;
+      bool intpol : 1;
+    };
+  };
+};
+
+namespace TMC2660_n {
+  struct CHOPCONF_t {
+    constexpr static uint8_t address = 0b100;
+    union {
+      uint32_t sr;
+      struct {
+        uint8_t toff : 4;
+        uint8_t hstrt : 3;
+        uint8_t hend : 4;
+        uint8_t hdec : 2;
+        bool rndtf : 1;
+        bool chm : 1;
+        uint8_t tbl : 2;
+      };
+    };
+  };
+}
+
+struct SMARTEN_t {
+  constexpr static uint8_t address = 0b101;
+  union {
+    uint32_t sr;
+    struct {
+      uint8_t semin : 4,
+                    : 1,
+              seup  : 2,
+                    : 1,
+              semax : 4,
+                    : 1,
+              sedn : 2;
+      bool seimin : 1;
+    };
+  };
+};
+
+struct SGCSCONF_t {
+  constexpr static uint8_t address = 0b110;
+  union {
+    uint32_t sr;
+    struct {
+      uint8_t cs : 5;
+      uint8_t    : 3;
+      uint8_t sgt : 7;
+      uint8_t : 1;
+      bool sfilt : 1;
+    };
+  };
+};
+
+struct DRVCONF_t {
+  constexpr static uint8_t address = 0b111;
+  union {
+    uint32_t sr;
+    struct {
+      uint8_t : 4;
+      uint8_t rdsel : 2;
+      bool vsense : 1;
+      bool sdoff : 1;
+      uint8_t ts2g : 2;
+      bool diss2g : 1;
+      uint8_t : 1;
+      uint8_t slpl : 2;
+      uint8_t slph : 2;
+      bool tst : 1;
+    };
+  };
+};
+
+struct READ_RDSEL00_t {
+  union {
+    uint32_t sr;
+    struct {
+      bool  sg_value : 1,
+            ot : 1,
+            otpw : 1,
+            s2ga : 1,
+            s2gb : 1,
+            ola : 1,
+            olb : 1,
+            stst : 1;
+      uint8_t : 2;
+      uint16_t mstep : 10;
+    };
+  };
+};
+
+struct READ_RDSEL01_t {
+  union {
+    uint32_t sr;
+    struct {
+      bool  sg_value : 1,
+            ot : 1,
+            otpw : 1,
+            s2ga : 1,
+            s2gb : 1,
+            ola : 1,
+            olb : 1,
+            stst : 1;
+      uint8_t : 2;
+      uint16_t sg_result : 10;
+    };
+  };
+};
+
+struct READ_RDSEL10_t {
+  union {
+    uint32_t sr;
+    struct {
+      bool  sg_value : 1,
+            ot : 1,
+            otpw : 1,
+            s2ga : 1,
+            s2gb : 1,
+            ola : 1,
+            olb : 1,
+            stst : 1;
+      uint8_t : 2;
+      uint8_t se : 5;
+      uint8_t sg_result : 5;
+    };
+  };
+};
+*/
+#pragma pack(pop)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/TMC5130_bitfields.h	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,238 @@
+#pragma once
+#pragma pack(push, 1)
+
+struct SLAVECONF_t {
+  constexpr static uint8_t address = 0x03;
+  union {
+    uint16_t sr : 12;
+    struct {
+      uint8_t slaveaddr : 8;
+      uint8_t senddelay : 4;
+    };
+  };
+};
+
+namespace TMC5130_n {
+  struct IOIN_t {
+    constexpr static uint8_t address = 0x04;
+    union {
+      uint32_t sr;
+      struct {
+        bool  refl_step : 1,
+              refr_dir : 1,
+              encb_dcen_cfg4 : 1,
+              enca_dcin_cfg5 : 1,
+              drv_enn_cfg6 : 1,
+              enc_n_dco : 1,
+              sd_mode : 1,
+              swcomp_in : 1;
+        uint16_t : 16;
+        uint8_t version : 8;
+      };
+    };
+  };
+}
+
+struct OUTPUT_t {
+  constexpr static uint8_t address = 0x04;
+  bool sr : 1;
+};
+
+struct X_COMPARE_t {
+  constexpr static uint8_t address = 0x05;
+  uint32_t sr;
+};
+
+struct RAMPMODE_t {
+  constexpr static uint8_t address = 0x20;
+  uint8_t sr : 2;
+};
+
+struct XACTUAL_t {
+  constexpr static uint8_t address = 0x21;
+  uint32_t sr;
+};
+
+struct VSTART_t {
+  constexpr static uint8_t address = 0x23;
+  uint32_t sr : 18;
+};
+
+struct A1_t {
+  constexpr static uint8_t address = 0x24;
+  uint16_t sr : 16;
+};
+
+struct V1_t {
+  constexpr static uint8_t address = 0x25;
+  uint32_t sr : 20;
+};
+
+struct AMAX_t {
+  constexpr static uint8_t address = 0x26;
+  uint16_t sr : 16;
+};
+
+struct VMAX_t {
+  constexpr static uint8_t address = 0x27;
+  uint32_t sr : 23;
+};
+
+struct DMAX_t {
+  constexpr static uint8_t address = 0x28;
+  uint16_t sr : 16;
+};
+
+struct D1_t {
+  constexpr static uint8_t address = 0x2A;
+  uint16_t sr : 16;
+};
+
+struct VSTOP_t {
+  constexpr static uint8_t address = 0x2B;
+  uint32_t sr : 18;
+};
+
+struct TZEROWAIT_t {
+  constexpr static uint8_t address = 0x2C;
+  uint16_t sr : 16;
+};
+
+struct SW_MODE_t {
+  constexpr static uint8_t address = 0x34;
+  union {
+    uint16_t sr : 12;
+    struct {
+      bool  stop_l_enable : 1,
+            stop_r_enable : 1,
+            pol_stop_l : 1,
+            pol_stop_r : 1,
+            swap_lr : 1,
+            latch_l_active : 1,
+            latch_l_inactive : 1,
+            latch_r_active : 1,
+            latch_r_inactive : 1,
+            en_latch_encoder : 1,
+            sg_stop : 1,
+            en_softstop : 1;
+    };
+  };
+};
+
+struct RAMP_STAT_t {
+  constexpr static uint8_t address = 0x35;
+  union {
+    uint16_t sr : 14;
+    struct {
+      bool  status_stop_l : 1,
+            status_stop_r : 1,
+            status_latch_l : 1,
+            status_latch_r : 1,
+            event_stop_l : 1,
+            event_stop_r : 1,
+            event_stop_sg : 1,
+            event_pos_reached : 1,
+            velocity_reached : 1,
+            position_reached : 1,
+            vzero : 1,
+            t_zerowait_active : 1,
+            second_move : 1,
+            status_sg : 1;
+    };
+  };
+};
+
+struct ENCMODE_t {
+  constexpr static uint8_t address = 0x38;
+  union {
+    uint16_t sr : 11;
+    struct {
+      bool  pol_a : 1,
+            pol_b : 1,
+            pol_n : 1,
+            ignore_ab : 1,
+            clr_cont : 1,
+            clr_once : 1,
+            pos_edge : 1,
+            neg_edge : 1,
+            clr_enc_x : 1,
+            latch_x_act : 1,
+            enc_sel_decimal : 1;
+    };
+  };
+};
+
+struct ENC_CONST_t {
+  constexpr static uint8_t address = 0x3A;
+  uint32_t sr;
+};
+
+struct MSLUT0_t {
+  constexpr static uint8_t address = 0x60;
+  uint32_t sr;
+};
+
+struct MSLUT1_t {
+  constexpr static uint8_t address = 0x61;
+  uint32_t sr;
+};
+
+struct MSLUT2_t {
+  constexpr static uint8_t address = 0x62;
+  uint32_t sr;
+};
+
+struct MSLUT3_t {
+  constexpr static uint8_t address = 0x63;
+  uint32_t sr;
+};
+
+struct MSLUT4_t {
+  constexpr static uint8_t address = 0x64;
+  uint32_t sr;
+};
+
+struct MSLUT5_t {
+  constexpr static uint8_t address = 0x65;
+  uint32_t sr;
+};
+
+struct MSLUT6_t {
+  constexpr static uint8_t address = 0x66;
+  uint32_t sr;
+};
+
+struct MSLUT7_t {
+  constexpr static uint8_t address = 0x67;
+  uint32_t sr;
+};
+
+struct MSLUTSEL_t {
+  constexpr static uint8_t address = 0x68;
+  union {
+    uint32_t sr;
+    struct {
+      uint8_t w0 : 2,
+              w1 : 2,
+              w2 : 2,
+              w3 : 2,
+              x1 : 8,
+              x2 : 8,
+              x3 : 8;
+    };
+  };
+};
+
+struct MSLUTSTART_t {
+  constexpr static uint8_t address = 0x69;
+  union {
+    uint32_t sr : 24;
+    struct {
+      uint8_t start_sin : 8,
+                        : 8,
+              start_sin90 : 8;
+    };
+  };
+};
+
+#pragma pack(pop)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/TMC5160_bitfields.h	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,61 @@
+#pragma once
+#pragma pack(push, 1)
+
+struct SHORT_CONF_t {
+  constexpr static uint8_t address = 0x09;
+  union {
+    uint32_t sr : 19;
+    struct {
+      uint8_t s2vs_level  : 4,
+                          : 4,
+              s2g_level   : 4,
+                          : 4,
+              shortfilter : 2;
+      bool shortdelay : 1;
+    };
+  };
+};
+
+struct DRV_CONF_t {
+  constexpr static uint8_t address = 0x0A;
+  union {
+    uint32_t sr : 22;
+    struct {
+      uint8_t bbmtime : 5,
+                      : 3,
+              bbmclks : 4,
+                      : 4,
+              otselect : 2,
+              drvstrength : 2,
+              filt_isense : 2;
+    };
+  };
+};
+
+struct GLOBAL_SCALER_t {
+  constexpr static uint8_t address = 0x0B;
+  uint8_t sr;
+};
+
+struct OFFSET_READ_t {
+  constexpr static uint8_t address = 0x0C;
+};
+
+struct ENC_DEVIATION_t {
+  constexpr static uint8_t address = 0x3D;
+  uint32_t sr : 20;
+};
+
+struct PWM_AUTO_t {
+  constexpr static uint8_t address = 0x72;
+  union {
+    uint32_t sr : 24;
+    struct {
+      uint8_t pwm_ofs_auto : 8,
+                           : 8,
+              pwm_grad_auto : 8;
+    };
+  };
+};
+
+#pragma pack(pop)
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/TMCStepper.cpp	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,157 @@
+#include "TMCStepper.h"
+
+
+/*
+  Requested current = mA = I_rms/1000
+  Equation for current:
+  I_rms = (CS+1)/32 * V_fs/(R_sense+0.02ohm) * 1/sqrt(2)
+  Solve for CS ->
+  CS = 32*sqrt(2)*I_rms*(R_sense+0.02)/V_fs - 1
+
+  Example:
+  vsense = 0b0 -> V_fs = 0.325V
+  mA = 1640mA = I_rms/1000 = 1.64A
+  R_sense = 0.10 Ohm
+  ->
+  CS = 32*sqrt(2)*1.64*(0.10+0.02)/0.325 - 1 = 26.4
+  CS = 26
+*/
+
+uint16_t TMCStepper::cs2rms(uint8_t CS) {
+  return (float)(CS+1)/32.0 * (vsense() ? 0.180 : 0.325)/(Rsense+0.02) / 1.41421 * 1000;
+}
+
+void TMCStepper::rms_current(uint16_t mA) {
+  uint8_t CS = 32.0*1.41421*mA/1000.0*(Rsense+0.02)/0.325 - 1;
+  // If Current Scale is too low, turn on high sensitivity R_sense and calculate again
+  if (CS < 16) {
+    vsense(true);
+    CS = 32.0*1.41421*mA/1000.0*(Rsense+0.02)/0.180 - 1;
+  } else { // If CS >= 16, turn off high_sense_r
+    vsense(false);
+  }
+
+  if (CS > 31)
+    CS = 31;
+
+  irun(CS);
+  ihold(CS*holdMultiplier);
+  //val_mA = mA;
+}
+void TMCStepper::rms_current(uint16_t mA, float mult) {
+  holdMultiplier = mult;
+  rms_current(mA);
+}
+
+uint16_t TMCStepper::rms_current() {
+  return cs2rms(irun());
+}
+
+uint8_t TMCStepper::test_connection() {
+  uint32_t drv_status = DRV_STATUS();
+  switch (drv_status) {
+      case 0xFFFFFFFF: return 1;
+      case 0: return 2;
+      default: return 0;
+  }
+}
+
+void TMCStepper::hysteresis_end(int8_t value) { hend(value+3); }
+int8_t TMCStepper::hysteresis_end() { return hend()-3; };
+
+void TMCStepper::hysteresis_start(uint8_t value) { hstrt(value-1); }
+uint8_t TMCStepper::hysteresis_start() { return hstrt()+1; }
+
+void TMCStepper::microsteps(uint16_t ms) {
+  switch(ms) {
+    case 256: mres(0); break;
+    case 128: mres(1); break;
+    case  64: mres(2); break;
+    case  32: mres(3); break;
+    case  16: mres(4); break;
+    case   8: mres(5); break;
+    case   4: mres(6); break;
+    case   2: mres(7); break;
+    case   1: mres(8); break;
+    default: break;
+  }
+}
+
+uint16_t TMCStepper::microsteps() {
+  switch(mres()) {
+    case 0: return 256;
+    case 1: return 128;
+    case 2: return  64;
+    case 3: return  32;
+    case 4: return  16;
+    case 5: return   8;
+    case 6: return   4;
+    case 7: return   2;
+    case 8: return   1;
+  }
+  return 1;
+}
+
+void TMCStepper::blank_time(uint8_t value) {
+  switch (value) {
+    case 16: tbl(0b00); break;
+    case 24: tbl(0b01); break;
+    case 36: tbl(0b10); break;
+    case 54: tbl(0b11); break;
+  }
+}
+
+uint8_t TMCStepper::blank_time() {
+  switch (tbl()) {
+    case 0b00: return 16;
+    case 0b01: return 24;
+    case 0b10: return 36;
+    case 0b11: return 54;
+  }
+  return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////////////
+// R+C: GSTAT
+uint8_t TMCStepper::GSTAT()  { return read(GSTAT_t::address); }
+void  TMCStepper::GSTAT(uint8_t){ write(GSTAT_t::address, 0b111); }
+bool  TMCStepper::reset()    { GSTAT_t r; r.sr = GSTAT(); return r.reset; }
+bool  TMCStepper::drv_err()  { GSTAT_t r; r.sr = GSTAT(); return r.drv_err; }
+bool  TMCStepper::uv_cp()    { GSTAT_t r; r.sr = GSTAT(); return r.uv_cp; }
+///////////////////////////////////////////////////////////////////////////////////////
+// W: TPOWERDOWN
+uint8_t TMCStepper::TPOWERDOWN() { return TPOWERDOWN_register.sr; }
+void TMCStepper::TPOWERDOWN(uint8_t input) {
+  TPOWERDOWN_register.sr = input;
+  write(TPOWERDOWN_register.address, TPOWERDOWN_register.sr);
+}
+///////////////////////////////////////////////////////////////////////////////////////
+// R: TSTEP
+uint32_t TMCStepper::TSTEP() { return read(TSTEP_t::address); }
+///////////////////////////////////////////////////////////////////////////////////////
+// W: TPWMTHRS
+uint32_t TMCStepper::TPWMTHRS() { return TPWMTHRS_register.sr; }
+void TMCStepper::TPWMTHRS(uint32_t input) {
+  TPWMTHRS_register.sr = input;
+  write(TPWMTHRS_register.address, TPWMTHRS_register.sr);
+}
+
+uint16_t TMCStepper::MSCNT() {
+  return read(MSCNT_t::address);
+}
+
+uint32_t TMCStepper::MSCURACT() { return read(MSCURACT_t::address); }
+int16_t TMCStepper::cur_a() {
+  MSCURACT_t r{0};
+  r.sr = MSCURACT();
+  int16_t value = r.cur_a;
+  if (value > 255) value -= 512;
+  return value;
+}
+int16_t TMCStepper::cur_b() {
+  MSCURACT_t r{0};
+  r.sr = MSCURACT();
+  int16_t value = r.cur_b;
+  if (value > 255) value -= 512;
+  return value;
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/source/TMC_MACROS.h	Thu Feb 04 19:46:56 2021 +0000
@@ -0,0 +1,5 @@
+#pragma once
+
+#define DEBUG_PRINT(CFG, VAL) Serial.print(CFG); Serial.print('('); Serial.print(VAL, HEX); Serial.println(')')
+//#define WRITE_REG(R) write(R##_register.address, R##_register.sr)
+//#define READ_REG(R) read(R##_register.address)
\ No newline at end of file