Ver código fonte

Single SPIClass for Teensy 3.x

main
PaulStoffregen 7 anos atrás
pai
commit
a98c4fc42b
2 arquivos alterados com 276 adições e 95 exclusões
  1. +182
    -44
      SPI.cpp
  2. +94
    -51
      SPI.h

+ 182
- 44
SPI.cpp Ver arquivo





/**********************************************************/ /**********************************************************/
/* 32 bit Teensy 3.0 and 3.1 */
/* 32 bit Teensy 3.x */
/**********************************************************/ /**********************************************************/


#elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISK) #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISK)




SPIClass SPI;

uint8_t SPIClass::interruptMasksUsed = 0;
uint32_t SPIClass::interruptMask[(NVIC_NUM_INTERRUPTS+31)/32];
uint32_t SPIClass::interruptSave[(NVIC_NUM_INTERRUPTS+31)/32];
#ifdef SPI_TRANSACTION_MISMATCH_LED
uint8_t SPIClass::inTransactionFlag = 0;
#if defined(__MK20DX128__) || defined(__MK20DX256__)
void _spi_dma_rxISR0(void) {/*SPI.dma_rxisr();*/}
const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = {
SIM_SCGC6, SIM_SCGC6_SPI0, 4, IRQ_SPI0,
32767, DMAMUX_SOURCE_SPI0_TX, DMAMUX_SOURCE_SPI0_RX,
_spi_dma_rxISR0,
12, 8,
2, 2,
11, 7,
2, 2,
13, 14,
2, 2,
10, 2, 9, 6, 20, 23, 21, 22, 15,
2, 2, 2, 2, 2, 2, 2, 2, 2,
0x1, 0x1, 0x2, 0x2, 0x4, 0x4, 0x8, 0x8, 0x10
};
SPIClass SPI((uintptr_t)&KINETISK_SPI0, (uintptr_t)&SPIClass::spi0_hardware);

#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
void _spi_dma_rxISR0(void) {/*SPI.dma_rxisr();*/}
void _spi_dma_rxISR1(void) {/*SPI1.dma_rxisr();*/}
void _spi_dma_rxISR2(void) {/*SPI2.dma_rxisr();*/}
const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = {
SIM_SCGC6, SIM_SCGC6_SPI0, 4, IRQ_SPI0,
32767, DMAMUX_SOURCE_SPI0_TX, DMAMUX_SOURCE_SPI0_RX,
_spi_dma_rxISR0,
12, 8, 39, 255,
2, 2, 2, 0,
11, 7, 28, 255,
2, 2, 2, 0,
13, 14, 27,
2, 2, 2,
10, 2, 9, 6, 20, 23, 21, 22, 15, 26, 45,
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 3,
0x1, 0x1, 0x2, 0x2, 0x4, 0x4, 0x8, 0x8, 0x10, 0x1, 0x20
};
const SPIClass::SPI_Hardware_t SPIClass::spi1_hardware = {
SIM_SCGC6, SIM_SCGC6_SPI1, 1, IRQ_SPI1,
#if defined(__MK66FX1M0__)
32767, DMAMUX_SOURCE_SPI1_TX, DMAMUX_SOURCE_SPI1_RX,
#else
// T3.5 does not have good DMA support on 1 and 2
511, 0, DMAMUX_SOURCE_SPI1,
#endif
_spi_dma_rxISR1,
1, 5, 61, 59,
2, 7, 2, 7,
0, 21, 61, 59,
2, 7, 7, 2,
32, 20, 60,
2, 7, 2,
6, 31, 58, 62, 63, 255, 255, 255, 255, 255, 255,
7, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0,
0x1, 0x1, 0x2, 0x1, 0x4, 0, 0, 0, 0, 0, 0
};
const SPIClass::SPI_Hardware_t SPIClass::spi2_hardware = {
SIM_SCGC3, SIM_SCGC3_SPI2, 1, IRQ_SPI2,
#if defined(__MK66FX1M0__)
32767, DMAMUX_SOURCE_SPI2_TX, DMAMUX_SOURCE_SPI2_RX,
#else
// T3.5 does not have good DMA support on 1 and 2
511, 0, DMAMUX_SOURCE_SPI2,
#endif
_spi_dma_rxISR2,
45, 51, 255, 255,
2, 2, 0, 0,
44, 52, 255, 255,
2, 2, 0, 0,
46, 53, 255,
2, 2, 0,
43, 54, 55, 255, 255, 255, 255, 255, 255, 255, 255,
2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0,
0x1, 0x2, 0x1, 0, 0, 0, 0, 0, 0, 0, 0
};
//SPIClass SPI((uintptr_t)&KINETISK_SPI0, SPIClass::spi0_hardware);
SPIClass SPI((uintptr_t)&KINETISK_SPI0, (uintptr_t)&SPIClass::spi0_hardware);
//SPIClass SPI1((uintptr_t)&KINETISK_SPI1, SPIClass::spi1_hardware);
//SPIClass SPI2((uintptr_t)&KINETISK_SPI2, SPIClass::spi2_hardware);
#endif #endif



