//***************Arduino Sketch from the video*********************.
//This code was used for a tutorial on the ForceTronics YouTube channel. It shows how to save power
//by putting Arduino's based on the SAMD21 MCU (MKR1000, Zero, etc) to sleep and how to wake them
//This code is public domain for anybody to use or modify
//#include "RTCZero.h"
#include <RTCZero.h>
/* Create an rtc object */
RTCZero rtc;
/* Change these values to set the current initial time */
const byte seconds = 0;
const byte minutes = 00;
const byte hours = 00;
/* Change these values to set the current initial date */
const byte day = 24;
const byte month = 9;
const byte year = 16;
void setup()
{
delay(5000); //delay so we can see normal current draw
pinMode(LED_BUILTIN, OUTPUT); //set LED pin to output
digitalWrite(LED_BUILTIN, LOW); //turn LED off
rtc.begin(); //Start RTC library, this is where the clock source is initialized
rtc.setTime(hours, minutes, seconds); //set time
rtc.setDate(day, month, year); //set date
rtc.setAlarmTime(00, 00, 10); //set alarm time to go off in 10 seconds
//following two lines enable alarm, comment both out if you want to do external interrupt
rtc.enableAlarm(rtc.MATCH_HHMMSS); //set alarm
rtc.attachInterrupt(ISR); //creates an interrupt that wakes the SAMD21 which is triggered by a FTC alarm
//comment out the below line if you are using RTC alarm for interrupt
// extInterrupt(A1); //creates an interrupt source on external pin
//puts SAMD21 to sleep
rtc.standbyMode(); //library call
//samSleep(); //function to show how call works
}
void loop()
{
//do nothing in main loop
}
//interrupt service routine (ISR), called when interrupt is triggered
//executes after MCU wakes up
void ISR()
{
digitalWrite(LED_BUILTIN, HIGH);
}
//function that sets up external interrupt
void extInterrupt(int interruptPin) {
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(interruptPin, ISR, LOW);
}
//function to show how to put the
void samSleep()
{
// Set the sleep mode to standby
SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;
// SAMD sleep
__WFI();
}
//**********************Changed "begin" function from RTCZero Library**************
void RTCZero::begin(bool resetTime)
{
uint16_t tmp_reg = 0;
PM->APBAMASK.reg |= PM_APBAMASK_RTC; // turn on digital interface clock
//config32kOSC();
// If the RTC is in clock mode and the reset was
// not due to POR or BOD, preserve the clock time
// POR causes a reset anyway, BOD behaviour is?
bool validTime = false;
RTC_MODE2_CLOCK_Type oldTime;
if ((!resetTime) && (PM->RCAUSE.reg & (PM_RCAUSE_SYST | PM_RCAUSE_WDT | PM_RCAUSE_EXT))) {
if (RTC->MODE2.CTRL.reg & RTC_MODE2_CTRL_MODE_CLOCK) {
validTime = true;
oldTime.reg = RTC->MODE2.CLOCK.reg;
}
}
// Setup clock GCLK2 with OSC32K divided by 32
GCLK->GENDIV.reg = GCLK_GENDIV_ID(2)|GCLK_GENDIV_DIV(4);
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY)
; /*XOSC32K*/
GCLK->GENCTRL.reg = (GCLK_GENCTRL_GENEN | GCLK_GENCTRL_SRC_OSCULP32K | GCLK_GENCTRL_ID(2) | GCLK_GENCTRL_DIVSEL );
while (GCLK->STATUS.reg & GCLK_STATUS_SYNCBUSY)
;
GCLK->CLKCTRL.reg = (uint32_t)((GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK2 | (RTC_GCLK_ID << GCLK_CLKCTRL_ID_Pos)));
while (GCLK->STATUS.bit.SYNCBUSY)
;
RTCdisable();
RTCreset();
tmp_reg |= RTC_MODE2_CTRL_MODE_CLOCK; // set clock operating mode
tmp_reg |= RTC_MODE2_CTRL_PRESCALER_DIV1024; // set prescaler to 1024 for MODE2
tmp_reg &= ~RTC_MODE2_CTRL_MATCHCLR; // disable clear on match
//According to the datasheet RTC_MODE2_CTRL_CLKREP = 0 for 24h
tmp_reg &= ~RTC_MODE2_CTRL_CLKREP; // 24h time representation
RTC->MODE2.READREQ.reg &= ~RTC_READREQ_RCONT; // disable continuously mode
RTC->MODE2.CTRL.reg = tmp_reg;
while (RTCisSyncing())
;
NVIC_EnableIRQ(RTC_IRQn); // enable RTC interrupt
NVIC_SetPriority(RTC_IRQn, 0x00);
RTC->MODE2.INTENSET.reg |= RTC_MODE2_INTENSET_ALARM0; // enable alarm interrupt
RTC->MODE2.Mode2Alarm[0].MASK.bit.SEL = MATCH_OFF; // default alarm match is off (disabled)
while (RTCisSyncing())
;
RTCenable();
RTCresetRemove();
// If desired and valid, restore the time value
if ((!resetTime) && (validTime)) {
RTC->MODE2.CLOCK.reg = oldTime.reg;
while (RTCisSyncing())
;
}
_configured = true;
}