Skip to content

Commit

Permalink
reorganise internal methods to make it more readable
Browse files Browse the repository at this point in the history
  • Loading branch information
PRosenb committed Aug 16, 2016
1 parent 1c9a3d3 commit 6b6f5c8
Showing 1 changed file with 99 additions and 89 deletions.
188 changes: 99 additions & 89 deletions DeepSleepScheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,9 @@ class Scheduler {
#endif

void insertTask(Task *task);
inline SleepMode evaluateAndPrepareSleep();
inline void sleepIfRequired();
inline SleepMode evaluateSleepModeAndEnableWdtIfRequired();
inline unsigned long enableWdt(unsigned long maxWaitTimeMillis);
};

/**
Expand Down Expand Up @@ -583,60 +585,7 @@ void Scheduler::execute() {
}
wdt_reset();

// Enable sleep bit with sleep_enable() before the sleep time evaluation because it can happen
// that the WDT interrupt occurs during sleep time evaluation but before the CPU
// sleeps. In that case, the WDT interrupt clears the sleep bit and the CPU will not sleep
// but continue execution immediatelly.
sleep_enable(); // enables the sleep bit, a safety pin
SleepMode sleepMode = IDLE;
noInterrupts();
bool queueEmpty = first == NULL;
interrupts();
if (!queueEmpty) {
sleepMode = evaluateAndPrepareSleep();
} else {
// nothing in the queue
if (doesDeepSleep()
#ifdef DEEP_SLEEP_DELAY
&& millis() >= lastTaskFinishedMillis + DEEP_SLEEP_DELAY
#endif
) {
wdt_disable();
sleepMode = PWR_DOWN;
} else {
sleepMode = IDLE;
}
}
if (sleepMode != NO_SLEEP) {
#ifdef AWAKE_INDICATION_PIN
digitalWrite(AWAKE_INDICATION_PIN, LOW);
#endif
byte adcsraSave = 0;
if (sleepMode == PWR_DOWN) {
noInterrupts();
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
adcsraSave = ADCSRA;
ADCSRA = 0; // disable ADC
// turn off brown-out in software
#if defined(BODS) && defined(BODSE)
sleep_bod_disable();
#endif
interrupts (); // guarantees next instruction executed
sleep_cpu(); // here the device is actually put to sleep
} else { // IDLE
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_cpu(); // here the device is actually put to sleep
}
// THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
#ifdef AWAKE_INDICATION_PIN
digitalWrite(AWAKE_INDICATION_PIN, HIGH);
#endif
if (adcsraSave != 0) {
// re-enable ADC
ADCSRA = adcsraSave;
}
}
sleep_disable();
sleepIfRequired();

noInterrupts();
unsigned long wdtSleepTimeMillisLocal = wdtSleepTimeMillis;
Expand All @@ -659,10 +608,64 @@ void Scheduler::execute() {
// never executed so no need to deactivate the WDT
}

// returns true if sleep SLEEP_MODE_IDLE or SLEEP_MODE_PWR_DOWN is needed
Scheduler::SleepMode Scheduler::evaluateAndPrepareSleep() {
SleepMode sleepMode = NO_SLEEP;
inline void Scheduler::sleepIfRequired() {
// Enable sleep bit with sleep_enable() before the sleep time evaluation because it can happen
// that the WDT interrupt occurs during sleep time evaluation but before the CPU
// sleeps. In that case, the WDT interrupt clears the sleep bit and the CPU will not sleep
// but continue execution immediatelly.
sleep_enable(); // enables the sleep bit, a safety pin
noInterrupts();
bool queueEmpty = first == NULL;
interrupts();
SleepMode sleepMode = IDLE;
if (!queueEmpty) {
sleepMode = evaluateSleepModeAndEnableWdtIfRequired();
} else {
// nothing in the queue
if (doesDeepSleep()
#ifdef DEEP_SLEEP_DELAY
&& millis() >= lastTaskFinishedMillis + DEEP_SLEEP_DELAY
#endif
) {
wdt_disable();
sleepMode = PWR_DOWN;
} else {
sleepMode = IDLE;
}
}
if (sleepMode != NO_SLEEP) {
#ifdef AWAKE_INDICATION_PIN
digitalWrite(AWAKE_INDICATION_PIN, LOW);
#endif
byte adcsraSave = 0;
if (sleepMode == PWR_DOWN) {
noInterrupts();
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
adcsraSave = ADCSRA;
ADCSRA = 0; // disable ADC
// turn off brown-out in software
#if defined(BODS) && defined(BODSE)
sleep_bod_disable();
#endif
interrupts (); // guarantees next instruction executed
sleep_cpu(); // here the device is actually put to sleep
} else { // IDLE
set_sleep_mode(SLEEP_MODE_IDLE);
sleep_cpu(); // here the device is actually put to sleep
}
// THE PROGRAM CONTINUES FROM HERE AFTER WAKING UP
#ifdef AWAKE_INDICATION_PIN
digitalWrite(AWAKE_INDICATION_PIN, HIGH);
#endif
if (adcsraSave != 0) {
// re-enable ADC
ADCSRA = adcsraSave;
}
}
sleep_disable();
}

Scheduler::SleepMode Scheduler::evaluateSleepModeAndEnableWdtIfRequired() {
noInterrupts();
unsigned long wdtSleepTimeMillisLocal = wdtSleepTimeMillis;
unsigned long currentSchedulerMillis = getMillis();
Expand All @@ -673,6 +676,7 @@ Scheduler::SleepMode Scheduler::evaluateAndPrepareSleep() {
}
interrupts();

SleepMode sleepMode = NO_SLEEP;
if (wdtSleepTimeMillisLocal == 0) {
// not woken up during WDT sleep

Expand All @@ -694,37 +698,7 @@ Scheduler::SleepMode Scheduler::evaluateAndPrepareSleep() {
sleepMode = PWR_DOWN;
firstRegularlyScheduledUptimeAfterSleep = firstScheduledUptimeMillis;

if (maxWaitTimeMillis >= SLEEP_TIME_8S + BUFFER_TIME) {
wdtSleepTimeMillisLocal = SLEEP_TIME_8S;
wdt_enable(WDTO_8S);
} else if (maxWaitTimeMillis >= SLEEP_TIME_4S + BUFFER_TIME) {
wdtSleepTimeMillisLocal = SLEEP_TIME_4S;
wdt_enable(WDTO_4S);
} else if (maxWaitTimeMillis >= SLEEP_TIME_2S + BUFFER_TIME) {
wdtSleepTimeMillisLocal = SLEEP_TIME_2S;
wdt_enable(WDTO_2S);
} else if (maxWaitTimeMillis >= SLEEP_TIME_1S + BUFFER_TIME) {
wdtSleepTimeMillisLocal = SLEEP_TIME_1S;
wdt_enable(WDTO_1S);
} else if (maxWaitTimeMillis >= SLEEP_TIME_500MS + BUFFER_TIME) {
wdtSleepTimeMillisLocal = SLEEP_TIME_500MS;
wdt_enable(WDTO_500MS);
} else if (maxWaitTimeMillis >= SLEEP_TIME_250MS + BUFFER_TIME) {
wdtSleepTimeMillisLocal = SLEEP_TIME_250MS;
wdt_enable(WDTO_250MS);
} else if (maxWaitTimeMillis >= SLEEP_TIME_120MS + BUFFER_TIME) {
wdtSleepTimeMillisLocal = SLEEP_TIME_120MS;
wdt_enable(WDTO_120MS);
} else if (maxWaitTimeMillis >= SLEEP_TIME_60MS + BUFFER_TIME) {
wdtSleepTimeMillisLocal = SLEEP_TIME_60MS;
wdt_enable(WDTO_60MS);
} else if (maxWaitTimeMillis >= SLEEP_TIME_30MS + BUFFER_TIME) {
wdtSleepTimeMillisLocal = SLEEP_TIME_30MS;
wdt_enable(WDTO_30MS);
} else { // maxWaitTimeMs >= 17
wdtSleepTimeMillisLocal = SLEEP_TIME_15MS;
wdt_enable(WDTO_15MS);
}
wdtSleepTimeMillisLocal = enableWdt(maxWaitTimeMillis);

noInterrupts();
wdtSleepTimeMillis = wdtSleepTimeMillisLocal;
Expand Down Expand Up @@ -761,6 +735,42 @@ Scheduler::SleepMode Scheduler::evaluateAndPrepareSleep() {
return sleepMode;
}

inline unsigned long Scheduler::enableWdt(const unsigned long maxWaitTimeMillis) {
unsigned long wdtSleepTimeMillis;
if (maxWaitTimeMillis >= SLEEP_TIME_8S + BUFFER_TIME) {
wdtSleepTimeMillis = SLEEP_TIME_8S;
wdt_enable(WDTO_8S);
} else if (maxWaitTimeMillis >= SLEEP_TIME_4S + BUFFER_TIME) {
wdtSleepTimeMillis = SLEEP_TIME_4S;
wdt_enable(WDTO_4S);
} else if (maxWaitTimeMillis >= SLEEP_TIME_2S + BUFFER_TIME) {
wdtSleepTimeMillis = SLEEP_TIME_2S;
wdt_enable(WDTO_2S);
} else if (maxWaitTimeMillis >= SLEEP_TIME_1S + BUFFER_TIME) {
wdtSleepTimeMillis = SLEEP_TIME_1S;
wdt_enable(WDTO_1S);
} else if (maxWaitTimeMillis >= SLEEP_TIME_500MS + BUFFER_TIME) {
wdtSleepTimeMillis = SLEEP_TIME_500MS;
wdt_enable(WDTO_500MS);
} else if (maxWaitTimeMillis >= SLEEP_TIME_250MS + BUFFER_TIME) {
wdtSleepTimeMillis = SLEEP_TIME_250MS;
wdt_enable(WDTO_250MS);
} else if (maxWaitTimeMillis >= SLEEP_TIME_120MS + BUFFER_TIME) {
wdtSleepTimeMillis = SLEEP_TIME_120MS;
wdt_enable(WDTO_120MS);
} else if (maxWaitTimeMillis >= SLEEP_TIME_60MS + BUFFER_TIME) {
wdtSleepTimeMillis = SLEEP_TIME_60MS;
wdt_enable(WDTO_60MS);
} else if (maxWaitTimeMillis >= SLEEP_TIME_30MS + BUFFER_TIME) {
wdtSleepTimeMillis = SLEEP_TIME_30MS;
wdt_enable(WDTO_30MS);
} else { // maxWaitTimeMs >= 17
wdtSleepTimeMillis = SLEEP_TIME_15MS;
wdt_enable(WDTO_15MS);
}
return wdtSleepTimeMillis;
}

void Scheduler::isrWdt() {
sleep_disable();
millisInDeepSleep += wdtSleepTimeMillis;
Expand Down

0 comments on commit 6b6f5c8

Please sign in to comment.