#include <Wire.h>
#include <RTClib.h>
#include <Adafruit_NeoPixel.h>
#define LED_PIN 6
#define LED_COUNT 60
#define BUTTON_MARKER 2
#define BUTTON_MODE 3
#define BUTTON_7SEG 4
#define FADE_STEP 5
#define MODE_CLOCK 0
#define MODE_RAINBOW_FAST 1
#define MODE_COLOR_WHEEL 2
#define MODE_RAINBOW_ONE 3
RTC_DS1307 rtc;
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
uint8_t r[LED_COUNT], g[LED_COUNT], b[LED_COUNT];
bool showHourMarkers = true;
bool sevenSegEnabled = true;
uint8_t mode = MODE_CLOCK;
uint8_t lastMode = 255;
unsigned long lastAnim = 0;
uint16_t animOffset = 0;
#define MARKER_R 40
#define MARKER_G 40
#define MARKER_B 40
const uint8_t wheelColors[6][3] = {
{250,219,6},{75,218,29},{22,163,238},
{179,75,206},{238,57,65},{241,162,6}
};
const byte segPins[7] = {8,7,A0,A1,A2,A3,5};
const byte digitPins[4] = {9,10,11,12};
const byte dotPin = 13;
byte numbers[10][7] = {
{1,1,1,1,1,1,0},{0,1,1,0,0,0,0},
{1,1,0,1,1,0,1},{1,1,1,1,0,0,1},
{0,1,1,0,0,1,1},{1,0,1,1,0,1,1},
{1,0,1,1,1,1,1},{1,1,1,0,0,0,0},
{1,1,1,1,1,1,1},{1,1,1,1,0,1,1}
};
bool isHourMarker(int i){ return (i%5==0); }
void clearToWhite(){
for(int i=0;i<LED_COUNT;i++) r[i]=g[i]=b[i]=255;
}
void fadeToWhite(){
for(int i=0;i<LED_COUNT;i++){
if(showHourMarkers && isHourMarker(i)) continue;
if(r[i]<255) r[i]+=FADE_STEP;
if(g[i]<255) g[i]+=FADE_STEP;
if(b[i]<255) b[i]+=FADE_STEP;
}
}
void setHourMarkers(){
for(int h=0;h<12;h++){
int p=h*5;
r[p]=MARKER_R; g[p]=MARKER_G; b[p]=MARKER_B;
}
}
void drawClock(){
DateTime now=rtc.now();
fadeToWhite();
if(showHourMarkers) setHourMarkers();
int s=now.second();
int m=now.minute();
int h=(now.hour()%12)*5+m/12;
r[h]=255; g[h]=0; b[h]=0;
r[m]=255; g[m]=80; b[m]=0;
r[s]=255; g[s]=255; b[s]=0;
}
void rainbowCycle(bool same){
for(int i=0;i<LED_COUNT;i++){
uint16_t hue=same?animOffset*256:(i*65536L/LED_COUNT+animOffset*256);
uint32_t c=strip.gamma32(strip.ColorHSV(hue));
r[i]=(c>>16)&255; g[i]=(c>>8)&255; b[i]=c&255;
}
}
void colorWheelBlock10(){
for(int i=0;i<LED_COUNT;i++){
int s=(i-animOffset)%LED_COUNT; if(s<0)s+=LED_COUNT;
int b10=(s/10)%6;
r[i]=wheelColors[b10][0];
g[i]=wheelColors[b10][1];
b[i]=wheelColors[b10][2];
}
}
void display7Seg(){
if(!sevenSegEnabled){
for(int i=0;i<4;i++) digitalWrite(digitPins[i],HIGH);
return;
}
static byte d=0;
DateTime now=rtc.now();
int val[4]={now.hour()/10,now.hour()%10,now.minute()/10,now.minute()%10};
for(int i=0;i<4;i++) digitalWrite(digitPins[i],HIGH);
for(int i=0;i<7;i++) digitalWrite(segPins[i],numbers[val[d]][i]);
digitalWrite(digitPins[d],LOW);
digitalWrite(dotPin,now.second()%2);
d=(d+1)%4;
}
void setup(){
Wire.begin();
rtc.begin();
if(!rtc.isrunning()) rtc.adjust(DateTime(F(__DATE__),F(__TIME__)));
pinMode(BUTTON_MARKER,INPUT_PULLUP);
pinMode(BUTTON_MODE,INPUT_PULLUP);
pinMode(BUTTON_7SEG,INPUT_PULLUP);
for(int i=0;i<7;i++) pinMode(segPins[i],OUTPUT);
for(int i=0;i<4;i++) pinMode(digitPins[i],OUTPUT);
pinMode(dotPin,OUTPUT);
strip.begin();
strip.setBrightness(255);
strip.show();
clearToWhite();
}
void loop(){
display7Seg();
static bool lm=HIGH;
bool bm=digitalRead(BUTTON_MARKER);
if(lm && !bm){ showHourMarkers=!showHourMarkers; delay(200); }
lm=bm;
static bool lmd=HIGH;
bool bmd=digitalRead(BUTTON_MODE);
if(lmd && !bmd){ mode=(mode+1)%4; lastAnim=millis(); delay(200); }
lmd=bmd;
static bool l7=HIGH;
bool b7=digitalRead(BUTTON_7SEG);
if(l7 && !b7){ sevenSegEnabled=!sevenSegEnabled; delay(200); }
l7=b7;
switch(mode){
case MODE_CLOCK: drawClock(); break;
case MODE_RAINBOW_FAST:
if(millis()-lastAnim>30){animOffset++; lastAnim=millis();}
rainbowCycle(false); break;
case MODE_COLOR_WHEEL:
if(millis()-lastAnim>20){animOffset++; lastAnim=millis();}
colorWheelBlock10(); break;
case MODE_RAINBOW_ONE:
if(millis()-lastAnim>40){animOffset++; lastAnim=millis();}
rainbowCycle(true); break;
}
for(int i=0;i<LED_COUNT;i++)
strip.setPixelColor(i,strip.Color(r[i],g[i],b[i]));
strip.show();
}