void SPIClass::begin() void SPIClass::begin()
{ {
SIM_SCGC6 |= SIM_SCGC6_SPI0;
SPI0_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
SPI0_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
SPI0_CTAR1 = SPI_CTAR_FMSZ(15) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F);
SPCR.enable_pins(); // pins managed by SPCRemulation in avr_emulation.h
volatile uint32_t *reg;

hardware().clock_gate_register |= hardware().clock_gate_mask;
port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
port().CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
port().CTAR1 = SPI_CTAR_FMSZ(15) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
port().MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F);
reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
*reg = PORT_PCR_MUX(hardware().mosi_mux[mosi_pin_index]);
reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
*reg= PORT_PCR_MUX(hardware().miso_mux[miso_pin_index]);
reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
*reg = PORT_PCR_MUX(hardware().sck_mux[sck_pin_index]);
} }


void SPIClass::end() {
SPCR.disable_pins();
SPI0_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
void SPIClass::end()
{
volatile uint32_t *reg;

//SPCR.disable_pins();
reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
*reg = 0;
reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
*reg = 0;
reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
*reg = 0;
port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
} }


void SPIClass::usingInterrupt(IRQ_NUMBER_t interruptName) void SPIClass::usingInterrupt(IRQ_NUMBER_t interruptName)
SPI_CTAR_PBR(1) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7) SPI_CTAR_PBR(1) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7)
}; };


static void updateCTAR(uint32_t ctar)
void SPIClass::updateCTAR(uint32_t ctar)
{ {
if (SPI0_CTAR0 != ctar) {
uint32_t mcr = SPI0_MCR;
if (port().CTAR0 != ctar) {
uint32_t mcr = port().MCR;
if (mcr & SPI_MCR_MDIS) { if (mcr & SPI_MCR_MDIS) {
SPI0_CTAR0 = ctar;
SPI0_CTAR1 = ctar | SPI_CTAR_FMSZ(8);
port().CTAR0 = ctar;
port().CTAR1 = ctar | SPI_CTAR_FMSZ(8);
} else { } else {
SPI0_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
SPI0_CTAR0 = ctar;
SPI0_CTAR1 = ctar | SPI_CTAR_FMSZ(8);
SPI0_MCR = mcr;
port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
port().CTAR0 = ctar;
port().CTAR1 = ctar | SPI_CTAR_FMSZ(8);
port().MCR = mcr;
} }
} }
} }


