Skip to content
Snippets Groups Projects
Commit 83cf1c0b authored by Thibaut VIARD's avatar Thibaut VIARD
Browse files

Merge branch 'zero' of github.com:arduino/ArduinoZero into zero

Conflicts:
	hardware/arduino/samd/variants/arduino_zero/variant.cpp
parents ab89e9e4 86b6f106
No related branches found
No related tags found
No related merge requests found
...@@ -82,6 +82,7 @@ typedef void (*voidFuncPtr)( void ) ; ...@@ -82,6 +82,7 @@ typedef void (*voidFuncPtr)( void ) ;
#include "HardwareSerial.h" #include "HardwareSerial.h"
#include "wiring_pulse.h" #include "wiring_pulse.h"
#include "delay.h" #include "delay.h"
#include "Uart.h"
#endif // __cplusplus #endif // __cplusplus
......
...@@ -29,7 +29,7 @@ static void banzai() { ...@@ -29,7 +29,7 @@ static void banzai() {
__disable_irq(); __disable_irq();
// Reset the device // Reset the device
// todo NVIC_SystemReset() ;
while (true); while (true);
} }
......
#include "SERCOM.h" #include "SERCOM.h"
// Constants for Clock multiplexers
#define GENERIC_CLOCK_SERCOM0 (0x14ul)
#define GENERIC_CLOCK_SERCOM1 (0x15ul)
#define GENERIC_CLOCK_SERCOM2 (0x16ul)
#define GENERIC_CLOCK_SERCOM3 (0x17ul)
#define GENERIC_CLOCK_SERCOM4 (0x18ul)
#define GENERIC_CLOCK_SERCOM5 (0x19ul)
SERCOM::SERCOM(Sercom* sercom) SERCOM::SERCOM(Sercom* s)
{ {
this->sercom = sercom; sercom = s;
} }
/* ========================= /* =========================
* ===== Sercom UART * ===== Sercom UART
* ========================= * =========================
*/ */
void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate) void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate)
{ {
resetUART(); resetUART();
initClock();
//Setting the CTRLA register //Setting the CTRLA register
sercom->USART.CTRLA.reg = SERCOM_USART_CTRLA_MODE(mode) | sercom->USART.CTRLA.reg = SERCOM_USART_CTRLA_MODE(mode) |
SERCOM_USART_CTRLA_SAMPR(sampleRate); SERCOM_USART_CTRLA_SAMPR(sampleRate);
//Setting the Interrupt register //Setting the Interrupt register
sercom->USART.INTENSET.reg = SERCOM_USART_INTENSET_DRE | //Data Register Empty sercom->USART.INTENSET.reg = SERCOM_USART_INTENSET_RXC | //Received complete
SERCOM_USART_INTENSET_RXC | //Received complete
SERCOM_USART_INTENSET_ERROR; //All others errors SERCOM_USART_INTENSET_ERROR; //All others errors
NVIC_EnableIRQ(SERCOM0_IRQn);
NVIC_SetPriority (SERCOM0_IRQn, (1<<__NVIC_PRIO_BITS) - 1); /* set Priority for Systick Interrupt */
if(mode == UART_INT_CLOCK) if(mode == UART_INT_CLOCK)
{ {
...@@ -35,7 +47,13 @@ void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint ...@@ -35,7 +47,13 @@ void SERCOM::initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint
sampleRateValue = 3; sampleRateValue = 3;
//Asynchronous arithmetic mode //Asynchronous arithmetic mode
sercom->USART.BAUD.reg = 65535 * ( 1 - sampleRateValue * division(baudrate,SERCOM_FREQ_REF)); //sercom->USART.BAUD.reg = 65535 * ( 1 - sampleRateValue * division(baudrate,SERCOM_FREQ_REF));
uint16_t tmpBaud = (baudrate / SERCOM_FREQ_REF);
tmpBaud = ( 1 - sampleRateValue * tmpBaud);
tmpBaud = (65535ul) * tmpBaud;
tmpBaud = 63019;
sercom->USART.BAUD.reg = tmpBaud;
} }
} }
void SERCOM::initFrame(SercomUartCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits) void SERCOM::initFrame(SercomUartCharSize charSize, SercomDataOrder dataOrder, SercomParityMode parityMode, SercomNumberStopBit nbStopBits)
...@@ -132,7 +150,7 @@ int SERCOM::writeDataUART(uint8_t data) ...@@ -132,7 +150,7 @@ int SERCOM::writeDataUART(uint8_t data)
flushUART(); flushUART();
//Put data into DATA register //Put data into DATA register
sercom->USART.DATA.bit.DATA = data; sercom->USART.DATA.reg = (uint16_t)data;
return 1; return 1;
} }
...@@ -155,7 +173,7 @@ void SERCOM::initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize ch ...@@ -155,7 +173,7 @@ void SERCOM::initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize ch
(0x1ul) << SERCOM_SPI_CTRLB_RXEN_Pos; //Active the SPI receiver. (0x1ul) << SERCOM_SPI_CTRLB_RXEN_Pos; //Active the SPI receiver.
} }
void SERCOM::initClock(SercomSpiClockMode clockMode, uint32_t baudrate) void SERCOM::initSPIClock(SercomSpiClockMode clockMode, uint32_t baudrate)
{ {
//Extract data from clockMode //Extract data from clockMode
int cpha, cpol; int cpha, cpol;
...@@ -291,36 +309,36 @@ uint8_t SERCOM::calculateBaudrateSynchronous(uint32_t baudrate) ...@@ -291,36 +309,36 @@ uint8_t SERCOM::calculateBaudrateSynchronous(uint32_t baudrate)
uint32_t SERCOM::division(uint32_t dividend, uint32_t divisor) uint32_t SERCOM::division(uint32_t dividend, uint32_t divisor)
{ {
// division WITHOUT division operator //// division WITHOUT division operator
//
uint32_t denom = divisor; //uint32_t denom = divisor;
uint32_t current = 1; //uint32_t current = 1;
uint32_t answer = 0; //uint32_t answer = 0;
//
if ( denom > dividend) //if ( denom > dividend)
return 0; //return 0;
//
if ( denom == dividend) //if ( denom == dividend)
return 1; //return 1;
//
while (denom <= dividend) { //while (denom <= dividend) {
denom <<= 1; //denom <<= 1;
current <<= 1; //current <<= 1;
} //}
//
denom >>= 1; //denom >>= 1;
current >>= 1; //current >>= 1;
//
while (current!=0) { //while (current!=0) {
if ( dividend >= denom) { //if ( dividend >= denom) {
dividend -= denom; //dividend -= denom;
answer |= current; //answer |= current;
} //}
current >>= 1; //current >>= 1;
denom >>= 1; //denom >>= 1;
} //}
//
return answer; //return answer;
} }
...@@ -515,3 +533,56 @@ uint8_t SERCOM::readDataWIRE() ...@@ -515,3 +533,56 @@ uint8_t SERCOM::readDataWIRE()
else else
return sercom->I2CS.DATA.reg; return sercom->I2CS.DATA.reg;
} }
void SERCOM::initClock()
{
uint8_t clockId;
if(sercom == SERCOM0)
{
clockId = GENERIC_CLOCK_SERCOM0;
}
else if(sercom == SERCOM1)
{
clockId = GENERIC_CLOCK_SERCOM1;
}
else if(sercom == SERCOM2)
{
clockId = GENERIC_CLOCK_SERCOM2;
}
else if(sercom == SERCOM3)
{
clockId = GENERIC_CLOCK_SERCOM3;
}
else if(sercom == SERCOM4)
{
clockId = GENERIC_CLOCK_SERCOM4;
}
else if(sercom == SERCOM5)
{
clockId = GENERIC_CLOCK_SERCOM5;
}
//Setting clock
GCLK->CLKCTRL.reg = GCLK_CLKCTRL_ID( clockId ) | // Generic Clock 0 (SERCOMx)
GCLK_CLKCTRL_GEN_GCLK0 | // Generic Clock Generator 0 is source
GCLK_CLKCTRL_CLKEN ;
while ( GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY )
{
/* Wait for synchronization */
}
}
/* =========================
* ===== SERCOM DEFINITION
* =========================
*/
SERCOM * SERCOM::sercom0 = new SERCOM(SERCOM0);
SERCOM * SERCOM::sercom1 = new SERCOM(SERCOM1);
SERCOM * SERCOM::sercom2 = new SERCOM(SERCOM2);
SERCOM * SERCOM::sercom3 = new SERCOM(SERCOM3);
SERCOM * SERCOM::sercom4 = new SERCOM(SERCOM4);
SERCOM * SERCOM::sercom5 = new SERCOM(SERCOM5);
...@@ -61,10 +61,10 @@ typedef enum ...@@ -61,10 +61,10 @@ typedef enum
typedef enum typedef enum
{ {
UART_TX_PAD_0 = 0, //Only for Intern Clock UART_TX_PAD_0 = 0x0ul, //Only for UART
UART_TX_PAD_1 = 0, //Only for Extern Clock UART_TX_PAD_2 = 0x1ul, //Only for UART
UART_TX_PAD_2 = 1, //Only for Intern Clock //UART_TX_PAD_1 = 0x0ul, //DON'T USE
UART_TX_PAD_3 = 1 //Only for Extern Clock //UART_TX_PAD_3 = 0x1ul //DON'T USE
} SercomUartTXPad; } SercomUartTXPad;
typedef enum typedef enum
...@@ -76,10 +76,10 @@ typedef enum ...@@ -76,10 +76,10 @@ typedef enum
typedef enum typedef enum
{ {
SPI_MODE_0 = 0, // CPOL : 0 | CPHA : 0 SERCOM_SPI_MODE_0 = 0, // CPOL : 0 | CPHA : 0
SPI_MODE_1, // CPOL : 0 | CPHA : 1 SERCOM_SPI_MODE_1, // CPOL : 0 | CPHA : 1
SPI_MODE_2, // CPOL : 1 | CPHA : 0 SERCOM_SPI_MODE_2, // CPOL : 1 | CPHA : 0
SPI_MODE_3 // CPOL : 1 | CPHA : 1 SERCOM_SPI_MODE_3 // CPOL : 1 | CPHA : 1
} SercomSpiClockMode; } SercomSpiClockMode;
typedef enum typedef enum
...@@ -127,7 +127,15 @@ typedef enum ...@@ -127,7 +127,15 @@ typedef enum
class SERCOM class SERCOM
{ {
public: public:
SERCOM(Sercom* sercom); SERCOM(Sercom* s);
/* ========== SERCOM OBJECT ========== */
static SERCOM * sercom0;
static SERCOM * sercom1;
static SERCOM * sercom2;
static SERCOM * sercom3;
static SERCOM * sercom4;
static SERCOM * sercom5;
/* ========== UART ========== */ /* ========== UART ========== */
void initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate=0); void initUART(SercomUartMode mode, SercomUartSampleRate sampleRate, uint32_t baudrate=0);
...@@ -148,7 +156,7 @@ class SERCOM ...@@ -148,7 +156,7 @@ class SERCOM
/* ========== SPI ========== */ /* ========== SPI ========== */
void initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder); void initSPI(SercomSpiTXPad mosi, SercomRXPad miso, SercomSpiCharSize charSize, SercomDataOrder dataOrder);
void initClock(SercomSpiClockMode clockMode, uint32_t baudrate); void initSPIClock(SercomSpiClockMode clockMode, uint32_t baudrate);
void resetSPI(); void resetSPI();
void enableSPI(); void enableSPI();
...@@ -190,6 +198,7 @@ class SERCOM ...@@ -190,6 +198,7 @@ class SERCOM
Sercom* sercom; Sercom* sercom;
uint8_t calculateBaudrateSynchronous(uint32_t baudrate); uint8_t calculateBaudrateSynchronous(uint32_t baudrate);
uint32_t division(uint32_t dividend, uint32_t divisor); uint32_t division(uint32_t dividend, uint32_t divisor);
void initClock();
}; };
#endif #endif
#include "SERCOMUart.h" #include "Uart.h"
SERCOMUart::SERCOMUart(SERCOM *sercom) Uart::Uart(SERCOM *sercom)
{ {
this->sercom = sercom; this->sercom = sercom;
pinPeripheral(0, PIO_SERCOM);
pinPeripheral(1, PIO_SERCOM);
} }
void SERCOMUart::begin(uint16_t baudrate) void Uart::begin(unsigned long baudrate)
{ {
begin(baudrate, SERIAL_8N1); begin(baudrate, SERIAL_8N1);
} }
void SERCOMUart::begin(uint16_t baudrate, uint8_t config) void Uart::begin(unsigned long baudrate, uint8_t config)
{ {
sercom->initUART(UART_INT_CLOCK, SAMPLE_RATE_x16, baudrate); sercom->initUART(UART_INT_CLOCK, SAMPLE_RATE_x16, baudrate);
sercom->initFrame(extractCharSize(config), LSB_FIRST, extractParity(config), extractNbStopBit(config)); sercom->initFrame(extractCharSize(config), LSB_FIRST, extractParity(config), extractNbStopBit(config));
sercom->initPads(UART_TX_PAD_0, SERCOM_RX_PAD_2); sercom->initPads(UART_TX_PAD_2, SERCOM_RX_PAD_3);
sercom->enableUART(); sercom->enableUART();
} }
void SERCOMUart::end() void Uart::end()
{ {
sercom->resetUART(); sercom->resetUART();
rxBuffer.clear(); rxBuffer.clear();
} }
void SERCOMUart::flush() void Uart::flush()
{ {
sercom->flushUART(); sercom->flushUART();
} }
void SERCOMUart::IrqHandler() void Uart::IrqHandler()
{ {
if(sercom->availableDataUART()) if(sercom->availableDataUART())
{ {
rxBuffer.store_char(sercom->readDataUART()); rxBuffer.store_char(sercom->readDataUART());
} }
if(sercom->isDataRegisterEmptyUART())
{
sercom->writeDataUART(txBuffer.read_char());
}
if( sercom->isBufferOverflowErrorUART() || if( sercom->isBufferOverflowErrorUART() ||
sercom->isFrameErrorUART() || sercom->isFrameErrorUART() ||
sercom->isParityErrorUART()) sercom->isParityErrorUART())
...@@ -51,31 +49,41 @@ void SERCOMUart::IrqHandler() ...@@ -51,31 +49,41 @@ void SERCOMUart::IrqHandler()
} }
} }
int SERCOMUart::available() int Uart::available()
{ {
return rxBuffer.available(); return rxBuffer.available();
} }
int SERCOMUart::peek() int Uart::peek()
{ {
return rxBuffer.peek(); return rxBuffer.peek();
} }
int SERCOMUart::read() int Uart::read()
{ {
return rxBuffer.read_char(); return rxBuffer.read_char();
} }
size_t SERCOMUart::write(uint8_t data) size_t Uart::write(const uint8_t data)
{ {
if(txBuffer.isFull()) sercom->writeDataUART(data);
return 0;
txBuffer.store_char(data);
return 1; return 1;
} }
SercomNumberStopBit SERCOMUart::extractNbStopBit(uint8_t config) size_t Uart::write(const char * data)
{
size_t writed = 0;
while(*data != '\0')
{
writed += write(*data);
++data;
}
return writed;
}
SercomNumberStopBit Uart::extractNbStopBit(uint8_t config)
{ {
switch(config & HARDSER_STOP_BIT_MASK) switch(config & HARDSER_STOP_BIT_MASK)
{ {
...@@ -88,7 +96,7 @@ SercomNumberStopBit SERCOMUart::extractNbStopBit(uint8_t config) ...@@ -88,7 +96,7 @@ SercomNumberStopBit SERCOMUart::extractNbStopBit(uint8_t config)
} }
} }
SercomUartCharSize SERCOMUart::extractCharSize(uint8_t config) SercomUartCharSize Uart::extractCharSize(uint8_t config)
{ {
switch(config & HARDSER_DATA_MASK) switch(config & HARDSER_DATA_MASK)
{ {
...@@ -108,7 +116,7 @@ SercomUartCharSize SERCOMUart::extractCharSize(uint8_t config) ...@@ -108,7 +116,7 @@ SercomUartCharSize SERCOMUart::extractCharSize(uint8_t config)
} }
} }
SercomParityMode SERCOMUart::extractParity(uint8_t config) SercomParityMode Uart::extractParity(uint8_t config)
{ {
switch(config & HARDSER_PARITY_MASK) switch(config & HARDSER_PARITY_MASK)
{ {
...@@ -124,3 +132,13 @@ SercomParityMode SERCOMUart::extractParity(uint8_t config) ...@@ -124,3 +132,13 @@ SercomParityMode SERCOMUart::extractParity(uint8_t config)
} }
} }
Uart Serial = Uart(SERCOM::sercom0);
void SERCOM0_Handler()
{
Serial.IrqHandler();
}
void SERCOM5_Handler()
{
Serial.IrqHandler();
}
#ifndef _SERCOM_UART_CLASS #ifndef _SERCOM_UART_CLASS
#define _SERCOM_UART_CLASS #define _SERCOM_UART_CLASS
#include "wiring_digital.h"
#include "HardwareSerial.h" #include "HardwareSerial.h"
#include "SERCOM.h" #include "SERCOM.h"
#include "RingBuffer.h" #include "RingBuffer.h"
...@@ -8,18 +10,19 @@ ...@@ -8,18 +10,19 @@
#include <cstddef> #include <cstddef>
class SERCOMUart : public HardwareSerial class Uart : public HardwareSerial
{ {
public: public:
SERCOMUart(SERCOM *sercom); Uart(SERCOM *sercom);
void begin(uint16_t baudRate); void begin(unsigned long baudRate);
void begin(uint16_t baudrate, uint8_t config); void begin(unsigned long baudrate, uint8_t config);
void end(); void end();
int available(); int available();
int peek(); int peek();
int read(); int read();
void flush(); void flush();
size_t write(const uint8_t c); size_t write(const uint8_t data);
size_t write(const char * data);
void IrqHandler(); void IrqHandler();
...@@ -28,12 +31,12 @@ class SERCOMUart : public HardwareSerial ...@@ -28,12 +31,12 @@ class SERCOMUart : public HardwareSerial
private: private:
SERCOM *sercom; SERCOM *sercom;
RingBuffer rxBuffer; RingBuffer rxBuffer;
RingBuffer txBuffer;
SercomNumberStopBit extractNbStopBit(uint8_t config); SercomNumberStopBit extractNbStopBit(uint8_t config);
SercomUartCharSize extractCharSize(uint8_t config); SercomUartCharSize extractCharSize(uint8_t config);
SercomParityMode extractParity(uint8_t config); SercomParityMode extractParity(uint8_t config);
}; };
extern Uart Serial;
#endif #endif
...@@ -10,22 +10,22 @@ ...@@ -10,22 +10,22 @@
#include "SPI.h" #include "SPI.h"
SPIClass::SPIClass(SERCOM *sercom) SPIClass::SPIClass(SERCOM *s)
{ {
this->sercom = sercom; sercom = s;
} }
void SPIClass::begin() { void SPIClass::begin() {
// Default speed set to 4Mhz, SPI mode set to MODE 0 and Bit order set to MSB first. // 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); sercom->initSPI(SPI_PAD_2_SCK_3, SERCOM_RX_PAD_0, SPI_CHAR_SIZE_8_BITS, MSB_FIRST);
sercom->initClock(MODE_0, 4000000); sercom->initClock(SERCOM_SPI_MODE_0, 4000000);
} }
void SPIClass::end() { void SPIClass::end() {
sercom->resetSPI(); sercom->resetSPI();
} }
void setBitOrder(BitOrder order) void SPIClass::setBitOrder(BitOrder order)
{ {
if(order == LSBFIRST) if(order == LSBFIRST)
sercom->setDataOrderSPI(LSB_FIRST); sercom->setDataOrderSPI(LSB_FIRST);
...@@ -33,24 +33,24 @@ void setBitOrder(BitOrder order) ...@@ -33,24 +33,24 @@ void setBitOrder(BitOrder order)
sercom->setDataOrderSPI(MSB_FIRST); sercom->setDataOrderSPI(MSB_FIRST);
} }
void setDataMode(uint8_t mode) void SPIClass::setDataMode(uint8_t mode)
{ {
switch(mode) switch(mode)
{ {
case SPI_MODE0: case SPI_MODE0:
sercom->setClockModeSPI(MODE_0); sercom->setClockModeSPI(SERCOM_SPI_MODE_0);
break; break;
case SPI_MODE1: case SPI_MODE1:
sercom->setClockModeSPI(MODE_1); sercom->setClockModeSPI(SERCOM_SPI_MODE_1);
break; break;
case SPI_MODE2: case SPI_MODE2:
sercom->setClockModeSPI(MODE_2); sercom->setClockModeSPI(SERCOM_SPI_MODE_2);
break; break;
case SPI_MODE3: case SPI_MODE3:
sercom->setClockModeSPI(MODE_3); sercom->setClockModeSPI(SERCOM_SPI_MODE_3);
break; break;
default: default:
...@@ -58,12 +58,12 @@ void setDataMode(uint8_t mode) ...@@ -58,12 +58,12 @@ void setDataMode(uint8_t mode)
} }
} }
void setClockDivider(uint8_t div) void SPIClass::setClockDivider(uint8_t div)
{ {
sercom->setBaudrateSPI(div); sercom->setBaudrateSPI(div);
} }
byte SPIClass::transfer(uint8_t _data) byte SPIClass::transfer(uint8_t data)
{ {
//Can writing new data? //Can writing new data?
while(!sercom->isDataRegisterEmptySPI()); while(!sercom->isDataRegisterEmptySPI());
...@@ -87,23 +87,5 @@ void SPIClass::detachInterrupt() { ...@@ -87,23 +87,5 @@ void SPIClass::detachInterrupt() {
} }
#if SPI_INTERFACES_COUNT > 0 #if SPI_INTERFACES_COUNT > 0
static void SPI_0_Init(void) { SPIClass SPI(SERCOM::sercom4);
PIO_Configure(
g_APinDescription[PIN_SPI_MOSI].pPort,
g_APinDescription[PIN_SPI_MOSI].ulPinType,
g_APinDescription[PIN_SPI_MOSI].ulPin,
g_APinDescription[PIN_SPI_MOSI].ulPinConfiguration);
PIO_Configure(
g_APinDescription[PIN_SPI_MISO].pPort,
g_APinDescription[PIN_SPI_MISO].ulPinType,
g_APinDescription[PIN_SPI_MISO].ulPin,
g_APinDescription[PIN_SPI_MISO].ulPinConfiguration);
PIO_Configure(
g_APinDescription[PIN_SPI_SCK].pPort,
g_APinDescription[PIN_SPI_SCK].ulPinType,
g_APinDescription[PIN_SPI_SCK].ulPin,
g_APinDescription[PIN_SPI_SCK].ulPinConfiguration);
}
SPIClass SPI(SPI_INTERFACE, SPI_INTERFACE_ID, SPI_0_Init);
#endif #endif
...@@ -13,14 +13,20 @@ ...@@ -13,14 +13,20 @@
#include "variant.h" #include "variant.h"
#include "SERCOM.h" #include "SERCOM.h"
#include "wiring_constants.h"
#include <stdio.h> #include <stdio.h>
#define SPI_MODE0 0x02
#define SPI_MODE1 0x00
#define SPI_MODE2 0x03
#define SPI_MODE3 0x01
class SPIClass { class SPIClass {
public: public:
SPIClass(SERCOM *sercom); SPIClass(SERCOM *s);
byte transfer(uint8_t _data); byte transfer(uint8_t data);
// SPI Configuration methods // SPI Configuration methods
void attachInterrupt(); void attachInterrupt();
......
...@@ -24,9 +24,9 @@ extern "C" { ...@@ -24,9 +24,9 @@ extern "C" {
#include "Wire.h" #include "Wire.h"
TwoWire::TwoWire(SERCOM * sercom) TwoWire::TwoWire(SERCOM * s)
{ {
this->sercom = sercom; this->sercom = s;
transmissionBegun = false; transmissionBegun = false;
} }
...@@ -42,16 +42,16 @@ void TwoWire::begin(uint8_t address) { ...@@ -42,16 +42,16 @@ void TwoWire::begin(uint8_t address) {
sercom->enableWIRE(); sercom->enableWIRE();
} }
size_t SERCOM::resquestFrom(uint8_t address, size_t quantity, bool stopBit) uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit)
{ {
//Quantity > 0 AND startTransmission worked ? //Quantity > 0 AND startTransmission worked ?
if(quantity == 0 || !sercom->startTransmissionWIRE(address, READ_FLAG)) if(quantity == 0 || !sercom->startTransmissionWIRE(address, WIRE_READ_FLAG))
return 0; return 0;
for(size_t readed = 0; read < quantity; ++readed) for(size_t readed = 0; readed < quantity; ++readed)
{ {
//Prepare stop bit ? user want stop bit ? //Prepare stop bit ? user want stop bit ?
if(quantity - read == 1 && stopBit) if(quantity - readed == 1 && stopBit)
sercom->prepareStopBitWIRE(); sercom->prepareStopBitWIRE();
else else
sercom->prepareAckBitWIRE(); sercom->prepareAckBitWIRE();
...@@ -62,7 +62,7 @@ size_t SERCOM::resquestFrom(uint8_t address, size_t quantity, bool stopBit) ...@@ -62,7 +62,7 @@ size_t SERCOM::resquestFrom(uint8_t address, size_t quantity, bool stopBit)
return quantity; return quantity;
} }
size_t SERCOM::resquestFrom(uint8_t address, size_t quantity) uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity)
{ {
return requestFrom(address, quantity, true); return requestFrom(address, quantity, true);
} }
...@@ -129,7 +129,7 @@ uint8_t TwoWire::endTransmission(bool stopBit) ...@@ -129,7 +129,7 @@ uint8_t TwoWire::endTransmission(bool stopBit)
return 4; return 4;
//Start I2C transmission //Start I2C transmission
if(!sercom->startTransmissionWIRE(txAddress, WRITE_FLAG)) if(!sercom->startTransmissionWIRE(txAddress, WIRE_WRITE_FLAG))
return 2; //Address error return 2; //Address error
//Send all buffer //Send all buffer
...@@ -165,8 +165,11 @@ size_t TwoWire::write(uint8_t data) ...@@ -165,8 +165,11 @@ size_t TwoWire::write(uint8_t data)
} }
else else
{ {
sercom->sendDataSlaveWIRE(data); if(sercom->sendDataSlaveWIRE(data))
return 1;
} }
return 0;
} }
size_t TwoWire::write(const uint8_t *data, size_t quantity) size_t TwoWire::write(const uint8_t *data, size_t quantity)
...@@ -175,7 +178,7 @@ size_t TwoWire::write(const uint8_t *data, size_t quantity) ...@@ -175,7 +178,7 @@ size_t TwoWire::write(const uint8_t *data, size_t quantity)
for(size_t i = 0; i < quantity; ++i) for(size_t i = 0; i < quantity; ++i)
{ {
//Return the number of data stored, when the buffer is full (if write return 0) //Return the number of data stored, when the buffer is full (if write return 0)
if(!write(data[i]) if(!write(data[i]))
return i; return i;
} }
...@@ -324,7 +327,7 @@ void TwoWire::onService(void) ...@@ -324,7 +327,7 @@ void TwoWire::onService(void)
*/ */
#if WIRE_INTERFACES_COUNT > 0 #if WIRE_INTERFACES_COUNT > 0
static void Wire_Init(void) { /*static void Wire_Init(void) {
pmc_enable_periph_clk(WIRE_INTERFACE_ID); pmc_enable_periph_clk(WIRE_INTERFACE_ID);
PIO_Configure( PIO_Configure(
g_APinDescription[PIN_WIRE_SDA].pPort, g_APinDescription[PIN_WIRE_SDA].pPort,
...@@ -341,38 +344,13 @@ static void Wire_Init(void) { ...@@ -341,38 +344,13 @@ static void Wire_Init(void) {
NVIC_ClearPendingIRQ(WIRE_ISR_ID); NVIC_ClearPendingIRQ(WIRE_ISR_ID);
NVIC_SetPriority(WIRE_ISR_ID, 0); NVIC_SetPriority(WIRE_ISR_ID, 0);
NVIC_EnableIRQ(WIRE_ISR_ID); NVIC_EnableIRQ(WIRE_ISR_ID);
} }*/
TwoWire Wire = TwoWire(WIRE_INTERFACE, Wire_Init);
void WIRE_ISR_HANDLER(void) { TwoWire Wire(SERCOM::sercom3);
Wire.onService();
}
#endif
#if WIRE_INTERFACES_COUNT > 1 void SERCOM3_Handler(void) {
static void Wire1_Init(void) { Wire.onService();
pmc_enable_periph_clk(WIRE1_INTERFACE_ID);
PIO_Configure(
g_APinDescription[PIN_WIRE1_SDA].pPort,
g_APinDescription[PIN_WIRE1_SDA].ulPinType,
g_APinDescription[PIN_WIRE1_SDA].ulPin,
g_APinDescription[PIN_WIRE1_SDA].ulPinConfiguration);
PIO_Configure(
g_APinDescription[PIN_WIRE1_SCL].pPort,
g_APinDescription[PIN_WIRE1_SCL].ulPinType,
g_APinDescription[PIN_WIRE1_SCL].ulPin,
g_APinDescription[PIN_WIRE1_SCL].ulPinConfiguration);
NVIC_DisableIRQ(WIRE1_ISR_ID);
NVIC_ClearPendingIRQ(WIRE1_ISR_ID);
NVIC_SetPriority(WIRE1_ISR_ID, 0);
NVIC_EnableIRQ(WIRE1_ISR_ID);
} }
TwoWire Wire1 = TwoWire(WIRE1_INTERFACE, Wire1_Init);
void WIRE1_ISR_HANDLER(void) {
Wire1.onService();
}
#endif #endif
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
#ifndef TwoWire_h #ifndef TwoWire_h
#define TwoWire_h #define TwoWire_h
#include <include/twi.h> //#include <include/twi.h>
#include "Stream.h" #include "Stream.h"
#include "variant.h" #include "variant.h"
...@@ -32,77 +32,73 @@ ...@@ -32,77 +32,73 @@
#define BUFFER_LENGTH 32 #define BUFFER_LENGTH 32
class TwoWire : public Stream { class TwoWire : public Stream {
public: public:
TwoWire(SERCOM *sercom); TwoWire(SERCOM *s);
void begin(); void begin();
void begin(uint8_t); void begin(uint8_t);
uint8_t beginTransmission(uint8_t); void beginTransmission(uint8_t);
uint8_t endTransmission(void); uint8_t endTransmission(bool stopBit);
uint8_t endTransmission(void);
uint8_t requestFrom(uint8_t address, size_t quantity, bool stopBit); uint8_t requestFrom(uint8_t address, size_t quantity, bool stopBit);
uint8_t requestFrom(uint8_t address, size_t quantity); uint8_t requestFrom(uint8_t address, size_t quantity);
size_t write(uint8_t data); size_t write(uint8_t data);
size_t write(const uint8_t * data, size_t quantity); size_t write(const uint8_t * data, size_t quantity);
virtual int available(void); virtual int available(void);
virtual int read(void); virtual int read(void);
virtual int peek(void); virtual int peek(void);
virtual void flush(void); virtual void flush(void);
void onReceive(void(*)(int)); void onReceive(void(*)(int));
void onRequest(void(*)(void)); void onRequest(void(*)(void));
using Print::write; using Print::write;
//void onService(void); void onService(void);
private: private:
SERCOM * sercom; SERCOM * sercom;
bool transmissionBegun; bool transmissionBegun;
// RX Buffer // RX Buffer
RingBuffer rxBuffer; RingBuffer rxBuffer;
//TX buffer //TX buffer
RingBuffer txBuffer; RingBuffer txBuffer;
uint8_t txAddress; uint8_t txAddress;
// Service buffer // Service buffer
//uint8_t srvBuffer[BUFFER_LENGTH]; //uint8_t srvBuffer[BUFFER_LENGTH];
//uint8_t srvBufferIndex; //uint8_t srvBufferIndex;
//uint8_t srvBufferLength; //uint8_t srvBufferLength;
// Callback user functions // Callback user functions
void (*onRequestCallback)(void); void (*onRequestCallback)(void);
void (*onReceiveCallback)(int); void (*onReceiveCallback)(int);
// TWI state // TWI state
//enum TwoWireStatus { //enum TwoWireStatus {
// UNINITIALIZED, // UNINITIALIZED,
// MASTER_IDLE, // MASTER_IDLE,
// MASTER_SEND, // MASTER_SEND,
// MASTER_RECV, // MASTER_RECV,
// SLAVE_IDLE, // SLAVE_IDLE,
// SLAVE_RECV, // SLAVE_RECV,
// SLAVE_SEND // SLAVE_SEND
//}; //};
//TwoWireStatus status; //TwoWireStatus status;
// TWI clock frequency // TWI clock frequency
static const uint32_t TWI_CLOCK = 100000; static const uint32_t TWI_CLOCK = 100000;
// Timeouts // Timeouts
//static const uint32_t RECV_TIMEOUT = 100000; //static const uint32_t RECV_TIMEOUT = 100000;
//static const uint32_t XMIT_TIMEOUT = 100000; //static const uint32_t XMIT_TIMEOUT = 100000;
}; };
#if WIRE_INTERFACES_COUNT > 0
extern TwoWire Wire; extern TwoWire Wire;
#endif
#if WIRE_INTERFACES_COUNT > 1
extern TwoWire Wire1;
#endif
#endif #endif
...@@ -73,8 +73,23 @@ ...@@ -73,8 +73,23 @@
* | 33 | | PA24 | USB_NEGATIVE | USB/DM * | 33 | | PA24 | USB_NEGATIVE | USB/DM
* | 34 | | PA25 | USB_POSITIVE | USB/DP * | 34 | | PA25 | USB_POSITIVE | USB/DP
* +------------+------------------+--------+-----------------+------------------------------ * +------------+------------------+--------+-----------------+------------------------------
* | 35 | CDC_UART TX | PB22 | | *SERCOM5/PAD[2] * | | EDBG | | |
* | 36 | CDC_UART RX | PB23 | | *SERCOM5/PAD[3] * +------------+------------------+--------+-----------------+------------------------------
* | 35 | | PB22 | EDBG_UART TX | SERCOM5/PAD[2]
* | 36 | | PB23 | EDBG_UART RX | SERCOM5/PAD[3]
* +------------+------------------+--------+-----------------+------------------------------
* | 37 | | PA22 | EDBG_SDA | SERCOM3/PAD[0]
* | 38 | | PA23 | EDBG_SCL | SERCOM3/PAD[1]
* +------------+------------------+--------+-----------------+------------------------------
* | 39 | | PA19 | EDBG_MISO | SERCOM1/PAD[3]
* | 40 | | PA16 | EDBG_MOSI | SERCOM1/PAD[0]
* | 41 | | PA18 | EDBG_SS | SERCOM1/PAD[2]
* | 42 | | PA17 | EDBG_SCK | SERCOM1/PAD[1]
* +------------+------------------+--------+-----------------+------------------------------
* | 43 | | PA13 | EDBG_GPIO0 | EIC/EXTINT[13] *TCC2/WO[1] TCC0/WO[7]
* | 44 | | PA21 | EDBG_GPIO1 | Pin 7
* | 45 | | PA06 | EDBG_GPIO2 | Pin 8
* | 46 | | PA07 | EDBG_GPIO3 | Pin 9
* +------------+------------------+--------+-----------------+------------------------------ * +------------+------------------+--------+-----------------+------------------------------
* | |32.768KHz Crystal | | | * | |32.768KHz Crystal | | |
* +------------+------------------+--------+-----------------+------------------------------ * +------------+------------------+--------+-----------------+------------------------------
...@@ -82,8 +97,6 @@ ...@@ -82,8 +97,6 @@
* | | | PA01 | XOUT32 | EXTINT[1] SERCOM1/PAD[1] TCC2/WO[1] * | | | PA01 | XOUT32 | EXTINT[1] SERCOM1/PAD[1] TCC2/WO[1]
* +------------+------------------+--------+-----------------+------------------------------ * +------------+------------------+--------+-----------------+------------------------------
*/ */
PB22_S5_CDC_TX
PB23_S5_CDC_RX
#include "variant.h" #include "variant.h"
...@@ -120,7 +133,7 @@ const PinDescription g_APinDescription[]= ...@@ -120,7 +133,7 @@ const PinDescription g_APinDescription[]=
// 15 (AREF) // 15 (AREF)
{ PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // DAC/VREFP { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // DAC/VREFP
// 16..17 I2C (SDA/SCL) // 16..17 I2C (SDA/SCL and also EDBG:SDA/SCL)
{ PORTA, 22, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SDA: SERCOM3/PAD[0] { PORTA, 22, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SDA: SERCOM3/PAD[0]
{ PORTA, 23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SCL: SERCOM3/PAD[1] { PORTA, 23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SCL: SERCOM3/PAD[1]
...@@ -153,9 +166,25 @@ const PinDescription g_APinDescription[]= ...@@ -153,9 +166,25 @@ const PinDescription g_APinDescription[]=
{ PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // USB/DM { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // USB/DM
{ PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // USB/DP { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // USB/DP
// 35 .. 36 - EDBG // 35 .. 46 - EDBG
// ---------------------- // ----------------------
// 35/36 - SERCOM/UART (Serial) // 35/36 - EDBG/UART
{ PORTB, 22, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // TX: SERCOM5/PAD[2] { PORTB, 22, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // TX: SERCOM5/PAD[2]
{ PORTB, 23, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // RX: SERCOM5/PAD[3] { PORTB, 23, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // RX: SERCOM5/PAD[3]
// 37/38 I2C (SDA/SCL and also EDBG:SDA/SCL)
{ PORTA, 22, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SDA: SERCOM3/PAD[0]
{ PORTA, 23, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SCL: SERCOM3/PAD[1]
// 39 .. 42 - EDBG/SPI
{ PORTA, 19, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // MISO: SERCOM1/PAD[3]
{ PORTA, 16, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // MOSI: SERCOM1/PAD[0]
{ PORTA, 18, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SS: SERCOM1/PAD[2]
{ PORTA, 17, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER }, // SCK: SERCOM1/PAD[1]
// 43 .. 46 - EDBG/Digital
{ PORTA, 13, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM0_CH5, NOT_ON_TIMER }, // EIC/EXTINT[13] *TCC2/WO[1] TCC0/WO[7]
{ PORTA, 21, PIO_PWM_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM0_CH7, NOT_ON_TIMER }, // Pin 7
{ PORTA, 6, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM1_CH0, NOT_ON_TIMER }, // Pin 8
{ PORTA, 7, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM1_CH1, NOT_ON_TIMER }, // Pin 9
} ; } ;
...@@ -93,9 +93,11 @@ extern "C"{ ...@@ -93,9 +93,11 @@ extern "C"{
#define PIN_SPI_SS1 (87u) #define PIN_SPI_SS1 (87u)
#define PIN_SPI_SS2 (86u) #define PIN_SPI_SS2 (86u)
#define PIN_SPI_SS3 (78u) #define PIN_SPI_SS3 (78u)
#define PIN_SPI_MOSI (75u) */
#define PIN_SPI_MISO (74u) #define PIN_SPI_MOSI (21u)
#define PIN_SPI_SCK (76u) #define PIN_SPI_MISO (18u)
#define PIN_SPI_SCK (20u)
/*
#define BOARD_SPI_SS0 (10u) #define BOARD_SPI_SS0 (10u)
#define BOARD_SPI_SS1 (4u) #define BOARD_SPI_SS1 (4u)
#define BOARD_SPI_SS2 (52u) #define BOARD_SPI_SS2 (52u)
......
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