Created
September 3, 2015 21:40
-
-
Save possan/189071e8066ebab1e03c to your computer and use it in GitHub Desktop.
A simple clock for the dotstar disk by adafruit https://www.adafruit.com/products/2477
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 <EEPROM.h> | |
#include <Adafruit_DotStar.h> | |
#include <SPI.h> | |
#include "TimerThree.h" | |
// R0 = 4x12 leds | |
// R1 = 4x11 leds | |
// R2 = 4x10 leds | |
// R3 = 4x9 leds | |
#define _______ 0,0,0, | |
#define _XXXX__ 7,7,0, | |
#define _XXXXoo 7,7,1, | |
#define _ooXXXX 1,7,7, | |
#define _ooXX__ 1,7,0, | |
#define ___XXXX 0,7,7, | |
#define _XXXXXX 7,7,7, | |
#define _ooXXoo 1,7,1, | |
#define _XX__XX 7,0,7, | |
#define _____XX 0,0,7, | |
#define ___XX__ 0,7,0, | |
#define _XX____ 7,0,0, | |
unsigned char numbers[7*3*10] = { | |
_______ | |
_ooXXoo | |
_XX__XX | |
_XX__XX | |
_XX__XX | |
_ooXXoo | |
_______ | |
_______ | |
_ooXX__ | |
___XX__ | |
___XX__ | |
___XX__ | |
_ooXXoo | |
_______ | |
_______ | |
_XXXXoo | |
_____XX | |
_ooXXoo | |
_XX____ | |
_XXXXXX | |
_______ | |
_______ | |
_XXXXoo | |
_____XX | |
_ooXXXX | |
_____XX | |
_XXXXoo | |
_______ | |
_______ | |
_XX____ | |
_XX__XX | |
_ooXXXX | |
_____XX | |
_____XX | |
_______ | |
_______ | |
_XXXXXX | |
_XX____ | |
_ooXXoo | |
_____XX | |
_XXXXoo | |
_______ | |
_______ | |
_ooXXXX | |
_XX____ | |
_XXXXoo | |
_XX__XX | |
_ooXXoo | |
_______ | |
_______ | |
_XXXXXX | |
_____XX | |
_____XX | |
___XX__ | |
___XX__ | |
_______ | |
_______ | |
_XXXXXX | |
_XX__XX | |
_XXXXXX | |
_XX__XX | |
_XXXXXX | |
_______ | |
_______ | |
_XXXXXX | |
_XX__XX | |
_XXXXXX | |
_____XX | |
_____XX | |
_______ | |
}; | |
#define NUMPIXELS 255 | |
#define DATAPIN 4 | |
#define CLOCKPIN 3 | |
Adafruit_DotStar strip = Adafruit_DotStar(NUMPIXELS, DATAPIN, CLOCKPIN, DOTSTAR_BGR); | |
#define KNOBPIN1 5 | |
#define KNOBPIN2 6 | |
#define BUTTONPIN 7 | |
#define HOURADDR 1 | |
#define MINUTEADDR 3 | |
#define SECONDADDR 5 | |
int t_edit = 0; | |
int t_hour = 0; | |
int t_minute = 0; | |
int t_second = 0; | |
long t_millis = 0; | |
long t_lastmillis = 0; | |
int last_knob = 0; | |
int last_button = 0; | |
int button_stable = 0; | |
long last_input = 0; | |
/* | |
#define NUMSTARS 4 | |
int starposition[NUMSTARS] = { 0, }; | |
int starphase[NUMSTARS] = { 0, }; | |
long starcolor[NUMSTARS] = { 0, }; | |
*/ | |
long digitrowcolors[] = { 0, 0, 0, 0, 0, 0, 0, 0 }; | |
void setup() { | |
strip.begin(); // Initialize pins for output | |
strip.show(); // Turn all LEDs off ASAP | |
pinMode(KNOBPIN1, INPUT); | |
pinMode(KNOBPIN2, INPUT); | |
pinMode(BUTTONPIN, INPUT); | |
Timer3.initialize(5); // initialize timer1, and set a 1/2 second period | |
Timer3.pwm(9, 512); // setup pwm on pin 9, 50% duty cycle | |
Timer3.attachInterrupt(callback); // | |
t_hour = EEPROM.read(HOURADDR); | |
t_minute = EEPROM.read(MINUTEADDR); | |
t_second = EEPROM.read(SECONDADDR); | |
t_millis = millis(); | |
t_lastmillis = millis(); | |
/* | |
for(int k=0; k<NUMSTARS; k++) { | |
starphase[k] = rand() % 255; | |
starposition[k] = 40 + (rand() % 200); | |
starcolor[k] = ((rand() % 127) << 16) + ((rand() % 127) << 8) + ((rand() % 127) << 0); | |
} | |
*/ | |
} | |
void blendPixel(int index, long color) { | |
int oldcolor = strip.getPixelColor(index); | |
int r = ((oldcolor >> 16) & 255) + ((color >> 16) & 255); | |
int g = ((oldcolor >> 8) & 255) + ((color >> 8) & 255); | |
int b = ((oldcolor >> 0) & 255) + ((color >> 0) & 255); | |
if (r > 255) r = 255; | |
if (g > 255) g = 255; | |
if (b > 255) b = 255; | |
int newcolor = (r << 16) + (g << 8) + (b << 0); | |
strip.setPixelColor(index, newcolor); | |
} | |
void blendPixel2(int index, int color, int multiplier) { | |
int oldcolor = strip.getPixelColor(index); | |
int r = ((oldcolor >> 16) & 255) + ((((color >> 16) & 255) * multiplier) >> 8); | |
int g = ((oldcolor >> 8) & 255) + ((((color >> 8) & 255) * multiplier) >> 8); | |
int b = ((oldcolor >> 0) & 255) + ((((color >> 0) & 255) * multiplier) >> 8); | |
if (r > 255) r = 255; | |
if (g > 255) g = 255; | |
if (b > 255) b = 255; | |
int newcolor = (r << 16) + (g << 8) + (b << 0); | |
strip.setPixelColor(index, newcolor); | |
} | |
void drawDigitColumn(int digit, int col, int start, int flip, int color2) { | |
long o = (digit * 7 * 3) + col; | |
// int color2 = 0x000040; | |
for(int row=0; row<7; row++) { | |
if (numbers[o] > 0) { | |
if (flip) { | |
blendPixel2(start + 6 - row, color2 != 0 ? color2 : digitrowcolors[row], numbers[o] * 32); | |
} else { | |
blendPixel2(start + row, color2 != 0 ? color2 : digitrowcolors[row], numbers[o] * 32); | |
} | |
} | |
o += 3; | |
} | |
} | |
void changesecond(int d) { | |
t_second += d; | |
if (t_second < 0) { | |
t_second = 59; | |
changeminute(-1); | |
} | |
if (t_second > 59) { | |
t_second = 0; | |
changeminute(1); | |
} | |
EEPROM.write(SECONDADDR, t_second); | |
t_lastmillis = millis(); | |
} | |
void changeminute(int d) { | |
t_minute += d; | |
if (t_minute < 0) { | |
t_minute = 59; | |
changehour(-1); | |
} | |
if (t_minute > 59) { | |
t_minute = 0; | |
changehour(1); | |
} | |
EEPROM.write(MINUTEADDR, t_minute); | |
} | |
void changehour(int d) { | |
t_hour += d; | |
if (t_hour < 0) { | |
t_hour = 23; | |
} | |
if (t_hour > 23) { | |
t_hour = 0; | |
} | |
EEPROM.write(HOURADDR, t_hour); | |
} | |
void change(int d) { | |
if (t_edit == 1) changehour(d); | |
if (t_edit == 2) changeminute(d); | |
if (t_edit == 3) changesecond(d); | |
} | |
void scan() { | |
int k1 = digitalRead(KNOBPIN1); | |
int k2 = digitalRead(KNOBPIN2); | |
int b = digitalRead(BUTTONPIN); | |
int k = k1 + (k2 << 1); | |
if (k != last_knob) { | |
// 0 3 1 -> right | |
// 0 1 3 -> left | |
if (k == 3 && last_knob == 1) change(-1); | |
if (k == 1 && last_knob == 3) change(1); | |
last_input = millis(); | |
last_knob = k; | |
} | |
if (b != last_button) { | |
last_button = b; | |
button_stable = 0; | |
last_input = millis(); | |
} else { | |
button_stable ++; | |
} | |
if (b == 1 && button_stable == 50) { | |
t_edit ++; | |
t_edit %= 4; | |
} | |
long actdelta = millis() - last_input; | |
if (actdelta > 3000) { | |
if (t_edit != 0) { | |
t_edit = 0; | |
} | |
} | |
} | |
void tick() { | |
long t = millis(); | |
t_millis = t - t_lastmillis; | |
if (t_millis > 1000) { | |
t_lastmillis = t; | |
changesecond(1); | |
} | |
} | |
void callback() | |
{ | |
scan(); | |
tick(); | |
} | |
void setrightdigits(int n2, int color) { | |
int d22 = n2 % 10; | |
int d21 = (n2 / 10) % 10; | |
drawDigitColumn(d22, 2, 9, false, color); | |
drawDigitColumn(d22, 1, 48+8, false, color); | |
drawDigitColumn(d22, 0, 48+44+7, false, color); | |
drawDigitColumn(d21, 2, 48+44+40+36, false, color); | |
drawDigitColumn(d21, 1, 48+44+40+36+27, false, color); | |
drawDigitColumn(d21, 0, 48+44+40+36+27+23, false, color); | |
} | |
void setleftdigits(int n1, int color) { | |
int d12 = n1 % 10; | |
int d11 = (n1 / 10) % 10; | |
drawDigitColumn(d12, 2, 48+44+40+36+27+23+10, true, color); | |
drawDigitColumn(d12, 1, 48+44+40+36+27+12, true, color); | |
drawDigitColumn(d12, 0, 48+44+40+36+14, true, color); | |
drawDigitColumn(d11, 2, 48+44+7+20, true, color); | |
drawDigitColumn(d11, 1, 48+8+22, true, color); | |
drawDigitColumn(d11, 0, 9+24, true, color); | |
} | |
void blendPixelRing2(int ring, float column, int color, int multiplier) { | |
int first = 0; | |
int columns = 0; | |
if (ring == 1) { | |
first = 0; | |
columns = 48; | |
} | |
if (ring == 2) { | |
first = 48; | |
columns = 44; | |
} | |
if (ring == 3) { | |
first = 48 + 44; | |
columns = 40; | |
} | |
if (ring == 4) { | |
first = 48 + 44 + 40; | |
columns = 32; | |
} | |
if (ring == 5) { | |
first = 48 + 44 + 40 + 32; | |
columns = 28; | |
} | |
if (ring == 6) { | |
first = 48 + 44 + 40 + 32 + 28; | |
columns = 24; | |
} | |
column += columns; | |
// column %= columns; | |
float frac = (float)(round(column * 1000.0f) % 1000) / 1000.0f; | |
float ifrac = 1.0f - frac; | |
frac *= frac; | |
ifrac *= ifrac; | |
int column1 = (int)floor(column) % columns; | |
int column2 = (column1 + 1) % columns; | |
blendPixel2(first + column1, color, round(multiplier * ifrac)); | |
blendPixel2(first + column2, color, round(multiplier * frac)); | |
} | |
long hsv2color(int in_h, int in_s, int in_v) | |
{ | |
unsigned char region, remainder, p, q, t; | |
unsigned char out_r, out_g, out_b; | |
if (in_s == 0) | |
{ | |
out_r = in_v; | |
out_g = in_v; | |
out_b = in_v; | |
return (out_r << 16) + (out_g << 8) + (out_b); | |
} | |
region = in_h / 43; | |
remainder = (in_h - (region * 43)) * 6; | |
p = (in_v * (255 - in_s)) >> 8; | |
q = (in_v * (255 - ((in_s * remainder) >> 8))) >> 8; | |
t = (in_v * (255 - ((in_s * (255 - remainder)) >> 8))) >> 8; | |
switch(region) { | |
case 0: | |
out_r = in_v; | |
out_g = t; | |
out_b = p; | |
break; | |
case 1: | |
out_r = q; | |
out_g = in_v; | |
out_b = p; | |
break; | |
case 2: | |
out_r = p; | |
out_g = in_v; | |
out_b = t; | |
break; | |
case 3: | |
out_r = p; | |
out_g = q; | |
out_b = in_v; | |
break; | |
case 4: | |
out_r = t; | |
out_g = p; | |
out_b = in_v; | |
break; | |
case 5: | |
default: | |
out_r = in_v; | |
out_g = p; | |
out_b = q; | |
break; | |
} | |
return (out_r << 16) + (out_g << 8) + (out_b); | |
} | |
void loop() { | |
strip.clear(); | |
int huebase = (millis() / 150) % 255; | |
for(int i=0; i<7; i++) { | |
digitrowcolors[i] = hsv2color((huebase + i * 8) % 255, 255, 50); | |
} | |
setleftdigits(t_hour, t_edit == 1 ? 0x00FF00 : 0); | |
setrightdigits(t_minute, t_edit == 2 ? 0x00FF00 : 0); | |
for(int i=0; i<12; i++) { | |
blendPixel(i * 4, 0x050505); | |
} | |
// float millisring = ((48.0f * t_millis) / 1000.0f); | |
// blendPixelRing2(1, millisring, 0x000005, 255); | |
// second line | |
float fsecond = (float)t_second + ((float)t_millis / 1000.0f); | |
float secondring1 = ((48.0f * fsecond) / 60.0f); | |
float secondring2 = ((44.0f * fsecond) / 60.0f); | |
float secondring3 = ((40.0f * fsecond) / 60.0f); | |
float secondring4 = ((32.0f * fsecond) / 60.0f); | |
float secondring5 = ((28.0f * fsecond) / 60.0f); | |
float secondring6 = ((24.0f * fsecond) / 60.0f); | |
blendPixelRing2(1, secondring1, t_edit == 3 ? 0x00FF00 : 0xFFFFFF, 255); | |
blendPixelRing2(2, secondring2, t_edit == 3 ? 0x00FF00 : 0xFFFFFF, 80); | |
blendPixelRing2(3, secondring3, t_edit == 3 ? 0x00FF00 : 0xFFFFFF, 30); | |
blendPixelRing2(4, secondring4, t_edit == 3 ? 0x00FF00 : 0xFFFFFF, 15); | |
blendPixelRing2(5, secondring5, t_edit == 3 ? 0x00FF00 : 0xFFFFFF, 8); | |
blendPixelRing2(6, secondring6, t_edit == 3 ? 0x00FF00 : 0xFFFFFF, 3); | |
// second blink | |
int secondblink = (255 * (500 - abs(500 - t_millis)) / 500); | |
blendPixel2(248, digitrowcolors[2], secondblink); | |
blendPixel2(251, digitrowcolors[4], secondblink); | |
/* | |
// random stars | |
for(int k=0; k<NUMSTARS; k++) { | |
int starblink = (255 * max(0, (64 - abs(64 - starphase[k]))) / 64); | |
blendPixel2(starposition[k], starcolor[k], starblink); | |
} | |
*/ | |
strip.show(); // Refresh strip | |
delay(1); | |
/* | |
for(int k=0; k<NUMSTARS; k++) { | |
starphase[k] += 2; | |
if (starphase[k] > 255) { | |
starphase[k] = 0; | |
starposition[k] = 40 + (rand() % 200); | |
starcolor[k] = ((rand() % 127) << 16) + ((rand() % 127) << 8) + ((rand() % 127) << 0); | |
} | |
} | |
*/ | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment