diff --git a/cores/arduino/SERCOM.cpp b/cores/arduino/SERCOM.cpp index 298ed07ed79768fc469071e742fa04bd200c362f..920c56d7df198bd0962fab6f5b743970242e0fd1 100644 --- a/cores/arduino/SERCOM.cpp +++ b/cores/arduino/SERCOM.cpp @@ -8,103 +8,182 @@ SERCOM::SERCOM(Sercom* sercom) sercomSpi = sercom->SPI; } +/* ========================= + * ===== Sercom UART + * ========================= +*/ void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate) { 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); + // if(mode == UART_INT_CLOCK) { uint32_t sampleRateValue; + if(sampleRate == SAMPLE_RATE_x16) - { sampleRateValue = 16; - } else if(sampleRate == SAMPLE_RATE_x8) - { sampleRateValue = 8; - } else - { sampleRateValue = 3; - } - + //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; - 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 | - (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); - 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; } void SERCOM::resetUART() { - sercomUart->CTRLA.bit.SWRST = 0x1u; - while(sercomUart->CTRLA.bit.SWRST || sercomUart->SYNCBUSY.SWRST); + //Setting the Software bit to 1 + 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() { - 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() { - 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() { - sercomUart->STATUS.reg = SERCOM_USART_STATUS_RESETVALUE; + //Reset (with 0) the STATUS register + sercom->USART.STATUS.reg = SERCOM_USART_STATUS_RESETVALUE; } bool SERCOM::availableDataUART() { - return sercomUart->INTFLAG.bit.RXC; + return sercom->USART.INTFLAG.bit.RXC; } bool SERCOM::isBufferOverflowErrorUART() { - return sercomUart->STATUS.bit.BUFOVF; + return sercom->USART.STATUS.bit.BUFOVF; } bool SERCOM::isFrameErrorUART() { - return sercomUart->STATUS.bit.FERR; + return sercom->USART.STATUS.bit.FERR; } bool SERCOM::isParityErrorUART() { - return sercomUart->STATUS.bit.PERR; + return sercom->USART.STATUS.bit.PERR; } uint8_t SERCOM::readDataUART() { - return sercomUart->DATA.bit.DATA; + return sercom->USART.DATA.bit.DATA; } int SERCOM::writeDataUART(uint8_t data) { + //Flush UART buffer flushUART(); - sercomUart->DATA.bit.DATA = data; + //Put data into DATA register + sercom->USART.DATA.bit.DATA = data; 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) +{ + 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 = SERCOM_FREQ_REF / (2 * baudrate) - 1; +} + +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); +} + +bool SERCOM::isBufferOverflowErrorSPI() +{ + return sercom->SPI.STATUS.bit.BUFOVF; +} diff --git a/cores/arduino/SERCOM.h b/cores/arduino/SERCOM.h index db45139a464c4ac15e19cb2e58188ab56faf7224..a549db89f571c7268ce4ef40767bfd7da2176f7b 100644 --- a/cores/arduino/SERCOM.h +++ b/cores/arduino/SERCOM.h @@ -49,7 +49,7 @@ typedef enum 5_BITS = 0x5u, 6_BITS, 7_BITS -} SercomCharSize; +} SercomUartCharSize; typedef enum { @@ -57,7 +57,7 @@ typedef enum PAD_1, PAD_2, PAD_3 -} SercomUartRXPad; +} SercomRXPad; Vtypedef enum { @@ -76,15 +76,25 @@ typedef enum typedef enum { - CPOL_0 = 0, - CPOL_1 -} SercomSpiCphaMode; + SPI_MODE_0 = 0, // CPOL : 0 | CPHA : 0 + SPI_MODE_1, // CPOL : 0 | CPHA : 1 + SPI_MODE_2, // CPOL : 1 | CPHA : 0 + SPI_MODE_3 // CPOL : 1 | CPHA : 1 +} SercomSpiClockMode; typedef enum { - CPHA_0 = 0, - CPHA_1 -} SercomSpiCpolMode; + PAD_0_SCK_1 = 0, + PAD_2_SCK_3, + PAD_3_SCK_1, + PAD_0_SCK_3 +} SercomSpiTXPad; + +typedef enum +{ + 8_BITS = 0, + 9_BITS = 1 +} SercomSpiCharSize; class SERCOM { @@ -93,8 +103,8 @@ class SERCOM /* ========== UART ========== */ void initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate=0); - void initFrame(SercomCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits); - void initPads(SercomUartTXPad txPad, SercomUartRXPad rxPad); + void initFrame(SercomUartCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits); + void initPads(SercomUartTXPad txPad, SercomRXPad rxPad); void resetUART(); void enableUART(); @@ -108,13 +118,17 @@ class SERCOM int writeDataUART(uint8_t data); /* ========== SPI ========== */ - void initSPI(); + void initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder); + void initClock(SercomSpiClockMode clockMode, uint32_t baudrate); + + void resetSPI(); + void enableSPI(); + bool isBufferOverflowErrorSPI(); + private: Sercom* sercom; - SercomUart* sercomUart; - SercomSpi* sercomSpi; }; #endif diff --git a/cores/arduino/SERCOMUart.cpp b/cores/arduino/SERCOMUart.cpp index c3aa4a139514b64d407eb59df53a015328c4b304..87a8a11d377245c57bfba7f354aee452f891a7f2 100644 --- a/cores/arduino/SERCOMUart.cpp +++ b/cores/arduino/SERCOMUart.cpp @@ -46,7 +46,7 @@ void SERCOMUart::IrqHandler() } } -bool SERCOMUart::available() +int SERCOMUart::available() { return rxBuffer.available(); } diff --git a/libraries/SPI/SPI.h b/libraries/SPI/SPI.h index 735bd4bf9a517af2c6a5e7f68bf7dde9bf00fdc3..697de19eae5aa7c9dc82ce18ecfab8856dcd86a0 100644 --- a/libraries/SPI/SPI.h +++ b/libraries/SPI/SPI.h @@ -32,26 +32,15 @@ class SPIClass { byte transfer(byte _channel, uint8_t _data, SPITransferMode _mode = SPI_LAST); // SPI Configuration methods - void attachInterrupt(void); void detachInterrupt(void); void begin(void); void end(void); - - // 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); }; + + void setBitOrder(BitOrder _order); + void setDataMode(uint8_t _mode); + void setClockDivider(uint8_t _div); private: void init();