diff --git a/.gitignore b/.gitignore
index 2ad1d1f8..77bb5aa8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,27 @@
+# Compiled Object files
+*.o
+*.obj
+
+# Visual Studio Code
+**/.vscode/
+
+# Executables
+*.out
+*.app
+
+*.pyc
+/tools/.idea/
+/tools/midi_tests/node_modules
+
+.DS_Store
+*.swp
+/Output
+
+# Ignore local overrides of platform.txt and boards.txt,
+/boards.local.txt
+/platform.local.txt
+/libraries/**/build/
+
*.bz2
bootloaders/*/build/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index c062452d..e83dfeeb 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -36,6 +36,37 @@ start:
- master
- branches
+######## PUSH
+push:
+ stage: start
+ only: ['tags']
+ except: ['master', 'branches']
+
+ allow_failure: true
+
+ variables:
+ GIT_STRATEGY: clone
+
+ before_script:
+ - eval `python3 check-version-tag.py ${CI_COMMIT_TAG}`
+
+ script:
+ #- apk add git
+ - git remote add github https://$GITHUB_BOT_USERNAME:$GITHUB_ACCESS_TOKEN@github.com/$GITHUB_DEST_REPO
+ #- git remote show github
+ #- git remote show origin
+ #- git branch -a
+ - git checkout $CI_COMMIT_TAG
+ - git fetch github
+ #- git push github $CI_COMMIT_REF_NAME --force
+ - >
+ if [[ ${PRE_RELEASE} == "test" ]]; then
+ echo "not performing TAG push";
+ else
+ git push github ${CI_COMMIT_TAG}
+ fi
+ - git push github --all --force
+
#################################
####### PACKAGE #######
#################################
@@ -57,6 +88,24 @@ package_release:
- sed -i "s:\(version\)=.*:\1=$CI_COMMIT_TAG:" ./platform.txt
- jq --arg tag_ver ${CI_COMMIT_TAG} '.version = $tag_ver' package.json|sponge package.json
+ # adding Arduino-FreeRTOS-SAMD21 into core
+ - git clone $REPO_LIB_FREERTOS_URL -b v2.3.0-smartmeio.1 libraries/FreeRTOS-SAMD21
+
+ # adding ArduinoJson into core
+ - git clone $REPO_LIB_ARDUINOJSON_URL -b v6.18.0 libraries/ArduinoJson
+
+ # adding MsgPack into core
+ - git clone $REPO_LIB_MSGPACK_URL -b 0.3.8 libraries/MsgPack
+
+ # adding MsgPacketizer into core
+ - git clone $REPO_LIB_MSGPACKETIZER_URL -b 0.3.0 libraries/MsgPacketizer
+
+ # adding Microcontroller ID into core
+ - git clone $REPO_LIB_MICROCONTROLLER_ID_URL -b 1.0.0 libraries/Microcontroller-id
+
+ # adding PubSubClient into core
+ - git clone $REPO_LIB_PUBSUBCLIENT_URL -b v2.8 libraries/PubSubClient
+
- cd ..
# tar files and move temp folder back
- tar --exclude=tmp --exclude=.git* --exclude=*.DS_Store* -cvjf $PKG_NAME.tar.bz2 $CI_PROJECT_NAME
diff --git a/CHANGELOG b/CHANGELOG
index a16f16b1..a340e271 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,3 +1,10 @@
+#### v 1.3.0 - 2021.11.16
+
+* added FreeRTOS-SAMD21 library tag 2.3.0 that include freeRtos core version 10.2.1 [#nt82u1](https://app.clickup.com/t/nt82u1)
+* enabled atomic mode for analogRead and analogWrite function [#kd95qa](https://app.clickup.com/t/kd95qa)
+* definition of a new variable `MCU_FAMILY`[#1nf8f15](#https://app.clickup.com/t/1nf8f15)
+* moved the libraries used by arancino-library into the core
+
#### v 1.2.2 - 2021.03.11
* main features of previous release
diff --git a/README.md b/README.md
index 20744d73..b2b225d9 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ for Atmel's SAMD21 processor (used on the Arancino and Arancino Mignon boards).
This core is available as a package in the Arduino IDE cores manager. If you want to install it:
1. Open the **Preferences** of the Arduino IDE.
- 2. Add this URL `https://git.smartme.io/smartme.io/arancino/arduino/smartmeio-package-index/raw/master/package_smartmeio_index.json` in the **Additional Boards Manager URLs** field, and click OK.
+ 2. Add this URL `https://raw.githubusercontent.com/smartmeio/arancino-boards/master/package_smartmeio_index.json` in the **Additional Boards Manager URLs** field, and click OK.
3. Open the **Boards Manager** (menu Tools->Board->Board Manager...)
4. Install **Arancino Boards**
5. Select one of the boards under **Arancino Boards** in Tools->Board menu
@@ -43,4 +43,4 @@ and customized by smartme.IO s.r.l.
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
```
-Arduino and Atmel are trademarks of their respective owners.
\ No newline at end of file
+Arduino and Atmel are trademarks of their respective owners.
diff --git a/boards.txt b/boards.txt
index b2a272c0..46e86a3d 100644
--- a/boards.txt
+++ b/boards.txt
@@ -31,11 +31,6 @@ arancino_mignon.menu.UploadTool.ArancinoOTA.upload.tool=ArancinoOTA
arancino_mignon.menu.UploadTool.bossac=Serial
arancino_mignon.menu.UploadTool.bossac.upload.tool=bossac
-arancino_mignon.menu.freertos.no=No
-arancino_mignon.menu.freertos.yes=Yes
-arancino_mignon.menu.freertos.no.build.arancino_extra_flags=
-arancino_mignon.menu.freertos.yes.build.arancino_extra_flags=-DUSEFREERTOS
-
arancino_mignon.upload.protocol=sam-ba
arancino_mignon.upload.maximum_size=262144
arancino_mignon.upload.use_1200bps_touch=true
@@ -47,7 +42,7 @@ arancino_mignon.build.usb_product="Arancino Mignon"
arancino_mignon.build.usb_manufacturer="smartme.IO"
arancino_mignon.build.board=SAMD_ZERO
arancino_mignon.build.core=arancino
-arancino_mignon.build.extra_flags=-D__SAMD21G18A__ {build.usb_flags}
+arancino_mignon.build.extra_flags=-D__SAMD21G18A__ {build.usb_flags} -DUSEFREERTOS -DENABLE_CALLOC_REALLOC=1
arancino_mignon.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
arancino_mignon.build.openocdscript=openocd_scripts/arancino.cfg
arancino_mignon.build.variant=arancino
@@ -63,11 +58,6 @@ arancino.name=Arancino
arancino.vid.0=0x04D8
arancino.pid.0=0xECDA
-arancino.menu.freertos.no=No
-arancino.menu.freertos.yes=Yes
-arancino.menu.freertos.no.build.arancino_extra_flags=
-arancino.menu.freertos.yes.build.arancino_extra_flags=-DUSEFREERTOS
-
arancino.upload.tool=ArancinoOTA
arancino.upload.protocol=sam-ba
arancino.upload.maximum_size=262144
@@ -80,7 +70,7 @@ arancino.build.usb_product="Arancino"
arancino.build.usb_manufacturer="smartme.IO"
arancino.build.board=SAMD_ZERO
arancino.build.core=arancino
-arancino.build.extra_flags=-D__SAMD21G18A__ {build.usb_flags}
+arancino.build.extra_flags=-D__SAMD21G18A__ {build.usb_flags} -DUSEFREERTOS -DENABLE_CALLOC_REALLOC=1
arancino.build.ldscript=linker_scripts/gcc/flash_with_bootloader.ld
arancino.build.openocdscript=openocd_scripts/arancino.cfg
arancino.build.variant=arancino
diff --git a/cores/arancino/Arduino.h b/cores/arancino/Arduino.h
index 9165cd8e..c499ff8c 100644
--- a/cores/arancino/Arduino.h
+++ b/cores/arancino/Arduino.h
@@ -135,6 +135,10 @@ void loop( void ) ;
#define ARANCINO_CORE_VERSION "0.0.0"
#endif
+#ifndef MCU_FAMILY
+#define MCU_FAMILY "SAMD21"
+#endif
+
// USB Device
#include "USB/USBDesc.h"
#include "USB/USBCore.h"
diff --git a/cores/arancino/wiring_analog.c b/cores/arancino/wiring_analog.c
index 8655f6ec..5bc8c063 100644
--- a/cores/arancino/wiring_analog.c
+++ b/cores/arancino/wiring_analog.c
@@ -127,6 +127,10 @@ void analogReference(eAnalogReference mode)
uint32_t analogRead(uint32_t pin)
{
+ //noInterrupts();
+ #if defined(USEFREERTOS)
+ noInterrupts();
+ #endif
uint32_t valueRead = 0;
if (pin < A0) {
@@ -182,7 +186,11 @@ uint32_t analogRead(uint32_t pin)
syncADC();
ADC->CTRLA.bit.ENABLE = 0x00; // Disable ADC
syncADC();
-
+
+ #if defined(USEFREERTOS)
+ interrupts();
+ #endif
+ //interrupts();
return mapResolution(valueRead, _ADCResolution, _readResolution);
}
@@ -195,6 +203,9 @@ void analogWrite(uint32_t pin, uint32_t value)
{
PinDescription pinDesc = g_APinDescription[pin];
uint32_t attr = pinDesc.ulPinAttribute;
+ #if defined(USEFREERTOS)
+ noInterrupts();
+ #endif
if ((attr & PIN_ATTR_ANALOG) == PIN_ATTR_ANALOG)
{
@@ -303,6 +314,9 @@ void analogWrite(uint32_t pin, uint32_t value)
syncTCC(TCCx);
}
}
+ #if defined(USEFREERTOS)
+ interrupts();
+ #endif
return;
}
diff --git a/libraries/ElectronicCats_InternalTemperatureZero/.github/workflows/LibraryBuild.yml b/libraries/ElectronicCats_InternalTemperatureZero/.github/workflows/LibraryBuild.yml
new file mode 100644
index 00000000..c3adad2d
--- /dev/null
+++ b/libraries/ElectronicCats_InternalTemperatureZero/.github/workflows/LibraryBuild.yml
@@ -0,0 +1,66 @@
+# LibraryBuild.yml
+# Github workflow script to test compile all examples of an Arduino library repository.
+#
+# Copyright (C) 2020 Armin Joachimsmeyer
+# https://github.com/ArminJo/Github-Actions
+#
+
+# This is the name of the workflow, visible on GitHub UI.
+name: LibraryBuild
+on: [push, pull_request] # see: https://help.github.com/en/actions/reference/events-that-trigger-workflows#pull-request-event-pull_request
+
+jobs:
+ build:
+ name: ${{ matrix.arduino-boards-fqbn }} - test compiling examples
+
+ runs-on: ubuntu-latest # I picked Ubuntu to use shell scripts.
+ env:
+ PLATFORM_DEFAULT_URL: https://adafruit.github.io/arduino-board-index/package_adafruit_index.json
+ strategy:
+ matrix:
+ # The matrix will produce one job for each configuration parameter of type `arduino-boards-fqbn`
+ # In the Arduino IDE, the fqbn is printed in the first line of the verbose output for compilation as parameter -fqbn=... for the "arduino-builder -dump-prefs" command
+ #
+ # Examples: arduino:avr:uno, arduino:avr:leonardo, arduino:avr:nano, arduino:avr:mega
+ # arduino:sam:arduino_due_x, arduino:samd:arduino_zero_native"
+ # ATTinyCore:avr:attinyx5:chip=85,clock=1internal, digistump:avr:digispark-tiny, digistump:avr:digispark-pro
+ # STM32:stm32:GenF1:pnum=BLUEPILL_F103C8
+ # esp8266:esp8266:huzzah:eesz=4M3M,xtal=80, esp32:esp32:featheresp32:FlashFreq=80
+ # You may add a suffix behind the fqbn with "|" to specify one board for e.g. different compile options like arduino:avr:uno|trace
+ #############################################################################################################
+ arduino-boards-fqbn:
+ - arduino:samd:nano_33_iot
+ - arduino:samd:arduino_zero_native
+ - arduino:samd:mkrwan1300
+ - arduino:samd:mkrzero
+ - adafruit:samd:adafruit_itsybitsy_m4
+
+ # Specify parameters for each board.
+ # Parameters can be: platform-url, examples-exclude and examples-build-properties
+ # With examples-exclude you may exclude specific examples for a board. Use a space separated list.
+ #############################################################################################################
+ include:
+ - arduino-boards-fqbn: arduino:samd:nano_33_iot
+ - arduino-boards-fqbn: arduino:samd:arduino_zero_native
+ - arduino-boards-fqbn: arduino:samd:mkrwan1300
+ - arduino-boards-fqbn: arduino:samd:mkrzero
+ - arduino-boards-fqbn: adafruit:samd:adafruit_itsybitsy_m4
+ sketches-exclude: Example4_BasicTemperatureReadingSleep
+
+ # Do not cancel all jobs / architectures if one job fails
+ fail-fast: false
+
+ # This is the list of steps this job will run.
+ steps:
+
+ # First of all, we clone the repo using the `checkout` action.
+ - name: Checkout
+ uses: actions/checkout@master
+
+ - name: Compile all examples
+ uses: ArminJo/arduino-test-compile@v3
+ with:
+ arduino-board-fqbn: ${{ matrix.arduino-boards-fqbn }}
+ platform-default-url: ${{ env.PLATFORM_DEFAULT_URL }}
+ required-libraries: RTCZero
+ sketches-exclude: ${{ matrix.sketches-exclude }}
diff --git a/libraries/ElectronicCats_InternalTemperatureZero/.github/workflows/arduino-lint.yml b/libraries/ElectronicCats_InternalTemperatureZero/.github/workflows/arduino-lint.yml
new file mode 100644
index 00000000..997a112b
--- /dev/null
+++ b/libraries/ElectronicCats_InternalTemperatureZero/.github/workflows/arduino-lint.yml
@@ -0,0 +1,17 @@
+name: arduino-lint
+on: [push, pull_request]
+jobs:
+ lint:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: arduino/arduino-lint-action@v1
+ with:
+ # path: ./
+ version: 1.x
+ compliance: strict
+ library-manager: update
+ project-type: library
+ recursive: true
+ # report-file:
+ verbose: false
diff --git a/libraries/ElectronicCats_InternalTemperatureZero/LICENSE b/libraries/ElectronicCats_InternalTemperatureZero/LICENSE
new file mode 100644
index 00000000..eb66f084
--- /dev/null
+++ b/libraries/ElectronicCats_InternalTemperatureZero/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2020 ElectronicCats
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/libraries/ElectronicCats_InternalTemperatureZero/README.md b/libraries/ElectronicCats_InternalTemperatureZero/README.md
new file mode 100644
index 00000000..92d81f67
--- /dev/null
+++ b/libraries/ElectronicCats_InternalTemperatureZero/README.md
@@ -0,0 +1,37 @@
+# ElectronicCats Internal Temperature Zero
+
+Arduino library for internal temperature of the family SAMD21 and SAMD51
+
+### Quick Installing
+
+To install, use the Arduino Library Manager and search for "Electronic Cats Internal Temperature Zero Library" and install the library.
+
+### Manual Installing
+To install this library:
+
+ - install it using the Arduino Library manager ("Sketch" -> "Include
+ Library" -> "Manage Libraries..."), or
+ - download a zipfile from github using the "Download ZIP" button and
+ install it using the IDE ("Sketch" -> "Include Library" -> "Add .ZIP
+ Library..."
+ - clone this git repository into your sketchbook/libraries folder.
+
+For more info, see https://www.arduino.cc/en/Guide/Libraries
+
+## Features of this version
+
+- Support for SAMD21 and SAMD51
+
+### Maintainer
+
+
+
+
+
+
+Electronic Cats invests time and resources providing this open source design, please support Electronic Cats and open-source hardware by purchasing products from Electronic Cats!
+
+### License
+
+MIT
+
diff --git a/libraries/ElectronicCats_InternalTemperatureZero/examples/Example1_BasicTemperatureReading/Example1_BasicTemperatureReading.ino b/libraries/ElectronicCats_InternalTemperatureZero/examples/Example1_BasicTemperatureReading/Example1_BasicTemperatureReading.ino
new file mode 100644
index 00000000..b7941e42
--- /dev/null
+++ b/libraries/ElectronicCats_InternalTemperatureZero/examples/Example1_BasicTemperatureReading/Example1_BasicTemperatureReading.ino
@@ -0,0 +1,31 @@
+/***************************************************************************
+ This is a library for internal temperature of the family SAMD
+
+ Electronic Cats invests time and resources providing this open source code,
+ please support Electronic Cats and open-source hardware by purchasing products
+ from Electronic Cats!
+
+ Written by Andrés Sabas Electronic Cats.
+ This code is beerware; if you see me (or any other Electronic Cats
+ member) at the local, and you've found our code helpful,
+ please buy us a round!
+ Distributed as-is; no warranty is given.
+ ***************************************************************************/
+
+#include
+
+TemperatureZero TempZero = TemperatureZero();
+
+void setup() {
+ // put your setup code here, to run once:
+ Serial.begin(9600);
+ TempZero.init();
+}
+
+void loop() {
+ // put your main code here, to run repeatedly:
+ float temperature = TempZero.readInternalTemperature();
+ Serial.print("Internal Temperature is : ");
+ Serial.println(temperature);
+ delay(500);
+}
diff --git a/libraries/ElectronicCats_InternalTemperatureZero/examples/Example2_UserCalibration/Example2_UserCalibration.ino b/libraries/ElectronicCats_InternalTemperatureZero/examples/Example2_UserCalibration/Example2_UserCalibration.ino
new file mode 100644
index 00000000..73d90c64
--- /dev/null
+++ b/libraries/ElectronicCats_InternalTemperatureZero/examples/Example2_UserCalibration/Example2_UserCalibration.ino
@@ -0,0 +1,51 @@
+#include
+
+TemperatureZero TempZero = TemperatureZero();
+
+void setup() {
+ // put your setup code here, to run once:
+ Serial.begin(9600);
+ TempZero.init();
+
+ // Correct the output using a 2-point measurement. That is, a measurement at a known cold
+ // and at a known hot temperature. Ideally, at the edges of the range-of-interest.
+ // In order to provide a clear example, we'll setup a case where the sensor mistakenly shifts
+ // down by one degree and halves the temperature:
+ // Real cold temp = 10 degres, TempZero indicates (10 - 1) / 2 = 4.5
+ // Real hot temp = 100 degrees, TempZero indicates (100 - 1) / 2 = 49.5
+ // We would now expect the user correction to double the temperature and shift it up 1 degree
+ TempZero.setUserCalibration2P(10.0, 4.5, 100.0, 49.5, false);
+
+ // As an alternative to the setup of a 2-point calibration measurement,
+ // we could create a table with two temperature columns in a spreadsheet. One column for
+ // a known temperature, from a 'trusted' temperature sensor. and one for the measured
+ // TempZero temperature. Ideally this table would cover the range of interest evenly.
+ // Then, using a spreadsheet program, we could create a 'linear fit' between both columns.
+ // Search for the function LINEST. This fit yields two numbers: A and B. These numbers
+ // are the best values for using the following formula:
+ // = A * + B
+ // These A and B values could be used directly in TempZero as follows:
+ // TempZero.setUserCalibration(A, -B/A);
+}
+
+void loop() {
+ // put your main code here, to run repeatedly:
+
+ Serial.println("\nUser calibration evaluation, expectation T x 2 + 1: ");
+
+ // Below code takes two measurements.
+ // One is displayed without user calibration and the other with it.
+ // Since there are two separate measurements, the measured temperature could vary between measurements.
+ // As the temperature sensor is a bit noisy, this effect means the the user calibration may not seem 100%
+ // accurate all the time. This could be resolved using a higher level of averaging (separate example)
+
+ TempZero.disableUserCalibration();
+ float temp = TempZero.readInternalTemperature();
+ Serial.print("Internal Temperature is : ");
+ Serial.print(temp, 1);
+
+ TempZero.enableUserCalibration();
+ float userTemp = TempZero.readInternalTemperature();
+ Serial.print(", user corrected : ");
+ Serial.println(userTemp, 1);
+}
diff --git a/libraries/ElectronicCats_InternalTemperatureZero/examples/Example3_Averaging/Example3_Averaging.ino b/libraries/ElectronicCats_InternalTemperatureZero/examples/Example3_Averaging/Example3_Averaging.ino
new file mode 100644
index 00000000..e79cc306
--- /dev/null
+++ b/libraries/ElectronicCats_InternalTemperatureZero/examples/Example3_Averaging/Example3_Averaging.ino
@@ -0,0 +1,93 @@
+#include
+
+TemperatureZero TempZero = TemperatureZero();
+
+void setup() {
+ // put your setup code here, to run once:
+ Serial.begin(9600);
+ TempZero.init();
+}
+
+// The internal temperature sensor is a bit noisy. This means that it benefits from
+// taking an average over a number of samples. Per default this is already setup,
+// using 64 samples per measurement. However, this could be changed sing the following
+// call:
+//
+// TempZero.setAveraging(TZ_AVERAGING_256);
+//
+// Let's evaluate the effect of varying the averaging mode from 1 to 256 samples
+// This influences the measurement speed, as well as the variance in the results
+// Below example measures the effectiveness of each averaging mode.
+
+#define NR_AVG_MODES 9
+#define MEASUREMENTS_PER_MODE 100
+
+const char * average_mode_desc[] = {"1 ", "2 ", "4 ", "8 ", "16 ", "32 ", "64 ", "128", "256"};
+
+uint16_t averaging_mode[] = {
+ TZ_AVERAGING_1,
+ TZ_AVERAGING_2,
+ TZ_AVERAGING_4,
+ TZ_AVERAGING_8,
+ TZ_AVERAGING_16,
+ TZ_AVERAGING_32,
+ TZ_AVERAGING_64,
+ TZ_AVERAGING_128,
+ TZ_AVERAGING_256,
+};
+
+struct {
+ uint16_t delay_avg;
+ float temp_min;
+ float temp_max;
+ float temp_avg;
+ float temp_var;
+} stats_avg_mode;
+
+void loop() {
+ // put your main code here, to run repeatedly:
+
+ Serial.print("\nAveraging mode evaluation (");
+ Serial.print(MEASUREMENTS_PER_MODE);
+ Serial.println(" measurements per mode):");
+
+ for (int i=0; i stats_avg_mode.temp_max ? temp : stats_avg_mode.temp_max;
+ stats_avg_mode.temp_min = temp < stats_avg_mode.temp_min ? temp : stats_avg_mode.temp_min;
+ stat_temp_sum += temp;
+ stat_temp_var_Ex += stat_temp_var_shift - temp;
+ stat_temp_var_Ex2 += (stat_temp_var_shift - temp) * (stat_temp_var_shift - temp);
+ }
+ stats_avg_mode.delay_avg = float(stat_time_sum) / MEASUREMENTS_PER_MODE;
+ stats_avg_mode.temp_avg = stat_temp_sum / MEASUREMENTS_PER_MODE;
+ stats_avg_mode.temp_var = (stat_temp_var_Ex2 - (stat_temp_var_Ex * stat_temp_var_Ex)/MEASUREMENTS_PER_MODE)/(MEASUREMENTS_PER_MODE - 1);
+
+ Serial.print("Mode : ");
+ Serial.print(average_mode_desc[i]);
+ Serial.print(" - delay : ");
+ Serial.print(stats_avg_mode.delay_avg);
+ Serial.print(" ms, temp (max-min) / avg / var : ");
+ Serial.print(stats_avg_mode.temp_max - stats_avg_mode.temp_min, 1);
+ Serial.print(" / ");
+ Serial.print(stats_avg_mode.temp_avg, 1);
+ Serial.print(" / ");
+ Serial.println(stats_avg_mode.temp_var, 4);
+ }
+}
diff --git a/libraries/ElectronicCats_InternalTemperatureZero/examples/Example4_BasicTemperatureReadingSleep/Example4_BasicTemperatureReadingSleep.ino b/libraries/ElectronicCats_InternalTemperatureZero/examples/Example4_BasicTemperatureReadingSleep/Example4_BasicTemperatureReadingSleep.ino
new file mode 100644
index 00000000..f2d14b58
--- /dev/null
+++ b/libraries/ElectronicCats_InternalTemperatureZero/examples/Example4_BasicTemperatureReadingSleep/Example4_BasicTemperatureReadingSleep.ino
@@ -0,0 +1,42 @@
+#include
+#include
+
+TemperatureZero TempZero = TemperatureZero();
+RTCZero rtc;
+
+void setup() {
+ // put your setup code here, to run once:
+
+ pinMode(LED_BUILTIN, OUTPUT);
+ digitalWrite(LED_BUILTIN, HIGH);
+
+ Serial.begin(115200);
+
+ rtc.begin();
+ rtc.setTime(0, 0, 0);
+ rtc.setDate(1, 1, 20);
+ rtc.setAlarmTime(00, 00, 00);
+ rtc.enableAlarm(rtc.MATCH_SS); // Raise alarm every minute
+
+ delay(5000); //Delay for programming before sleep
+}
+
+void loop() {
+ // put your main code here, to run repeatedly:
+ digitalWrite(LED_BUILTIN, HIGH);
+
+ TempZero.init();
+ delay(500);
+ printTemp();
+ delay(500);
+ TempZero.disable(); //saves ~60uA in standby
+
+ digitalWrite(LED_BUILTIN, LOW);
+ rtc.standbyMode(); // Sleep until next alarm match
+}
+
+void printTemp() {
+ float temperature = TempZero.readInternalTemperature();
+ Serial.print("Internal Temperature is : ");
+ Serial.println(temperature);
+}
diff --git a/libraries/ElectronicCats_InternalTemperatureZero/keywords.txt b/libraries/ElectronicCats_InternalTemperatureZero/keywords.txt
new file mode 100644
index 00000000..8ee85513
--- /dev/null
+++ b/libraries/ElectronicCats_InternalTemperatureZero/keywords.txt
@@ -0,0 +1,33 @@
+#######################################
+# Syntax Coloring Map For Test
+#######################################
+
+#######################################
+# Datatypes (KEYWORD1)
+#######################################
+
+TemperatureZero KEYWORD1
+
+#######################################
+# Methods and Functions (KEYWORD2)
+#######################################
+
+init KEYWORD2
+readInternalTemperature KEYWORD2
+wakeup KEYWORD2
+disable KEYWORD2
+setAveraging KEYWORD2
+setUserCalibration2P KEYWORD2
+setUserCalibration KEYWORD2
+enableUserCalibration KEYWORD2
+disableUserCalibration KEYWORD2
+readInternalTemperatureRaw KEYWORD2
+raw2temp KEYWORD2
+readInternalTemperature KEYWORD2
+enableDebugging KEYWORD2
+disableDebugging KEYWORD2
+
+#######################################
+# Constants (LITERAL1)
+#######################################
+
diff --git a/libraries/ElectronicCats_InternalTemperatureZero/library.properties b/libraries/ElectronicCats_InternalTemperatureZero/library.properties
new file mode 100644
index 00000000..857e09c4
--- /dev/null
+++ b/libraries/ElectronicCats_InternalTemperatureZero/library.properties
@@ -0,0 +1,9 @@
+name=TemperatureZero
+version=1.2.0
+author=Electronic Cats
+maintainer=Electronic Cats
+sentence=Arduino library for internal temperature of the family SAMD21 and SAM51
+paragraph=Arduino library for internal temperature of the family SAMD21 and SAMD51
+category=Device Control
+url=https://github.com/ElectronicCats/ElectronicCats_InternalTemperatureZero
+architectures=samd
diff --git a/libraries/ElectronicCats_InternalTemperatureZero/src/TemperatureZero.cpp b/libraries/ElectronicCats_InternalTemperatureZero/src/TemperatureZero.cpp
new file mode 100755
index 00000000..330939bf
--- /dev/null
+++ b/libraries/ElectronicCats_InternalTemperatureZero/src/TemperatureZero.cpp
@@ -0,0 +1,420 @@
+/*
+ TemperatureZero.h - Arduino library for internal temperature of the family SAMD21 and SAMD51 -
+ Copyright (c) 2018 Electronic Cats. All right reserved.
+ Based in the work of Mitchell Pontague https://github.com/arduino/ArduinoCore-samd/pull/277
+ Based in the work of @manitou48 for SAMD51 https://github.com/manitou48/samd51/blob/master/m4temp.ino
+ and CircuitPython https://github.com/adafruit/circuitpython/blob/master/ports/atmel-samd/common-hal/microcontroller/Processor.c
+ Thanks!
+*/
+
+#include "Arduino.h"
+#include "TemperatureZero.h"
+
+#ifdef __SAMD51__ // M4
+// m4 SAMD51 chip temperature sensor on ADC
+// Decimal to fraction conversion. (adapted from ASF sample).
+//#define NVMCTRL_TEMP_LOG (0x00800100) // ref pg 59
+#define NVMCTRL_TEMP_LOG NVMCTRL_TEMP_LOG_W0
+
+static float convert_dec_to_frac(uint8_t val) {
+ float float_val = (float)val;
+ if (val < 10) {
+ return (float_val / 10.0);
+ } else if (val < 100) {
+ return (float_val / 100.0);
+ } else {
+ return (float_val / 1000.0);
+ }
+}
+#endif
+
+#ifdef _SAMD21_ // M0
+// Convert raw 12 bit adc reading into temperature float.
+// uses factory calibration data and, only when set and enabled, user calibration data
+float TemperatureZero::raw2temp (uint16_t adcReading) {
+ // Get course temperature first, in order to estimate the internal 1V reference voltage level at this temperature
+ float meaurementVoltage = ((float)adcReading)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
+ float coarse_temp = _roomTemperature + (((_hotTemperature - _roomTemperature)/(_hotVoltageCompensated - _roomVoltageCompensated)) * (meaurementVoltage - _roomVoltageCompensated));
+ // Estimate the reference voltage using the course temperature
+ float ref1VAtMeasurement = _roomInt1vRef + (((_hotInt1vRef - _roomInt1vRef) * (coarse_temp - _roomTemperature))/(_hotTemperature - _roomTemperature));
+ // Now first compensate the raw adc reading using the estimation of the 1V reference output at current temperature
+ float measureVoltageCompensated = ((float)adcReading * ref1VAtMeasurement)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
+ // Repeat the temperature interpolation using the compensated measurement voltage
+ float refinedTemp = _roomTemperature + (((_hotTemperature - _roomTemperature)/(_hotVoltageCompensated - _roomVoltageCompensated)) * (measureVoltageCompensated - _roomVoltageCompensated));
+ float result = refinedTemp;
+ if (_isUserCalEnabled) {
+ result = (refinedTemp - _userCalOffsetCorrection) * _userCalGainCorrection;
+ }
+ #ifdef TZ_WITH_DEBUG_CODE
+ if (_debug) {
+ _debugSerial->println(F("\n+++ Temperature calculation:"));
+ _debugSerial->print(F("raw adc reading : "));
+ _debugSerial->println(adcReading);
+ _debugSerial->print(F("Course temperature : "));
+ _debugSerial->println(coarse_temp, 1);
+ _debugSerial->print(F("Estimated 1V ref @Course temperature : "));
+ _debugSerial->println(ref1VAtMeasurement, 4);
+ _debugSerial->print(F("Temperature compensated measurement voltage : "));
+ _debugSerial->println(measureVoltageCompensated, 4);
+ _debugSerial->print(F("Refined temperature : "));
+ _debugSerial->println(refinedTemp, 1);
+ _debugSerial->print(F("User calibration post processing is : "));
+ if (_isUserCalEnabled) {
+ _debugSerial->println(F("Enabled"));
+ _debugSerial->print(F("User calibration offset correction : "));
+ _debugSerial->println(_userCalOffsetCorrection, 4);
+ _debugSerial->print(F("User calibration gain correction : "));
+ _debugSerial->println(_userCalGainCorrection, 4);
+ _debugSerial->print(F("User calibration corrected temperature = "));
+ _debugSerial->println(result, 2);
+ } else {
+ _debugSerial->println(F("Disabled"));
+ }
+ }
+#endif
+ return result;
+}
+#endif
+
+#ifdef __SAMD51__ // M4
+float TemperatureZero::raw2temp(uint16_t TP, uint16_t TC) {
+ uint32_t TLI = (*(uint32_t *)FUSES_ROOM_TEMP_VAL_INT_ADDR & FUSES_ROOM_TEMP_VAL_INT_Msk) >> FUSES_ROOM_TEMP_VAL_INT_Pos;
+ uint32_t TLD = (*(uint32_t *)FUSES_ROOM_TEMP_VAL_DEC_ADDR & FUSES_ROOM_TEMP_VAL_DEC_Msk) >> FUSES_ROOM_TEMP_VAL_DEC_Pos;
+ float TL = TLI + convert_dec_to_frac(TLD);
+
+ uint32_t THI = (*(uint32_t *)FUSES_HOT_TEMP_VAL_INT_ADDR & FUSES_HOT_TEMP_VAL_INT_Msk) >> FUSES_HOT_TEMP_VAL_INT_Pos;
+ uint32_t THD = (*(uint32_t *)FUSES_HOT_TEMP_VAL_DEC_ADDR & FUSES_HOT_TEMP_VAL_DEC_Msk) >> FUSES_HOT_TEMP_VAL_DEC_Pos;
+ float TH = THI + convert_dec_to_frac(THD);
+
+ uint16_t VPL = (*(uint32_t *)FUSES_ROOM_ADC_VAL_PTAT_ADDR & FUSES_ROOM_ADC_VAL_PTAT_Msk) >> FUSES_ROOM_ADC_VAL_PTAT_Pos;
+ uint16_t VPH = (*(uint32_t *)FUSES_HOT_ADC_VAL_PTAT_ADDR & FUSES_HOT_ADC_VAL_PTAT_Msk) >> FUSES_HOT_ADC_VAL_PTAT_Pos;
+
+ uint16_t VCL = (*(uint32_t *)FUSES_ROOM_ADC_VAL_CTAT_ADDR & FUSES_ROOM_ADC_VAL_CTAT_Msk) >> FUSES_ROOM_ADC_VAL_CTAT_Pos;
+ uint16_t VCH = (*(uint32_t *)FUSES_HOT_ADC_VAL_CTAT_ADDR & FUSES_HOT_ADC_VAL_CTAT_Msk) >> FUSES_HOT_ADC_VAL_CTAT_Pos;
+
+ // From SAMD51 datasheet: section 45.6.3.1 (page 1327).
+ return (TL*VPH*TC - VPL*TH*TC - TL*VCH*TP + TH*VCL*TP) / (VCL*TP - VCH*TP - VPL*TC + VPH*TC);
+}
+#endif
+
+TemperatureZero::TemperatureZero() {
+}
+
+void TemperatureZero::init() {
+#ifdef TZ_WITH_DEBUG_CODE
+ _debug = false;
+#endif
+ _averaging = TZ_AVERAGING_64; // on 48Mhz takes approx 26 ms
+ _isUserCalEnabled = false;
+ getFactoryCalibration();
+ wakeup();
+}
+
+
+// After sleeping, the temperature sensor seems disabled. So, let's re-enable it.
+void TemperatureZero::wakeup() {
+ #ifdef _SAMD21_
+ SYSCTRL->VREF.reg |= SYSCTRL_VREF_TSEN; // Enable the temperature sensor
+ while( ADC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains
+ #endif
+ #ifdef __SAMD51__
+ SUPC->VREF.reg |= SUPC_VREF_TSEN | SUPC_VREF_ONDEMAND; // Enable the temperature sensor
+ while( ADC0->SYNCBUSY.reg == 1 ); // Wait for synchronization of registers between the clock domains
+ #endif
+}
+
+
+
+void TemperatureZero::disable() {
+ #ifdef _SAMD21_
+ SYSCTRL->VREF.reg &= ~SYSCTRL_VREF_TSEN; // Disable the temperature sensor
+ while( ADC->STATUS.bit.SYNCBUSY == 1 ); // Wait for synchronization of registers between the clock domains
+ #endif
+ #ifdef __SAMD51__
+ SUPC->VREF.reg &= ~SUPC_VREF_TSEN | SUPC_VREF_ONDEMAND; // Disable the temperature sensor
+ while( ADC0->SYNCBUSY.reg == 1 ); // Wait for synchronization of registers between the clock domains
+ #endif
+}
+
+
+// Set the sample averaging as the internal sensor is somewhat noisy
+// Default value is TZ_AVERAGING_64 which takes approx 26 ms at 48 Mhz clock
+void TemperatureZero::setAveraging(uint8_t averaging) {
+ _averaging = averaging;
+}
+
+// Reads temperature using internal ADC channel
+// Datasheet chapter 37.10.8 - Temperature Sensor Characteristics
+float TemperatureZero::readInternalTemperature() {
+ #ifdef _SAMD21_ // M0
+ uint16_t adcReading = readInternalTemperatureRaw();
+ return raw2temp(adcReading);
+ #endif
+ #ifdef __SAMD51__ // M4
+ return readInternalTemperatureRaw();
+ #endif
+}
+
+#ifdef TZ_WITH_DEBUG_CODE
+// To follow along, the detailed temperature calculation, enable library debugging
+void TemperatureZero::enableDebugging(Stream &debugPort) {
+ _debugSerial = &debugPort;
+ _debug = true;
+}
+
+// Disable library debugging
+void TemperatureZero::disableDebugging(void) {
+ _debug = false;
+}
+#endif
+
+
+// Get all factory calibration parameters and process them
+// This includes both the temperature sensor calibration as well as the 1v reference calibration
+void TemperatureZero::getFactoryCalibration() {
+ #ifdef _SAMD21_ // M0
+ // Factory room temperature readings
+ uint8_t roomInteger = (*(uint32_t*)FUSES_ROOM_TEMP_VAL_INT_ADDR & FUSES_ROOM_TEMP_VAL_INT_Msk) >> FUSES_ROOM_TEMP_VAL_INT_Pos;
+ uint8_t roomDecimal = (*(uint32_t*)FUSES_ROOM_TEMP_VAL_DEC_ADDR & FUSES_ROOM_TEMP_VAL_DEC_Msk) >> FUSES_ROOM_TEMP_VAL_DEC_Pos;
+ _roomTemperature = roomInteger + convertDecToFrac(roomDecimal);
+ _roomReading = ((*(uint32_t*)FUSES_ROOM_ADC_VAL_ADDR & FUSES_ROOM_ADC_VAL_Msk) >> FUSES_ROOM_ADC_VAL_Pos);
+ // Factory hot temperature readings
+ uint8_t hotInteger = (*(uint32_t*)FUSES_HOT_TEMP_VAL_INT_ADDR & FUSES_HOT_TEMP_VAL_INT_Msk) >> FUSES_HOT_TEMP_VAL_INT_Pos;
+ uint8_t hotDecimal = (*(uint32_t*)FUSES_HOT_TEMP_VAL_DEC_ADDR & FUSES_HOT_TEMP_VAL_DEC_Msk) >> FUSES_HOT_TEMP_VAL_DEC_Pos;
+ _hotTemperature = hotInteger + convertDecToFrac(hotDecimal);
+ _hotReading = ((*(uint32_t*)FUSES_HOT_ADC_VAL_ADDR & FUSES_HOT_ADC_VAL_Msk) >> FUSES_HOT_ADC_VAL_Pos);
+ // Factory internal 1V voltage reference readings at both room and hot temperatures
+ int8_t roomInt1vRefRaw = (int8_t)((*(uint32_t*)FUSES_ROOM_INT1V_VAL_ADDR & FUSES_ROOM_INT1V_VAL_Msk) >> FUSES_ROOM_INT1V_VAL_Pos);
+ int8_t hotInt1vRefRaw = (int8_t)((*(uint32_t*)FUSES_HOT_INT1V_VAL_ADDR & FUSES_HOT_INT1V_VAL_Msk) >> FUSES_HOT_INT1V_VAL_Pos);
+ _roomInt1vRef = 1 - ((float)roomInt1vRefRaw/INT1V_DIVIDER_1000);
+ _hotInt1vRef = 1 - ((float)hotInt1vRefRaw/INT1V_DIVIDER_1000);
+ // Combining the temperature dependent 1v reference with the ADC readings
+ _roomVoltageCompensated = ((float)_roomReading * _roomInt1vRef)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
+ _hotVoltageCompensated = ((float)_hotReading * _hotInt1vRef)/ADC_12BIT_FULL_SCALE_VALUE_FLOAT;
+ #endif
+ #ifdef __SAMD51__
+ uint32_t TLI = (*(uint32_t *)FUSES_ROOM_TEMP_VAL_INT_ADDR & FUSES_ROOM_TEMP_VAL_INT_Msk) >> FUSES_ROOM_TEMP_VAL_INT_Pos;
+ uint32_t TLD = (*(uint32_t *)FUSES_ROOM_TEMP_VAL_DEC_ADDR & FUSES_ROOM_TEMP_VAL_DEC_Msk) >> FUSES_ROOM_TEMP_VAL_DEC_Pos;
+ float TL = TLI + convert_dec_to_frac(TLD);
+
+ uint32_t THI = (*(uint32_t *)FUSES_HOT_TEMP_VAL_INT_ADDR & FUSES_HOT_TEMP_VAL_INT_Msk) >> FUSES_HOT_TEMP_VAL_INT_Pos;
+ uint32_t THD = (*(uint32_t *)FUSES_HOT_TEMP_VAL_DEC_ADDR & FUSES_HOT_TEMP_VAL_DEC_Msk) >> FUSES_HOT_TEMP_VAL_DEC_Pos;
+ float TH = THI + convert_dec_to_frac(THD);
+
+ uint16_t VPL = (*(uint32_t *)FUSES_ROOM_ADC_VAL_PTAT_ADDR & FUSES_ROOM_ADC_VAL_PTAT_Msk) >> FUSES_ROOM_ADC_VAL_PTAT_Pos;
+ uint16_t VPH = (*(uint32_t *)FUSES_HOT_ADC_VAL_PTAT_ADDR & FUSES_HOT_ADC_VAL_PTAT_Msk) >> FUSES_HOT_ADC_VAL_PTAT_Pos;
+ uint16_t VCL = (*(uint32_t *)FUSES_ROOM_ADC_VAL_CTAT_ADDR & FUSES_ROOM_ADC_VAL_CTAT_Msk) >> FUSES_ROOM_ADC_VAL_CTAT_Pos;
+ uint16_t VCH = (*(uint32_t *)FUSES_HOT_ADC_VAL_CTAT_ADDR & FUSES_HOT_ADC_VAL_CTAT_Msk) >> FUSES_HOT_ADC_VAL_CTAT_Pos;
+
+ #endif
+#ifdef TZ_WITH_DEBUG_CODE
+ if (_debug) {
+ _debugSerial->println(F("\n+++ Factory calibration parameters:"));
+ _debugSerial->print(F("Room Temperature : "));
+ _debugSerial->println(_roomTemperature, 1);
+ _debugSerial->print(F("Hot Temperature : "));
+ _debugSerial->println(_hotTemperature, 1);
+ _debugSerial->print(F("Room Reading : "));
+ _debugSerial->println(_roomReading);
+ _debugSerial->print(F("Hot Reading : "));
+ _debugSerial->println(_hotReading);
+ _debugSerial->print(F("Room Voltage ref raw / interpreted : "));
+ _debugSerial->print(roomInt1vRefRaw);
+ _debugSerial->print(F(" / "));
+ _debugSerial->println(_roomInt1vRef, 4);
+ _debugSerial->print(F("Hot Voltage ref raw / interpreted : "));
+ _debugSerial->print(hotInt1vRefRaw);
+ _debugSerial->print(F(" / "));
+ _debugSerial->println(_hotInt1vRef, 4);
+ _debugSerial->print(F("Room Reading compensated : "));
+ _debugSerial->println(_roomVoltageCompensated, 4);
+ _debugSerial->print(F("Hot Reading compensated : "));
+ _debugSerial->println(_hotVoltageCompensated, 4);
+ }
+#endif
+}
+
+
+// Extra safe decimal to fractional conversion
+float TemperatureZero::convertDecToFrac(uint8_t val) {
+ if (val < 10) {
+ return ((float)val/10.0);
+ } else if (val <100) {
+ return ((float)val/100.0);
+ } else {
+ return ((float)val/1000.0);
+ }
+}
+
+// Set user calibration params, using two point linear interpolation for hot and cold measurements
+void TemperatureZero::setUserCalibration2P(float userCalColdGroundTruth,
+ float userCalColdMeasurement,
+ float userCalHotGroundTruth,
+ float userCalHotMeasurement,
+ bool isEnabled) {
+ _userCalOffsetCorrection = userCalColdMeasurement - userCalColdGroundTruth * (userCalHotMeasurement - userCalColdMeasurement) / (userCalHotGroundTruth - userCalColdGroundTruth);
+ _userCalGainCorrection = userCalHotGroundTruth / (userCalHotMeasurement - _userCalOffsetCorrection);
+ _isUserCalEnabled = isEnabled;
+}
+
+// Set user calibration params explixitly
+void TemperatureZero::setUserCalibration(float userCalGainCorrection,
+ float userCalOffsetCorrection,
+ bool isEnabled) {
+ _userCalOffsetCorrection = userCalOffsetCorrection;
+ _userCalGainCorrection = userCalGainCorrection;
+ _isUserCalEnabled = isEnabled;
+}
+
+void TemperatureZero::enableUserCalibration() {
+ _isUserCalEnabled = true;
+}
+
+void TemperatureZero::disableUserCalibration() {
+ _isUserCalEnabled = false;
+}
+
+// Get raw 12 bit adc reading
+uint16_t TemperatureZero::readInternalTemperatureRaw() {
+
+#ifdef _SAMD21_ // M0
+ // Save ADC settings
+ uint16_t oldReadResolution = ADC->CTRLB.reg;
+ uint16_t oldSampling = ADC->SAMPCTRL.reg;
+ uint16_t oldSampleAveraging = ADC->SAMPCTRL.reg;
+ uint16_t oldReferenceGain = ADC->INPUTCTRL.bit.GAIN;
+ uint16_t oldReferenceSelect = ADC->REFCTRL.bit.REFSEL;
+
+ // Set to 12 bits resolution
+ ADC->CTRLB.reg = ADC_CTRLB_RESSEL_12BIT | ADC_CTRLB_PRESCALER_DIV256;
+ // Wait for synchronization of registers between the clock domains
+ while (ADC->STATUS.bit.SYNCBUSY == 1);
+ // Ensure we are sampling slowly
+ ADC->SAMPCTRL.reg = ADC_SAMPCTRL_SAMPLEN(0x3f);
+ while (ADC->STATUS.bit.SYNCBUSY == 1);
+ // Set ADC reference to internal 1v
+ ADC->INPUTCTRL.bit.GAIN = ADC_INPUTCTRL_GAIN_1X_Val;
+ ADC->REFCTRL.bit.REFSEL = ADC_REFCTRL_REFSEL_INT1V_Val;
+ while (ADC->STATUS.bit.SYNCBUSY == 1);
+ // Select MUXPOS as temperature channel, and MUXNEG as internal ground
+ ADC->INPUTCTRL.bit.MUXPOS = ADC_INPUTCTRL_MUXPOS_TEMP_Val;
+ ADC->INPUTCTRL.bit.MUXNEG = ADC_INPUTCTRL_MUXNEG_GND_Val;
+ while (ADC->STATUS.bit.SYNCBUSY == 1);
+ // Enable ADC
+ ADC->CTRLA.bit.ENABLE = 1;
+ while (ADC->STATUS.bit.SYNCBUSY == 1);
+ // Start ADC conversion & discard the first sample
+ ADC->SWTRIG.bit.START = 1;
+ // Wait until ADC conversion is done, prevents the unexpected offset bug
+ while (!(ADC->INTFLAG.bit.RESRDY));
+ // Clear the Data Ready flag
+ ADC->INTFLAG.reg = ADC_INTFLAG_RESRDY;
+ // perform averaging
+ switch(_averaging) {
+ case TZ_AVERAGING_1:
+ ADC->AVGCTRL.reg = 0;
+ break;
+ case TZ_AVERAGING_2:
+ ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_2 | ADC_AVGCTRL_ADJRES(0x1);
+ break;
+ case TZ_AVERAGING_4:
+ ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_4 | ADC_AVGCTRL_ADJRES(0x2);
+ break;
+ case TZ_AVERAGING_8:
+ ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_8 | ADC_AVGCTRL_ADJRES(0x3);
+ break;
+ case TZ_AVERAGING_16:
+ ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_16 | ADC_AVGCTRL_ADJRES(0x4);
+ break;
+ case TZ_AVERAGING_32:
+ ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_32 | ADC_AVGCTRL_ADJRES(0x4);
+ break;
+ case TZ_AVERAGING_64:
+ ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_64 | ADC_AVGCTRL_ADJRES(0x4);
+ break;
+ case TZ_AVERAGING_128:
+ ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_128 | ADC_AVGCTRL_ADJRES(0x4);
+ break;
+ case TZ_AVERAGING_256:
+ ADC->AVGCTRL.reg = ADC_AVGCTRL_SAMPLENUM_256 | ADC_AVGCTRL_ADJRES(0x4);
+ break;
+ }
+ while (ADC->STATUS.bit.SYNCBUSY == 1);
+ // Start conversion again, since The first conversion after the reference is changed must not be used.
+ ADC->SWTRIG.bit.START = 1;
+ // Wait until ADC conversion is done
+ while (!(ADC->INTFLAG.bit.RESRDY));
+ while (ADC->STATUS.bit.SYNCBUSY == 1);
+ // Get result
+ uint16_t adcReading = ADC->RESULT.reg;
+ // Clear result ready flag
+ ADC->INTFLAG.reg = ADC_INTFLAG_RESRDY;
+ while (ADC->STATUS.bit.SYNCBUSY == 1);
+ // Disable ADC
+ ADC->CTRLA.bit.ENABLE = 0;
+ while (ADC->STATUS.bit.SYNCBUSY == 1);
+ // Restore pervious ADC settings
+ ADC->CTRLB.reg = oldReadResolution;
+ while (ADC->STATUS.bit.SYNCBUSY == 1);
+ ADC->SAMPCTRL.reg = oldSampling;
+ ADC->SAMPCTRL.reg = oldSampleAveraging;
+ while (ADC->STATUS.bit.SYNCBUSY == 1);
+ ADC->INPUTCTRL.bit.GAIN = oldReferenceGain;
+ ADC->REFCTRL.bit.REFSEL = oldReferenceSelect;
+ while (ADC->STATUS.bit.SYNCBUSY == 1);
+
+ return adcReading;
+ #endif
+
+ #ifdef __SAMD51__ // M4
+ // enable and read 2 ADC temp sensors, 12-bit res
+ volatile uint16_t ptat;
+ volatile uint16_t ctat;
+
+ SUPC->VREF.reg |= SUPC_VREF_TSEN | SUPC_VREF_ONDEMAND; // activate temperature sensor
+ ADC0->CTRLB.bit.RESSEL = ADC_CTRLB_RESSEL_12BIT_Val;
+ while (ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_CTRLB); //wait for sync
+ while ( ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_INPUTCTRL ); //wait for sync
+ ADC0->INPUTCTRL.bit.MUXPOS = ADC_INPUTCTRL_MUXPOS_PTAT;
+ while ( ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_ENABLE ); //wait for sync
+ ADC0->CTRLA.bit.ENABLE = 0x01; // Enable ADC
+
+ // Start conversion
+ while ( ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_ENABLE ); //wait for sync
+
+ ADC0->SWTRIG.bit.START = 1;
+
+ // Clear the Data Ready flag
+ ADC0->INTFLAG.reg = ADC_INTFLAG_RESRDY;
+
+ // Start conversion again, since The first conversion after the reference is changed must not be used.
+ ADC0->SWTRIG.bit.START = 1;
+
+ while (ADC0->INTFLAG.bit.RESRDY == 0); // Waiting for conversion to complete
+ ptat = ADC0->RESULT.reg;
+
+ while ( ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_INPUTCTRL ); //wait for sync
+ ADC0->INPUTCTRL.bit.MUXPOS = ADC_INPUTCTRL_MUXPOS_CTAT;
+ // Start conversion
+ while ( ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_ENABLE ); //wait for sync
+
+ ADC0->SWTRIG.bit.START = 1;
+
+ // Clear the Data Ready flag
+ ADC0->INTFLAG.reg = ADC_INTFLAG_RESRDY;
+
+ // Start conversion again, since The first conversion after the reference is changed must not be used.
+ ADC0->SWTRIG.bit.START = 1;
+
+ while (ADC0->INTFLAG.bit.RESRDY == 0); // Waiting for conversion to complete
+ ctat = ADC0->RESULT.reg;
+
+
+ while ( ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_ENABLE ); //wait for sync
+ ADC0->CTRLA.bit.ENABLE = 0x00; // Disable ADC
+ while ( ADC0->SYNCBUSY.reg & ADC_SYNCBUSY_ENABLE ); //wait for sync
+
+ return raw2temp(ptat, ctat);
+
+ #endif
+}
\ No newline at end of file
diff --git a/libraries/ElectronicCats_InternalTemperatureZero/src/TemperatureZero.h b/libraries/ElectronicCats_InternalTemperatureZero/src/TemperatureZero.h
new file mode 100755
index 00000000..b9b04815
--- /dev/null
+++ b/libraries/ElectronicCats_InternalTemperatureZero/src/TemperatureZero.h
@@ -0,0 +1,93 @@
+/*
+ TemperatureZero.h - Arduino library for internal temperature of the family SAMD21 and SAMD51 -
+ Copyright (c) 2018 Electronic Cats. All right reserved.
+ Based in the work of Mitchell Pontague https://github.com/arduino/ArduinoCore-samd/pull/277
+ Based in the work of @manitou48 for SAMD51 https://github.com/manitou48/samd51/blob/master/m4temp.ino
+ and CircuitPython https://github.com/adafruit/circuitpython/blob/master/ports/atmel-samd/common-hal/microcontroller/Processor.c
+ Thanks!
+*/
+
+#ifndef TEMPERATUREZERO_h
+#define TEMPERATUREZERO_h
+
+#define TZ_AVERAGING_1 0
+#define TZ_AVERAGING_2 1
+#define TZ_AVERAGING_4 2
+#define TZ_AVERAGING_8 3
+#define TZ_AVERAGING_16 4
+#define TZ_AVERAGING_32 5
+#define TZ_AVERAGING_64 6
+#define TZ_AVERAGING_128 7
+#define TZ_AVERAGING_256 8
+
+#define INT1V_DIVIDER_1000 1000.0
+#define ADC_12BIT_FULL_SCALE_VALUE_FLOAT 4095.0
+
+class TemperatureZero
+{
+ public:
+ TemperatureZero();
+ void init();
+ void wakeup();
+ void disable();
+ void setAveraging(uint8_t averaging);
+ void setUserCalibration2P(float userCalColdGroundTruth,
+ float userCalColdMeasurement,
+ float userCalHotGroundTruth,
+ float userCalHotMeasurement,
+ bool isEnabled);
+ void setUserCalibration(float userCalGainCorrection,
+ float userCalOffsetCorrection,
+ bool isEnabled);
+ void enableUserCalibration();
+ void disableUserCalibration();
+ uint16_t readInternalTemperatureRaw();
+#ifdef _SAMD21_
+ float raw2temp (uint16_t adcReading);
+#endif
+#ifdef __SAMD51__
+ float raw2temp(uint16_t TP, uint16_t TC);
+#endif
+ float readInternalTemperature();
+#ifdef TZ_WITH_DEBUG_CODE
+ void enableDebugging(Stream &debugPort);
+ void disableDebugging(void);
+#endif
+
+ private:
+#ifdef TZ_WITH_DEBUG_CODE
+ bool _debug;
+ Stream * _debugSerial;
+#endif
+ uint8_t _averaging;
+
+ float _roomTemperature;
+ uint16_t _roomReading;
+ float _hotTemperature;
+ uint16_t _hotReading;
+ float _roomInt1vRef;
+ float _hotInt1vRef;
+ float _roomVoltageCompensated;
+ float _hotVoltageCompensated;
+
+ uint32_t TLI;
+ uint32_t TLD;
+ float TL;
+ uint32_t THI;
+ uint32_t THD;
+ float TH;
+ uint16_t VPL;
+ uint16_t VPH;
+ uint16_t VCL;
+ uint16_t VCH;
+
+ bool _isUserCalEnabled;
+ float _userCalGainCorrection;
+ float _userCalOffsetCorrection;
+
+ void getFactoryCalibration();
+ float convertDecToFrac(uint8_t);
+};
+
+#endif
+
diff --git a/package.json b/package.json
index 78ba9d5f..b8cb9149 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "framework-arduino-samd-arancino",
- "version": "1.2.1",
+ "version": "1.3.0",
"description": "The official SmartME Wiring-based Framework for Microchip SAM D microcontrollers",
"keywords": [
"framework",
diff --git a/platform.txt b/platform.txt
index c07fe09a..d301b525 100644
--- a/platform.txt
+++ b/platform.txt
@@ -19,8 +19,8 @@
# For more info:
# https://github.com/arduino/Arduino/wiki/Arduino-IDE-1.5---3rd-party-Hardware-specification
-name=Arancino Boards
-version=1.2.0
+name=Arancino SAMD Boards
+version=1.3.0
# Compile variables
# -----------------
@@ -87,13 +87,13 @@ build.usb_manufacturer="Unknown"
# ----------------
## 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} {build.arancino_extra_flags} {compiler.arm.cmsis.c.flags} {includes} "{source_file}" -o "{object_file}"
+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.c.flags} {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} {build.arancino_extra_flags} {compiler.arm.cmsis.c.flags} {includes} "{source_file}" -o "{object_file}"
+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.c.flags} {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} {build.arancino_extra_flags} {compiler.arm.cmsis.c.flags} {includes} "{source_file}" -o "{object_file}"
+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.c.flags} {includes} "{source_file}" -o "{object_file}"
## Create archives
# archive_file_path is needed for backwards compatibility with IDE 1.6.5 or older, IDE 1.6.6 or newer overrides this value