#include <Arduino.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <util/atomic.h>
#include <digitalWriteFast.h>
#include "Classes.hpp"
#define CS ATOMIC_BLOCK(ATOMIC_RESTORESTATE) // Critical Section
//
// global constant(s)
//
constexpr uint8_t gcInterruptPin {PB3};
constexpr uint8_t gcSignalPin {PB4};
constexpr uint8_t gcStateLedPin {PB2};
constexpr uint8_t gcInputMask {_BV(gcInterruptPin) | _BV(PB1) | _BV(PB0)}; // Mask for setting DDRB and PORTB
//
// global variable(s) / object(s)
//
SignalData signals[3] {
{200, 200, 3, 600},
{600, 200, 3, 600},
{200, 200, 3, 2000}
};
OutputPin<gcSignalPin> signalPin;
ProcessSignal processSignal;
bool isAction = false;
//
// functions
//
ISR(PCINT0_vect) { isAction = true; } // Pin change interrupt service routine
//////////////////////////////////////////////////////////////////////////////
/// \brief Configure pin settings
///
//////////////////////////////////////////////////////////////////////////////
void configurePins() {
signalPin.begin();
DDRB |= _BV(gcStateLedPin); // set as output
// DDRB &= ~gcInputMask; // set as input (include unsued pins) // Input is default after startup
PORTB |= gcInputMask; // INPUT_PULLUP (include unused pins)
PCMSK |= _BV(gcInterruptPin); // set interrupt pin mask
}
//////////////////////////////////////////////////////////////////////////////
/// \brief Turns of the ADC
///
//////////////////////////////////////////////////////////////////////////////
inline void adcDisable() { ADCSRA &= ~(_BV(ADEN)); }
//////////////////////////////////////////////////////////////////////////////
/// \brief Manage sleep mode
/// Sleep modes are not available in wokwi.
//////////////////////////////////////////////////////////////////////////////
void enterSleepMode() {
PORTB &= ~_BV(gcStateLedPin); // switch control LED off
GIMSK |= _BV(PCIE); // (Re)enable pin change interrupt
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // SLEEP_MODE_PWR_DOWN for lowest power consumption.
sleep_enable();
sleep_mode();
// Program will be continued here after waking up -----------
sleep_disable();
GIMSK &= ~_BV(PCIE); // disable pin change interrupt
PORTB |= _BV(gcStateLedPin); // light up control LED
}
//
// Main Program setup() and loop()
//
void setup() {
configurePins();
adcDisable();
wdt_disable();
}
void loop() {
if (isAction) {
// This if is necessary because no sleep mode is available
if (bitRead(GIMSK,PCIE)) {
GIMSK &= ~_BV(PCIE); // disable pin change interrupt
PORTB |= _BV(gcStateLedPin); // light up control LED
};
CS isAction = !processSignal(signalPin, signals);
} else { // Anything is ready
// enterSleepMode();
// This if is necessary because no sleep mode is available
GIMSK |= _BV(PCIE); // (Re)enable pin change interrupt
PORTB &= ~_BV(gcStateLedPin); // switch control LED off
}
}
White LED: Program is active
Green LED: Pulse is active
Press the button to generate an SOS Signal.