Skip to content
Snippets Groups Projects
Commit 953980a8 authored by Jonathan BAUDIN's avatar Jonathan BAUDIN
Browse files

Merge branch 'sercom' into zero

parents 2c41d468 1014ac90
No related branches found
No related tags found
No related merge requests found
...@@ -78,4 +78,9 @@ int RingBuffer::peek() ...@@ -78,4 +78,9 @@ int RingBuffer::peek()
int RingBuffer::nextIndex(int index) int RingBuffer::nextIndex(int index)
{ {
return (uint32_t)(index + 1) % SERIAL_BUFFER_SIZE; return (uint32_t)(index + 1) % SERIAL_BUFFER_SIZE;
}
int RingBuffer::isFull()
{
return (nextIndex(_iTail) == _iHead);
} }
\ No newline at end of file
...@@ -41,6 +41,7 @@ class RingBuffer ...@@ -41,6 +41,7 @@ class RingBuffer
int read_char(); int read_char();
int available(); int available();
int peek(); int peek();
bool isFull();
private: private:
int nextIndex(int index); int nextIndex(int index);
......
...@@ -8,103 +8,280 @@ SERCOM::SERCOM(Sercom* sercom) ...@@ -8,103 +8,280 @@ SERCOM::SERCOM(Sercom* sercom)
sercomSpi = sercom->SPI; sercomSpi = sercom->SPI;
} }
/* =========================
* ===== Sercom UART
* =========================
*/
void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate) void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate)
{ {
resetUART(); resetUART();
sercomUart->CTRLA.reg = SERCOM_UART_CTRLA_MODE(mode) | //Setting the CTRLA register
sercom->USART.CTRLA.reg = SERCOM_UART_CTRLA_MODE(mode) |
SERCOM_USART_CTRLA_SAMPR(sampleRate); SERCOM_USART_CTRLA_SAMPR(sampleRate);
//
if(mode == UART_INT_CLOCK) if(mode == UART_INT_CLOCK)
{ {
uint32_t sampleRateValue; uint32_t sampleRateValue;
if(sampleRate == SAMPLE_RATE_x16) if(sampleRate == SAMPLE_RATE_x16)
{
sampleRateValue = 16; sampleRateValue = 16;
}
else if(sampleRate == SAMPLE_RATE_x8) else if(sampleRate == SAMPLE_RATE_x8)
{
sampleRateValue = 8; sampleRateValue = 8;
}
else else
{
sampleRateValue = 3; sampleRateValue = 3;
}
//Asynchronous arithmetic mode //Asynchronous arithmetic mode
sercomUart->BAUD.reg = 65535 * ( 1 - sampleRateValue * (baudrate / SERCOM_FREQ_REF)); sercom->USART.BAUD.reg = 65535 * ( 1 - sampleRateValue * (baudrate / SERCOM_FREQ_REF));
} }
} }
void initFrame(SercomCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits) void initFrame(SercomUartCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits)
{ {
sercomUart->CTRLA.reg |= SERCOM_UART_CTRLA_FORM( (parityMode == NO_PARITY ? 0 : 1) ) | //Setting the CTRLA register
sercom->USART.CTRLA.reg |= SERCOM_UART_CTRLA_FORM( (parityMode == NO_PARITY ? 0 : 1) ) |
dataOrder << SERCOM_UART_CTRLA_DORD_Pos; dataOrder << SERCOM_UART_CTRLA_DORD_Pos;
sercomUart->CTRLB.reg |= SERCOM_UART_CTRLB_CHSIZE(charSize) | //Setting the CRTLB register
sercom->USART.CTRLB.reg |= SERCOM_UART_CTRLB_CHSIZE(charSize) |
nbStopBits << SERCOM_UART_CTRLB_SBMODE_Pos | nbStopBits << SERCOM_UART_CTRLB_SBMODE_Pos |
(parityMode == NO_PARITY ? 0 : parityMode) << SERCOM_UART_CTRLB_PMODE_Pos |; (parityMode == NO_PARITY ? 0 : parityMode) << SERCOM_UART_CTRLB_PMODE_Pos; //If no parity use default value
} }
void initPads(SercomUartTXPad txPad, SercomUartRXPad rxPad) void initPads(SercomUartTXPad txPad, SercomRXPad rxPad)
{ {
sercomUart->CTRLA.reg |= SERCOM_UART_CTRLA_TXPO(txPad) | //Setting the CTRLA register
sercom->USART.CTRLA.reg |= SERCOM_UART_CTRLA_TXPO(txPad) |
SERCOM_UART_CTRLA_RXPO(rxPad); SERCOM_UART_CTRLA_RXPO(rxPad);
sercomUart->CTRLB.reg |= SERCOM_UART_CTRLB_TXEN | //Setting the CRTLB register (Enabling Transceiver and Receiver)
sercom->USART.CTRLB.reg |= SERCOM_UART_CTRLB_TXEN |
SERCOM_UART_CTRLB_RXEN; SERCOM_UART_CTRLB_RXEN;
} }
void SERCOM::resetUART() void SERCOM::resetUART()
{ {
sercomUart->CTRLA.bit.SWRST = 0x1u; //Setting the Software bit to 1
while(sercomUart->CTRLA.bit.SWRST || sercomUart->SYNCBUSY.SWRST); sercom->USART.CTRLA.bit.SWRST = 0x1u;
//Wait for both bits Software Reset from CTRLA and SYNCBUSY are equal to 0
while(sercom->USART.CTRLA.bit.SWRST || sercom->USART.SYNCBUSY.SWRST);
} }
void SERCOM::enableUART() void SERCOM::enableUART()
{ {
sercomUart->CTRLA.bit.ENABLE = 0x1u; //Setting the enable bit to 1
sercom->USART.CTRLA.bit.ENABLE = 0x1u;
//Wait for then enable bit from SYNCBUSY is equal to 0;
while(sercom->USART.SYNCBUSY.bit.ENABLE);
} }
void SERCOM::flushUART() void SERCOM::flushUART()
{ {
while(sercomUart->INTFLAG.bit.DRE != SERCOM_USART_INTFLAG_DRE); // Wait for transmission to complete
while(sercom->USART.INTFLAG.bit.DRE != SERCOM_USART_INTFLAG_DRE);
} }
void SERCOM::clearStatusUART() void SERCOM::clearStatusUART()
{ {
sercomUart->STATUS.reg = SERCOM_USART_STATUS_RESETVALUE; //Reset (with 0) the STATUS register
sercom->USART.STATUS.reg = SERCOM_USART_STATUS_RESETVALUE;
} }
bool SERCOM::availableDataUART() bool SERCOM::availableDataUART()
{ {
return sercomUart->INTFLAG.bit.RXC; //RXC : Receive Complete
return sercom->USART.INTFLAG.bit.RXC;
} }
bool SERCOM::isBufferOverflowErrorUART() bool SERCOM::isBufferOverflowErrorUART()
{ {
return sercomUart->STATUS.bit.BUFOVF; //BUFOVF : Buffer Overflow
return sercom->USART.STATUS.bit.BUFOVF;
} }
bool SERCOM::isFrameErrorUART() bool SERCOM::isFrameErrorUART()
{ {
return sercomUart->STATUS.bit.FERR; //FERR : Frame Error
return sercom->USART.STATUS.bit.FERR;
} }
bool SERCOM::isParityErrorUART() bool SERCOM::isParityErrorUART()
{ {
return sercomUart->STATUS.bit.PERR; //PERR : Parity Error
return sercom->USART.STATUS.bit.PERR;
}
bool SERCOM::isDataRegisterEmptyUART()
{
//DRE : Data Register Empty
return sercom->USART.INTFLAG.bit.DRE;
} }
uint8_t SERCOM::readDataUART() uint8_t SERCOM::readDataUART()
{ {
return sercomUart->DATA.bit.DATA; return sercom->USART.DATA.bit.DATA;
} }
int SERCOM::writeDataUART(uint8_t data) int SERCOM::writeDataUART(uint8_t data)
{ {
//Flush UART buffer
flushUART(); flushUART();
sercomUart->DATA.bit.DATA = data; //Put data into DATA register
sercom->USART.DATA.bit.DATA = data;
return 1; return 1;
} }
/* =========================
* ===== Sercom SPI
* =========================
*/
void SERCOM::initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder)
{
resetSPI();
//Setting the CTRLA register
sercom->SPI.CTRLA.reg = SERCOM_SPI_CTRLA_MODE(SPI_MASTER_OPERATION) |
SERCOM_SPI_CTRLA_DOPO(mosi) |
SERCOM_SPI_CTRLA_DIPO(miso) |
dataOrder << SERCOM_SPI_CTRLA_DORD_Pos;
//Setting the CTRLB register
sercom->SPI.CTRLB.reg = SERCOM_SPI_CTRLB_CHSIZE(charSize) |
(0x1ul) << SERCOM_SPI_CTRLB_RXEN_Pos; //Active the SPI receiver.
}
void SERCOM::initClock(SercomSpiClockMode clockMode, uint32_t baudrate)
{
//Extract data from clockMode
int cpha, cpol;
if((clockMode & (0x1ul)) == 0 )
cpha = 0;
else
cpha = 1;
if((clockMode & (0x2ul)) == 0)
cpol = 0;
else
cpol = 1;
//Setting the CTRLA register
sercom->SPI.CTRLA.reg |= cpha << SERCOM_SPI_CTRLA_CPHA_Pos |
cpol << SERCOM_SPI_CTRLA_CPOL_Pos;
//Synchronous arithmetic
sercom->SPI.BAUD.reg = calculateBaudrateSynchronous(baudrate);
}
void SERCOM::resetSPI()
{
//Set the Software bit to 1
sercom->SPI.CTRLA.bit.SWRST = 0x1u;
//Wait both bits Software Reset from CTRLA and SYNCBUSY are equal to 0
while(sercom->SPI.CTRLA.bit.SWRST || sercom->SPI.SYNCBUSY.SWRST);
}
void SERCOM::enableSPI()
{
//Set the enable bit to 1
sercom->SPI.CTRLA.bit.ENABLE = 0x1ul;
//Waiting then enable bit from SYNCBUSY is equal to 0;
while(sercom->SPI.SYNCBUSY.bit.ENABLE);
}
void SERCOM::disableSPI()
{
//Set the enable bit to 0
sercom->SPI.CTRLA.bit.ENABLE = 0x0ul;
//Waiting then enable bit from SYNCBUSY is equal to 0;
while(sercom->SPI.SYNCBUSY.bit.ENABLE);
}
void setDataOrderSPI(SercomDataOrder dataOrder)
{
//Register enable-protected
disableSPI();
sercom->SPI.CTRLA.bit.DORD = dataOrder;
enableSPI();
}
void setBaudrateSPI(uint8_t divider)
{
//Can't divide by 0
if(baudrate == 0)
return;
//Register enable-protected
disableSPI();
sercom->SPI.BAUD.reg = calculateBaudrateSynchronous(SERCOM_FREQ_REF / baudrate);
enableSPI();
}
void setClockModeSPI(SercomSpiClockMode clockMode)
{
int cpha, cpol;
if((clockMode & (0x1ul)) == 0)
cpha = 0;
else
cpha = 1;
if((clockMode & (0x2ul)) == 0)
cpol = 0;
else
cpol = 1;
//Register enable-protected
disableSPI();
sercom->SPI.CTRLA.bit.CPOL = cpol;
sercom->SPI.CTRLA.bit.CPHA = cpha;
enableSPI();
}
void writeDataSPI(uint8_t data)
{
sercom->SPI.DATA.bit.DATA = data;
}
uint8_t readDataSPI()
{
return sercom->SPI.DATA.bit.DATA;
}
bool SERCOM::isBufferOverflowErrorSPI()
{
return sercom->SPI.STATUS.bit.BUFOVF;
}
bool SERCOM::isDataRegisterEmptySPI()
{
//DRE : Data Register Empty
return sercom->SPI.INTFLAG.bit.DRE;
}
bool SERCOM::isTransmitCompleteSPI()
{
//TXC : Transmit complete
return sercom->SPI.INTFLAG.bit.TXC;
}
bool SERCOM::isReceiveCompleteSPI()
{
//RXC : Receive complete
return sercom->SPI.INTFLAG.bit.RXC;
}
uint8_t SERCOM::calculateBaudrateSynchronous(uint32_t baudrate)
{
return SERCOM_FREQ_REF / (2 * baudrate) - 1;
}
...@@ -49,7 +49,7 @@ typedef enum ...@@ -49,7 +49,7 @@ typedef enum
5_BITS = 0x5u, 5_BITS = 0x5u,
6_BITS, 6_BITS,
7_BITS 7_BITS
} SercomCharSize; } SercomUartCharSize;
typedef enum typedef enum
{ {
...@@ -57,7 +57,7 @@ typedef enum ...@@ -57,7 +57,7 @@ typedef enum
PAD_1, PAD_1,
PAD_2, PAD_2,
PAD_3 PAD_3
} SercomUartRXPad; } SercomRXPad;
Vtypedef enum Vtypedef enum
{ {
...@@ -76,15 +76,25 @@ typedef enum ...@@ -76,15 +76,25 @@ typedef enum
typedef enum typedef enum
{ {
CPOL_0 = 0, SPI_MODE_0 = 0, // CPOL : 0 | CPHA : 0
CPOL_1 SPI_MODE_1, // CPOL : 0 | CPHA : 1
} SercomSpiCphaMode; SPI_MODE_2, // CPOL : 1 | CPHA : 0
SPI_MODE_3 // CPOL : 1 | CPHA : 1
} SercomSpiClockMode;
typedef enum typedef enum
{ {
CPHA_0 = 0, PAD_0_SCK_1 = 0,
CPHA_1 PAD_2_SCK_3,
} SercomSpiCpolMode; PAD_3_SCK_1,
PAD_0_SCK_3
} SercomSpiTXPad;
typedef enum
{
8_BITS = 0,
9_BITS = 1
} SercomSpiCharSize;
class SERCOM class SERCOM
{ {
...@@ -93,8 +103,8 @@ class SERCOM ...@@ -93,8 +103,8 @@ class SERCOM
/* ========== UART ========== */ /* ========== UART ========== */
void initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate=0); void initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate=0);
void initFrame(SercomCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits); void initFrame(SercomUartCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits);
void initPads(SercomUartTXPad txPad, SercomUartRXPad rxPad); void initPads(SercomUartTXPad txPad, SercomRXPad rxPad);
void resetUART(); void resetUART();
void enableUART(); void enableUART();
...@@ -104,17 +114,31 @@ class SERCOM ...@@ -104,17 +114,31 @@ class SERCOM
bool isBufferOverflowErrorUART(); bool isBufferOverflowErrorUART();
bool isFrameErrorUART(); bool isFrameErrorUART();
bool isParityErrorUART(); bool isParityErrorUART();
bool isDataRegisterEmptyUART()
uint8_t readDataUART(); uint8_t readDataUART();
int writeDataUART(uint8_t data); int writeDataUART(uint8_t data);
/* ========== SPI ========== */ /* ========== SPI ========== */
void initSPI(); void initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder);
void initClock(SercomSpiClockMode clockMode, uint32_t baudrate);
void resetSPI();
void enableSPI();
void disableSPI();
void setDataOrderSPI(SercomDataOrder dataOrder);
void setBaudrateSPI(uint8_t divider);
void setClockModeSPI(SercomSpiClockMode clockMode);
void writeDataSPI(uint8_t data);
uint8_t readDataSPI();
bool isBufferOverflowErrorSPI();
bool isDataRegisterEmptySPI();
bool isTransmitCompleteSPI();
bool isReceiveCompleteSPI();
private: private:
Sercom* sercom; Sercom* sercom;
SercomUart* sercomUart; uint8_t calculateBaudrateSynchronous(uint32_t baudrate);
SercomSpi* sercomSpi;
}; };
#endif #endif
...@@ -37,7 +37,12 @@ void SERCOMUart::IrqHandler() ...@@ -37,7 +37,12 @@ void SERCOMUart::IrqHandler()
{ {
rxBuffer.store_char(sercom->readDataUART()) rxBuffer.store_char(sercom->readDataUART())
} }
if(sercom->isDataRegisterEmptyUART())
{
writeDataUART(txBuffer.read_char());
}
if( sercom->isBufferOverflowErrorUART() || if( sercom->isBufferOverflowErrorUART() ||
sercom->isFrameErrorUART() || sercom->isFrameErrorUART() ||
sercom->isParityErrorUART()) sercom->isParityErrorUART())
...@@ -46,7 +51,7 @@ void SERCOMUart::IrqHandler() ...@@ -46,7 +51,7 @@ void SERCOMUart::IrqHandler()
} }
} }
bool SERCOMUart::available() int SERCOMUart::available()
{ {
return rxBuffer.available(); return rxBuffer.available();
} }
...@@ -63,7 +68,11 @@ int SERCOMUart::read() ...@@ -63,7 +68,11 @@ int SERCOMUart::read()
size_t SERCOMUart::write(uint8_t data) size_t SERCOMUart::write(uint8_t data)
{ {
return sercom->writeDataUART(data); if(txBuffer.isFull())
return 0;
txBuffer.store_char(data);
return 1;
} }
SercomNumberStopBit extractNbStopBit(uint8_t config) SercomNumberStopBit extractNbStopBit(uint8_t config)
......
...@@ -25,6 +25,7 @@ class SERCOMUart ...@@ -25,6 +25,7 @@ class SERCOMUart
private: private:
SERCOM *sercom; SERCOM *sercom;
RingBuffer rxBuffer; RingBuffer rxBuffer;
RingBuffer txBuffer;
SercomNumberStopBit extractNbStopBit(uint8_t config); SercomNumberStopBit extractNbStopBit(uint8_t config);
SercomCharSize extractCharSize(uint8_t config); SercomCharSize extractCharSize(uint8_t config);
......
...@@ -10,109 +10,79 @@ ...@@ -10,109 +10,79 @@
#include "SPI.h" #include "SPI.h"
SPIClass::SPIClass(Spi *_spi, uint32_t _id, void(*_initCb)(void)) : SPIClass::SPIClass(SERCOM *sercom)
spi(_spi), id(_id), initCb(_initCb), initialized(false)
{ {
// Empty this->sercom = sercom;
} }
void SPIClass::begin() { void SPIClass::begin() {
init(); // Default speed set to 4Mhz, SPI mode set to MODE 0 and Bit order set to MSB first.
sercom->initSPI(PAD_0_SCK_1, PAD_2, 8_BITS, MSB_FIRST);
// NPCS control is left to the user sercom->initClock(MODE_0, 4000000);
// Default speed set to 4Mhz
setClockDivider(BOARD_SPI_DEFAULT_SS, 21);
setDataMode(BOARD_SPI_DEFAULT_SS, SPI_MODE0);
setBitOrder(BOARD_SPI_DEFAULT_SS, MSBFIRST);
}
void SPIClass::begin(uint8_t _pin) {
init();
uint32_t spiPin = BOARD_PIN_TO_SPI_PIN(_pin);
PIO_Configure(
g_APinDescription[spiPin].pPort,
g_APinDescription[spiPin].ulPinType,
g_APinDescription[spiPin].ulPin,
g_APinDescription[spiPin].ulPinConfiguration);
// Default speed set to 4Mhz
setClockDivider(_pin, 21);
setDataMode(_pin, SPI_MODE0);
setBitOrder(_pin, MSBFIRST);
}
void SPIClass::init() {
if (initialized)
return;
initCb();
SPI_Configure(spi, id, SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS);
SPI_Enable(spi);
initialized = true;
}
void SPIClass::end(uint8_t _pin) {
uint32_t spiPin = BOARD_PIN_TO_SPI_PIN(_pin);
// Setting the pin as INPUT will disconnect it from SPI peripheral
pinMode(spiPin, INPUT);
} }
void SPIClass::end() { void SPIClass::end() {
SPI_Disable(spi); sercom->resetSPI();
initialized = false;
} }
void SPIClass::setBitOrder(uint8_t _pin, BitOrder _bitOrder) { void setBitOrder(BitOrder order)
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin); {
bitOrder[ch] = _bitOrder; if(order == LSBFIRST)
sercom->setDataOrderSPI(LSB_FIRST);
else
sercom->setDataOrderSPI(MSB_FIRST);
} }
void SPIClass::setDataMode(uint8_t _pin, uint8_t _mode) { void setDataMode(uint8_t mode)
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin); {
mode[ch] = _mode | SPI_CSR_CSAAT; switch(mode)
// SPI_CSR_DLYBCT(1) keeps CS enabled for 32 MCLK after a completed {
// transfer. Some device needs that for working properly. case SPI_MODE0:
SPI_ConfigureNPCS(spi, ch, mode[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1)); sercom->setClockModeSPI(MODE_0);
break;
case SPI_MODE1:
sercom->setClockModeSPI(MODE_1);
break;
case SPI_MODE2:
sercom->setClockModeSPI(MODE_2);
break;
case SPI_MODE3:
sercom->setClockModeSPI(MODE_3);
break;
default:
break;
}
} }
void SPIClass::setClockDivider(uint8_t _pin, uint8_t _divider) { void setClockDivider(uint8_t div)
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin); {
divider[ch] = _divider; sercom->setBaudrateSPI(div);
// SPI_CSR_DLYBCT(1) keeps CS enabled for 32 MCLK after a completed
// transfer. Some device needs that for working properly.
SPI_ConfigureNPCS(spi, ch, mode[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1));
} }
byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) { byte SPIClass::transfer(uint8_t _data)
uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin); {
// Reverse bit order //Can writing new data?
if (bitOrder[ch] == LSBFIRST) while(!sercom->isDataRegisterEmptySPI());
_data = __REV(__RBIT(_data));
uint32_t d = _data | SPI_PCS(ch); //Writing the data
if (_mode == SPI_LAST) sercom->writeDataSPI(data);
d |= SPI_TDR_LASTXFER;
//Data sent? new data to read?
// SPI_Write(spi, _channel, _data); while(!sercom->isTransmitCompleteSPI() || !sercom->isReceiveCompleteSPI());
while ((spi->SPI_SR & SPI_SR_TDRE) == 0)
; //Read data
spi->SPI_TDR = d; return sercom->readDataSPI();
// return SPI_Read(spi);
while ((spi->SPI_SR & SPI_SR_RDRF) == 0)
;
d = spi->SPI_RDR;
// Reverse bit order
if (bitOrder[ch] == LSBFIRST)
d = __REV(__RBIT(d));
return d & 0xFF;
} }
void SPIClass::attachInterrupt(void) { void SPIClass::attachInterrupt() {
// Should be enableInterrupt() // Should be enableInterrupt()
} }
void SPIClass::detachInterrupt(void) { void SPIClass::detachInterrupt() {
// Should be disableInterrupt() // Should be disableInterrupt()
} }
......
...@@ -12,57 +12,29 @@ ...@@ -12,57 +12,29 @@
#define _SPI_H_INCLUDED #define _SPI_H_INCLUDED
#include "variant.h" #include "variant.h"
#include <stdio.h> #include "SERCOM.h"
#define SPI_MODE0 0x02
#define SPI_MODE1 0x00
#define SPI_MODE2 0x03
#define SPI_MODE3 0x01
enum SPITransferMode { #include <stdio.h>
SPI_CONTINUE,
SPI_LAST
};
class SPIClass { class SPIClass {
public: public:
SPIClass(Spi *_spi, uint32_t _id, void(*_initCb)(void)); SPIClass(SERCOM *sercom);
byte transfer(uint8_t _data, SPITransferMode _mode = SPI_LAST) { return transfer(BOARD_SPI_DEFAULT_SS, _data, _mode); } byte transfer(uint8_t _data);
byte transfer(byte _channel, uint8_t _data, SPITransferMode _mode = SPI_LAST);
// SPI Configuration methods // SPI Configuration methods
void attachInterrupt();
void detachInterrupt();
void attachInterrupt(void); void begin();
void detachInterrupt(void); void end();
void begin(void); void setBitOrder(BitOrder order);
void end(void); void setDataMode(uint8_t mode);
void setClockDivider(uint8_t div);
// Attach/Detach pin to/from SPI controller
void begin(uint8_t _pin);
void end(uint8_t _pin);
// These methods sets a parameter on a single pin
void setBitOrder(uint8_t _pin, BitOrder);
void setDataMode(uint8_t _pin, uint8_t);
void setClockDivider(uint8_t _pin, uint8_t);
// These methods sets the same parameters but on default pin BOARD_SPI_DEFAULT_SS
void setBitOrder(BitOrder _order) { setBitOrder(BOARD_SPI_DEFAULT_SS, _order); };
void setDataMode(uint8_t _mode) { setDataMode(BOARD_SPI_DEFAULT_SS, _mode); };
void setClockDivider(uint8_t _div) { setClockDivider(BOARD_SPI_DEFAULT_SS, _div); };
private: private:
void init(); SERCOM *sercom;
Spi *spi;
uint32_t id;
BitOrder bitOrder[SPI_CHANNELS_NUM];
uint32_t divider[SPI_CHANNELS_NUM];
uint32_t mode[SPI_CHANNELS_NUM];
void (*initCb)(void);
bool initialized;
}; };
#if SPI_INTERFACES_COUNT > 0 #if SPI_INTERFACES_COUNT > 0
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment