Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix SPI bus sharing (TFT, SD, Touch, TMC, etc...) #255

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
65 changes: 47 additions & 18 deletions src/TMCStepper.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@

#if defined(ARDUINO) && ARDUINO >= 100
#include <Arduino.h>
#include <SPI.h>
#ifndef TMC_NO_GENERIC_SPI
#include <SPI.h>
#endif
#include <Stream.h>
#elif defined(bcm2835)
#include <bcm2835.h>
Expand All @@ -18,8 +20,12 @@
#if __has_include(<Arduino.h>)
#include <Arduino.h>
#endif
#if __has_include(<SPI.h>)
#include <SPI.h>
#ifndef TMC_NO_GENERIC_SPI
#if __has_include(<SPI.h>)
#include <SPI.h>
#else
#define TMC_NO_GENERIC_SPI
#endif
#endif
#if __has_include(<Stream.h>)
#include <Stream.h>
Expand Down Expand Up @@ -63,6 +69,8 @@

#define TMCSTEPPER_VERSION 0x000703 // v0.7.3

#include "TMCStepper_fixing.h"

class TMCStepper {
public:
uint16_t cs2rms(uint8_t CS);
Expand Down Expand Up @@ -149,11 +157,20 @@ class TMCStepper {
float holdMultiplier = 0.5;
};

#include "TMCStepper_SPI.h"

#ifndef TMC_NO_GENERIC_SPI
#define _TMC_SOFTSPI_DEFAULT false
#else
#define _TMC_SOFTSPI_DEFAULT true
#endif

class TMC2130Stepper : public TMCStepper {
public:
TMC2130Stepper(uint16_t pinCS, float RS = default_RS, int8_t link_index = -1);
TMC2130Stepper(uint16_t pinCS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1);
TMC2130Stepper(uint16_t pinCS, float RS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1);
TMC2130Stepper(uint16_t pinCS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1, bool softSPI = _TMC_SOFTSPI_DEFAULT);
TMC2130Stepper(uint16_t pinCS, float RS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1, bool softSPI = _TMC_SOFTSPI_DEFAULT);
TMC2130Stepper(uint16_t pinCS, float RS, TMCSPIInterface *spiMan, int8_t link_index = -1);
void begin();
void defaults();
void setSPISpeed(uint32_t speed);
Expand Down Expand Up @@ -369,7 +386,12 @@ class TMC2130Stepper : public TMCStepper {

static uint32_t spi_speed; // Default 2MHz
const uint16_t _pinCS;
const uint16_t _pinMISO;
const uint16_t _pinMOSI;
const uint16_t _pinSCK;
const bool _has_pins;
SW_SPIClass * TMC_SW_SPI = nullptr;
TMCSPIInterface* _spiMan;
static constexpr float default_RS = 0.11;

int8_t link_index;
Expand All @@ -379,8 +401,8 @@ class TMC2130Stepper : public TMCStepper {
class TMC2160Stepper : public TMC2130Stepper {
public:
TMC2160Stepper(uint16_t pinCS, float RS = default_RS, int8_t link_index = -1);
TMC2160Stepper(uint16_t pinCS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1);
TMC2160Stepper(uint16_t pinCS, float RS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1);
TMC2160Stepper(uint16_t pinCS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1, bool softSPI = _TMC_SOFTSPI_DEFAULT);
TMC2160Stepper(uint16_t pinCS, float RS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1, bool softSPI = _TMC_SOFTSPI_DEFAULT);
void begin();
void defaults();
void push();
Expand Down Expand Up @@ -478,8 +500,8 @@ class TMC2160Stepper : public TMC2130Stepper {
class TMC5130Stepper : public TMC2160Stepper {
public:
TMC5130Stepper(uint16_t pinCS, float RS = default_RS, int8_t link_index = -1);
TMC5130Stepper(uint16_t pinCS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1);
TMC5130Stepper(uint16_t pinCS, float RS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1);
TMC5130Stepper(uint16_t pinCS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1, bool softSPI = _TMC_SOFTSPI_DEFAULT);
TMC5130Stepper(uint16_t pinCS, float RS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1, bool softSPI = _TMC_SOFTSPI_DEFAULT);

void begin();
void defaults();
Expand Down Expand Up @@ -722,8 +744,8 @@ class TMC5130Stepper : public TMC2160Stepper {
class TMC5160Stepper : public TMC5130Stepper {
public:
TMC5160Stepper(uint16_t pinCS, float RS = default_RS, int8_t link_index = -1);
TMC5160Stepper(uint16_t pinCS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1);
TMC5160Stepper(uint16_t pinCS, float RS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1);
TMC5160Stepper(uint16_t pinCS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1, bool softSPI = _TMC_SOFTSPI_DEFAULT);
TMC5160Stepper(uint16_t pinCS, float RS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1, bool softSPI = _TMC_SOFTSPI_DEFAULT);

void rms_current(uint16_t mA) { TMC2160Stepper::rms_current(mA); }
void rms_current(uint16_t mA, float mult) { TMC2160Stepper::rms_current(mA, mult); }
Expand Down Expand Up @@ -815,11 +837,12 @@ class TMC5160Stepper : public TMC5130Stepper {

class TMC5161Stepper : public TMC5160Stepper {
public:
TMC5161Stepper(uint16_t pinCS, float RS = default_RS, int8_t link_index = -1) : TMC5160Stepper(pinCS, RS, link_index) {}
TMC5161Stepper(uint16_t pinCS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1) :
TMC5160Stepper(pinCS, pinMOSI, pinMISO, pinSCK, link_index) {}
TMC5161Stepper(uint16_t pinCS, float RS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1) :
TMC5160Stepper(pinCS, RS, pinMOSI, pinMISO, pinSCK, link_index) {}
TMC5161Stepper(uint16_t pinCS, float RS = default_RS, int8_t link_index = -1) :
TMC5160Stepper(pinCS, RS, link_index) {}
TMC5161Stepper(uint16_t pinCS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1, bool softSPI = _TMC_SOFTSPI_DEFAULT) :
TMC5160Stepper(pinCS, pinMOSI, pinMISO, pinSCK, link_index, softSPI) {}
TMC5161Stepper(uint16_t pinCS, float RS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, int8_t link_index = -1, bool softSPI = _TMC_SOFTSPI_DEFAULT) :
TMC5160Stepper(pinCS, RS, pinMOSI, pinMISO, pinSCK, link_index, softSPI) {}
};

class TMC2208Stepper : public TMCStepper {
Expand Down Expand Up @@ -1104,8 +1127,9 @@ class TMC2224Stepper : public TMC2208Stepper {
class TMC2660Stepper {
public:
TMC2660Stepper(uint16_t pinCS, float RS = default_RS);
TMC2660Stepper(uint16_t pinCS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK);
TMC2660Stepper(uint16_t pinCS, float RS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK);
TMC2660Stepper(uint16_t pinCS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, bool softSPI = _TMC_SOFTSPI_DEFAULT);
TMC2660Stepper(uint16_t pinCS, float RS, uint16_t pinMOSI, uint16_t pinMISO, uint16_t pinSCK, bool softSPI = _TMC_SOFTSPI_DEFAULT);
TMC2660Stepper(uint16_t pinCS, float RS, TMCSPIInterface *spiMan);
void write(uint8_t addressByte, uint32_t config);
uint32_t read();
void switchCSpin(bool state);
Expand Down Expand Up @@ -1255,6 +1279,11 @@ class TMC2660Stepper {
INIT_REGISTER(READ_RDSEL10){{.sr=0}};

const uint16_t _pinCS;
const uint16_t _pinMISO;
const uint16_t _pinMOSI;
const uint16_t _pinSCK;
const bool _has_pins;
TMCSPIInterface *_spiMan;
const float Rsense;
static constexpr float default_RS = 0.1;
float holdMultiplier = 0.5;
Expand Down
16 changes: 16 additions & 0 deletions src/TMCStepper_SPI.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#pragma once

#define TMCSPI_BITORDER_LSB 0
#define TMCSPI_BITORDER_MSB 1

#define TMCSPI_CLKMODE_0 0
#define TMCSPI_CLKMODE_1 1
#define TMCSPI_CLKMODE_2 2
#define TMCSPI_CLKMODE_3 3

struct TMCSPIInterface {
virtual void begin(uint32_t maxClockFreq, int bitOrder, int clkMode) = 0;
virtual void end() = 0;
virtual uint8_t transfer(uint8_t txval) = 0;
virtual void sendRepeat(uint8_t val, uint16_t repcnt) = 0;
};
107 changes: 107 additions & 0 deletions src/TMCStepper_fixing.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#pragma once

#ifndef TMC_NO_GENERIC_SPI

namespace _TMC_FIXING
{

// BEGIN https://en.cppreference.com/w/cpp/types/add_reference
namespace detail {

template <class T>
struct type_identity { using type = T; };

template <class T>
auto try_add_rvalue_reference(int) -> type_identity<T&&>;
template <class T>
auto try_add_rvalue_reference(...) -> type_identity<T>;

} // namespace detail

template <class T>
struct add_rvalue_reference : decltype(detail::try_add_rvalue_reference<T>(0)) {};

// END https://en.cppreference.com/w/cpp/types/add_reference

// BEGIN https://en.cppreference.com/w/cpp/utility/declval (inspired)
template<typename T>
struct always_false
{
enum { value = false };
};

template<typename T>
typename add_rvalue_reference<T>::type declval() {
static_assert(always_false<T>::value, "declval not allowed in an evaluated context");
}

// END https://en.cppreference.com/w/cpp/utility/declval

struct true_type {
enum { value = true };
};
struct false_type {
enum { value = false };
};

} // namespace TMC_FIXING

// Since we don't have C++20 we need to do some ugly hacks to ensure compat.
// https://stackoverflow.com/questions/63253287/using-sfinae-to-detect-method-with-gcc
// Did you know that ATMEL AVR does not support standard C++ headers???
#define __DEF_HAS_METH( methName ) \
template<typename T> \
struct ___has_##methName \
{ \
template<typename C> \
static constexpr auto test(...) -> _TMC_FIXING::false_type; \
template<typename C> \
static constexpr auto test(int) \
-> decltype(static_cast<void>(_TMC_FIXING::declval<C>().methName(0)), _TMC_FIXING::true_type()); \
using result_type = decltype(test<T>(0)); \
static const bool value = result_type::value; \
}
#define __HAS_METH( className, methName ) \
( ___has_##methName <className>::value )

__DEF_HAS_METH( setMISO );
__DEF_HAS_METH( setMOSI );
__DEF_HAS_METH( setSCLK );

#define SPI_SET_PIN_HELPER( pinDescName ) \
template <bool hasPin> \
struct _spiInitHelper_##pinDescName \
{}; \
template <> \
struct _spiInitHelper_##pinDescName <true> \
{ \
template <typename SPIClassT> \
static void spiSet##pinDescName( SPIClassT& spi, uint16_t pin ) { spi.set##pinDescName( pin ); } \
}; \
template <> \
struct _spiInitHelper_##pinDescName <false> \
{ \
template <typename SPIClassT> \
static void spiSet##pinDescName( SPIClassT& spi, uint16_t pin ) {} \
}

SPI_SET_PIN_HELPER( MISO );
SPI_SET_PIN_HELPER( MOSI );
SPI_SET_PIN_HELPER( SCLK );

#define SPI_INIT_PIN( spi, pinDescName, val ) _spiInitHelper_##pinDescName <__HAS_METH(SPIClass, set##pinDescName)> ::spiSet##pinDescName( spi, val )

// Speciality of the ESP32 platform.
#ifdef ESP_PLATFORM
// https://github.com/espressif/arduino-esp32/blob/master/libraries/SPI/src/SPI.cpp SPIClass::begin method.
#define SPI_BEGIN( spi, sck, miso, mosi ) ( spi.begin( sck, miso, mosi ) )
#else
// Other platforms.
#define SPI_BEGIN( spi, sck, miso, mosi ) \
{ SPI_INIT_PIN( spi, MISO, miso ); \
SPI_INIT_PIN( SPI, MOSI, mosi ); \
SPI_INIT_PIN( SPI, SCLK, sck ); \
spi.begin(); }
#endif

#endif //TMC_NO_GENERIC_SPI
Loading