void SPIClass::setBitOrder(uint8_t bitOrder) void SPIClass::setBitOrder(uint8_t bitOrder)
{ {
SIM_SCGC6 |= SIM_SCGC6_SPI0;
uint32_t ctar = SPI0_CTAR0;
hardware().clock_gate_register |= hardware().clock_gate_mask;
uint32_t ctar = port().CTAR0;
if (bitOrder == LSBFIRST) { if (bitOrder == LSBFIRST) {
ctar |= SPI_CTAR_LSBFE; ctar |= SPI_CTAR_LSBFE;
} else { } else {


void SPIClass::setDataMode(uint8_t dataMode) void SPIClass::setDataMode(uint8_t dataMode)
{ {
SIM_SCGC6 |= SIM_SCGC6_SPI0;
hardware().clock_gate_register |= hardware().clock_gate_mask;
//uint32_t ctar = port().CTAR0;


// TODO: implement with native code // TODO: implement with native code

SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode;
//SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode;
} }


void SPIClass::setClockDivider_noInline(uint32_t clk) void SPIClass::setClockDivider_noInline(uint32_t clk)
{ {
SIM_SCGC6 |= SIM_SCGC6_SPI0;
uint32_t ctar = SPI0_CTAR0;
hardware().clock_gate_register |= hardware().clock_gate_mask;
uint32_t ctar = port().CTAR0;
ctar &= (SPI_CTAR_CPOL | SPI_CTAR_CPHA | SPI_CTAR_LSBFE); ctar &= (SPI_CTAR_CPOL | SPI_CTAR_CPHA | SPI_CTAR_LSBFE);
if (ctar & SPI_CTAR_CPHA) { if (ctar & SPI_CTAR_CPHA) {
clk = (clk & 0xFFFF0FFF) | ((clk & 0xF000) >> 4); clk = (clk & 0xFFFF0FFF) | ((clk & 0xF000) >> 4);


uint8_t SPIClass::pinIsChipSelect(uint8_t pin) uint8_t SPIClass::pinIsChipSelect(uint8_t pin)
{ {
for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
if (pin == hardware().cs_pin[i]) return hardware().cs_mask[i];
}
return 0;
/*
switch (pin) { switch (pin) {
case 10: return 0x01; // PTC4 case 10: return 0x01; // PTC4
case 2: return 0x01; // PTD0 case 2: return 0x01; // PTD0
case 45: return 0x20; // CS5 case 45: return 0x20; // CS5
#endif #endif
} }

return 0; return 0;
*/
} }


bool SPIClass::pinIsChipSelect(uint8_t pin1, uint8_t pin2) bool SPIClass::pinIsChipSelect(uint8_t pin1, uint8_t pin2)
// setCS() is not intended for use from normal Arduino programs/sketches. // setCS() is not intended for use from normal Arduino programs/sketches.
uint8_t SPIClass::setCS(uint8_t pin) uint8_t SPIClass::setCS(uint8_t pin)
{ {
for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
if (pin == hardware().cs_pin[i]) {
volatile uint32_t *reg = portConfigRegister(pin);
*reg = PORT_PCR_MUX(hardware().cs_mux[i]);
return hardware().cs_mask[i];
}
}
return 0;
/*
switch (pin) { switch (pin) {
case 10: CORE_PIN10_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTC4 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 2: CORE_PIN2_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTD0
#endif #endif
} }
return 0; return 0;
*/
}

void SPIClass::setMOSI(uint8_t pin)
{
if (pin != hardware().mosi_pin[mosi_pin_index]) {
for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
if (pin == hardware().mosi_pin[i]) {
mosi_pin_index = i;
return;
}
}
}
}

void SPIClass::setMISO(uint8_t pin)
{
if (pin != hardware().miso_pin[miso_pin_index]) {
for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
if (pin == hardware().miso_pin[i]) {
miso_pin_index = i;
return;
}
}
}
} }


void SPIClass::setSCK(uint8_t pin)
{
if (pin != hardware().sck_pin[sck_pin_index]) {
for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
if (pin == hardware().sck_pin[i]) {
sck_pin_index = i;
return;
}
}
}
}


void SPIClass::transfer(void *buf, size_t count) void SPIClass::transfer(void *buf, size_t count)
{ {
uint8_t *p_write = (uint8_t *)buf; uint8_t *p_write = (uint8_t *)buf;
uint8_t *p_read = p_write; uint8_t *p_read = p_write;
size_t count_read = count; size_t count_read = count;
bool lsbfirst = (SPI0_CTAR0 & SPI_CTAR_LSBFE) ? true : false;
bool lsbfirst = (port().CTAR0 & SPI_CTAR_LSBFE) ? true : false;


// Lets clear the reader queue // Lets clear the reader queue
SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);
port().MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);


uint32_t sr; uint32_t sr;


// Now lets loop while we still have data to output // Now lets loop while we still have data to output
if (count & 1) { if (count & 1) {
if (count > 1) if (count > 1)
KINETISK_SPI0.PUSHR = *p_write++ | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0);
port().PUSHR = *p_write++ | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0);
else else
KINETISK_SPI0.PUSHR = *p_write++ | SPI_PUSHR_CTAS(0);
port().PUSHR = *p_write++ | SPI_PUSHR_CTAS(0);
count--; count--;
} }


w |= *p_write++; w |= *p_write++;
if (lsbfirst) w = __builtin_bswap16(w); if (lsbfirst) w = __builtin_bswap16(w);
if (count == 2) if (count == 2)
KINETISK_SPI0.PUSHR = w | SPI_PUSHR_CTAS(1);
port().PUSHR = w | SPI_PUSHR_CTAS(1);
else else
KINETISK_SPI0.PUSHR = w | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1);
port().PUSHR = w | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1);
count -= 2; // how many bytes to output. count -= 2; // how many bytes to output.
// Make sure queue is not full before pushing next byte out // Make sure queue is not full before pushing next byte out
do { do {
sr = KINETISK_SPI0.SR;
sr = port().SR;
if (sr & 0xF0) { if (sr & 0xF0) {
uint16_t w = KINETISK_SPI0.POPR; // Read any pending RX bytes in
uint16_t w = port().POPR; // Read any pending RX bytes in
if (count_read & 1) { if (count_read & 1) {
*p_read++ = w; // Read any pending RX bytes in *p_read++ = w; // Read any pending RX bytes in
count_read--; count_read--;


// now lets wait for all of the read bytes to be returned... // now lets wait for all of the read bytes to be returned...
while (count_read) { while (count_read) {
sr = KINETISK_SPI0.SR;
sr = port().SR;
if (sr & 0xF0) { if (sr & 0xF0) {
uint16_t w = KINETISK_SPI0.POPR; // Read any pending RX bytes in
uint16_t w = port().POPR; // Read any pending RX bytes in
if (count_read & 1) { if (count_read & 1) {
*p_read++ = w; // Read any pending RX bytes in *p_read++ = w; // Read any pending RX bytes in
count_read--; count_read--;

+ 94
- 51
SPI.h Ver arquivo







class SPIClass {
class SPIClass { // AVR
public: public:
// Initialize the SPI library // Initialize the SPI library
static void begin(); static void begin();




/**********************************************************/ /**********************************************************/
/* 32 bit Teensy 3.0 and 3.1, 3.2, 3.5, 3.6 */
/* 32 bit Teensy 3.x */
/**********************************************************/ /**********************************************************/


#elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISK) #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISK)






class SPIClass {
class SPIClass { // Teensy 3.x
public: public:
#if defined(__MK20DX128__) || defined(__MK20DX256__)
static const uint8_t CNT_MISO_PINS = 2;
static const uint8_t CNT_MOSI_PINS = 2;
static const uint8_t CNT_SCK_PINS = 2;
static const uint8_t CNT_CS_PINS = 9;
#elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
static const uint8_t CNT_MISO_PINS = 4;
static const uint8_t CNT_MOSI_PINS = 4;
static const uint8_t CNT_SCK_PINS = 3;
static const uint8_t CNT_CS_PINS = 11;
#endif
typedef struct {
volatile uint32_t &clock_gate_register;
uint32_t clock_gate_mask;
uint8_t queue_size;
uint8_t spi_irq;
uint32_t max_dma_count;
uint8_t tx_dma_channel;
uint8_t rx_dma_channel;
void (*dma_rxisr)();
uint8_t miso_pin[CNT_MISO_PINS];
uint8_t miso_mux[CNT_MISO_PINS];
uint8_t mosi_pin[CNT_MOSI_PINS];
uint8_t mosi_mux[CNT_MOSI_PINS];
uint8_t sck_pin[CNT_SCK_PINS];
uint8_t sck_mux[CNT_SCK_PINS];
uint8_t cs_pin[CNT_CS_PINS];
uint8_t cs_mux[CNT_CS_PINS];
uint8_t cs_mask[CNT_CS_PINS];
} SPI_Hardware_t;
static const SPI_Hardware_t spi0_hardware;
static const SPI_Hardware_t spi1_hardware;
static const SPI_Hardware_t spi2_hardware;
public:
constexpr SPIClass(uintptr_t myport, uintptr_t myhardware)
: port_addr(myport), hardware_addr(myhardware) {
}
/*constexpr SPIClass() : port_addr((uintptr_t)&KINETISK_SPI0), hardware(spi0_hardware) {
}*/
// Initialize the SPI library // Initialize the SPI library
static void begin();
void begin();


// If SPI is to used from within an interrupt, this function registers // If SPI is to used from within an interrupt, this function registers
// that interrupt with the SPI library, so beginTransaction() can // that interrupt with the SPI library, so beginTransaction() can
// prevent conflicts. The input interruptNumber is the number used // prevent conflicts. The input interruptNumber is the number used
// with attachInterrupt. If SPI is used from a different interrupt // with attachInterrupt. If SPI is used from a different interrupt
// (eg, a timer), interruptNumber should be 255. // (eg, a timer), interruptNumber should be 255.
static void usingInterrupt(uint8_t n) {
void usingInterrupt(uint8_t n) {
if (n == 3 || n == 4 || n == 24 || n == 33) { if (n == 3 || n == 4 || n == 24 || n == 33) {
usingInterrupt(IRQ_PORTA); usingInterrupt(IRQ_PORTA);
} else if (n == 0 || n == 1 || (n >= 16 && n <= 19) || n == 25 || n == 32) { } else if (n == 0 || n == 1 || (n >= 16 && n <= 19) || n == 25 || n == 32) {
usingInterrupt(IRQ_PORTE); usingInterrupt(IRQ_PORTE);
} }
} }
static void usingInterrupt(IRQ_NUMBER_t interruptName);
static void notUsingInterrupt(IRQ_NUMBER_t interruptName);
void usingInterrupt(IRQ_NUMBER_t interruptName);
void notUsingInterrupt(IRQ_NUMBER_t interruptName);


// Before using SPI.transfer() or asserting chip select pins, // Before using SPI.transfer() or asserting chip select pins,
// this function is used to gain exclusive access to the SPI bus // this function is used to gain exclusive access to the SPI bus
// and configure the correct settings. // and configure the correct settings.
inline static void beginTransaction(SPISettings settings) {
void beginTransaction(SPISettings settings) {
if (interruptMasksUsed) { if (interruptMasksUsed) {
__disable_irq(); __disable_irq();
if (interruptMasksUsed & 0x01) { if (interruptMasksUsed & 0x01) {
} }
inTransactionFlag = 1; inTransactionFlag = 1;
#endif #endif
if (SPI0_CTAR0 != settings.ctar) {
SPI0_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
SPI0_CTAR0 = settings.ctar;
SPI0_CTAR1 = settings.ctar| SPI_CTAR_FMSZ(8);
SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F);
if (port().CTAR0 != settings.ctar) {
port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
port().CTAR0 = settings.ctar;
port().CTAR1 = settings.ctar| SPI_CTAR_FMSZ(8);
port().MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F);
} }
} }


// Write to the SPI bus (MOSI pin) and also receive (MISO pin) // Write to the SPI bus (MOSI pin) and also receive (MISO pin)
inline static uint8_t transfer(uint8_t data) {
SPI0_SR = SPI_SR_TCF;
SPI0_PUSHR = data;
while (!(SPI0_SR & SPI_SR_TCF)) ; // wait
return SPI0_POPR;
}
inline static uint16_t transfer16(uint16_t data) {
SPI0_SR = SPI_SR_TCF;
SPI0_PUSHR = data | SPI_PUSHR_CTAS(1);
while (!(SPI0_SR & SPI_SR_TCF)) ; // wait
return SPI0_POPR;
}
static void transfer(void *buf, size_t count);
uint8_t transfer(uint8_t data) {
port().SR = SPI_SR_TCF;
port().PUSHR = data;
while (!(port().SR & SPI_SR_TCF)) ; // wait
return port().POPR;
}
uint16_t transfer16(uint16_t data) {
port().SR = SPI_SR_TCF;
port().PUSHR = data | SPI_PUSHR_CTAS(1);
while (!(port().SR & SPI_SR_TCF)) ; // wait
return port().POPR;
}
void transfer(void *buf, size_t count);
// After performing a group of transfers and releasing the chip select // After performing a group of transfers and releasing the chip select
// signal, this function allows others to access the SPI bus // signal, this function allows others to access the SPI bus
inline static void endTransaction(void) {
void endTransaction(void) {
#ifdef SPI_TRANSACTION_MISMATCH_LED #ifdef SPI_TRANSACTION_MISMATCH_LED
if (!inTransactionFlag) { if (!inTransactionFlag) {
pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT); pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
} }


// Disable the SPI bus // Disable the SPI bus
static void end();
void end();


// This function is deprecated. New applications should use // This function is deprecated. New applications should use
// beginTransaction() to configure SPI settings. // beginTransaction() to configure SPI settings.
static void setBitOrder(uint8_t bitOrder);
void setBitOrder(uint8_t bitOrder);


// This function is deprecated. New applications should use // This function is deprecated. New applications should use
// beginTransaction() to configure SPI settings. // beginTransaction() to configure SPI settings.
static void setDataMode(uint8_t dataMode);
void setDataMode(uint8_t dataMode);


// This function is deprecated. New applications should use // This function is deprecated. New applications should use
// beginTransaction() to configure SPI settings. // beginTransaction() to configure SPI settings.
inline static void setClockDivider(uint8_t clockDiv) {
void setClockDivider(uint8_t clockDiv) {
if (clockDiv == SPI_CLOCK_DIV2) { if (clockDiv == SPI_CLOCK_DIV2) {
setClockDivider_noInline(SPISettings(12000000, MSBFIRST, SPI_MODE0).ctar); setClockDivider_noInline(SPISettings(12000000, MSBFIRST, SPI_MODE0).ctar);
} else if (clockDiv == SPI_CLOCK_DIV4) { } else if (clockDiv == SPI_CLOCK_DIV4) {
setClockDivider_noInline(SPISettings(125000, MSBFIRST, SPI_MODE0).ctar); setClockDivider_noInline(SPISettings(125000, MSBFIRST, SPI_MODE0).ctar);
} }
} }
static void setClockDivider_noInline(uint32_t clk);
void setClockDivider_noInline(uint32_t clk);


// These undocumented functions should not be used. SPI.transfer() // These undocumented functions should not be used. SPI.transfer()
// polls the hardware flag which is automatically cleared as the // polls the hardware flag which is automatically cleared as the
// AVR responds to SPI's interrupt // AVR responds to SPI's interrupt
inline static void attachInterrupt() { }
inline static void detachInterrupt() { }
void attachInterrupt() { }
void detachInterrupt() { }


// Teensy 3.x can use alternate pins for these 3 SPI signals. // Teensy 3.x can use alternate pins for these 3 SPI signals.
inline static void setMOSI(uint8_t pin) __attribute__((always_inline)) {
SPCR.setMOSI(pin);
}
inline static void setMISO(uint8_t pin) __attribute__((always_inline)) {
SPCR.setMISO(pin);
}
inline static void setSCK(uint8_t pin) __attribute__((always_inline)) {
SPCR.setSCK(pin);
}
void setMOSI(uint8_t pin);
void setMISO(uint8_t pin);
void setSCK(uint8_t pin);

// return true if "pin" has special chip select capability // return true if "pin" has special chip select capability
static uint8_t pinIsChipSelect(uint8_t pin);
uint8_t pinIsChipSelect(uint8_t pin);
// return true if both pin1 and pin2 have independent chip select capability // return true if both pin1 and pin2 have independent chip select capability
static bool pinIsChipSelect(uint8_t pin1, uint8_t pin2);
bool pinIsChipSelect(uint8_t pin1, uint8_t pin2);
// configure a pin for chip select and return its SPI_MCR_PCSIS bitmask // configure a pin for chip select and return its SPI_MCR_PCSIS bitmask
// setCS() is a special function, not intended for use from normal Arduino // setCS() is a special function, not intended for use from normal Arduino
// programs/sketches. See the ILI3941_t3 library for an example. // programs/sketches. See the ILI3941_t3 library for an example.
static uint8_t setCS(uint8_t pin);
uint8_t setCS(uint8_t pin);


private: private:
static uint8_t interruptMasksUsed;
static uint32_t interruptMask[(NVIC_NUM_INTERRUPTS+31)/32];
static uint32_t interruptSave[(NVIC_NUM_INTERRUPTS+31)/32];
KINETISK_SPI_t & port() { return *(KINETISK_SPI_t *)port_addr; }
const SPI_Hardware_t & hardware() { return *(const SPI_Hardware_t *)hardware_addr; }
void updateCTAR(uint32_t ctar);
uintptr_t port_addr;
uintptr_t hardware_addr;
//const SPI_Hardware_t &hardware;
uint8_t miso_pin_index = 0;
uint8_t mosi_pin_index = 0;
uint8_t sck_pin_index = 0;
uint8_t interruptMasksUsed = 0;
uint32_t interruptMask[(NVIC_NUM_INTERRUPTS+31)/32] = {};
uint32_t interruptSave[(NVIC_NUM_INTERRUPTS+31)/32] = {};
#ifdef SPI_TRANSACTION_MISMATCH_LED #ifdef SPI_TRANSACTION_MISMATCH_LED
static uint8_t inTransactionFlag;
uint8_t inTransactionFlag = 0;
#endif #endif
}; };


}; };




class SPIClass {
class SPIClass { // Teensy-LC
public: public:
// Initialize the SPI library // Initialize the SPI library
static void begin(); static void begin();

Carregando…
Cancelar
Salvar