//todo:
//implement tone adjustment for manual mode and (brightness adjustment for both: done)
//(implement pwm output for brightness and tone :done)
//fix bug where underline doesn't show
//implement auto shutoff
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeSansBold18pt7b.h>
#define SCREEN_WIDTH 128 //oled stuff
#define SCREEN_HEIGHT 64
#define OLED_RESET 4
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#include "RTClib.h" //real time clock stuff
RTC_DS1307 rtc; //switch this when uploading to real arduino
int pot;
int pot2;
int button = 2;
int automatic_mode;
int manual_mode;
int tone_adjust;
long brightness_adjust = 0;
//long brightness_output = 0;
long blue_led;
long red_led;
long blue_led_output;
long red_led_output;
//variables to use when changing current time on oled
int set_hour;
int set_minute;
int set_second;
//variables to store times for display on oled
int wake_hour = 10;
int wake_minute = 0;
int sleep_hour = 10;
int sleep_minute = 2;
//variables to store current state when navigating menu
int depth = 0;
int screen = 0;
//timing variables
long CT; //current time
long WT; //wake time
long ST; //sleep time
long L; //cycle length
long X; //time since cycle start
float prog; //progress along cycle as a percentage
long blue; //blue light percent output by automatic mode(out of 100)
long bright; //brightness percent output by automatic mode (out of 100)
void setup() {
Serial.begin(9600);
pinMode(A2, INPUT);
pinMode(A3, INPUT);
pinMode(button, INPUT_PULLUP); //button pin
pinMode(5, INPUT_PULLUP); //switch pins
pinMode(6, INPUT_PULLUP); //switch pins
display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //initialize display
display.clearDisplay(); //initial display settings
display.setTextSize(1);
display.setTextColor(WHITE);
//display.setRotation(2); //rotates the screen 180 degrees
if (! rtc.begin()) { //initialize real time clock
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}
}
void loop() {
DateTime now = rtc.now(); //update real time clock functions
pot = (analogRead(A3)); //potentiometer pin
pot2 = (analogRead(A2)); //brightness pot pin
brightness_adjust = map(pot2, 0, 1023, 0, 100); //brightness adjustment dial
blue_led = (blue * bright * brightness_adjust);
blue_led_output = map(blue_led, 0, 1000000, 0, 255);
red_led = (100 - blue) * bright * brightness_adjust;
red_led_output = map(red_led, 0, 1000000, 0, 255);
analogWrite(9,red_led_output);
analogWrite(10,blue_led_output);
//set_hour = now.hour(); //rtc variables for oled
//set_minute = now.minute();
//set_second = now.second();
display.fillRect(0,0,128,128,BLACK); //clears screen
automatic_mode = digitalRead(5); //checks switch position
manual_mode = digitalRead(6); //checks switch position
CT = 60 * now.hour() + 60 * now.minute() + now.second(); //timing variable math
ST = 60 * sleep_hour + 60 * sleep_minute;
WT = 60 * wake_hour + 60 * wake_minute;
L = ST - WT;
X = CT - WT;
prog = (float) X / L;
//display menu code
if(automatic_mode == 0){ //checks if the three position switch is set to automatic mode
//brightness_output = brightness_adjust + bright; //makes brightness output a function of both brightness dial and automatic mode
//blue light timing functions
if((CT >= WT - (L/14)) && (CT < WT + (3*L/14))){
blue = 80L;
}
else if((CT >= WT + (3*L/14)) && ((CT < WT + (L/2)))){
blue = 80L + (3L * 105L / 14L) - 105L * prog;
}
else if((CT >= WT + (L/2)) && (CT < WT + (9.4*L/14))){
blue = 50L +(700L / 6L) - (700L/3) * prog;
}
else if((CT >= WT + (9.4*L/14)) && (CT < ST)){
blue = 10L;
}
else {
blue = 0;
}
//brightness timing functions
if((CT >= WT - (L/14)) && (CT < WT)){
bright = (840L*1L/14L) + 840L*prog;
}
else if((CT >= WT) && (CT < WT + (5*L/14))){
bright = 60L + (112L*prog);
}
else if((CT >= WT + (5*L/14)) && (CT < WT + (8*L/14))){
bright = 100L;
}
else if((CT >= WT + (8*L/14)) && (CT < WT + (11*L/14))){
bright = 100L + (8L*140L/14L) - (140L*prog);
}
else if((CT >= WT + (11*L/14)) && (CT < WT + (13*L/14))){
bright = 70L + (210L*11L/14L) - (210L*prog);
}
else if((CT >= WT + (13*L/14)) && (CT < ST)){//changed wt to st
bright = 40L + (560L*13L/14L) - (560L*prog);
}
else {
bright = 0;
}
if(digitalRead(button) == LOW && depth <= 1){ //increment menu position if button is pressed
depth++;
delay(100);
}
else if(digitalRead(button) == LOW && depth >= 2){
depth = 0;
delay(100);
}
if(depth == 0){ //if you arent currently adjusting a time setting, lets potentiometer control which page is selected
screen = map(pot, 0, 1023, 0, 3);
}
if(screen == 0){ //if "current time" screen is selected
display.setFont();
display.setTextSize(1);
display.setCursor(10,0);
display.print(" Current Time >"); //prints a label indicating this is the current time screen
if(now.hour() < 10){display.setCursor(30,40);}
else{display.setCursor(20,40);}
display.setFont(&FreeSansBold18pt7b);
display.print(now.hour(), DEC); //prints the current time
display.print(':');
if(now.minute() < 10){
display.print("0");
}
display.print(now.minute(),DEC);
if(depth == 1){ //if the button has been pressed once on this screen to select the hour's number
set_hour = map(pot, 0, 1023, 0, 24); //make the hours number of the current time adjustable with the potentiometer
rtc.adjust(DateTime(2024,3,23,set_hour,set_minute,now.second())); //update clock
if(now.hour() < 10) {display.drawFastHLine(30, 50, 18, WHITE);}//draw an underline under the selected number
else{display.drawFastHLine(20, 50, 36, WHITE);}
}
if(depth == 2){
set_minute = map(pot, 0, 1023, 0, 60); //make the minutes number adjustable
rtc.adjust(DateTime(2024,3,23,set_hour,set_minute,now.second())); //update clock
if(now.hour() < 10) {display.drawFastHLine(58, 50, 36, WHITE);}//draw an underline under the selected number
else{display.drawFastHLine(68, 50, 36, WHITE);}
}
}
if(screen == 1){ //if "wake time" screen is selected
display.setFont();
display.setTextSize(1);
display.setCursor(10,0);
display.print("< Wake Time >"); //prints a label indicating this is the current time screen
if(wake_hour < 10){display.setCursor(30,40);}
else{display.setCursor(20,40);}
display.setFont(&FreeSansBold18pt7b);
display.print(wake_hour); //prints the current time
display.print(':');
if(wake_minute < 10){
display.print("0");
}
display.print(wake_minute);
if(depth == 1){ //if the button has been pressed once on this screen to select the hour's number
wake_hour = map(pot, 0, 1023, 0, 24); //make the hours number of the current time adjustable with the potentiometer
if(wake_hour < 10) {display.drawFastHLine(30, 50, 18, WHITE);}//draw an underline under the selected number
else{display.drawFastHLine(20, 50, 36, WHITE);}
}
if(depth == 2){
wake_minute = map(pot, 0, 1023, 0, 60); //make the minutes number adjustable
if(wake_hour < 10) {display.drawFastHLine(58, 50, 36, WHITE);}//draw an underline under the selected number
else{display.drawFastHLine(68, 50, 36, WHITE);}
}
}
if(screen >= 2){ //if "sleep time" screen is selected
display.setFont();
display.setTextSize(1);
display.setCursor(10,0);
display.print("< Sleep Time"); //prints a label indicating this is the current time screen
if(sleep_hour < 10){display.setCursor(30,40);}
else{display.setCursor(20,40);}
display.setFont(&FreeSansBold18pt7b);
display.print(sleep_hour); //prints the current time
display.print(':');
if(sleep_minute < 10){
display.print("0");
}
display.print(sleep_minute);
if(depth == 1){ //if the button has been pressed once on this screen to select the hour's number
sleep_hour = map(pot, 0, 1023, 0, 24); //make the hours number of the current time adjustable with the potentiometer
if(sleep_hour < 10) {display.drawFastHLine(30, 50, 18, WHITE);}//draw an underline under the selected number
else{display.drawFastHLine(20, 50, 36, WHITE);}
}
if(depth == 2){
sleep_minute = map(pot, 0, 1023, 0, 60); //make the minutes number adjustable
if(sleep_hour < 10) {display.drawFastHLine(58, 50, 36, WHITE);}//draw an underline under the selected number
else{display.drawFastHLine(68, 50, 36, WHITE);}
}
}
}
if(manual_mode == 0){ //if switch is in manual mode
//brightness_output = 2*brightness_adjust;
bright = 100;
blue = map(pot, 0, 1023, 0, 100);
display.setCursor(32,0);
display.setTextSize(1);
display.setFont();
display.print("Manual Mode");
}
display.display(); //update display
Serial.print("red:");
Serial.print(red_led_output);
Serial.print(" blue:");
Serial.println(blue_led_output);
}