TiltAlarm/src/main.cpp

177 lines
2.8 KiB
C++

#include <stdint.h>
#include <avr/sleep.h>
#include "./Adafruit_TLC59711.h"
void sleepUntilInterrupt();
Adafruit_TLC59711 controller(1);
#define PinTiltSwitch 3
#define PinTiltSwitchMask PB3
//#define PinDebugLED 4
#define Timeout 2000
/* For PCB layout purposes the LED segments are connected to different pins. */
#define SegmentCount 8
const uint8_t channels[SegmentCount] = {
0,
1,
2,
3,
6,
7,
8,
9
};
#define AnimationSteps 6
const uint16_t pwmValues[AnimationSteps] = {
1024,
2048,
4096,
8192,
16384,
65535
};
/*
void debugBlink(uint8_t count)
{
for (uint8_t i = 0; i < count; i++)
{
digitalWrite(PinDebugLED, HIGH);
delay(150);
digitalWrite(PinDebugLED, LOW);
delay(150);
}
}
*/
volatile bool tiltChanged = false;
uint8_t currentSegment = 0;
uint32_t animationStartTime = 0;
bool animationStopping = false;
uint8_t animationValues[SegmentCount];
void setup()
{
pinMode(PinTiltSwitch, INPUT_PULLUP);
//pinMode(PinDebugLED, OUTPUT);
memset(animationValues, 0, sizeof(animationValues));
controller.begin();
for (uint8_t channel = 0; channel < 12; channel++)
controller.setPWM(channel, 0);
controller.write();
// Turn ADC off
ADCSRA &= ~_BV(ADEN);
// Clear outstanding interrupts
GIFR |= _BV(PCIF);
// Enable pin change interrupts
GIMSK |= _BV(PCIE);
// Set up pin change mask
PCMSK = _BV(PinTiltSwitchMask);
sleepUntilInterrupt();
}
void loop()
{
if (tiltChanged)
{
animationStartTime = millis();
animationStopping = false;
tiltChanged = false;
}
// Decrease all current values
bool allStopped = true;
for (uint8_t segment = 0; segment < SegmentCount; segment++)
{
if (animationValues[segment] > 0)
{
animationValues[segment]--;
allStopped = false;
}
}
if (!animationStopping)
{
allStopped = false;
animationValues[currentSegment] = AnimationSteps;
// Check for timeout
if (millis() - animationStartTime >= Timeout)
animationStopping = true;
}
// Output the current values
for (uint8_t segment = 0; segment < SegmentCount; segment++)
{
uint8_t animationValue = animationValues[segment];
if (animationValue > 0)
controller.setPWM(channels[segment], pwmValues[animationValue - 1]);
else
controller.setPWM(channels[segment], 0);
}
controller.write();
currentSegment++;
if (currentSegment == SegmentCount)
currentSegment = 0;
// If the animation has ended, sleep
if (allStopped)
{
sleepUntilInterrupt();
return;
}
else
delay(75);
}
void sleepUntilInterrupt()
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();
sleep_disable();
tiltChanged = true;
}
// Interrupt for pin changes
ISR(PCINT0_vect)
{
tiltChanged = true;
}