Skip to content

Instantly share code, notes, and snippets.

@possan
Created September 3, 2015 21:40
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save possan/189071e8066ebab1e03c to your computer and use it in GitHub Desktop.
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
#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