@@ -213,6 +213,39 @@ void SPIClass::setClockDivider_noInline(uint32_t clk) | |||
updateCTAR(ctar); | |||
} | |||
bool SPIClass::pinIsChipSelect(uint8_t pin) | |||
{ | |||
if (pin == 10 || pin == 9 || pin == 6 || pin == 2 || pin == 15) return true; | |||
if (pin >= 20 && pin <= 23) return true; | |||
return false; | |||
} | |||
bool SPIClass::pinIsChipSelect(uint8_t pin1, uint8_t pin2) | |||
{ | |||
if (!pinIsChipSelect(pin1) || !pinIsChipSelect(pin2)) return false; | |||
if ((pin1 == 2 && pin2 == 10) || (pin1 == 10 && pin2 == 2)) return false; | |||
if ((pin1 == 6 && pin2 == 9) || (pin1 == 9 && pin2 == 6)) return false; | |||
if ((pin1 == 20 && pin2 == 23) || (pin1 == 23 && pin2 == 20)) return false; | |||
if ((pin1 == 21 && pin2 == 22) || (pin1 == 22 && pin2 == 21)) return false; | |||
return true; | |||
} | |||
uint8_t SPIClass::setCS(uint8_t pin) | |||
{ | |||
switch (pin) { | |||
case 10: CORE_PIN10_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTC4 | |||
case 2: CORE_PIN2_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTD0 | |||
case 9: CORE_PIN9_CONFIG = PORT_PCR_MUX(2); return 0x02; // PTC3 | |||
case 6: CORE_PIN6_CONFIG = PORT_PCR_MUX(2); return 0x02; // PTD4 | |||
case 20: CORE_PIN20_CONFIG = PORT_PCR_MUX(2); return 0x04; // PTD5 | |||
case 23: CORE_PIN23_CONFIG = PORT_PCR_MUX(2); return 0x04; // PTC2 | |||
case 21: CORE_PIN21_CONFIG = PORT_PCR_MUX(2); return 0x08; // PTD6 | |||
case 22: CORE_PIN22_CONFIG = PORT_PCR_MUX(2); return 0x08; // PTC1 | |||
case 15: CORE_PIN15_CONFIG = PORT_PCR_MUX(2); return 0x10; // PTC0 | |||
} | |||
return 0; | |||
} | |||
#endif | |||
@@ -183,6 +183,26 @@ public: | |||
while (!(SPSR & _BV(SPIF))) ; // wait | |||
return SPDR; | |||
} | |||
inline static uint16_t transfer16(uint16_t data) { | |||
union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out; | |||
in.val = data; | |||
if (!(SPCR & _BV(DORD))) { | |||
SPDR = in.msb; | |||
while (!(SPSR & _BV(SPIF))) ; | |||
out.msb = SPDR; | |||
SPDR = in.lsb; | |||
while (!(SPSR & _BV(SPIF))) ; | |||
out.lsb = SPDR; | |||
} else { | |||
SPDR = in.lsb; | |||
while (!(SPSR & _BV(SPIF))) ; | |||
out.lsb = SPDR; | |||
SPDR = in.msb; | |||
while (!(SPSR & _BV(SPIF))) ; | |||
out.msb = SPDR; | |||
} | |||
return out.val; | |||
} | |||
inline static void transfer(void *buf, size_t count) { | |||
if (count == 0) return; | |||
uint8_t *p = (uint8_t *)buf; | |||
@@ -423,7 +443,6 @@ public: | |||
// Write to the SPI bus (MOSI pin) and also receive (MISO pin) | |||
inline static uint8_t transfer(uint8_t data) { | |||
SPDR = data; | |||
asm volatile("nop"); | |||
while (!(SPSR & _BV(SPIF))) ; // wait | |||
return SPDR; | |||
} | |||
@@ -505,6 +524,12 @@ public: | |||
inline static void setSCK(uint8_t pin) __attribute__((always_inline)) { | |||
SPCR.setSCK(pin); | |||
} | |||
// return true if "pin" has special chip select capability | |||
static bool pinIsChipSelect(uint8_t pin); | |||
// return true if both pin1 and pin2 have independent chip select capability | |||
static bool pinIsChipSelect(uint8_t pin1, uint8_t pin2); | |||
// configure a pin for chip select and return its SPI_MCR_PCSIS bitmask | |||
static uint8_t setCS(uint8_t pin); | |||
private: | |||
static uint8_t interruptMode; // 0=none, 1=mask, 2=global |