Skip to content

Commit

Permalink
Fix SPI
Browse files Browse the repository at this point in the history
  • Loading branch information
giulcioffi committed Nov 24, 2020
1 parent f25e3da commit ca7b32d
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 29 deletions.
32 changes: 5 additions & 27 deletions libraries/SPI/SPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,7 @@
#define SPI_IMODE_EXTINT 1
#define SPI_IMODE_GLOBAL 2

//const SPISettings DEFAULT_SPI_SETTINGS = SPISettings();

static inline SercomDataOrder getBitOrder(SPISettings& settings) {
return (settings.getBitOrder() == MSBFIRST ? MSB_FIRST : LSB_FIRST);
}

static inline SercomSpiClockMode getDataMode(SPISettings& settings) {
switch (settings.getDataMode())
{
case SPI_MODE0:
return SERCOM_SPI_MODE_0; break;
case SPI_MODE1:
return SERCOM_SPI_MODE_1; break;
case SPI_MODE2:
return SERCOM_SPI_MODE_2; break;
case SPI_MODE3:
return SERCOM_SPI_MODE_3; break;
default:
return SERCOM_SPI_MODE_0; break;
}
}

SPIClass::SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI, SercomSpiTXPad PadTx, SercomRXPad PadRx)
SPIClass::SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI, SercomSpiTXPad PadTx, SercomRXPad PadRx) : settings(SPISettings(0, MSBFIRST, SPI_MODE0))
{
initialized = false;
assert(p_sercom != NULL);
Expand Down Expand Up @@ -86,14 +64,14 @@ void SPIClass::init()
initialized = true;
}

void SPIClass::config(SPISettings settings)
void SPIClass::config(SPISettingsSAMD settings)
{
if (this->settings != settings) {
this->settings = settings;
_p_sercom->disableSPI();

_p_sercom->initSPI(_padTx, _padRx, SPI_CHAR_SIZE_8_BITS, getBitOrder(settings));
_p_sercom->initSPIClock(getDataMode(settings), settings.getClockFreq());
_p_sercom->initSPI(_padTx, _padRx, SPI_CHAR_SIZE_8_BITS, settings.bitOrder);
_p_sercom->initSPIClock(settings.dataMode, settings.clockFreq);

_p_sercom->enableSPI();
}
Expand Down Expand Up @@ -155,7 +133,7 @@ void SPIClass::notUsingInterrupt(int interruptNumber)
interrupts();
}

void SPIClass::beginTransaction(SPISettings settings)
void SPIClass::beginTransaction(SPISettingsSAMD settings)
{
if (interruptMode != SPI_IMODE_NONE)
{
Expand Down
57 changes: 55 additions & 2 deletions libraries/SPI/SPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,53 @@
#define SPI_MIN_CLOCK_DIVIDER (uint8_t)(1 + ((F_CPU - 1) / 12000000))
#endif

class SPISettingsSAMD : public arduino::SPISettings {
public:
SPISettingsSAMD(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) {
if (__builtin_constant_p(clock)) {
init_AlwaysInline(clock, bitOrder, dataMode);
} else {
init_MightInline(clock, bitOrder, dataMode);
}
}

// Default speed set to 4MHz, SPI mode set to MODE 0 and Bit order set to MSB first.
SPISettingsSAMD() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); }

SPISettingsSAMD(SPISettings& x) { SPISettingsSAMD(x.getClockFreq(), x.getBitOrder(), x.getDataMode()); }

private:
void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) {
init_AlwaysInline(clock, bitOrder, dataMode);
}

void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) __attribute__((__always_inline__)) {
this->clockFreq = (clock >= (F_CPU / SPI_MIN_CLOCK_DIVIDER) ? F_CPU / SPI_MIN_CLOCK_DIVIDER : clock);

this->bitOrder = (bitOrder == MSBFIRST ? MSB_FIRST : LSB_FIRST);

switch (dataMode)
{
case SPI_MODE0:
this->dataMode = SERCOM_SPI_MODE_0; break;
case SPI_MODE1:
this->dataMode = SERCOM_SPI_MODE_1; break;
case SPI_MODE2:
this->dataMode = SERCOM_SPI_MODE_2; break;
case SPI_MODE3:
this->dataMode = SERCOM_SPI_MODE_3; break;
default:
this->dataMode = SERCOM_SPI_MODE_0; break;
}
}

uint32_t clockFreq;
SercomSpiClockMode dataMode;
SercomDataOrder bitOrder;

friend class SPIClassSAMD;
};

class SPIClassSAMD : public arduino::HardwareSPI {
public:
SPIClassSAMD(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI, SercomSpiTXPad, SercomRXPad);
Expand All @@ -57,7 +104,10 @@ class SPIClassSAMD : public arduino::HardwareSPI {
// Transaction Functions
void usingInterrupt(int interruptNumber);
void notUsingInterrupt(int interruptNumber);
void beginTransaction(SPISettings settings);
void beginTransaction(SPISettingsSAMD settings);
void beginTransaction(SPISettings settings) {
beginTransaction(SPISettingsSAMD(settings));
}
void endTransaction(void);

// SPI Configuration methods
Expand All @@ -73,7 +123,10 @@ class SPIClassSAMD : public arduino::HardwareSPI {

private:
void init();
void config(SPISettings settings);
void config(SPISettingsSAMD settings);
void config(SPISettings settings) {
config(SPISettingsSAMD(settings));
}

SERCOM *_p_sercom;
uint8_t _uc_pinMiso;
Expand Down

0 comments on commit ca7b32d

Please sign in to comment.