Created
September 23, 2016 10:28
-
-
Save larsch/90173bdc9cfa11518ff175151675f275 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <avr/sleep.h> | |
// const int com[4] = { 10, 13, 14, 4 }; | |
// const int com[4] = { 4, 14, 13, 10 }; | |
// const int dig[8] = { 11, 15, 6, 8, 9, 12, 5, 7 }; | |
// const int dig[8] = { 13, 17, 4, 6, 7, 14, 3, 5 }; | |
// const int num[10] = { 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f }; | |
// int nmd[10] = {}; | |
// int nmb[10] = {}; | |
// int nmc[10] = {}; | |
#define debug(x) \ | |
Serial.print(#x " "); Serial.println(x) | |
#define BUTTON_READ A7 | |
#define BUTTON_PULLUP A5 | |
#define USE_TIMER1 1 | |
int8_t sine[256]; | |
void sineInit() { | |
uint8_t i = 0; | |
do { | |
sine[i] = lround(127.0 * sin(i * 2.0 * M_PI / 256.0)); | |
++i; | |
} while (i != 0); | |
} | |
void checkButton(); | |
void timerReady(); | |
void timerCountDown(); | |
// Wiring: | |
// | |
// D12 D13 A0 A1 A2 A3 | |
// | | | | | | | |
// 12 11 10 9 8 7 | |
// [ 7-Segment LED ] | |
// 1 2 3 4 5 6 | |
// | | | | | | | |
// D7 D6 D5 D4 D3 D2 | |
// | |
// __ | |
// A5---^ ---A7--[20 kΩ]---GND | |
// | |
// Port registers: | |
// | |
// bit 7 6 5 4 3 2 1 0 | |
// PORT D e d DP c g 4 | |
// PORT B a 1 | |
// PORT C r b 3 2 f | |
// | |
// r = button | |
// 1-4 = anodes | |
// a-g = cathodes | |
#define MASK_D 0xFC | |
#define MASK_B 0x30 | |
#define MASK_C 0x0F | |
#define CATHODE_MASK_D 0xF8 | |
#define CATHODE_MASK_B 0x20 | |
#define CATHODE_MASK_C 0x09 | |
#define ANODE_MASK_D 0x04 | |
#define ANODE_MASK_B 0x10 | |
#define ANODE_MASK_C 0x06 | |
#define INVMASKD (MASK_D ^ 0xFF) | |
#define INVMASKB (MASK_B ^ 0xFF) | |
#define INVMASKC (MASK_C ^ 0xFF) | |
static unsigned long start; | |
// 11 10 9 8 7 6 5 4 3 2 1 0 | |
// e d DP c g 4 a 1 b 3 2 f | |
#define SEG_A 0x020 | |
#define SEG_B 0x008 | |
#define SEG_C 0x100 | |
#define SEG_E 0x800 | |
#define SEG_D 0x400 | |
#define SEG_F 0x001 | |
#define SEG_G 0x080 | |
#define SEG_P 0x200 | |
#define COM_1 0x010 | |
#define COM_2 0x002 | |
#define COM_3 0x004 | |
#define COM_4 0x040 | |
const static uint16_t seg[8] = { SEG_A, SEG_B, SEG_C, SEG_D, SEG_E, SEG_F, SEG_G, SEG_P }; | |
uint16_t decimal[10] = { | |
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F, | |
SEG_B | SEG_C, | |
SEG_A | SEG_B | SEG_G | SEG_E | SEG_D, | |
SEG_A | SEG_B | SEG_G | SEG_C | SEG_D, | |
SEG_B | SEG_C | SEG_F | SEG_G, | |
SEG_A | SEG_F | SEG_G | SEG_C | SEG_D, | |
SEG_A | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G, | |
SEG_A | SEG_B | SEG_C, | |
SEG_A | SEG_B | SEG_C | SEG_D | SEG_E | SEG_F | SEG_G, | |
SEG_A | SEG_B | SEG_C | SEG_D | SEG_F | SEG_G | |
}; | |
#define BITS_D(x) ((((x) >> 4) & MASK_D) ^ CATHODE_MASK_D) | |
#define BITS_B(x) (((x) & MASK_B) ^ CATHODE_MASK_B) | |
#define BITS_C(x) (((x) & MASK_C) ^ CATHODE_MASK_C) | |
const uint16_t combits[4] = { COM_1, COM_2, COM_3, COM_4 }; | |
static uint16_t displayReg[4] = {}; | |
static unsigned long nextDigitMicros = 0; | |
static uint8_t currentDigit = 3; | |
static volatile bool displayComplete = false; | |
static uint8_t frameNumber = 0; | |
#define MAX_ANIM 4 | |
static int animationNumber = 0; | |
static unsigned long waitTime = 2000; | |
unsigned long lastFrame = micros(); | |
void showNextDigit() { | |
// Turn off current anode | |
switch (currentDigit) { | |
case 0: DDRB &= 0b11101111; break; | |
case 1: DDRC &= 0b11111101; break; | |
case 2: DDRC &= 0b11111011; break; | |
case 3: DDRD &= 0b11111011; break; | |
} | |
// Advance to next digit | |
currentDigit = (currentDigit + 1) % 4; | |
// Update cathode output state (high/low) | |
uint16_t combit = combits[currentDigit]; | |
PORTD = (INVMASKD & PORTD) | BITS_D(displayReg[currentDigit] | combit); | |
PORTB = (INVMASKB & PORTB) | BITS_B(displayReg[currentDigit] | combit); | |
PORTC = (INVMASKC & PORTC) | BITS_C(displayReg[currentDigit] | combit); | |
// Turn on current anode | |
switch (currentDigit) { | |
case 0: DDRB |= 0b00010000; break; | |
case 1: DDRC |= 0b00000010; break; | |
case 2: DDRC |= 0b00000100; break; | |
case 3: DDRD |= 0b00000100; break; | |
} | |
nextDigitMicros += waitTime; | |
if (currentDigit == 3) { | |
displayComplete = true; | |
frameNumber++; | |
} | |
} | |
inline void checkUpdateDisplay() { | |
#if !USE_TIMER1 | |
if ((long)(nextDigitMicros - micros()) < 0) { | |
showNextDigit(); | |
checkButton(); | |
} | |
#endif | |
} | |
void setDisplay(uint16_t digs[4]) { | |
// Serial.print(currentDigit); | |
// Serial.print(' '); | |
// Serial.println(nextDigitMicros - micros()); | |
// waitTime += displayComplete ? 50 : -5; | |
// if (waitTime < 1000) | |
// waitTime = 1000; | |
unsigned long before = micros(); | |
#if USE_TIMER1 | |
set_sleep_mode(SLEEP_MODE_IDLE); | |
cli(); | |
while (!displayComplete) { | |
sleep_enable(); | |
sei(); | |
sleep_cpu(); | |
sleep_disable(); | |
} | |
sei(); | |
#else | |
while (!displayComplete) | |
checkUpdateDisplay(); | |
#endif | |
unsigned long now = micros(); | |
unsigned long frameTime = before - lastFrame + 500; | |
if (frameTime < 4000) | |
frameTime = 4000; | |
#if USE_TIMER1 | |
ICR1 = frameTime * 2; | |
#else | |
waitTime = frameTime / 4; | |
#endif | |
lastFrame = now; | |
// Serial.print(DDRC); | |
// Serial.print(' '); | |
// Serial.println(PORTC); | |
unsigned long after = micros(); | |
// Serial.print(currentDigit); | |
// Serial.print(' '); | |
// Serial.print(frameNumber); | |
// Serial.print(' '); | |
// Serial.println(frameTime); | |
// Serial.print(after - before); | |
// Serial.print(' '); | |
// Serial.println(before - lastFrame); | |
// Serial.print(' '); | |
// Serial.print(count); | |
// Serial.print(' '); | |
// Serial.println(displayComplete); | |
displayComplete = false; | |
displayReg[0] = digs[0]; | |
displayReg[1] = digs[1]; | |
displayReg[2] = digs[2]; | |
displayReg[3] = digs[3]; | |
} | |
void animateWalkingSquare() { | |
#define UPBUBBLE (SEG_A|SEG_B|SEG_G|SEG_F) | |
#define DOWNBUBBLE (SEG_C|SEG_D|SEG_E|SEG_G) | |
unsigned long n = millis() / 100; | |
uint16_t digs[4] = { 0, 0, 0, 0 }; | |
unsigned long step = n % 8; | |
if (step < 4) | |
digs[step % 4] |= UPBUBBLE; | |
else | |
digs[3 - (step % 4)] |= DOWNBUBBLE; | |
setDisplay(digs); | |
} | |
void animateClimbingBars() { | |
#define ST1 (SEG_D) | |
#define ST2 (SEG_C|SEG_D|SEG_E|SEG_G) | |
#define ST3 (SEG_A|SEG_B|SEG_C|SEG_D|SEG_E|SEG_F|SEG_G) | |
#define ST4 (SEG_A|SEG_B|SEG_G|SEG_F) | |
#define ST5 (SEG_A) | |
uint16_t step[8] = { ST1, ST2, ST3, ST4, ST5, 0, 0, 0 }; | |
unsigned long n = millis() / 100; | |
uint16_t digs[4] = { }; | |
for (int i = 0; i < 4; ++i) | |
digs[i] = step[(n+i)%8]; | |
setDisplay(digs); | |
} | |
void animateLeftToRightSweep() { | |
#define LEFT (SEG_E|SEG_F) | |
#define MID (SEG_A|SEG_G|SEG_D) | |
#define RIGHT (SEG_B|SEG_C) | |
#define DOT (SEG_P) | |
const int dist[16] = { 14, 38, 64, | |
111, 136, 160, 168, | |
184, 208, 234, 258, | |
266, 306, 332, 356, | |
363 }; | |
const uint16_t p1[16] = { LEFT, MID, RIGHT, | |
0, 0, 0, DOT }; | |
const uint16_t p2[16] = { 0, 0, 0, | |
LEFT, MID, RIGHT, 0, | |
DOT }; | |
const uint16_t p3[16] = { 0, 0, 0, | |
0, 0, 0, 0, | |
0, LEFT, MID, RIGHT, | |
DOT }; | |
const uint16_t p4[16] = { 0, 0, 0, | |
0, 0, 0, 0, | |
0, 0, 0, 0, | |
0, LEFT, MID, RIGHT, DOT }; | |
unsigned long n = millis(); | |
long m = n % 650; | |
long o = m - 250; | |
uint16_t digs[4] = {}; | |
for (int i = 0; i < 16; ++i) { | |
if (m >= dist[i] && o < dist[i]) { | |
digs[0] |= p1[i]; | |
digs[1] |= p2[i]; | |
digs[2] |= p3[i]; | |
digs[3] |= p4[i]; | |
} | |
} | |
setDisplay(digs); | |
} | |
const int16_t coordinates[4][8][2] = { | |
{ | |
{ 139, 62 }, | |
{ 200, 132 }, | |
{ 181, 266 }, | |
{ 101, 324 }, | |
{ 41, 258 }, | |
{ 61, 123 }, | |
{ 122, 193 }, | |
{ 474, 324 }, | |
}, | |
{ | |
{ 398, 61 }, | |
{ 460, 127 }, | |
{ 442, 258 }, | |
{ 363, 324 }, | |
{ 302, 262 }, | |
{ 321, 126 }, | |
{ 385, 192 }, | |
{ 511, 193 }, | |
}, | |
{ | |
{ 661, 61 }, | |
{ 719, 130 }, | |
{ 701, 262 }, | |
{ 622, 324 }, | |
{ 562, 259 }, | |
{ 580, 125 }, | |
{ 640, 194 }, | |
{ 733, 323 }, | |
}, | |
{ | |
{ 920, 60 }, | |
{ 980, 127 }, | |
{ 961, 266 }, | |
{ 883, 323 }, | |
{ 821, 259 }, | |
{ 841, 126 }, | |
{ 901, 193 }, | |
{ 995, 323 } | |
} | |
}; | |
double sin1(long t, long w) { | |
return sin((t % w) / (double)w * 2 * M_PI); | |
} | |
void animateFlyingBlob() { | |
unsigned long time = millis(); | |
// double t = (time % 1000) / 1000.0; | |
// double t2 = (time % 759) / 759.0; | |
double ext = 128.0; | |
double midx = 512.0; | |
double midy = 193.0; | |
double pfx = midx + (midx + ext) * (0.3 * sin1(time, 1000) + 0.7 * sin1(time, 2623)); // sin(t * 2 * M_PI); | |
double pfy = midy + (midy + ext) * (0.3 * sin1(time, 759) + 0.7 * sin1(time, 1728)); // cos(t2 * 2 * M_PI); | |
int px = pfx; | |
int py = pfy; | |
uint16_t digs[4] = {}; | |
int size = 12 + 4.0 * sin1(time, 2873); | |
for (int d = 0; d < 4; ++d) { | |
for (int s = 0; s < 8; ++s) { | |
checkUpdateDisplay(); | |
long x = coordinates[d][s][0]; | |
long y = coordinates[d][s][1]; | |
double dx = x - px; | |
double dy = y - py; | |
double dist = sqrt(dx * dx + dy * dy); | |
int i = size - dist / 32; | |
if (i > frameNumber % 4) | |
digs[d] |= seg[s]; | |
} | |
} | |
setDisplay(digs); | |
} | |
inline long sqa(long a) { | |
return a * a; | |
} | |
void animateRotatingBar() { | |
unsigned long time = millis(); | |
// double t = (time % 2000) / 2000.0; | |
double x1 = 512.0 + 512.0 * sin1(time, 1672); | |
double y1 = 193.0 + 100.0 * sin1(time, 934); | |
double ta = (time % 2873) / 2873.0; | |
double tb = (time % 3273) / 3273.0; | |
double angle = 0.673 * M_PI * sin(ta * 2 * M_PI) + 0.842 * M_PI * sin(tb * 2 * M_PI); | |
double x2 = x1 + 128.0 * cos(angle); | |
double y2 = y1 + 128.0 * sin(angle); | |
double dy = (y2 - y1); | |
double dx = (x2 - x1); | |
double d3 = sqa(dx) + sqa(dy); | |
uint16_t digs[4] = {}; | |
for (int d = 0; d < 4; ++d) { | |
for (int s = 0; s < 8; ++s) { | |
checkUpdateDisplay(); | |
long x0 = coordinates[d][s][0]; | |
long y0 = coordinates[d][s][1]; | |
double d1 = dx * (y1 - y0) - (x1 - x0) * dy; | |
double dsq = (d1 * d1) / d3; | |
int dist = sqrt(dsq); | |
int i = 8 - dist / 32; | |
// 0x0f 0x07 0x0a 0x01 | |
if (i > frameNumber % 4) | |
digs[d] |= seg[s]; | |
// if (dsq < size2q) | |
// digs[d] |= seg[s]; | |
// else if (dsq < size2a && (frameNumber % 4)) | |
// digs[d] |= seg[s]; | |
// else if (dsq < size2b && (frameNumber % 2)) | |
// digs[d] |= seg[s]; | |
// else if (dsq < size2c && !(frameNumber % 4)) | |
// digs[d] |= seg[s]; | |
} | |
} | |
setDisplay(digs); | |
} | |
void animateWiper() { | |
unsigned long time = millis(); | |
// double t = (time % 2000) / 2000.0; | |
double x1 = 512.0; | |
double y1 = 600.0; | |
double angle = M_PI * (abs((long)(time % 2000) - 1000) / 1000.0); | |
double x2 = x1 + 128.0 * cos(angle); | |
double y2 = y1 + 128.0 * sin(angle); | |
double dy = (y2 - y1); | |
double dx = (x2 - x1); | |
double d3 = sqa(dx) + sqa(dy); | |
uint16_t digs[4] = {}; | |
for (int d = 0; d < 4; ++d) { | |
for (int s = 0; s < 8; ++s) { | |
checkUpdateDisplay(); | |
long x0 = coordinates[d][s][0]; | |
long y0 = coordinates[d][s][1]; | |
double d1 = dx * (y1 - y0) - (x1 - x0) * dy; | |
double dsq = (d1 * d1) / d3; | |
int dist = sqrt(dsq); | |
int i = 4 - dist / 64; | |
// 0x0f 0x07 0x0a 0x01 | |
if (i > frameNumber % 4) | |
digs[d] |= seg[s]; | |
// if (dsq < size2q) | |
// digs[d] |= seg[s]; | |
// else if (dsq < size2a && (frameNumber % 4)) | |
// digs[d] |= seg[s]; | |
// else if (dsq < size2b && (frameNumber % 2)) | |
// digs[d] |= seg[s]; | |
// else if (dsq < size2c && !(frameNumber % 4)) | |
// digs[d] |= seg[s]; | |
} | |
} | |
setDisplay(digs); | |
} | |
void animateRotatingWaves() { | |
unsigned long time = millis(); | |
// float t = (time % 2000) / 2000.0; | |
float t2 = (time % 3387) / 3387.0; | |
float distScale = (0.5 + 0.2 * sin(t2 * 2 * M_PI)); | |
float phase = (time % 2382) / 2382.0 * 2 * M_PI; | |
float x1 = 512.0; | |
float y1 = 193.0; | |
float ta = (time % 2873) / 2873.0; | |
float angle = ta * 2 * M_PI; | |
float x2 = x1 + 128.0 * cos(angle); | |
float y2 = y1 + 128.0 * sin(angle); | |
float dy = (y2 - y1); | |
float dx = (x2 - x1); | |
float d3 = sqa(dx) + sqa(dy); | |
uint16_t digs[4] = {}; | |
for (int d = 0; d < 4; ++d) { | |
for (int s = 0; s < 8; ++s) { | |
checkUpdateDisplay(); | |
float x0 = coordinates[d][s][0]; | |
float y0 = coordinates[d][s][1]; | |
float d1 = dx * (y1 - y0) - (x1 - x0) * dy; | |
float dsq = (d1 * d1) / d3; | |
int dist = sqrt(dsq) * distScale; | |
int i = 1.5 + 3.0 * cos(dist / 64 + phase); | |
// 0x0f 0x07 0x0a 0x01 | |
if (i > frameNumber % 4) | |
digs[d] |= seg[s]; | |
// if (dsq < size2q) | |
// digs[d] |= seg[s]; | |
// else if (dsq < size2a && (frameNumber % 4)) | |
// digs[d] |= seg[s]; | |
// else if (dsq < size2b && (frameNumber % 2)) | |
// digs[d] |= seg[s]; | |
// else if (dsq < size2c && !(frameNumber % 4)) | |
// digs[d] |= seg[s]; | |
} | |
} | |
// Serial.print(currentDigit); | |
// Serial.print(' '); | |
// Serial.println(nextDigitMicros - micros()); | |
setDisplay(digs); | |
} | |
void animateWaves() { | |
uint16_t digs[4] = {}; | |
uint16_t xoffset = micros() >> 9; // 32768 - sine[(millis()>>3) & 0xFF] << 3; | |
int16_t midx = 512; | |
int16_t midy = 193; | |
int8_t sina = sine[(millis()>>5) & 0xFF]; | |
int8_t cosa = sine[(64 + (millis()>>5)) & 0xFF]; | |
for (int d = 0; d < 4; ++d) { | |
for (int s = 0; s < 8; ++s) { | |
checkUpdateDisplay(); | |
long x0 = coordinates[d][s][0] - midx; | |
long y0 = coordinates[d][s][1] - midy; | |
long x = midx + (x0 * cosa - y0 * sina) / 130; | |
// long y = midy + (x0 * sina + y0 * cosa) / 128; | |
uint16_t c = x + xoffset; | |
int8_t v = sine[(c/4) & 0xFF]; | |
int8_t i = v / 48 + 2; | |
if (i > frameNumber % 4) | |
digs[d] |= seg[s]; | |
} | |
} | |
setDisplay(digs); | |
} | |
void buttonInit() | |
{ | |
DDRC |= 0x20; // A5 = output | |
PORTC |= 0x20; // A5 = high | |
// pinMode(A5, OUTPUT); | |
// digitalWrite(A5, HIGH); | |
Serial.print(DDRC); | |
Serial.print(' '); | |
Serial.println(PORTC); | |
} | |
void onButtonPress(); | |
void onButtonDoublePress(); | |
void onButtonRelease(); | |
void onButtonHold(); | |
static uint16_t pressRegister = 0; | |
static uint16_t releaseRegister = 0; | |
static unsigned long pressTime; | |
enum ButtonState { Released, PressedWait, ReleasedWait, Pressed }; | |
static ButtonState buttonState = Released; | |
void checkButton() | |
{ | |
unsigned long now = millis(); | |
int button = analogRead(BUTTON_READ) > 512; | |
pressRegister = (pressRegister << 1) | (!button) | 0xe000; | |
releaseRegister = (releaseRegister << 1) | button | 0xe000; | |
if (pressRegister == 0xf000) { | |
if (buttonState == ReleasedWait) { | |
onButtonDoublePress(); | |
buttonState = Pressed; | |
// Serial.println("Pressed"); | |
} else { | |
buttonState = PressedWait; | |
// Serial.println("PressedWait"); | |
} | |
pressTime = now; | |
} else if (releaseRegister == 0xf000) { | |
if (buttonState == PressedWait) { | |
buttonState = ReleasedWait; | |
// Serial.println("ReleasedWait"); | |
} else { | |
buttonState = Released; | |
// Serial.println("Released"); | |
} | |
} else { | |
unsigned long timePassed = millis() - pressTime; | |
if (buttonState == PressedWait) { | |
if (timePassed > 600) { | |
onButtonHold(); | |
buttonState = Pressed; | |
// Serial.println("Pressed"); | |
} | |
} else if (buttonState == ReleasedWait) { | |
if (timePassed > 400) { | |
onButtonPress(); | |
buttonState = Released; | |
// Serial.println("Released"); | |
} | |
} | |
} | |
} | |
// void loop1() | |
// { | |
// static int c = 0; | |
// static int d = 0; | |
// pinMode(com[c], INPUT); | |
// pinMode(dig[d], INPUT); | |
// d = (d + 1) % 8; | |
// if (d == 0) | |
// c = (c + 1) % 4; | |
// pinMode(com[c], OUTPUT); | |
// digitalWrite(com[c], 1); | |
// pinMode(dig[d], OUTPUT); | |
// digitalWrite(com[c], 1); | |
// delay(100); | |
// } | |
// void loop2() { | |
// static int n = 0; | |
// n = (millis() / 50); | |
// for (int c = 0; c < 4; ++c) { | |
// int m = n % 10; | |
// n /= 10; | |
// pinMode(com[c], OUTPUT); | |
// digitalWrite(com[c], 1); | |
// int mask = num[m]; | |
// for (int d = 0; d < 8; ++d) { | |
// // if (mask & 1) { | |
// // pinMode(dig[d], INPUT); | |
// // } else { | |
// // pinMode(dig[d], OUTPUT); | |
// // digitalWrite(dig[d], HIGH); | |
// // } | |
// pinMode(dig[d], OUTPUT); | |
// digitalWrite(dig[d], !(mask & 1)); | |
// mask >>= 1; | |
// } | |
// delay(5); | |
// for (int d = 0; d < 8; ++d) | |
// pinMode(dig[d], INPUT); | |
// pinMode(com[c], INPUT); | |
// } | |
// } | |
void (*animationFunction[MAX_ANIM])() = { | |
animateWaves, | |
animateWiper, | |
// animateRotatingWaves, | |
animateFlyingBlob, | |
// animateLeftToRightSweep, | |
// animateClimbingBars, | |
// animateWalkingSquare, | |
animateRotatingBar, | |
}; | |
unsigned long endTime; | |
#define WORK_DURATION (25L * 60L * 1000L) | |
#define BREAK_DURATION (5L * 60L * 1000L) | |
// #define WORK_DURATION (25L * 1000L) | |
// #define BREAK_DURATION (5L * 1000L) | |
unsigned long runTime = WORK_DURATION; | |
unsigned long readyTime; | |
unsigned long screenSaverTime; | |
uint8_t countDownMode = 0; | |
void (*state)(); | |
void makeDigs(uint16_t *digs, int val, bool dots) { | |
int min = (val / 60) % 100; | |
int sec = val % 60; | |
digs[0] = decimal[min / 10]; | |
digs[1] = decimal[min % 10]; | |
digs[2] = decimal[sec / 10]; | |
digs[3] = decimal[sec % 10]; | |
if (dots) | |
digs[1] |= SEG_P; | |
} | |
void setTimer(unsigned long duration) { | |
runTime = duration; | |
state = timerReady; | |
readyTime = millis(); | |
} | |
void startTimer() { | |
endTime = millis() + runTime; | |
state = timerCountDown; | |
countDownMode = 0; | |
} | |
void startScreenSaver(); | |
void nextScreenSaver() { | |
screenSaverTime = millis(); | |
animationNumber = (animationNumber + 1) % MAX_ANIM; | |
} | |
void screenSaver() { | |
if (millis() - screenSaverTime > 15000) | |
nextScreenSaver(); | |
animationFunction[animationNumber](); | |
} | |
void startScreenSaver() { | |
state = screenSaver; | |
nextScreenSaver(); | |
} | |
void timerReady() { | |
if ((millis() - readyTime) > 30000) | |
startScreenSaver(); | |
int i = 2 + 3 * sin1(millis(), 1234); | |
if (i > frameNumber % 4) { | |
uint16_t digs[4]; | |
makeDigs(digs, runTime / 1000, true); | |
setDisplay(digs); | |
} else { | |
uint16_t digs[4] = {}; | |
setDisplay(digs); | |
} | |
} | |
void showTimeLeft(long timeLeft) { | |
uint16_t digs[4]; | |
makeDigs(digs, (timeLeft + 999) / 1000, (timeLeft / 500) % 2); | |
setDisplay(digs); | |
} | |
void startNextTimer() { | |
if (runTime == WORK_DURATION) { | |
setTimer(BREAK_DURATION); | |
} else { | |
setTimer(WORK_DURATION); | |
} | |
} | |
void clearDisplay() { | |
uint16_t digs[4] = {}; | |
setDisplay(digs); | |
} | |
void timerCountDown() { | |
long timeLeft = endTime - millis(); | |
if (timeLeft < -500) | |
startNextTimer(); | |
else if (countDownMode == 0 || timeLeft < 60000L) | |
showTimeLeft(timeLeft); | |
else if (countDownMode == 1) | |
screenSaver(); | |
else | |
clearDisplay(); | |
} | |
void timerFinished() { | |
} | |
void onButtonPress() | |
{ | |
if (state == timerReady) | |
startTimer(); | |
else if (state == screenSaver) | |
nextScreenSaver(); | |
else if (state == timerCountDown) | |
countDownMode = (countDownMode + 1) % 3; | |
} | |
void onButtonDoublePress() { | |
if (state == timerReady) | |
startNextTimer(); | |
} | |
void onButtonRelease() { | |
} | |
void onButtonHold() { | |
if (state == timerReady) | |
startScreenSaver(); | |
else if (state == timerCountDown) | |
setTimer(WORK_DURATION); | |
else if (state == screenSaver) | |
setTimer(runTime); | |
} | |
#define TCCR1B_CS (_BV(CS10) | _BV(CS11) | _BV(CS12)) | |
void timerInterruptSetup() { | |
// 32000 cycles per interrupt = 500 hz = 2 ms/interrupt | |
ICR1 = 32000 / 2; | |
// Enable interrupt | |
TIMSK1 |= _BV(TOIE1); | |
// Enable timer 1 (mode 8) | |
TCCR1A = 0; | |
TCCR1B = _BV(WGM13) | _BV(CS10); | |
// debug(ICR1); | |
// debug(TIMSK1); | |
// debug(TCCR1A); | |
// debug(TCCR1B); | |
} | |
static unsigned long t; | |
ISR(TIMER1_OVF_vect) | |
{ | |
showNextDigit(); | |
checkButton(); | |
// debug(currentDigit); | |
} | |
void setup() | |
{ | |
Serial.begin(115200); | |
sineInit(); | |
buttonInit(); | |
start = millis(); | |
// Set all setDisplay pins to output mode | |
DDRD = (INVMASKD & DDRD) | MASK_D; | |
DDRB = (INVMASKB & DDRB) | MASK_B; | |
DDRC = (INVMASKC & DDRC) | MASK_C; | |
setTimer(WORK_DURATION); | |
state = screenSaver; | |
#if USE_TIMER1 | |
timerInterruptSetup(); | |
#endif | |
} | |
void loop() { | |
state(); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment