From 9faaf8e6f8c395c2ef19cc7195652914f41bd053 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=B8rch?= Date: Tue, 4 Aug 2015 22:33:06 +0200 Subject: [PATCH] Initial support for SAMD device in development branch --- hardware/MySensors/samd/boards.txt | 42 +++ .../CorrectADCResponse/CorrectADCResponse.ino | 210 +++++++++++ .../SAMD_AnalogCorrection/library.properties | 8 + .../src/SAMD_AnalogCorrection.cpp | 31 ++ .../src/SAMD_AnalogCorrection.h | 24 ++ hardware/MySensors/samd/libraries/SPI/SPI.cpp | 200 ++++++++++ hardware/MySensors/samd/libraries/SPI/SPI.h | 153 ++++++++ .../BarometricPressureSensor.ino | 143 +++++++ .../DigitalPotControl/DigitalPotControl.ino | 71 ++++ .../MySensors/samd/libraries/SPI/keywords.txt | 31 ++ .../MySensors/samd/libraries/Wire/Wire.cpp | 355 ++++++++++++++++++ hardware/MySensors/samd/libraries/Wire/Wire.h | 104 +++++ .../SFRRanger_reader/SFRRanger_reader.pde | 87 +++++ .../digital_potentiometer.pde | 39 ++ .../examples/master_reader/master_reader.pde | 32 ++ .../examples/master_writer/master_writer.pde | 31 ++ .../slave_receiver/slave_receiver.pde | 38 ++ .../examples/slave_sender/slave_sender.pde | 32 ++ .../samd/libraries/Wire/keywords.txt | 32 ++ hardware/MySensors/samd/platform.txt | 143 +++++++ .../mysensors_gw/debug_scripts/variant.gdb | 31 ++ .../gcc/flash_with_bootloader.ld | 211 +++++++++++ .../gcc/flash_without_bootloader.ld | 212 +++++++++++ .../openocd_scripts/mysensors_gw.cfg | 30 ++ .../samd/variants/mysensors_gw/pins_arduino.h | 21 ++ .../samd/variants/mysensors_gw/variant.cpp | 221 +++++++++++ .../samd/variants/mysensors_gw/variant.h | 201 ++++++++++ 27 files changed, 2733 insertions(+) create mode 100644 hardware/MySensors/samd/boards.txt create mode 100644 hardware/MySensors/samd/libraries/SAMD_AnalogCorrection/examples/CorrectADCResponse/CorrectADCResponse.ino create mode 100644 hardware/MySensors/samd/libraries/SAMD_AnalogCorrection/library.properties create mode 100644 hardware/MySensors/samd/libraries/SAMD_AnalogCorrection/src/SAMD_AnalogCorrection.cpp create mode 100644 hardware/MySensors/samd/libraries/SAMD_AnalogCorrection/src/SAMD_AnalogCorrection.h create mode 100644 hardware/MySensors/samd/libraries/SPI/SPI.cpp create mode 100644 hardware/MySensors/samd/libraries/SPI/SPI.h create mode 100644 hardware/MySensors/samd/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino create mode 100644 hardware/MySensors/samd/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino create mode 100644 hardware/MySensors/samd/libraries/SPI/keywords.txt create mode 100644 hardware/MySensors/samd/libraries/Wire/Wire.cpp create mode 100644 hardware/MySensors/samd/libraries/Wire/Wire.h create mode 100644 hardware/MySensors/samd/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.pde create mode 100644 hardware/MySensors/samd/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.pde create mode 100644 hardware/MySensors/samd/libraries/Wire/examples/master_reader/master_reader.pde create mode 100644 hardware/MySensors/samd/libraries/Wire/examples/master_writer/master_writer.pde create mode 100644 hardware/MySensors/samd/libraries/Wire/examples/slave_receiver/slave_receiver.pde create mode 100644 hardware/MySensors/samd/libraries/Wire/examples/slave_sender/slave_sender.pde create mode 100644 hardware/MySensors/samd/libraries/Wire/keywords.txt create mode 100644 hardware/MySensors/samd/platform.txt create mode 100644 hardware/MySensors/samd/variants/mysensors_gw/debug_scripts/variant.gdb create mode 100644 hardware/MySensors/samd/variants/mysensors_gw/linker_scripts/gcc/flash_with_bootloader.ld create mode 100644 hardware/MySensors/samd/variants/mysensors_gw/linker_scripts/gcc/flash_without_bootloader.ld create mode 100644 hardware/MySensors/samd/variants/mysensors_gw/openocd_scripts/mysensors_gw.cfg create mode 100644 hardware/MySensors/samd/variants/mysensors_gw/pins_arduino.h create mode 100644 hardware/MySensors/samd/variants/mysensors_gw/variant.cpp create mode 100644 hardware/MySensors/samd/variants/mysensors_gw/variant.h diff --git a/hardware/MySensors/samd/boards.txt b/hardware/MySensors/samd/boards.txt new file mode 100644 index 0000000..1728623 --- /dev/null +++ b/hardware/MySensors/samd/boards.txt @@ -0,0 +1,42 @@ +# Copyright (c) 2014-2015 Arduino LLC. All right reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +mysensors_gw_native.name=Sensebender GW (Native USB Port) +mysensors_gw_native.vid.0=0x2341 +mysensors_gw_native.pid.0=0x804d +mysensors_gw_native.vid.1=0x2341 +mysensors_gw_native.pid.1=0x004d +mysensors_gw_native.upload.tool=bossac +mysensors_gw_native.upload.protocol=sam-ba +mysensors_gw_native.upload.maximum_size=262144 +mysensors_gw_native.upload.use_1200bps_touch=true +mysensors_gw_native.upload.wait_for_upload_port=true +mysensors_gw_native.upload.native_usb=true +mysensors_gw_native.build.mcu=cortex-m0plus +mysensors_gw_native.build.f_cpu=48000000L +mysensors_gw_native.build.usb_product="Arduino Zero" +mysensors_gw_native.build.usb_manufacturer="Arduino LLC" +mysensors_gw_native.build.board=SAMD_ZERO +mysensors_gw_native.build.core=arduino:arduino +mysensors_gw_native.build.extra_flags=-D__SAMD21G18A__ {build.usb_flags} +mysensors_gw_native.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld +mysensors_gw_native.build.openocdscript=openocd_scripts/mysensors_gw.cfg +mysensors_gw_native.build.variant=mysensors_gw +mysensors_gw_native.build.variant_system_lib= +mysensors_gw_native.build.vid=0x2341 +mysensors_gw_native.build.pid=0x804d +mysensors_gw_native.bootloader.tool=openocd +mysensors_gw_native.bootloader.file=zero/samd21_sam_ba.bin diff --git a/hardware/MySensors/samd/libraries/SAMD_AnalogCorrection/examples/CorrectADCResponse/CorrectADCResponse.ino b/hardware/MySensors/samd/libraries/SAMD_AnalogCorrection/examples/CorrectADCResponse/CorrectADCResponse.ino new file mode 100644 index 0000000..2b74538 --- /dev/null +++ b/hardware/MySensors/samd/libraries/SAMD_AnalogCorrection/examples/CorrectADCResponse/CorrectADCResponse.ino @@ -0,0 +1,210 @@ +/* + This sketch easily and quickly finds the right ADC correction values for a particular Arduino ZERO board. + The correction values that are found are only valid for the board where the sketch is executed. + + This example code is in the public domain. + + Written 6 May 2015 by Claudio Indellicati +*/ + +/* + How to use this sketch + + 1) Remove any connection cable, shield or jumper from your Arduino ZERO + 2) Connect pin A1 to the nearest GND pin using the shortest jumper possible + 3) Connect pin A2 to the 3.3V pin using the shortest jumper possible + 4) Connect the Arduino ZERO to your PC using a USB cable plugged in the USB programming port of the board + 5) Upload this sketch and leave the board powered on for at least one minute + 6) Open the Serial Monitor and press the reset button on the Arduino ZERO + 7) At the and of the procedure you can find logged + - the offset and gain values for the board where the sketch has been just executed + - the instruction line to copy/paste in the final sketch +*/ + +#include "SAMD_AnalogCorrection.h" + +#define ADC_GND_PIN A1 +#define ADC_3V3_PIN A2 + +#define ADC_READS_SHIFT 8 +#define ADC_READS_COUNT (1 << ADC_READS_SHIFT) + +#define ADC_MIN_GAIN 0x0400 +#define ADC_UNITY_GAIN 0x0800 +#define ADC_MAX_GAIN (0x1000 - 1) +#define ADC_RESOLUTION_BITS 12 +#define ADC_RANGE (1 << ADC_RESOLUTION_BITS) +#define ADC_TOP_VALUE (ADC_RANGE - 1) + +#define MAX_TOP_VALUE_READS 10 + +void setup() +{ + Serial.begin(9600); + + Serial.println("\r\nCalibrating ADC with factory values"); + + analogReadResolution(ADC_RESOLUTION_BITS); + + Serial.println("\r\nReading GND and 3.3V ADC levels"); + Serial.print(" "); + readGndLevel(); + Serial.print(" "); + read3V3Level(); + + int offsetCorrectionValue = 0; + uint16_t gainCorrectionValue = ADC_UNITY_GAIN; + + Serial.print("\r\nOffset correction (@gain = "); + Serial.print(gainCorrectionValue); + Serial.println(" (unity gain))"); + + // Set default correction values and enable correction + analogReadCorrection(offsetCorrectionValue, gainCorrectionValue); + + for (int offset = 0; offset < (int)(ADC_OFFSETCORR_MASK >> 1); ++offset) + { + analogReadCorrection(offset, gainCorrectionValue); + + Serial.print(" Offset = "); + Serial.print(offset); + Serial.print(", "); + + if (readGndLevel() == 0) + { + offsetCorrectionValue = offset; + break; + } + } + + Serial.println("\r\nGain correction"); + + uint8_t topValueReadsCount = 0U; + + uint16_t minGain = 0U, + maxGain = 0U; + + analogReadCorrection(offsetCorrectionValue, gainCorrectionValue); + Serial.print(" Gain = "); + Serial.print(gainCorrectionValue); + Serial.print(", "); + uint16_t highLevelRead = read3V3Level(); + + if (highLevelRead < ADC_TOP_VALUE) + { + for (uint16_t gain = ADC_UNITY_GAIN + 1; gain <= ADC_MAX_GAIN; ++gain) + { + analogReadCorrection(offsetCorrectionValue, gain); + + Serial.print(" Gain = "); + Serial.print(gain); + Serial.print(", "); + highLevelRead = read3V3Level(); + + if (highLevelRead == ADC_TOP_VALUE) + { + if (minGain == 0U) + minGain = gain; + + if (++topValueReadsCount >= MAX_TOP_VALUE_READS) + { + maxGain = minGain; + break; + } + + maxGain = gain; + } + + if (highLevelRead > ADC_TOP_VALUE) + break; + } + } + else if (highLevelRead >= ADC_TOP_VALUE) + { + if (highLevelRead == ADC_TOP_VALUE) + maxGain = ADC_UNITY_GAIN; + + for (uint16_t gain = ADC_UNITY_GAIN - 1; gain >= ADC_MIN_GAIN; --gain) + { + analogReadCorrection(offsetCorrectionValue, gain); + + Serial.print(" Gain = "); + Serial.print(gain); + Serial.print(", "); + highLevelRead = read3V3Level(); + + if (highLevelRead == ADC_TOP_VALUE) + { + if (maxGain == 0U) + maxGain = gain; + + minGain = gain; + } + + if (highLevelRead < ADC_TOP_VALUE) + break; + } + } + + gainCorrectionValue = (minGain + maxGain) >> 1; + + analogReadCorrection(offsetCorrectionValue, gainCorrectionValue); + + Serial.println("\r\nReadings after corrections"); + Serial.print(" "); + readGndLevel(); + Serial.print(" "); + read3V3Level(); + + Serial.println("\r\n=================="); + Serial.println("\r\nCorrection values:"); + Serial.print(" Offset = "); + Serial.println(offsetCorrectionValue); + Serial.print(" Gain = "); + Serial.println(gainCorrectionValue); + Serial.println("\r\nAdd the next line to your sketch:"); + Serial.print(" analogReadCorrection("); + Serial.print(offsetCorrectionValue); + Serial.print(", "); + Serial.print(gainCorrectionValue); + Serial.println(");"); + Serial.println("\r\n=================="); +} + +void loop() +{ +} + +uint16_t readGndLevel() +{ + uint32_t readAccumulator = 0; + + for (int i = 0; i < ADC_READS_COUNT; ++i) + readAccumulator += analogRead(ADC_GND_PIN); + + uint16_t readValue = readAccumulator >> ADC_READS_SHIFT; + + Serial.print("ADC(GND) = "); + Serial.println(readValue); + + return readValue; +} + +uint16_t read3V3Level() +{ + uint32_t readAccumulator = 0; + + for (int i = 0; i < ADC_READS_COUNT; ++i) + readAccumulator += analogRead(ADC_3V3_PIN); + + uint16_t readValue = readAccumulator >> ADC_READS_SHIFT; + + if (readValue < (ADC_RANGE >> 1)) + readValue += ADC_RANGE; + + Serial.print("ADC(3.3V) = "); + Serial.println(readValue); + + return readValue; +} + diff --git a/hardware/MySensors/samd/libraries/SAMD_AnalogCorrection/library.properties b/hardware/MySensors/samd/libraries/SAMD_AnalogCorrection/library.properties new file mode 100644 index 0000000..e12ada2 --- /dev/null +++ b/hardware/MySensors/samd/libraries/SAMD_AnalogCorrection/library.properties @@ -0,0 +1,8 @@ +name=SAMD_AnalogCorrection +version=1.0 +author=Arduino +maintainer=Arduino +sentence=Sets and enables the digital correction logic of the SAMD ADC. +paragraph=Useful to correct the values returned by the ADC. +url= +architectures=samd diff --git a/hardware/MySensors/samd/libraries/SAMD_AnalogCorrection/src/SAMD_AnalogCorrection.cpp b/hardware/MySensors/samd/libraries/SAMD_AnalogCorrection/src/SAMD_AnalogCorrection.cpp new file mode 100644 index 0000000..1681b0a --- /dev/null +++ b/hardware/MySensors/samd/libraries/SAMD_AnalogCorrection/src/SAMD_AnalogCorrection.cpp @@ -0,0 +1,31 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include "SAMD_AnalogCorrection.h" + +void analogReadCorrection (int offset, uint16_t gain) +{ + // Set correction values + ADC->OFFSETCORR.reg = ADC_OFFSETCORR_OFFSETCORR(offset); + ADC->GAINCORR.reg = ADC_GAINCORR_GAINCORR(gain); + + // Enable digital correction logic + ADC->CTRLB.bit.CORREN = 1; + while(ADC->STATUS.bit.SYNCBUSY); +} + diff --git a/hardware/MySensors/samd/libraries/SAMD_AnalogCorrection/src/SAMD_AnalogCorrection.h b/hardware/MySensors/samd/libraries/SAMD_AnalogCorrection/src/SAMD_AnalogCorrection.h new file mode 100644 index 0000000..5edb91e --- /dev/null +++ b/hardware/MySensors/samd/libraries/SAMD_AnalogCorrection/src/SAMD_AnalogCorrection.h @@ -0,0 +1,24 @@ +/* + Copyright (c) 2015 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#pragma once + +#include + +void analogReadCorrection (int offset, uint16_t gain); + diff --git a/hardware/MySensors/samd/libraries/SPI/SPI.cpp b/hardware/MySensors/samd/libraries/SPI/SPI.cpp new file mode 100644 index 0000000..e4af046 --- /dev/null +++ b/hardware/MySensors/samd/libraries/SPI/SPI.cpp @@ -0,0 +1,200 @@ +/* + * SPI Master library for Arduino Zero. + * Copyright (c) 2015 Arduino LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "SPI.h" +#include +#include +#include + +#define SPI_IMODE_NONE 0 +#define SPI_IMODE_EXTINT 1 +#define SPI_IMODE_GLOBAL 2 + +const SPISettings DEFAULT_SPI_SETTINGS = SPISettings(); + +SPIClass::SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI) +{ + initialized = false; + assert(p_sercom != NULL); + _p_sercom = p_sercom; + + _uc_pinMiso = uc_pinMISO; + _uc_pinSCK = uc_pinSCK; + _uc_pinMosi = uc_pinMOSI; +} + +void SPIClass::begin() +{ + init(); + + // PIO init + pinPeripheral(_uc_pinMiso, g_APinDescription[_uc_pinMiso].ulPinType); + pinPeripheral(_uc_pinSCK, g_APinDescription[_uc_pinSCK].ulPinType); + pinPeripheral(_uc_pinMosi, g_APinDescription[_uc_pinMosi].ulPinType); + + config(DEFAULT_SPI_SETTINGS); +} + +void SPIClass::init() +{ + if (initialized) + return; + interruptMode = SPI_IMODE_NONE; + interruptSave = 0; + interruptMask = 0; + initialized = true; +} + +void SPIClass::config(SPISettings settings) +{ + _p_sercom->disableSPI(); + + _p_sercom->initSPI(SPI_PAD_2_SCK_3, SERCOM_RX_PAD_0, SPI_CHAR_SIZE_8_BITS, settings.bitOrder); + _p_sercom->initSPIClock(settings.dataMode, settings.clockFreq); + + _p_sercom->enableSPI(); +} + +void SPIClass::end() +{ + _p_sercom->resetSPI(); + initialized = false; +} + +#ifndef interruptsStatus +#define interruptsStatus() __interruptsStatus() +static inline unsigned char __interruptsStatus(void) __attribute__((always_inline, unused)); +static inline unsigned char __interruptsStatus(void) +{ + // See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0497a/CHDBIBGJ.html + return (__get_PRIMASK() ? 0 : 1); +} +#endif + +void SPIClass::usingInterrupt(int interruptNumber) +{ + if ((interruptNumber == NOT_AN_INTERRUPT) || (interruptNumber == EXTERNAL_INT_NMI)) + return; + + uint8_t irestore = interruptsStatus(); + noInterrupts(); + + if (interruptNumber >= EXTERNAL_NUM_INTERRUPTS) + interruptMode = SPI_IMODE_GLOBAL; + else + { + interruptMode |= SPI_IMODE_EXTINT; + interruptMask |= (1 << interruptNumber); + } + + if (irestore) + interrupts(); +} + +void SPIClass::beginTransaction(SPISettings settings) +{ + if (interruptMode != SPI_IMODE_NONE) + { + if (interruptMode & SPI_IMODE_GLOBAL) + { + interruptSave = interruptsStatus(); + noInterrupts(); + } + else if (interruptMode & SPI_IMODE_EXTINT) + EIC->INTENCLR.reg = EIC_INTENCLR_EXTINT(interruptMask); + } + + config(settings); +} + +void SPIClass::endTransaction(void) +{ + if (interruptMode != SPI_IMODE_NONE) + { + if (interruptMode & SPI_IMODE_GLOBAL) + { + if (interruptSave) + interrupts(); + } + else if (interruptMode & SPI_IMODE_EXTINT) + EIC->INTENSET.reg = EIC_INTENSET_EXTINT(interruptMask); + } +} + +void SPIClass::setBitOrder(BitOrder order) +{ + if (order == LSBFIRST) { + _p_sercom->setDataOrderSPI(LSB_FIRST); + } else { + _p_sercom->setDataOrderSPI(MSB_FIRST); + } +} + +void SPIClass::setDataMode(uint8_t mode) +{ + switch (mode) + { + case SPI_MODE0: + _p_sercom->setClockModeSPI(SERCOM_SPI_MODE_0); + break; + + case SPI_MODE1: + _p_sercom->setClockModeSPI(SERCOM_SPI_MODE_1); + break; + + case SPI_MODE2: + _p_sercom->setClockModeSPI(SERCOM_SPI_MODE_2); + break; + + case SPI_MODE3: + _p_sercom->setClockModeSPI(SERCOM_SPI_MODE_3); + break; + + default: + break; + } +} + +void SPIClass::setClockDivider(uint8_t div) +{ + if (div < SPI_MIN_CLOCK_DIVIDER) { + _p_sercom->setBaudrateSPI(SPI_MIN_CLOCK_DIVIDER); + } else { + _p_sercom->setBaudrateSPI(div); + } +} + +byte SPIClass::transfer(uint8_t data) +{ + // Writing the data + _p_sercom->writeDataSPI(data); + + // Read data + return _p_sercom->readDataSPI() & 0xFF; +} + +void SPIClass::attachInterrupt() { + // Should be enableInterrupt() +} + +void SPIClass::detachInterrupt() { + // Should be disableInterrupt() +} + +SPIClass SPI( &sercom4, PIN_SPI_MISO, PIN_SPI_SCK, PIN_SPI_MOSI ); diff --git a/hardware/MySensors/samd/libraries/SPI/SPI.h b/hardware/MySensors/samd/libraries/SPI/SPI.h new file mode 100644 index 0000000..6259d2d --- /dev/null +++ b/hardware/MySensors/samd/libraries/SPI/SPI.h @@ -0,0 +1,153 @@ +/* + * SPI Master library for Arduino Zero. + * Copyright (c) 2015 Arduino LLC + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _SPI_H_INCLUDED +#define _SPI_H_INCLUDED + +#include + +// SPI_HAS_TRANSACTION means SPI has +// - beginTransaction() +// - endTransaction() +// - usingInterrupt() +// - SPISetting(clock, bitOrder, dataMode) +#define SPI_HAS_TRANSACTION 1 + +#define SPI_MODE0 0x02 +#define SPI_MODE1 0x00 +#define SPI_MODE2 0x03 +#define SPI_MODE3 0x01 + +#if defined(__SAMD21G18A__) + // Even if not specified on the datasheet, the SAMD21G18A MCU + // doesn't operate correctly with clock dividers lower than 4. + // This allows a theoretical maximum SPI clock speed of 12Mhz + #define SPI_MIN_CLOCK_DIVIDER 4 + // Other SAMD21xxxxx MCU may be affected as well +#else + #define SPI_MIN_CLOCK_DIVIDER 2 +#endif + +class SPISettings { + public: + SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) { + if (__builtin_constant_p(clock)) { + init_AlwaysInline(clock, bitOrder, dataMode); + } else { + init_MightInline(clock, bitOrder, dataMode); + } + } + + // Default speed set to 4MHz, SPI mode set to MODE 0 and Bit order set to MSB first. + SPISettings() { init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0); } + + private: + void init_MightInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) { + init_AlwaysInline(clock, bitOrder, dataMode); + } + + void init_AlwaysInline(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) __attribute__((__always_inline__)) { + this->clockFreq = (clock >= (F_CPU / SPI_MIN_CLOCK_DIVIDER) ? F_CPU / SPI_MIN_CLOCK_DIVIDER : clock); + + this->bitOrder = (bitOrder == MSBFIRST ? MSB_FIRST : LSB_FIRST); + + switch (dataMode) + { + case SPI_MODE0: + this->dataMode = SERCOM_SPI_MODE_0; break; + case SPI_MODE1: + this->dataMode = SERCOM_SPI_MODE_1; break; + case SPI_MODE2: + this->dataMode = SERCOM_SPI_MODE_2; break; + case SPI_MODE3: + this->dataMode = SERCOM_SPI_MODE_3; break; + default: + this->dataMode = SERCOM_SPI_MODE_0; break; + } + } + + uint32_t clockFreq; + SercomSpiClockMode dataMode; + SercomDataOrder bitOrder; + + friend class SPIClass; +}; + +class SPIClass { + public: + SPIClass(SERCOM *p_sercom, uint8_t uc_pinMISO, uint8_t uc_pinSCK, uint8_t uc_pinMOSI); + + byte transfer(uint8_t data); + inline void transfer(void *buf, size_t count); + + // Transaction Functions + void usingInterrupt(int interruptNumber); + void beginTransaction(SPISettings settings); + void endTransaction(void); + + // SPI Configuration methods + void attachInterrupt(); + void detachInterrupt(); + + void begin(); + void end(); + + void setBitOrder(BitOrder order); + void setDataMode(uint8_t uc_mode); + void setClockDivider(uint8_t uc_div); + + private: + void init(); + void config(SPISettings settings); + + SERCOM *_p_sercom; + uint8_t _uc_pinMiso; + uint8_t _uc_pinMosi; + uint8_t _uc_pinSCK; + bool initialized; + uint8_t interruptMode; + char interruptSave; + uint32_t interruptMask; +}; + +void SPIClass::transfer(void *buf, size_t count) +{ + // TODO: Optimize for faster block-transfer + uint8_t *buffer = reinterpret_cast(buf); + for (size_t i=0; i 0 + extern SPIClass SPI; +#endif + +// For compatibility with sketches designed for AVR @ 16 MHz +// New programs should use SPI.beginTransaction to set the SPI clock +#if F_CPU == 48000000 + #define SPI_CLOCK_DIV2 6 + #define SPI_CLOCK_DIV4 12 + #define SPI_CLOCK_DIV8 24 + #define SPI_CLOCK_DIV16 48 + #define SPI_CLOCK_DIV32 96 + #define SPI_CLOCK_DIV64 192 + #define SPI_CLOCK_DIV128 255 +#endif + +#endif diff --git a/hardware/MySensors/samd/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino b/hardware/MySensors/samd/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino new file mode 100644 index 0000000..8104fcb --- /dev/null +++ b/hardware/MySensors/samd/libraries/SPI/examples/BarometricPressureSensor/BarometricPressureSensor.ino @@ -0,0 +1,143 @@ +/* + SCP1000 Barometric Pressure Sensor Display + + Shows the output of a Barometric Pressure Sensor on a + Uses the SPI library. For details on the sensor, see: + http://www.sparkfun.com/commerce/product_info.php?products_id=8161 + http://www.vti.fi/en/support/obsolete_products/pressure_sensors/ + + This sketch adapted from Nathan Seidle's SCP1000 example for PIC: + http://www.sparkfun.com/datasheets/Sensors/SCP1000-Testing.zip + + Circuit: + SCP1000 sensor attached to pins 6, 7, 10 - 13: + DRDY: pin 6 + CSB: pin 7 + MOSI: pin 11 + MISO: pin 12 + SCK: pin 13 + + created 31 July 2010 + modified 14 August 2010 + by Tom Igoe + */ + +// the sensor communicates using SPI, so include the library: +#include + +//Sensor's memory register addresses: +const int PRESSURE = 0x1F; //3 most significant bits of pressure +const int PRESSURE_LSB = 0x20; //16 least significant bits of pressure +const int TEMPERATURE = 0x21; //16 bit temperature reading +const byte READ = 0b11111100; // SCP1000's read command +const byte WRITE = 0b00000010; // SCP1000's write command + +// pins used for the connection with the sensor +// the other you need are controlled by the SPI library): +const int dataReadyPin = 6; +const int chipSelectPin = 7; + +void setup() { + Serial.begin(9600); + + // start the SPI library: + SPI.begin(); + + // initalize the data ready and chip select pins: + pinMode(dataReadyPin, INPUT); + pinMode(chipSelectPin, OUTPUT); + + //Configure SCP1000 for low noise configuration: + writeRegister(0x02, 0x2D); + writeRegister(0x01, 0x03); + writeRegister(0x03, 0x02); + // give the sensor time to set up: + delay(100); +} + +void loop() { + //Select High Resolution Mode + writeRegister(0x03, 0x0A); + + // don't do anything until the data ready pin is high: + if (digitalRead(dataReadyPin) == HIGH) { + //Read the temperature data + int tempData = readRegister(0x21, 2); + + // convert the temperature to celsius and display it: + float realTemp = (float)tempData / 20.0; + Serial.print("Temp[C]="); + Serial.print(realTemp); + + + //Read the pressure data highest 3 bits: + byte pressure_data_high = readRegister(0x1F, 1); + pressure_data_high &= 0b00000111; //you only needs bits 2 to 0 + + //Read the pressure data lower 16 bits: + unsigned int pressure_data_low = readRegister(0x20, 2); + //combine the two parts into one 19-bit number: + long pressure = ((pressure_data_high << 16) | pressure_data_low) / 4; + + // display the temperature: + Serial.println("\tPressure [Pa]=" + String(pressure)); + } +} + +//Read from or write to register from the SCP1000: +unsigned int readRegister(byte thisRegister, int bytesToRead ) { + byte inByte = 0; // incoming byte from the SPI + unsigned int result = 0; // result to return + Serial.print(thisRegister, BIN); + Serial.print("\t"); + // SCP1000 expects the register name in the upper 6 bits + // of the byte. So shift the bits left by two bits: + thisRegister = thisRegister << 2; + // now combine the address and the command into one byte + byte dataToSend = thisRegister & READ; + Serial.println(thisRegister, BIN); + // take the chip select low to select the device: + digitalWrite(chipSelectPin, LOW); + // send the device the register you want to read: + SPI.transfer(dataToSend); + // send a value of 0 to read the first byte returned: + result = SPI.transfer(0x00); + // decrement the number of bytes left to read: + bytesToRead--; + // if you still have another byte to read: + if (bytesToRead > 0) { + // shift the first byte left, then get the second byte: + result = result << 8; + inByte = SPI.transfer(0x00); + // combine the byte you just got with the previous one: + result = result | inByte; + // decrement the number of bytes left to read: + bytesToRead--; + } + // take the chip select high to de-select: + digitalWrite(chipSelectPin, HIGH); + // return the result: + return(result); +} + + +//Sends a write command to SCP1000 + +void writeRegister(byte thisRegister, byte thisValue) { + + // SCP1000 expects the register address in the upper 6 bits + // of the byte. So shift the bits left by two bits: + thisRegister = thisRegister << 2; + // now combine the register address and the command into one byte: + byte dataToSend = thisRegister | WRITE; + + // take the chip select low to select the device: + digitalWrite(chipSelectPin, LOW); + + SPI.transfer(dataToSend); //Send register location + SPI.transfer(thisValue); //Send value to record into register + + // take the chip select high to de-select: + digitalWrite(chipSelectPin, HIGH); +} + diff --git a/hardware/MySensors/samd/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino b/hardware/MySensors/samd/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino new file mode 100644 index 0000000..b135a74 --- /dev/null +++ b/hardware/MySensors/samd/libraries/SPI/examples/DigitalPotControl/DigitalPotControl.ino @@ -0,0 +1,71 @@ +/* + Digital Pot Control + + This example controls an Analog Devices AD5206 digital potentiometer. + The AD5206 has 6 potentiometer channels. Each channel's pins are labeled + A - connect this to voltage + W - this is the pot's wiper, which changes when you set it + B - connect this to ground. + + The AD5206 is SPI-compatible,and to command it, you send two bytes, + one with the channel number (0 - 5) and one with the resistance value for the + channel (0 - 255). + + The circuit: + * All A pins of AD5206 connected to +5V + * All B pins of AD5206 connected to ground + * An LED and a 220-ohm resisor in series connected from each W pin to ground + * CS - to digital pin 10 (SS pin) + * SDI - to digital pin 11 (MOSI pin) + * CLK - to digital pin 13 (SCK pin) + + created 10 Aug 2010 + by Tom Igoe + + Thanks to Heather Dewey-Hagborg for the original tutorial, 2005 + +*/ + + +// inslude the SPI library: +#include + + +// set pin 10 as the slave select for the digital pot: +const int slaveSelectPin = 10; + +void setup() { + // set the slaveSelectPin as an output: + pinMode (slaveSelectPin, OUTPUT); + // initialize SPI: + SPI.begin(); +} + +void loop() { + // go through the six channels of the digital pot: + for (int channel = 0; channel < 6; channel++) { + // change the resistance on this channel from min to max: + for (int level = 0; level < 255; level++) { + digitalPotWrite(channel, level); + delay(10); + } + // wait a second at the top: + delay(100); + // change the resistance on this channel from max to min: + for (int level = 0; level < 255; level++) { + digitalPotWrite(channel, 255 - level); + delay(10); + } + } + +} + +void digitalPotWrite(int address, int value) { + // take the SS pin low to select the chip: + digitalWrite(slaveSelectPin, LOW); + // send in the address and value via SPI: + SPI.transfer(address); + SPI.transfer(value); + // take the SS pin high to de-select the chip: + digitalWrite(slaveSelectPin, HIGH); +} diff --git a/hardware/MySensors/samd/libraries/SPI/keywords.txt b/hardware/MySensors/samd/libraries/SPI/keywords.txt new file mode 100644 index 0000000..47738f9 --- /dev/null +++ b/hardware/MySensors/samd/libraries/SPI/keywords.txt @@ -0,0 +1,31 @@ +####################################### +# Syntax Coloring Map SPI +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +SPI KEYWORD1 + +####################################### +# Methods and Functions (KEYWORD2) +####################################### +begin KEYWORD2 +end KEYWORD2 +transfer KEYWORD2 +#setBitOrder KEYWORD2 +setDataMode KEYWORD2 +setClockDivider KEYWORD2 + + +####################################### +# Constants (LITERAL1) +####################################### +SPI_MODE0 LITERAL1 +SPI_MODE1 LITERAL1 +SPI_MODE2 LITERAL1 +SPI_MODE3 LITERAL1 + +SPI_CONTINUE LITERAL1 +SPI_LAST LITERAL1 diff --git a/hardware/MySensors/samd/libraries/Wire/Wire.cpp b/hardware/MySensors/samd/libraries/Wire/Wire.cpp new file mode 100644 index 0000000..aabc1ef --- /dev/null +++ b/hardware/MySensors/samd/libraries/Wire/Wire.cpp @@ -0,0 +1,355 @@ +/* + * TWI/I2C library for Arduino Zero + * Copyright (c) 2015 Arduino LLC. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +extern "C" { +#include +} + +#include +#include + +#include "Wire.h" + +TwoWire::TwoWire(SERCOM * s) +{ + this->sercom = s; + transmissionBegun = false; +} + +void TwoWire::begin(void) { + //Master Mode + sercom->initMasterWIRE(TWI_CLOCK); + sercom->enableWIRE(); + + pinPeripheral(PIN_WIRE_SDA, g_APinDescription[PIN_WIRE_SDA].ulPinType); + pinPeripheral(PIN_WIRE_SCL, g_APinDescription[PIN_WIRE_SCL].ulPinType); +} + +void TwoWire::begin(uint8_t address) { + //Slave mode + sercom->initSlaveWIRE(address); + sercom->enableWIRE(); +} + +void TwoWire::setClock(uint32_t frequency) { + // dummy funtion +} + +uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity, bool stopBit) +{ + if(quantity == 0) + { + return 0; + } + + size_t byteRead = 0; + + if(sercom->startTransmissionWIRE(address, WIRE_READ_FLAG)) + { + // Read first data + rxBuffer.store_char(sercom->readDataWIRE()); + + // Connected to slave + //while(toRead--) + for(byteRead = 0; byteRead < quantity; ++byteRead) + { + if( byteRead == quantity - 1) // Stop transmission + { + sercom->prepareNackBitWIRE(); // Prepare NACK to stop slave transmission + //sercom->readDataWIRE(); // Clear data register to send NACK + sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); // Send Stop + } + else // Continue transmission + { + sercom->prepareAckBitWIRE(); // Prepare Acknowledge + sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_READ); // Prepare the ACK command for the slave + rxBuffer.store_char( sercom->readDataWIRE() ); // Read data and send the ACK + } + } + } + + return byteRead; +} + +uint8_t TwoWire::requestFrom(uint8_t address, size_t quantity) +{ + return requestFrom(address, quantity, true); +} + +void TwoWire::beginTransmission(uint8_t address) { + // save address of target and clear buffer + txAddress = address; + txBuffer.clear(); + + transmissionBegun = true; +} + +// Errors: +// 0 : Success +// 1 : Data too long +// 2 : NACK on transmit of address +// 3 : NACK on transmit of data +// 4 : Other error +uint8_t TwoWire::endTransmission(bool stopBit) +{ + transmissionBegun = false ; + + // Check if there are data to send + if ( txBuffer.available() == 0) + { + return 4 ; + } + + // Start I2C transmission + if ( !sercom->startTransmissionWIRE( txAddress, WIRE_WRITE_FLAG ) ) + { + sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); + return 2 ; // Address error + } + + // Send all buffer + while( txBuffer.available() ) + { + // Trying to send data + if ( !sercom->sendDataMasterWIRE( txBuffer.read_char() ) ) + { + sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); + return 3 ; // Nack or error + } + + if(txBuffer.available() == 0) + { + sercom->prepareCommandBitsWire(WIRE_MASTER_ACT_STOP); + } + } + + return 0; +} + +uint8_t TwoWire::endTransmission() +{ + return endTransmission(true); +} + +size_t TwoWire::write(uint8_t ucData) +{ + if(sercom->isMasterWIRE()) + { + // No writing, without begun transmission or a full buffer + if ( !transmissionBegun || txBuffer.isFull() ) + { + return 0 ; + } + + txBuffer.store_char( ucData ) ; + + return 1 ; + } + else + { + if(sercom->sendDataSlaveWIRE( ucData )) + { + return 1; + } + } + + return 0; +} + +size_t TwoWire::write(const uint8_t *data, size_t quantity) +{ + //Try to store all data + for(size_t i = 0; i < quantity; ++i) + { + //Return the number of data stored, when the buffer is full (if write return 0) + if(!write(data[i])) + return i; + } + + //All data stored + return quantity; +} + +int TwoWire::available(void) +{ + return rxBuffer.available(); +} + +int TwoWire::read(void) +{ + return rxBuffer.read_char(); +} + +int TwoWire::peek(void) +{ + return rxBuffer.peek(); +} + +void TwoWire::flush(void) +{ + // Do nothing, use endTransmission(..) to force + // data transfer. +} + +void TwoWire::onReceive(void(*function)(int)) +{ + onReceiveCallback = function; +} + +void TwoWire::onRequest(void(*function)(void)) +{ + onRequestCallback = function; +} + +void TwoWire::onService(void) +{ + if ( sercom->isSlaveWIRE() ) + { + //Received data + if(sercom->isDataReadyWIRE()) + { + //Store data + rxBuffer.store_char(sercom->readDataWIRE()); + + //Stop or Restart detected + if(sercom->isStopDetectedWIRE() || sercom->isRestartDetectedWIRE()) + { + //Calling onReceiveCallback, if exists + if(onReceiveCallback) + { + onReceiveCallback(available()); + } + } + } + + //Address Match + if(sercom->isAddressMatch()) + { + //Is a request ? + if(sercom->isMasterReadOperationWIRE()) + { + //Calling onRequestCallback, if exists + if(onRequestCallback) + { + onRequestCallback(); + } + } + } + } +} + +/* +void TwoWire::onService(void) +{ + // Retrieve interrupt status + uint32_t sr = TWI_GetStatus(twi); + + if (status == SLAVE_IDLE && TWI_STATUS_SVACC(sr)) { + TWI_DisableIt(twi, TWI_IDR_SVACC); + TWI_EnableIt(twi, TWI_IER_RXRDY | TWI_IER_GACC | TWI_IER_NACK + | TWI_IER_EOSACC | TWI_IER_SCL_WS | TWI_IER_TXCOMP); + + srvBufferLength = 0; + srvBufferIndex = 0; + + // Detect if we should go into RECV or SEND status + // SVREAD==1 means *master* reading -> SLAVE_SEND + if (!TWI_STATUS_SVREAD(sr)) { + status = SLAVE_RECV; + } else { + status = SLAVE_SEND; + + // Alert calling program to generate a response ASAP + if (onRequestCallback) + onRequestCallback(); + else + // create a default 1-byte response + write((uint8_t) 0); + } + } + + if (status != SLAVE_IDLE) { + if (TWI_STATUS_TXCOMP(sr) && TWI_STATUS_EOSACC(sr)) { + if (status == SLAVE_RECV && onReceiveCallback) { + // Copy data into rxBuffer + // (allows to receive another packet while the + // user program reads actual data) + for (uint8_t i = 0; i < srvBufferLength; ++i) + rxBuffer[i] = srvBuffer[i]; + rxBufferIndex = 0; + rxBufferLength = srvBufferLength; + + // Alert calling program + onReceiveCallback( rxBufferLength); + } + + // Transfer completed + TWI_EnableIt(twi, TWI_SR_SVACC); + TWI_DisableIt(twi, TWI_IDR_RXRDY | TWI_IDR_GACC | TWI_IDR_NACK + | TWI_IDR_EOSACC | TWI_IDR_SCL_WS | TWI_IER_TXCOMP); + status = SLAVE_IDLE; + } + } + + if (status == SLAVE_RECV) { + if (TWI_STATUS_RXRDY(sr)) { + if (srvBufferLength < BUFFER_LENGTH) + srvBuffer[srvBufferLength++] = TWI_ReadByte(twi); + } + } + + if (status == SLAVE_SEND) { + if (TWI_STATUS_TXRDY(sr) && !TWI_STATUS_NACK(sr)) { + uint8_t c = 'x'; + if (srvBufferIndex < srvBufferLength) + c = srvBuffer[srvBufferIndex++]; + TWI_WriteByte(twi, c); + } + } +} +*/ + +#if WIRE_INTERFACES_COUNT > 0 +/*static void Wire_Init(void) { + pmc_enable_periph_clk(WIRE_INTERFACE_ID); + PIO_Configure( + g_APinDescription[PIN_WIRE_SDA].pPort, + g_APinDescription[PIN_WIRE_SDA].ulPinType, + g_APinDescription[PIN_WIRE_SDA].ulPin, + g_APinDescription[PIN_WIRE_SDA].ulPinConfiguration); + PIO_Configure( + g_APinDescription[PIN_WIRE_SCL].pPort, + g_APinDescription[PIN_WIRE_SCL].ulPinType, + g_APinDescription[PIN_WIRE_SCL].ulPin, + g_APinDescription[PIN_WIRE_SCL].ulPinConfiguration); + + NVIC_DisableIRQ(WIRE_ISR_ID); + NVIC_ClearPendingIRQ(WIRE_ISR_ID); + NVIC_SetPriority(WIRE_ISR_ID, 0); + NVIC_EnableIRQ(WIRE_ISR_ID); +}*/ + + +TwoWire Wire(&sercom3); + +void SERCOM3_Handler(void) { + Wire.onService(); +} + +#endif diff --git a/hardware/MySensors/samd/libraries/Wire/Wire.h b/hardware/MySensors/samd/libraries/Wire/Wire.h new file mode 100644 index 0000000..844168e --- /dev/null +++ b/hardware/MySensors/samd/libraries/Wire/Wire.h @@ -0,0 +1,104 @@ +/* + * TWI/I2C library for Arduino Zero + * Copyright (c) 2015 Arduino LLC. All rights reserved. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef TwoWire_h +#define TwoWire_h + +#include "Stream.h" +#include "variant.h" + +#include "SERCOM.h" +#include "RingBuffer.h" + +#define BUFFER_LENGTH 32 + +class TwoWire : public Stream +{ + public: + TwoWire(SERCOM *s); + void begin(); + void begin(uint8_t); + void setClock(uint32_t); // dummy function + + void beginTransmission(uint8_t); + 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); + + size_t write(uint8_t data); + size_t write(const uint8_t * data, size_t quantity); + + virtual int available(void); + virtual int read(void); + virtual int peek(void); + virtual void flush(void); + void onReceive(void(*)(int)); + void onRequest(void(*)(void)); + + using Print::write; + + void onService(void); + + private: + SERCOM * sercom; + bool transmissionBegun; + + // RX Buffer + RingBuffer rxBuffer; + + //TX buffer + RingBuffer txBuffer; + uint8_t txAddress; + + + // Service buffer + //uint8_t srvBuffer[BUFFER_LENGTH]; + //uint8_t srvBufferIndex; + //uint8_t srvBufferLength; + + // Callback user functions + void (*onRequestCallback)(void); + void (*onReceiveCallback)(int); + + // TWI state + //enum TwoWireStatus + //{ + // UNINITIALIZED, + // MASTER_IDLE, + // MASTER_SEND, + // MASTER_RECV, + // SLAVE_IDLE, + // SLAVE_RECV, + // SLAVE_SEND + //}; + //TwoWireStatus status; + + // TWI clock frequency + static const uint32_t TWI_CLOCK = 100000; + + // Timeouts + //static const uint32_t RECV_TIMEOUT = 100000; + //static const uint32_t XMIT_TIMEOUT = 100000; +}; + +extern TwoWire Wire; + +#endif diff --git a/hardware/MySensors/samd/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.pde b/hardware/MySensors/samd/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.pde new file mode 100644 index 0000000..9c41c18 --- /dev/null +++ b/hardware/MySensors/samd/libraries/Wire/examples/SFRRanger_reader/SFRRanger_reader.pde @@ -0,0 +1,87 @@ +// I2C SRF10 or SRF08 Devantech Ultrasonic Ranger Finder +// by Nicholas Zambetti +// and James Tichenor + +// Demonstrates use of the Wire library reading data from the +// Devantech Utrasonic Rangers SFR08 and SFR10 + +// Created 29 April 2006 + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(); // join i2c bus (address optional for master) + Serial.begin(9600); // start serial communication at 9600bps +} + +int reading = 0; + +void loop() +{ + // step 1: instruct sensor to read echoes + Wire.beginTransmission(112); // transmit to device #112 (0x70) + // the address specified in the datasheet is 224 (0xE0) + // but i2c adressing uses the high 7 bits so it's 112 + Wire.write(byte(0x00)); // sets register pointer to the command register (0x00) + Wire.write(byte(0x50)); // command sensor to measure in "inches" (0x50) + // use 0x51 for centimeters + // use 0x52 for ping microseconds + Wire.endTransmission(); // stop transmitting + + // step 2: wait for readings to happen + delay(70); // datasheet suggests at least 65 milliseconds + + // step 3: instruct sensor to return a particular echo reading + Wire.beginTransmission(112); // transmit to device #112 + Wire.write(byte(0x02)); // sets register pointer to echo #1 register (0x02) + Wire.endTransmission(); // stop transmitting + + // step 4: request reading from sensor + Wire.requestFrom(112, 2); // request 2 bytes from slave device #112 + + // step 5: receive reading from sensor + if(2 <= Wire.available()) // if two bytes were received + { + reading = Wire.read(); // receive high byte (overwrites previous reading) + reading = reading << 8; // shift high byte to be high 8 bits + reading |= Wire.read(); // receive low byte as lower 8 bits + Serial.println(reading); // print the reading + } + + delay(250); // wait a bit since people have to read the output :) +} + + +/* + +// The following code changes the address of a Devantech Ultrasonic Range Finder (SRF10 or SRF08) +// usage: changeAddress(0x70, 0xE6); + +void changeAddress(byte oldAddress, byte newAddress) +{ + Wire.beginTransmission(oldAddress); + Wire.write(byte(0x00)); + Wire.write(byte(0xA0)); + Wire.endTransmission(); + + Wire.beginTransmission(oldAddress); + Wire.write(byte(0x00)); + Wire.write(byte(0xAA)); + Wire.endTransmission(); + + Wire.beginTransmission(oldAddress); + Wire.write(byte(0x00)); + Wire.write(byte(0xA5)); + Wire.endTransmission(); + + Wire.beginTransmission(oldAddress); + Wire.write(byte(0x00)); + Wire.write(newAddress); + Wire.endTransmission(); +} + +*/ diff --git a/hardware/MySensors/samd/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.pde b/hardware/MySensors/samd/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.pde new file mode 100644 index 0000000..38da1c5 --- /dev/null +++ b/hardware/MySensors/samd/libraries/Wire/examples/digital_potentiometer/digital_potentiometer.pde @@ -0,0 +1,39 @@ +// I2C Digital Potentiometer +// by Nicholas Zambetti +// and Shawn Bonkowski + +// Demonstrates use of the Wire library +// Controls AD5171 digital potentiometer via I2C/TWI + +// Created 31 March 2006 + +// This example code is in the public domain. + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(); // join i2c bus (address optional for master) +} + +byte val = 0; + +void loop() +{ + Wire.beginTransmission(44); // transmit to device #44 (0x2c) + // device address is specified in datasheet + Wire.write(byte(0x00)); // sends instruction byte + Wire.write(val); // sends potentiometer value byte + Wire.endTransmission(); // stop transmitting + + val++; // increment value + if(val == 64) // if reached 64th position (max) + { + val = 0; // start over from lowest value + } + delay(500); +} + diff --git a/hardware/MySensors/samd/libraries/Wire/examples/master_reader/master_reader.pde b/hardware/MySensors/samd/libraries/Wire/examples/master_reader/master_reader.pde new file mode 100644 index 0000000..4124d7d --- /dev/null +++ b/hardware/MySensors/samd/libraries/Wire/examples/master_reader/master_reader.pde @@ -0,0 +1,32 @@ +// Wire Master Reader +// by Nicholas Zambetti + +// Demonstrates use of the Wire library +// Reads data from an I2C/TWI slave device +// Refer to the "Wire Slave Sender" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(); // join i2c bus (address optional for master) + Serial.begin(9600); // start serial for output +} + +void loop() +{ + Wire.requestFrom(2, 6); // request 6 bytes from slave device #2 + + while(Wire.available()) // slave may send less than requested + { + char c = Wire.read(); // receive a byte as character + Serial.print(c); // print the character + } + + delay(500); +} diff --git a/hardware/MySensors/samd/libraries/Wire/examples/master_writer/master_writer.pde b/hardware/MySensors/samd/libraries/Wire/examples/master_writer/master_writer.pde new file mode 100644 index 0000000..ccaa036 --- /dev/null +++ b/hardware/MySensors/samd/libraries/Wire/examples/master_writer/master_writer.pde @@ -0,0 +1,31 @@ +// Wire Master Writer +// by Nicholas Zambetti + +// Demonstrates use of the Wire library +// Writes data to an I2C/TWI slave device +// Refer to the "Wire Slave Receiver" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(); // join i2c bus (address optional for master) +} + +byte x = 0; + +void loop() +{ + Wire.beginTransmission(4); // transmit to device #4 + Wire.write("x is "); // sends five bytes + Wire.write(x); // sends one byte + Wire.endTransmission(); // stop transmitting + + x++; + delay(500); +} diff --git a/hardware/MySensors/samd/libraries/Wire/examples/slave_receiver/slave_receiver.pde b/hardware/MySensors/samd/libraries/Wire/examples/slave_receiver/slave_receiver.pde new file mode 100644 index 0000000..60dd4bd --- /dev/null +++ b/hardware/MySensors/samd/libraries/Wire/examples/slave_receiver/slave_receiver.pde @@ -0,0 +1,38 @@ +// Wire Slave Receiver +// by Nicholas Zambetti + +// Demonstrates use of the Wire library +// Receives data as an I2C/TWI slave device +// Refer to the "Wire Master Writer" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(4); // join i2c bus with address #4 + Wire.onReceive(receiveEvent); // register event + Serial.begin(9600); // start serial for output +} + +void loop() +{ + delay(100); +} + +// function that executes whenever data is received from master +// this function is registered as an event, see setup() +void receiveEvent(int howMany) +{ + while(1 < Wire.available()) // loop through all but the last + { + char c = Wire.read(); // receive byte as a character + Serial.print(c); // print the character + } + int x = Wire.read(); // receive byte as an integer + Serial.println(x); // print the integer +} diff --git a/hardware/MySensors/samd/libraries/Wire/examples/slave_sender/slave_sender.pde b/hardware/MySensors/samd/libraries/Wire/examples/slave_sender/slave_sender.pde new file mode 100644 index 0000000..d3b238a --- /dev/null +++ b/hardware/MySensors/samd/libraries/Wire/examples/slave_sender/slave_sender.pde @@ -0,0 +1,32 @@ +// Wire Slave Sender +// by Nicholas Zambetti + +// Demonstrates use of the Wire library +// Sends data as an I2C/TWI slave device +// Refer to the "Wire Master Reader" example for use with this + +// Created 29 March 2006 + +// This example code is in the public domain. + + +#include + +void setup() +{ + Wire.begin(2); // join i2c bus with address #2 + Wire.onRequest(requestEvent); // register event +} + +void loop() +{ + delay(100); +} + +// function that executes whenever data is requested by master +// this function is registered as an event, see setup() +void requestEvent() +{ + Wire.write("hello "); // respond with message of 6 bytes + // as expected by master +} diff --git a/hardware/MySensors/samd/libraries/Wire/keywords.txt b/hardware/MySensors/samd/libraries/Wire/keywords.txt new file mode 100644 index 0000000..e75e929 --- /dev/null +++ b/hardware/MySensors/samd/libraries/Wire/keywords.txt @@ -0,0 +1,32 @@ +####################################### +# Syntax Coloring Map For Wire +####################################### + +####################################### +# Datatypes (KEYWORD1) +####################################### + +####################################### +# Methods and Functions (KEYWORD2) +####################################### + +begin KEYWORD2 +beginTransmission KEYWORD2 +endTransmission KEYWORD2 +requestFrom KEYWORD2 +send KEYWORD2 +receive KEYWORD2 +onReceive KEYWORD2 +onRequest KEYWORD2 + +####################################### +# Instances (KEYWORD2) +####################################### + +Wire KEYWORD2 +Wire1 KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### + diff --git a/hardware/MySensors/samd/platform.txt b/hardware/MySensors/samd/platform.txt new file mode 100644 index 0000000..b493921 --- /dev/null +++ b/hardware/MySensors/samd/platform.txt @@ -0,0 +1,143 @@ +# Copyright (c) 2014-2015 Arduino LLC. All right reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +# Arduino SAMD Core and platform. +# +# For more info: +# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification + +name=Mysensors SAMD (32-bits ARM Cortex-M0+) Boards +version=1.0.0 + +# Compile variables +# ----------------- + +compiler.warning_flags=-w +compiler.warning_flags.none=-w +compiler.warning_flags.default= +compiler.warning_flags.more=-Wall +compiler.warning_flags.all=-Wall -Wextra + +compiler.path={runtime.tools.arm-none-eabi-gcc.path}/bin/ +compiler.c.cmd=arm-none-eabi-gcc +compiler.c.flags=-mcpu={build.mcu} -mthumb -c -g -Os {compiler.warning_flags} -std=gnu11 -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -MMD +compiler.c.elf.cmd=arm-none-eabi-gcc +compiler.c.elf.flags=-Os -Wl,--gc-sections -save-temps +compiler.S.cmd=arm-none-eabi-gcc +compiler.S.flags=-c -g -x assembler-with-cpp +compiler.cpp.cmd=arm-none-eabi-g++ +compiler.cpp.flags=-mcpu={build.mcu} -mthumb -c -g -Os {compiler.warning_flags} -std=gnu++11 -ffunction-sections -fdata-sections -fno-threadsafe-statics -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -MMD +compiler.ar.cmd=arm-none-eabi-ar +compiler.ar.flags=rcs +compiler.objcopy.cmd=arm-none-eabi-objcopy +compiler.objcopy.eep.flags=-O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 +compiler.elf2hex.flags=-O binary +compiler.elf2hex.cmd=arm-none-eabi-objcopy +compiler.ldflags=-mcpu={build.mcu} -mthumb -Wl,--cref -Wl,--check-sections -Wl,--gc-sections -Wl,--unresolved-symbols=report-all -Wl,--warn-common -Wl,--warn-section-align +compiler.size.cmd=arm-none-eabi-size +compiler.define=-DARDUINO= + +# this can be overriden in boards.txt +build.extra_flags= + +# These can be overridden in platform.local.txt +compiler.c.extra_flags= +compiler.c.elf.extra_flags= +#compiler.c.elf.extra_flags=-v +compiler.cpp.extra_flags= +compiler.S.extra_flags= +compiler.ar.extra_flags= +compiler.elf2hex.extra_flags= + +compiler.arm.cmsis.path="-I{runtime.tools.CMSIS.path}/CMSIS/Include/" "-I{runtime.tools.CMSIS.path}/Device/ATMEL/" + +# USB Flags +# --------- +build.usb_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid} -DUSBCON '-DUSB_MANUFACTURER={build.usb_manufacturer}' '-DUSB_PRODUCT={build.usb_product}' + +# Default usb manufacturer will be replaced at compile time using +# numeric vendor ID if available or by board's specific value. +build.usb_manufacturer="Unknown" + + +# Compile patterns +# ---------------- + +## Compile c files +recipe.c.o.pattern="{compiler.path}{compiler.c.cmd}" {compiler.c.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.c.extra_flags} {build.extra_flags} {compiler.arm.cmsis.path} {includes} "{source_file}" -o "{object_file}" + +## Compile c++ files +recipe.cpp.o.pattern="{compiler.path}{compiler.cpp.cmd}" {compiler.cpp.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.cpp.extra_flags} {build.extra_flags} {compiler.arm.cmsis.path} {includes} "{source_file}" -o "{object_file}" + +## Compile S files +recipe.S.o.pattern="{compiler.path}{compiler.S.cmd}" {compiler.S.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} {compiler.S.extra_flags} {build.extra_flags} {compiler.arm.cmsis.path} {includes} "{source_file}" -o "{object_file}" + +## Create archives +recipe.ar.pattern="{compiler.path}{compiler.ar.cmd}" {compiler.ar.flags} {compiler.ar.extra_flags} "{build.path}/{archive_file}" "{object_file}" + +## Combine gc-sections, archives, and objects +recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" "-L{build.path}" {compiler.c.elf.flags} {compiler.c.elf.extra_flags} "-T{build.variant.path}/{build.ldscript}" "-Wl,-Map,{build.path}/{build.project_name}.map" --specs=nano.specs --specs=nosys.specs {compiler.ldflags} -o "{build.path}/{build.project_name}.elf" {object_files} -Wl,--start-group -lm "{build.path}/{archive_file}" -Wl,--end-group + +## Create output (bin file) +recipe.objcopy.bin.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin" + +## Save hex +recipe.output.tmp_file={build.project_name}.bin +recipe.output.save_file={build.project_name}.{build.variant}.bin + +## Compute size +recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf" +recipe.size.regex=\.text\s+([0-9]+).* + + +# Uploader tools +# -------------- + +# +# BOSSA +# +tools.bossac.path={runtime.tools.bossac-1.6-arduino.path} +tools.bossac.cmd=bossac +tools.bossac.cmd.windows=bossac.exe + +tools.bossac.upload.params.verbose=-i -d +tools.bossac.upload.params.quiet= +tools.bossac.upload.pattern="{path}/{cmd}" {upload.verbose} --port={serial.port.file} -U {upload.native_usb} -i -e -w -v "{build.path}/{build.project_name}.bin" -R + +# +# OpenOCD sketch upload +# + +tools.openocd.path={runtime.tools.openocd.path} +tools.openocd.cmd=bin/openocd +tools.openocd.cmd.windows=bin/openocd.exe + +tools.openocd.upload.params.verbose=-d2 +tools.openocd.upload.params.quiet=-d0 +tools.openocd.upload.pattern="{path}/{cmd}" {upload.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{{build.path}/{build.project_name}.bin}} verify reset 0x00002000; shutdown" + +tools.openocd.program.params.verbose=-d2 +tools.openocd.program.params.quiet=-d0 +tools.openocd.program.pattern="{path}/{cmd}" {program.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; program {{{build.path}/{build.project_name}.elf}} verify reset; shutdown" + +tools.openocd.erase.params.verbose=-d3 +tools.openocd.erase.params.quiet=-d0 +tools.openocd.erase.pattern= + +tools.openocd.bootloader.params.verbose=-d2 +tools.openocd.bootloader.params.quiet=-d0 +tools.openocd.bootloader.pattern="{path}/{cmd}" {bootloader.verbose} -s "{path}/share/openocd/scripts/" -f "{runtime.platform.path}/variants/{build.variant}/{build.openocdscript}" -c "telnet_port disabled; init; halt; at91samd bootloader 0; program {{{runtime.platform.path}/bootloaders/{bootloader.file}}} verify reset; shutdown" + diff --git a/hardware/MySensors/samd/variants/mysensors_gw/debug_scripts/variant.gdb b/hardware/MySensors/samd/variants/mysensors_gw/debug_scripts/variant.gdb new file mode 100644 index 0000000..3c37ffd --- /dev/null +++ b/hardware/MySensors/samd/variants/mysensors_gw/debug_scripts/variant.gdb @@ -0,0 +1,31 @@ +# +# Arduino Zero OpenOCD script. +# +# Copyright (c) 2014-2015 Arduino LLC. All right reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +# Define 'reset' command +define reset + +info reg + +break main + +# End of 'reset' command +end + +target remote | openocd -c "interface cmsis-dap" -c "set CHIPNAME at91samd21g18" -f target/at91samdXX.cfg -c "gdb_port pipe; log_output openocd.log" diff --git a/hardware/MySensors/samd/variants/mysensors_gw/linker_scripts/gcc/flash_with_bootloader.ld b/hardware/MySensors/samd/variants/mysensors_gw/linker_scripts/gcc/flash_with_bootloader.ld new file mode 100644 index 0000000..4475f95 --- /dev/null +++ b/hardware/MySensors/samd/variants/mysensors_gw/linker_scripts/gcc/flash_with_bootloader.ld @@ -0,0 +1,211 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/* Linker script to configure memory regions. + * Need modifying for a specific board. + * FLASH.ORIGIN: starting address of flash + * FLASH.LENGTH: length of flash + * RAM.ORIGIN: starting address of RAM bank 0 + * RAM.LENGTH: length of RAM bank 0 + */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2000 /* First 8KB used by bootloader */ + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* To copy multiple ROM to RAM sections, + * uncomment .copy.table section and, + * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ + /* + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + LONG (__etext2) + LONG (__data2_start__) + LONG (__data2_end__ - __data2_start__) + __copy_table_end__ = .; + } > FLASH + */ + + /* To clear multiple BSS sections, + * uncomment .zero.table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ + /* + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + LONG (__bss2_start__) + LONG (__bss2_end__ - __bss2_start__) + __zero_table_end__ = .; + } > FLASH + */ + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM); + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + __ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ; + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/hardware/MySensors/samd/variants/mysensors_gw/linker_scripts/gcc/flash_without_bootloader.ld b/hardware/MySensors/samd/variants/mysensors_gw/linker_scripts/gcc/flash_without_bootloader.ld new file mode 100644 index 0000000..0162f07 --- /dev/null +++ b/hardware/MySensors/samd/variants/mysensors_gw/linker_scripts/gcc/flash_without_bootloader.ld @@ -0,0 +1,212 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +/* Linker script to configure memory regions. + * Need modifying for a specific board. + * FLASH.ORIGIN: starting address of flash + * FLASH.LENGTH: length of flash + * RAM.ORIGIN: starting address of RAM bank 0 + * RAM.LENGTH: length of RAM bank 0 + */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 0x00040000 + RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +/* Linker script to place sections and symbol values. Should be used together + * with other linker script that defines memory regions FLASH and RAM. + * It references following symbols, which must be defined in code: + * Reset_Handler : Entry of reset handler + * + * It defines following symbols, which code can use without definition: + * __exidx_start + * __exidx_end + * __copy_table_start__ + * __copy_table_end__ + * __zero_table_start__ + * __zero_table_end__ + * __etext + * __data_start__ + * __preinit_array_start + * __preinit_array_end + * __init_array_start + * __init_array_end + * __fini_array_start + * __fini_array_end + * __data_end__ + * __bss_start__ + * __bss_end__ + * __end__ + * end + * __HeapLimit + * __StackLimit + * __StackTop + * __stack + * __ram_end__ + */ +ENTRY(Reset_Handler) + +SECTIONS +{ + .text : + { + KEEP(*(.isr_vector)) + *(.text*) + + KEEP(*(.init)) + KEEP(*(.fini)) + + /* .ctors */ + *crtbegin.o(.ctors) + *crtbegin?.o(.ctors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors) + *(SORT(.ctors.*)) + *(.ctors) + + /* .dtors */ + *crtbegin.o(.dtors) + *crtbegin?.o(.dtors) + *(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors) + *(SORT(.dtors.*)) + *(.dtors) + + *(.rodata*) + + KEEP(*(.eh_frame*)) + } > FLASH + + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > FLASH + + __exidx_start = .; + .ARM.exidx : + { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } > FLASH + __exidx_end = .; + + /* To copy multiple ROM to RAM sections, + * uncomment .copy.table section and, + * define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */ + /* + .copy.table : + { + . = ALIGN(4); + __copy_table_start__ = .; + LONG (__etext) + LONG (__data_start__) + LONG (__data_end__ - __data_start__) + LONG (__etext2) + LONG (__data2_start__) + LONG (__data2_end__ - __data2_start__) + __copy_table_end__ = .; + } > FLASH + */ + + /* To clear multiple BSS sections, + * uncomment .zero.table section and, + * define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */ + /* + .zero.table : + { + . = ALIGN(4); + __zero_table_start__ = .; + LONG (__bss_start__) + LONG (__bss_end__ - __bss_start__) + LONG (__bss2_start__) + LONG (__bss2_end__ - __bss2_start__) + __zero_table_end__ = .; + } > FLASH + */ + + __etext = .; + + .data : AT (__etext) + { + __data_start__ = .; + *(vtable) + *(.data*) + + . = ALIGN(4); + /* preinit data */ + PROVIDE_HIDDEN (__preinit_array_start = .); + KEEP(*(.preinit_array)) + PROVIDE_HIDDEN (__preinit_array_end = .); + + . = ALIGN(4); + /* init data */ + PROVIDE_HIDDEN (__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array)) + PROVIDE_HIDDEN (__init_array_end = .); + + + . = ALIGN(4); + /* finit data */ + PROVIDE_HIDDEN (__fini_array_start = .); + KEEP(*(SORT(.fini_array.*))) + KEEP(*(.fini_array)) + PROVIDE_HIDDEN (__fini_array_end = .); + + KEEP(*(.jcr*)) + . = ALIGN(4); + /* All data end */ + __data_end__ = .; + + } > RAM + + .bss : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > RAM + + .heap (COPY): + { + __end__ = .; + PROVIDE(end = .); + *(.heap*) + __HeapLimit = .; + } > RAM + + /* .stack_dummy section doesn't contains any symbols. It is only + * used for linker to calculate size of stack sections, and assign + * values to stack symbols later */ + .stack_dummy (COPY): + { + *(.stack*) + } > RAM + + /* Set stack top to end of RAM, and stack limit move down by + * size of stack_dummy section */ + __StackTop = ORIGIN(RAM) + LENGTH(RAM) ; + __StackLimit = __StackTop - SIZEOF(.stack_dummy); + PROVIDE(__stack = __StackTop); + + __ram_end__ = ORIGIN(RAM) + LENGTH(RAM) -1 ; + + /* Check if data + heap + stack exceeds RAM limit */ + ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack") +} diff --git a/hardware/MySensors/samd/variants/mysensors_gw/openocd_scripts/mysensors_gw.cfg b/hardware/MySensors/samd/variants/mysensors_gw/openocd_scripts/mysensors_gw.cfg new file mode 100644 index 0000000..36c65c3 --- /dev/null +++ b/hardware/MySensors/samd/variants/mysensors_gw/openocd_scripts/mysensors_gw.cfg @@ -0,0 +1,30 @@ +# +# Arduino Zero OpenOCD script. +# +# Copyright (c) 2014-2015 Arduino LLC. All right reserved. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +# + +source [find interface/cmsis-dap.cfg] + +# chip name +set CHIPNAME at91samd21g18 +set ENDIAN little + +# choose a port here +set telnet_port 0 + +source [find target/at91samdXX.cfg] diff --git a/hardware/MySensors/samd/variants/mysensors_gw/pins_arduino.h b/hardware/MySensors/samd/variants/mysensors_gw/pins_arduino.h new file mode 100644 index 0000000..db0e40c --- /dev/null +++ b/hardware/MySensors/samd/variants/mysensors_gw/pins_arduino.h @@ -0,0 +1,21 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +// API compatibility +#include "variant.h" + diff --git a/hardware/MySensors/samd/variants/mysensors_gw/variant.cpp b/hardware/MySensors/samd/variants/mysensors_gw/variant.cpp new file mode 100644 index 0000000..84df403 --- /dev/null +++ b/hardware/MySensors/samd/variants/mysensors_gw/variant.cpp @@ -0,0 +1,221 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ +/* + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * + Pin number + ZERO Board pin | PIN | Label/Name | Comments (* is for default peripheral in use) + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | | Digital Low | | | + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | 0 | 0 -> RX | PA11 | | EIC/EXTINT[11] ADC/AIN[19] PTC/X[3] *SERCOM0/PAD[3] SERCOM2/PAD[3] TCC0/WO[3] TCC1/WO[1] + * | 1 | 1 <- TX | PA10 | | EIC/EXTINT[10] ADC/AIN[18] PTC/X[2] *SERCOM0/PAD[2] TCC0/WO[2] TCC1/WO[0] + * | 2 | 2 | PA14 | | EIC/EXTINT[14] SERCOM2/PAD[2] SERCOM4/PAD[2] TC3/WO[0] TCC0/WO[4] + * | 3 | ~3 | PA09 | | EIC/EXTINT[9] ADC/AIN[17] PTC/X[1] SERCOM0/PAD[1] SERCOM2/PAD[1] *TCC0/WO[1] TCC1/WO[3] + * | 4 | ~4 | PA08 | | EIC/NMI ADC/AIN[16] PTC/X[0] SERCOM0/PAD[0] SERCOM2/PAD[0] *TCC0/WO[0] TCC1/WO[2] + * | 5 | ~5 | PA15 | | EIC/EXTINT[15] SERCOM2/PAD[3] SERCOM4/PAD[3] *TC3/WO[1] TCC0/WO[5] + * | 6 | ~6 | PA20 | | EIC/EXTINT[4] PTC/X[8] SERCOM5/PAD[2] SERCOM3/PAD[2] *TCC0/WO[6] + * | 7 | 7 | PA21 | | EIC/EXTINT[5] PTC/X[9] SERCOM5/PAD[3] SERCOM3/PAD[3] TCC0/WO[7] + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | | Digital High | | | + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | 8 | ~8 | PA06 | | EIC/EXTINT[6] ADC/AIN[6] AC/AIN[2] PTC/Y[4] SERCOM0/PAD[2] *TCC1/WO[0] + * | 9 | ~9 | PA07 | | EIC/EXTINT[7] ADC/AIN[7] AC/AIN[3] PTC/Y[5] SERCOM0/PAD[3] *TCC1/WO[1] + * | 10 | ~10 | PA18 | | EIC/EXTINT[2] PTC/X[6] +SERCOM1/PAD[2] SERCOM3/PAD[2] *TC3/WO[0] TCC0/WO[2] + * | 11 | ~11 | PA16 | | EIC/EXTINT[0] PTC/X[4] +SERCOM1/PAD[0] SERCOM3/PAD[0] *TCC2/WO[0] TCC0/WO[6] + * | 12 | ~12 | PA19 | | EIC/EXTINT[3] PTC/X[7] +SERCOM1/PAD[3] SERCOM3/PAD[3] TC3/WO[1] *TCC0/WO[3] + * | 13 | ~13 | PA17 | LED | EIC/EXTINT[1] PTC/X[5] +SERCOM1/PAD[1] SERCOM3/PAD[1] *TCC2/WO[1] TCC0/WO[7] + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | | Analog Connector | | | + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | 14 | A0 | PA02 | A0 | EIC/EXTINT[2] *ADC/AIN[0] DAC/VOUT PTC/Y[0] + * | 15 | A1 | PB08 | A1 | EIC/EXTINT[8] *ADC/AIN[2] PTC/Y[14] SERCOM4/PAD[0] TC4/WO[0] + * | 16 | A2 | PB09 | A2 | EIC/EXTINT[9] *ADC/AIN[3] PTC/Y[15] SERCOM4/PAD[1] TC4/WO[1] + * | 17 | A3 | PA04 | A3 | EIC/EXTINT[4] *ADC/AIN[4] AC/AIN[0] PTC/Y[2] SERCOM0/PAD[0] TCC0/WO[0] + * | 18 | A4 | PA05 | A4 | EIC/EXTINT[5] *ADC/AIN[5] AC/AIN[1] PTC/Y[5] SERCOM0/PAD[1] TCC0/WO[1] + * | 19 | A5 | PB02 | A5 | EIC/EXTINT[2] *ADC/AIN[10] PTC/Y[8] SERCOM5/PAD[0] + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | | Wire | | | + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | 20 | SDA | PA22 | SDA | EIC/EXTINT[6] PTC/X[10] *SERCOM3/PAD[0] SERCOM5/PAD[0] TC4/WO[0] TCC0/WO[4] + * | 21 | SCL | PA23 | SCL | EIC/EXTINT[7] PTC/X[11] *SERCOM3/PAD[1] SERCOM5/PAD[1] TC4/WO[1] TCC0/WO[5] + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | |SPI (Legacy ICSP) | | | + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | 22 | 1 | PA12 | MISO | EIC/EXTINT[12] SERCOM2/PAD[0] *SERCOM4/PAD[0] TCC2/WO[0] TCC0/WO[6] + * | | 2 | | 5V0 | + * | 23 | 4 | PB10 | MOSI | EIC/EXTINT[10] *SERCOM4/PAD[2] TC5/WO[0] TCC0/WO[4] + * | 24 | 3 | PB11 | SCK | EIC/EXTINT[11] *SERCOM4/PAD[3] TC5/WO[1] TCC0/WO[5] + * | | 5 | | RESET | + * | | 6 | | GND | + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | | LEDs | | | + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | 25 | | PB03 | RX | + * | 26 | | PA27 | TX | + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | | USB | | | + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | 27 | | PA28 | USB_HOST_ENABLE | EIC/EXTINT[8] + * | 28 | | PA24 | USB_NEGATIVE | *USB/DM + * | 29 | | PA25 | USB_POSITIVE | *USB/DP + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | | EDBG | | | + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | 30 | | PB22 | EDBG_UART TX | *SERCOM5/PAD[2] + * | 31 | | PB23 | EDBG_UART RX | *SERCOM5/PAD[3] + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | 32 | | PA22 | EDBG_SDA | Pin 20 (SDA) + * | 33 | | PA23 | EDBG_SCL | Pin 21 (SCL) + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | 34 | | PA19 | EDBG_MISO | EIC/EXTINT[3] *SERCOM1/PAD[3] SERCOM3/PAD[3] TC3/WO[1] TCC0/WO[3] + * | 35 | | PA16 | EDBG_MOSI | EIC/EXTINT[0] *SERCOM1/PAD[0] SERCOM3/PAD[0] TCC2/WO[0] TCC0/WO[6] + * | 36 | | PA18 | EDBG_SS | EIC/EXTINT[2] *SERCOM1/PAD[2] SERCOM3/PAD[2] TC3/WO[0] TCC0/WO[2] + * | 37 | | PA17 | EDBG_SCK | EIC/EXTINT[1] *SERCOM1/PAD[1] SERCOM3/PAD[1] TCC2/WO[1] TCC0/WO[7] + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | 38 | ATN | PA13 | EDBG_GPIO0 | EIC/EXTINT[13] SERCOM2/PAD[1] SERCOM4/PAD[1] *TCC2/WO[1] TCC0/WO[7] + * | 39 | | PA21 | EDBG_GPIO1 | Pin 7 + * | 40 | | PA06 | EDBG_GPIO2 | Pin 8 + * | 41 | | PA07 | EDBG_GPIO3 | Pin 9 + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | | | | | + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | | GND | | | + * | 42 | AREF | PA03 | | EIC/EXTINT[3] *[ADC|DAC]/VREFA ADC/AIN[1] PTC/Y[1] + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | |32.768KHz Crystal | | | + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + * | | | PA00 | XIN32 | EIC/EXTINT[0] SERCOM1/PAD[0] TCC2/WO[0] + * | | | PA01 | XOUT32 | EIC/EXTINT[1] SERCOM1/PAD[1] TCC2/WO[1] + * +------------+------------------+--------+-----------------+-------------------------------------------------------------------------------------------------------- + */ + + +#include "variant.h" + +/* + * Pins descriptions + */ +const PinDescription g_APinDescription[]= +{ + // 0..13 - Digital pins + // ---------------------- + // 0/1 - SERCOM/UART (Serial1) + { PORTA, 11, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // RX: SERCOM0/PAD[3] + { PORTA, 10, PIO_SERCOM, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // TX: SERCOM0/PAD[2] + + // 2..12 + // Digital Low + { PORTA, 14, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_14 }, + { PORTA, 9, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH1, TCC0_CH1, EXTERNAL_INT_9 }, // TCC0/WO[1] + { PORTA, 8, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH0, TCC0_CH0, EXTERNAL_INT_NMI }, // TCC0/WO[0] + { PORTA, 15, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH1, TC3_CH1, EXTERNAL_INT_15 }, // TC3/WO[1] + { PORTA, 20, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH6, TCC0_CH6, EXTERNAL_INT_4 }, // TCC0/WO[6] + { PORTA, 21, PIO_DIGITAL, (PIN_ATTR_DIGITAL), No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, + + // Digital High + { PORTA, 6, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM1_CH0, TCC1_CH0, EXTERNAL_INT_4 }, // TCC1/WO[0] + { PORTA, 7, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM1_CH1, TCC1_CH1, EXTERNAL_INT_5 }, // TCC1/WO[1] + { PORTA, 18, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM3_CH0, TC3_CH0, EXTERNAL_INT_2 }, // TC3/WO[0] + { PORTA, 16, PIO_TIMER, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM2_CH0, TCC2_CH0, EXTERNAL_INT_0 }, // TCC2/WO[0] + { PORTA, 19, PIO_TIMER_ALT, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM|PIN_ATTR_TIMER), No_ADC_Channel, PWM0_CH3, TCC0_CH3, EXTERNAL_INT_3 }, // TCC0/WO[3] + + // 13 (LED) + { PORTA, 17, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM2_CH1, NOT_ON_TIMER, EXTERNAL_INT_1 }, // TCC2/WO[1] + + // 14..19 - Analog pins + // -------------------- + { PORTA, 2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[0] + { PORTB, 8, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel2, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_8 }, // ADC/AIN[2] + { PORTB, 9, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel3, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_9 }, // ADC/AIN[3] + { PORTA, 4, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel4, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_4 }, // ADC/AIN[4] + { PORTA, 5, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel5, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_5 }, // ADC/AIN[5] + { PORTB, 2, PIO_ANALOG, PIN_ATTR_ANALOG, ADC_Channel10, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // ADC/AIN[10] + + // 20..21 I2C pins (SDA/SCL and also EDBG:SDA/SCL) + // ---------------------- + { PORTA, 22, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_6 }, // SDA: SERCOM3/PAD[0] + { PORTA, 23, PIO_SERCOM, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_7 }, // SCL: SERCOM3/PAD[1] + + // 22..24 - SPI pins (ICSP:MISO,SCK,MOSI) + // ---------------------- + { PORTA, 12, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_12 }, // MISO: SERCOM4/PAD[0] + { PORTB, 10, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_10 }, // MOSI: SERCOM4/PAD[2] + { PORTB, 11, PIO_SERCOM_ALT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_11 }, // SCK: SERCOM4/PAD[3] + + // 25..26 - RX/TX LEDS (PB03/PA27) + // -------------------- + { PORTB, 3, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // used as output only + { PORTA, 27, PIO_OUTPUT, PIN_ATTR_DIGITAL, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // used as output only + + // 27..29 - USB + // -------------------- + { PORTA, 28, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB Host enable + { PORTA, 24, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DM + { PORTA, 25, PIO_COM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // USB/DP + + // 30..41 - EDBG + // ---------------------- + // 30/31 - EDBG/UART + { PORTB, 22, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // TX: SERCOM5/PAD[2] + { PORTB, 23, PIO_SERCOM_ALT, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // RX: SERCOM5/PAD[3] + + // 32/33 I2C (SDA/SCL and also EDBG:SDA/SCL) + { PORTA, 22, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SDA: SERCOM3/PAD[0] + { PORTA, 23, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SCL: SERCOM3/PAD[1] + + // 34..37 - EDBG/SPI + { PORTA, 19, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // MISO: SERCOM1/PAD[3] + { PORTA, 16, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // MOSI: SERCOM1/PAD[0] + { PORTA, 18, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SS: SERCOM1/PAD[2] + { PORTA, 17, PIO_SERCOM, PIN_ATTR_NONE, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // SCK: SERCOM1/PAD[1] + + // 38..41 - EDBG/Digital + { PORTA, 13, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM0_CH5, NOT_ON_TIMER, EXTERNAL_INT_13 }, // 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, EXTERNAL_INT_NONE }, // Pin 7 + { PORTA, 6, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM1_CH0, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // Pin 8 + { PORTA, 7, PIO_PWM, (PIN_ATTR_DIGITAL|PIN_ATTR_PWM), No_ADC_Channel, PWM1_CH1, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // Pin 9 + + // 42 (AREF) + { PORTA, 3, PIO_ANALOG, PIN_ATTR_ANALOG, No_ADC_Channel, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_NONE }, // DAC/VREFP + + // ---------------------- + // 43 - Alternate use of A0 (DAC output) + { PORTA, 2, PIO_ANALOG, PIN_ATTR_ANALOG, DAC_Channel0, NOT_ON_PWM, NOT_ON_TIMER, EXTERNAL_INT_2 }, // DAC/VOUT +} ; + +const void* g_apTCInstances[TCC_INST_NUM+TC_INST_NUM]={ TCC0, TCC1, TCC2, TC3, TC4, TC5 } ; + +// Multi-serial objects instantiation +SERCOM sercom0( SERCOM0 ) ; +SERCOM sercom1( SERCOM1 ) ; +SERCOM sercom2( SERCOM2 ) ; +SERCOM sercom3( SERCOM3 ) ; +SERCOM sercom4( SERCOM4 ) ; +SERCOM sercom5( SERCOM5 ) ; + +Uart Serial1( &sercom0, PIN_SERIAL1_RX, PIN_SERIAL1_TX, PAD_SERIAL1_RX, PAD_SERIAL1_TX ) ; +Uart Serial( &sercom5, PIN_SERIAL_RX, PIN_SERIAL_TX, PAD_SERIAL_RX, PAD_SERIAL_TX ) ; +void SERCOM0_Handler() +{ + Serial1.IrqHandler(); +} + +void SERCOM5_Handler() +{ + Serial.IrqHandler(); +} + diff --git a/hardware/MySensors/samd/variants/mysensors_gw/variant.h b/hardware/MySensors/samd/variants/mysensors_gw/variant.h new file mode 100644 index 0000000..a1f1506 --- /dev/null +++ b/hardware/MySensors/samd/variants/mysensors_gw/variant.h @@ -0,0 +1,201 @@ +/* + Copyright (c) 2014-2015 Arduino LLC. All right reserved. + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _VARIANT_ARDUINO_ZERO_ +#define _VARIANT_ARDUINO_ZERO_ + +/*---------------------------------------------------------------------------- + * Definitions + *----------------------------------------------------------------------------*/ + +/** Frequency of the board main oscillator */ +#define VARIANT_MAINOSC (32768ul) + +/** Master clock frequency */ +#define VARIANT_MCK (48000000ul) + +/*---------------------------------------------------------------------------- + * Headers + *----------------------------------------------------------------------------*/ + +#include "WVariant.h" + +#ifdef __cplusplus +#include "SERCOM.h" +#include "Uart.h" +#endif // __cplusplus + +#ifdef __cplusplus +extern "C" +{ +#endif // __cplusplus + +/*---------------------------------------------------------------------------- + * Pins + *----------------------------------------------------------------------------*/ + +// Number of pins defined in PinDescription array +#define PINS_COUNT (26u) +#define NUM_DIGITAL_PINS (14u) +#define NUM_ANALOG_INPUTS (6u) +#define NUM_ANALOG_OUTPUTS (1u) + +#define digitalPinToPort(P) ( &(PORT->Group[g_APinDescription[P].ulPort]) ) +#define digitalPinToBitMask(P) ( 1 << g_APinDescription[P].ulPin ) +//#define analogInPinToBit(P) ( ) +#define portOutputRegister(port) ( &(port->OUT.reg) ) +#define portInputRegister(port) ( &(port->IN.reg) ) +#define portModeRegister(port) ( &(port->DIR.reg) ) +#define digitalPinHasPWM(P) ( g_APinDescription[P].ulPWMChannel != NOT_ON_PWM || g_APinDescription[P].ulTCChannel != NOT_ON_TIMER ) + +/* + * digitalPinToTimer(..) is AVR-specific and is not defined for SAMD + * architecture. If you need to check if a pin supports PWM you must + * use digitalPinHasPWM(..). + * + * https://github.com/arduino/Arduino/issues/1833 + */ +// #define digitalPinToTimer(P) + +// Interrupts +#define digitalPinToInterrupt(P) ( g_APinDescription[P].ulExtInt ) + +// LEDs +#define PIN_LED_13 (13u) +#define PIN_LED_RXL (25u) +#define PIN_LED_TXL (26u) +#define PIN_LED PIN_LED_13 +#define PIN_LED2 PIN_LED_RXL +#define PIN_LED3 PIN_LED_TXL +#define LED_BUILTIN PIN_LED_13 + +/* + * Analog pins + */ +#define PIN_A0 (14ul) +#define PIN_A1 (15ul) +#define PIN_A2 (16ul) +#define PIN_A3 (17ul) +#define PIN_A4 (18ul) +#define PIN_A5 (19ul) + +static const uint8_t A0 = PIN_A0 ; +static const uint8_t A1 = PIN_A1 ; +static const uint8_t A2 = PIN_A2 ; +static const uint8_t A3 = PIN_A3 ; +static const uint8_t A4 = PIN_A4 ; +static const uint8_t A5 = PIN_A5 ; +#define ADC_RESOLUTION 12 + +// Other pins +#define PIN_ATN (38ul) +static const uint8_t ATN = PIN_ATN; + +/* + * Serial interfaces + */ +// Serial (EDBG) +#define PIN_SERIAL_RX (31ul) +#define PIN_SERIAL_TX (30ul) +#define PAD_SERIAL_TX (UART_TX_PAD_2) +#define PAD_SERIAL_RX (SERCOM_RX_PAD_3) + +// Serial1 +#define PIN_SERIAL1_RX (0ul) +#define PIN_SERIAL1_TX (1ul) +#define PAD_SERIAL1_TX (UART_TX_PAD_2) +#define PAD_SERIAL1_RX (SERCOM_RX_PAD_3) + +/* + * SPI Interfaces + */ +#define SPI_INTERFACES_COUNT 1 + +#define PIN_SPI_MISO (22u) +#define PIN_SPI_MOSI (23u) +#define PIN_SPI_SCK (24u) + +static const uint8_t SS = PIN_A2 ; // SERCOM4 last PAD is present on A2 but HW SS isn't used. Set here only for reference. +static const uint8_t MOSI = PIN_SPI_MOSI ; +static const uint8_t MISO = PIN_SPI_MISO ; +static const uint8_t SCK = PIN_SPI_SCK ; + +/* + * Wire Interfaces + */ +#define WIRE_INTERFACES_COUNT 1 + +#define PIN_WIRE_SDA (20u) +#define PIN_WIRE_SCL (21u) + +/* + * USB + */ +#define PIN_USB_HOST_ENABLE (27ul) +#define PIN_USB_DM (28ul) +#define PIN_USB_DP (29ul) + +#ifdef __cplusplus +} +#endif + +/*---------------------------------------------------------------------------- + * Arduino objects - C++ only + *----------------------------------------------------------------------------*/ + +#ifdef __cplusplus + +/* ========================= + * ===== SERCOM DEFINITION + * ========================= +*/ +extern SERCOM sercom0; +extern SERCOM sercom1; +extern SERCOM sercom2; +extern SERCOM sercom3; +extern SERCOM sercom4; +extern SERCOM sercom5; + +extern Uart Serial; +extern Uart Serial1; + +#endif + +// These serial port names are intended to allow libraries and architecture-neutral +// sketches to automatically default to the correct port name for a particular type +// of use. For example, a GPS module would normally connect to SERIAL_PORT_HARDWARE_OPEN, +// the first hardware serial port whose RX/TX pins are not dedicated to another use. +// +// SERIAL_PORT_MONITOR Port which normally prints to the Arduino Serial Monitor +// +// SERIAL_PORT_USBVIRTUAL Port which is USB virtual serial +// +// SERIAL_PORT_LINUXBRIDGE Port which connects to a Linux system via Bridge library +// +// SERIAL_PORT_HARDWARE Hardware serial port, physical RX & TX pins. +// +// SERIAL_PORT_HARDWARE_OPEN Hardware serial ports which are open for use. Their RX & TX +// pins are NOT connected to anything by default. +#define SERIAL_PORT_USBVIRTUAL SerialUSB +#define SERIAL_PORT_MONITOR Serial +// Serial has no physical pins broken out, so it's not listed as HARDWARE port +#define SERIAL_PORT_HARDWARE Serial1 +#define SERIAL_PORT_HARDWARE_OPEN Serial1 + +#endif /* _VARIANT_ARDUINO_ZERO_ */ +