//#include <Wire.h>
#include <EEPROM.h>
//#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Fonts/FreeSerifBoldItalic12pt7b.h>
#include <Fonts/FreeSerifBoldItalic9pt7b.h>
#define FRAME_DELAY (4)
#define FRAME_WIDTH (32)
#define FRAME_HEIGHT (32)
#define FRAME_COUNT (sizeof(frames) / sizeof(frames[0]))
int frame = 0;
int lastClk = HIGH;
static unsigned long lastButtonPress2 = 0;
int toggle2=0;
// Define states for the state machine
unsigned long lastButtonPress = 0;
unsigned long lastScreenChangeTime = 0;
//const int debounceDelay = 50; // 50 milliseconds debounce delay
const unsigned long delayBetweenScreens = 3000; // 3 seconds delay between switching screens
const byte PROGMEM frames[][128] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,63,192,14,6,96,112,24,3,192,24,16,1,128,8,32,0,0,4,32,0,0,4,96,0,0,6,96,0,0,6,96,0,0,6,96,0,0,6,32,0,0,4,32,0,0,4,48,0,0,12,16,0,0,8,24,0,0,24,12,0,0,48,6,0,0,96,3,0,0,192,1,128,1,128,0,192,3,0,0,112,14,0,0,24,24,0,0,12,48,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,63,192,14,6,96,112,24,3,192,24,16,1,128,8,32,0,0,4,32,0,0,4,96,0,0,6,96,0,0,6,96,0,0,6,96,0,0,6,32,0,0,4,32,0,0,4,48,0,0,12,16,0,0,8,24,0,0,24,12,0,0,48,6,0,0,96,3,0,0,192,1,128,1,128,0,192,3,0,0,112,14,0,0,24,24,0,0,12,48,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,63,192,14,6,96,112,24,3,192,24,16,1,128,8,32,0,0,4,32,0,0,4,96,0,0,6,96,0,0,6,96,0,0,6,96,0,0,6,32,0,0,4,32,0,0,4,48,0,0,12,16,0,0,8,24,0,0,24,12,0,0,48,6,0,0,96,3,0,0,192,1,128,1,128,0,192,3,0,0,112,14,0,0,24,24,0,0,12,48,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,63,192,14,6,96,112,24,3,192,24,16,1,128,8,32,0,0,4,32,0,0,4,96,0,0,6,96,0,0,6,96,0,0,6,96,0,0,6,32,0,0,4,32,0,0,4,48,0,0,12,16,0,0,8,24,0,0,24,12,0,0,48,6,0,0,96,3,0,0,192,1,128,1,128,0,192,3,0,0,112,14,0,0,24,24,0,0,12,48,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,112,14,0,3,252,63,192,6,6,96,96,12,3,192,48,24,1,128,24,16,0,0,8,16,0,0,8,48,0,0,12,48,0,0,12,16,0,0,8,16,0,0,8,16,0,0,8,24,0,0,24,12,0,0,48,4,0,0,32,6,0,0,96,3,0,0,192,1,128,1,128,0,192,3,0,0,48,12,0,0,24,24,0,0,14,112,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,248,31,0,1,158,113,128,6,3,192,96,4,1,128,32,8,0,0,16,8,0,0,16,8,0,0,16,8,0,0,16,8,7,224,16,8,7,224,16,8,7,224,16,4,3,192,32,6,1,128,96,2,0,0,64,1,0,0,128,0,128,1,0,0,64,2,0,0,48,12,0,0,24,24,0,0,12,48,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,64,2,0,15,248,31,240,28,7,224,56,48,3,192,12,96,1,128,6,64,0,0,2,192,0,0,3,128,62,124,1,128,127,254,1,128,255,255,1,128,255,255,1,128,255,255,1,192,255,255,3,64,127,254,2,64,127,254,2,96,63,252,6,48,63,248,12,16,15,240,8,24,7,224,24,12,3,192,48,22,0,0,96,3,0,0,192,0,192,3,134,3,96,6,192,0,56,28,0,0,28,60,0,0,22,96,0,0,3,192,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,64,2,0,16,1,130,16,24,1,128,16,3,248,63,192,15,254,127,240,31,255,255,248,31,255,255,248,63,255,255,252,63,255,255,252,127,255,255,254,127,255,255,254,127,255,255,254,127,255,255,254,63,255,255,252,63,255,255,252,63,255,255,252,31,255,255,248,31,255,255,248,15,255,255,240,7,255,255,224,3,255,255,192,49,255,255,128,0,255,255,4,0,127,254,0,2,31,248,64,6,15,240,96,0,3,192,0,0,49,132,0,0,32,0,0,0,0,0,0},
{0,0,0,0,0,65,130,0,0,65,130,8,48,0,128,24,0,0,0,0,3,248,63,192,15,254,127,240,31,255,255,248,31,255,255,248,63,255,255,252,63,255,255,252,127,255,255,254,127,255,255,254,127,255,255,254,127,255,255,254,63,255,255,252,63,255,255,252,63,255,255,252,31,255,255,248,31,255,255,248,15,255,255,240,7,255,255,224,3,255,255,192,33,255,255,128,96,255,255,4,0,127,254,4,0,31,248,0,4,15,240,32,12,3,192,48,0,1,132,0,0,32,6,0,0,32,2,0},
{0,64,130,0,0,65,130,0,32,0,0,8,48,0,0,8,0,0,0,0,3,248,63,192,15,254,127,240,31,255,255,248,31,255,255,248,63,255,255,252,63,255,255,252,127,255,255,254,127,255,255,254,127,255,255,254,127,255,255,254,63,255,255,252,63,255,255,252,63,255,255,252,31,255,255,248,31,255,255,248,15,255,255,240,7,255,255,224,3,255,255,192,1,255,255,128,64,255,255,4,0,127,254,6,0,31,248,0,0,15,240,0,12,3,192,48,8,1,128,16,0,32,2,0,0,96,2,0},
{0,64,130,0,0,0,0,0,32,0,0,8,0,0,0,0,0,0,0,0,3,248,63,192,15,254,127,240,31,255,255,248,31,255,255,248,63,255,255,252,63,255,255,252,127,255,255,254,127,255,255,254,127,255,255,254,127,255,255,254,63,255,255,252,63,255,255,252,63,255,255,252,31,255,255,248,31,255,255,248,15,255,255,240,7,255,255,224,3,255,255,192,1,255,255,128,64,255,255,0,0,127,254,2,0,31,248,0,0,15,240,0,8,3,192,0,8,1,128,16,0,0,0,0,0,96,2,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,63,192,15,254,127,240,31,255,255,248,31,255,255,248,63,255,255,252,63,255,255,252,127,255,255,254,127,255,255,254,127,255,255,254,127,255,255,254,63,255,255,252,63,255,255,252,63,255,255,252,31,255,255,248,31,255,255,248,15,255,255,240,7,255,255,224,3,255,255,192,1,255,255,128,0,255,255,0,0,127,254,0,0,31,248,0,0,15,240,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,63,192,15,254,127,240,31,255,255,248,31,255,255,248,63,255,255,252,63,255,255,252,127,255,255,254,127,255,255,254,127,255,255,254,127,255,255,254,63,255,255,252,63,255,255,252,63,255,255,252,31,255,255,248,31,255,255,248,15,255,255,240,7,255,255,224,3,255,255,192,1,255,255,128,0,255,255,0,0,127,254,0,0,31,248,0,0,15,240,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,63,192,15,254,127,240,31,255,255,248,31,255,255,248,63,255,255,252,63,255,255,252,127,255,255,254,127,255,255,254,127,255,255,254,127,255,255,254,63,255,255,252,63,255,255,252,63,255,255,252,31,255,255,248,31,255,255,248,15,255,255,240,7,255,255,224,3,255,255,192,1,255,255,128,0,255,255,0,0,127,254,0,0,31,248,0,0,15,240,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,63,192,15,254,127,240,31,255,255,248,31,255,255,248,63,255,255,252,63,255,255,252,127,255,255,254,127,255,255,254,127,255,255,254,127,255,255,254,63,255,255,252,63,255,255,252,63,255,255,252,31,255,255,248,31,255,255,248,15,255,255,240,7,255,255,224,3,255,255,192,1,255,255,128,0,255,255,0,0,127,254,0,0,31,248,0,0,15,240,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,63,192,15,254,127,240,31,255,255,248,31,255,255,248,63,255,255,252,63,255,255,252,127,255,255,254,127,255,255,254,127,255,255,254,127,255,255,254,63,255,255,252,63,255,255,252,63,255,255,252,31,255,255,248,31,255,255,248,15,255,255,240,7,255,255,224,3,255,255,192,1,255,255,128,0,255,255,0,0,127,254,0,0,31,248,0,0,15,240,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,63,192,15,254,127,240,31,255,255,248,31,255,255,248,63,255,255,252,63,255,255,252,127,255,255,254,127,255,255,254,127,255,255,254,127,255,255,254,63,255,255,252,63,255,255,252,63,255,255,252,31,255,255,248,31,255,255,248,15,255,255,240,7,255,255,224,3,255,255,192,1,255,255,128,0,255,255,0,0,127,254,0,0,31,248,0,0,15,240,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,63,192,15,254,127,240,31,255,255,248,31,255,255,248,63,255,255,252,63,255,255,252,127,255,255,254,127,255,255,254,127,255,255,254,127,255,255,254,63,255,255,252,63,255,255,252,63,255,255,252,31,255,255,248,31,255,255,248,15,255,255,240,7,255,255,224,3,255,255,192,1,255,255,128,0,255,255,0,0,127,254,0,0,31,248,0,0,15,240,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,31,192,15,252,63,240,31,255,255,248,63,255,255,252,63,255,255,252,127,255,255,254,127,255,255,254,127,255,255,254,255,255,255,255,255,255,255,255,127,255,255,254,127,255,255,254,127,255,255,254,127,255,255,254,63,255,255,252,63,255,255,252,31,255,255,248,15,255,255,240,7,255,255,224,3,255,255,192,1,255,255,128,0,255,255,0,0,127,254,0,0,31,248,0,0,15,240,0,0,3,192,0,0,1,128,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7,248,31,224,31,254,127,248,63,255,255,252,127,255,255,254,127,255,255,254,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,127,255,255,254,127,255,255,254,127,255,255,254,63,255,255,252,31,255,255,248,31,255,255,248,15,255,255,240,7,255,255,224,3,255,255,192,0,255,255,0,0,127,254,0,0,63,252,0,0,15,240,0,0,7,224,0,0,3,192,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,240,15,128,7,252,63,224,15,254,127,240,31,255,255,248,63,255,255,252,127,255,255,252,127,255,255,254,127,255,255,254,127,255,255,254,127,255,255,254,127,255,255,254,127,255,255,254,63,255,255,252,63,255,255,252,63,255,255,252,31,255,255,248,15,255,255,240,15,255,255,240,7,255,255,224,3,255,255,128,0,255,255,0,0,127,254,0,0,63,252,0,0,15,240,0,0,7,224,0,0,1,128,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,31,192,7,254,127,224,15,255,255,240,31,255,255,248,63,255,255,248,63,255,255,252,63,255,255,252,63,255,255,252,63,255,255,252,63,255,255,252,63,255,255,252,63,255,255,252,31,255,255,248,31,255,255,248,15,255,255,240,7,255,255,224,7,255,255,224,3,255,255,192,0,255,255,0,0,127,254,0,0,63,252,0,0,31,240,0,0,7,224,0,0,3,192,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,31,192,6,14,112,96,12,3,192,48,24,1,128,24,48,24,24,12,32,126,126,4,32,255,255,4,33,255,255,4,33,255,255,132,33,255,255,132,33,255,255,132,48,255,255,12,16,255,255,8,24,127,254,24,8,63,252,16,12,31,248,48,6,15,240,96,3,7,224,192,1,129,129,128,0,96,6,0,0,48,12,0,0,24,24,0,0,6,96,0,0,3,192,0,0,1,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,63,192,14,6,96,112,24,3,192,24,16,1,128,8,32,0,0,4,32,0,0,4,96,0,0,6,96,0,0,6,96,6,96,6,96,15,240,6,32,15,240,4,32,15,240,4,48,7,224,12,16,3,192,8,24,0,0,24,12,0,0,48,6,0,0,96,3,0,0,192,1,128,1,128,0,192,3,0,0,112,14,0,0,24,24,0,0,12,48,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,63,192,14,6,96,112,24,3,192,24,16,1,128,8,32,0,0,4,32,0,0,4,96,0,0,6,96,0,0,6,96,0,0,6,96,0,0,6,32,1,128,4,32,1,128,4,48,0,0,12,16,0,0,8,24,0,0,24,12,0,0,48,6,0,0,96,3,0,0,192,1,128,1,128,0,192,3,0,0,112,14,0,0,24,24,0,0,12,48,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,63,192,14,6,96,112,24,3,192,24,16,1,128,8,32,0,0,4,32,0,0,4,96,0,0,6,96,0,0,6,96,0,0,6,96,0,0,6,32,0,0,4,32,0,0,4,48,0,0,12,16,0,0,8,24,0,0,24,12,0,0,48,6,0,0,96,3,0,0,192,1,128,1,128,0,192,3,0,0,112,14,0,0,24,24,0,0,12,48,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,63,192,14,6,96,112,24,3,192,24,16,1,128,8,32,0,0,4,32,0,0,4,96,0,0,6,96,0,0,6,96,0,0,6,96,0,0,6,32,0,0,4,32,0,0,4,48,0,0,12,16,0,0,8,24,0,0,24,12,0,0,48,6,0,0,96,3,0,0,192,1,128,1,128,0,192,3,0,0,112,14,0,0,24,24,0,0,12,48,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3,248,63,192,14,6,96,112,24,3,192,24,16,1,128,8,32,0,0,4,32,0,0,4,96,0,0,6,96,0,0,6,96,0,0,6,96,0,0,6,32,0,0,4,32,0,0,4,48,0,0,12,16,0,0,8,24,0,0,24,12,0,0,48,6,0,0,96,3,0,0,192,1,128,1,128,0,192,3,0,0,112,14,0,0,24,24,0,0,12,48,0,0,3,192,0,0,1,128,0,0,0,0,0,0,0,0,0}
};
#define encoderPinA 2 // Rotary encoder gpio pin
#define encoderPinB 4 // Rotary encoder gpio pin
#define encoderPress 3
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
struct DateTime {
int year;
int month;
int day;
int hour;
int minute;
int second;
};
#define EEPROM_ADDRESS_FIRST_DATE 0 // Starting address in EEPROM for the first date
#define EEPROM_ADDRESS_SECOND_DATE (EEPROM_ADDRESS_FIRST_DATE + sizeof(DateTime)) // Starting address in EEPROM for the second date
#define EEPROM_SIZE sizeof(DateTime)
DateTime startTime = {2024, 1, 1, 0, 0, 0}; // Example start time
DateTime eventTime = {2024, 1, 1, 0, 0, 0}; // Example end time
DateTime difference;
// Define constants for screen states
//const int SCREEN_OPTION_1 = 1;
//const int SCREEN_OPTION_2 = 2;
//const int SCREEN_OPTION_3 = 3;
//const int SCREEN_OPTION_4 = 4;
volatile int encoderValue = 0;
unsigned long previousMillis = 0;
const unsigned long debounceDelay = 200; // Adjust as needed
unsigned long lastDebounceTime = 0;
//volatile int aState, bState,aLastState;
//int buttonState = 1;
volatile int option=0;
int screen2=0,screen2option=0;
static int lastValue=0;
const unsigned long IDLE_TIMEOUT = 18000;
const long interval = 1000;
int mode=0;
int rtmode=0;
unsigned long lastUserInputMillis = 0;
int eventmode=0;
unsigned long currentMillis;
DateTime eventDateTime;
int selectedYear = 2024;
int selectedMonth = 1;
int selectedDay = 1;
int selectedHour = 0;
int selectedMinute = 0;
int selectedSecond = 0;
int rselectedYear = 2024;
int rselectedMonth = 1;
int rselectedDay = 1;
int rselectedHour = 0;
int rselectedMinute = 0;
int rselectedSecond = 0;
enum DateTimeComponent {
YEAR,
MONTH,
DAY,
HOUR,
MINUTE,
SECOND,
EXIT
};
DateTimeComponent currentComponent = HOUR;//SECOND;//YEAR;
int isBefore(DateTime endTime, DateTime startTime) {
if (endTime.year < startTime.year ||
(endTime.year == startTime.year && endTime.month < startTime.month) ||
(endTime.year == startTime.year && endTime.month == startTime.month && endTime.day < startTime.day) ||
(endTime.year == startTime.year && endTime.month == startTime.month && endTime.day == startTime.day && endTime.hour < startTime.hour) ||
(endTime.year == startTime.year && endTime.month == startTime.month && endTime.day == startTime.day && endTime.hour == startTime.hour && endTime.minute < startTime.minute) ||
(endTime.year == startTime.year && endTime.month == startTime.month && endTime.day == startTime.day && endTime.hour == startTime.hour && endTime.minute == startTime.minute && endTime.second < startTime.second)) {
return 1; // End time is before start time
} else {
return 0; // End time is not before start time
}
}
void serializeDateTime( DateTime &dateTime, int address) {
byte buffer[sizeof(DateTime)];
memcpy(buffer, &dateTime, sizeof(DateTime));
for (int i = 0; i < sizeof(DateTime); i++) {
EEPROM.update(address + i, buffer[i]);
}
}
void deserializeDateTime(DateTime &dateTime, int address) {
byte buffer[sizeof(DateTime)];
for (int i = 0; i < sizeof(DateTime); i++) {
buffer[i] = EEPROM.read(address + i);
}
memcpy(&dateTime, buffer, sizeof(DateTime));
}
void handle(){
if(screen2==0)
mode=1;
lastUserInputMillis = millis();
if(eventmode==1){
switch (currentComponent) {
case YEAR:
currentComponent = EXIT;
break;
case MONTH:
currentComponent = DAY;
break;
case DAY:
currentComponent = YEAR;
break;
case HOUR:
currentComponent = MINUTE;
break;
case MINUTE:
currentComponent = SECOND;
break;
case SECOND:
currentComponent = MONTH;
break;
case EXIT:
eventmode=0;
mode=0;
currentComponent = HOUR;
break;
}
}
}
Adafruit_SSD1306 oled(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
void drawAnimation() {
oled.clearDisplay();
oled.drawBitmap(48, 16, frames[frame], FRAME_WIDTH, FRAME_HEIGHT, 1);
oled.display();
frame = (frame + 1) % FRAME_COUNT;
delay(FRAME_DELAY);
}
bool setEventMode = false;
void showrealtime()
{
unsigned long starTime = millis();
while (millis() - starTime < 4000){
oled.clearDisplay();
oled.setFont(&FreeSerifBoldItalic12pt7b);
oled.setTextSize(1);
oled.setTextColor(WHITE);
oled.setCursor(0, 15);
oled.print("Real Time :");
oled.setFont(&FreeSerifBoldItalic9pt7b);
oled.setTextSize(1);
oled.setTextColor(WHITE);
oled.setCursor(0, 40);
oled.print(startTime.hour);
oled.print(" : ");
oled.print(startTime.minute);
oled.print(" : ");
oled.print(startTime.second);
oled.setCursor(0, 60);
oled.print(startTime.month);
oled.print(" / ");
oled.print(startTime.day);
oled.print(" / ");
oled.println(startTime.year);
oled.display();
if(mode==1){
delay(300);
if(digitalRead(encoderPress)==HIGH){
mode=0;
}
else{
mode=0;
eventmode=1;
rtmode=1;
setevent();
}
}
}
}
void setevent() {
while (eventmode == 1) {
updateSelectedDateTime();
oled.clearDisplay();
oled.setFont();
oled.setTextSize(1);
oled.setTextColor(SSD1306_WHITE);
oled.setCursor(0, 0);
if (rtmode == 1) {
oled.print("Set Real Time:");
oled.setFont();
oled.setTextSize(2);
oled.setCursor(0, 15);
if (currentComponent == HOUR) {
oled.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
} else {
oled.setTextColor(SSD1306_WHITE);
}
oled.print(rselectedHour);
oled.print(':');
if (currentComponent == MINUTE) {
oled.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
} else {
oled.setTextColor(SSD1306_WHITE);
}
oled.print(rselectedMinute);
oled.print(':');
if (currentComponent == SECOND) {
oled.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
} else {
oled.setTextColor(SSD1306_WHITE);
}
oled.print(rselectedSecond);
oled.print(':');
oled.setCursor(0, 35);
if (currentComponent == MONTH) {
oled.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
} else {
oled.setTextColor(SSD1306_WHITE);
}
oled.print(rselectedMonth);
oled.print('/');
if (currentComponent == DAY) {
oled.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
} else {
oled.setTextColor(SSD1306_WHITE);
}
oled.print(rselectedDay);
oled.print('/');
if (currentComponent == YEAR) {
oled.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
} else {
oled.setTextColor(SSD1306_WHITE);
}
oled.print(rselectedYear);
oled.setTextSize(1);
oled.setCursor(0, 55);
if (currentComponent == EXIT) {
oled.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
} else {
oled.setTextColor(SSD1306_WHITE);
}
oled.println("EXIT");
oled.display();
while (millis() - lastUserInputMillis > IDLE_TIMEOUT) {
oled.clearDisplay();
drawAnimation();
delay(500);
}
} else {
oled.println("Set Event Date/Time:");
oled.setTextSize(2);
oled.setCursor(0, 15);
oled.setTextColor(SSD1306_WHITE, SSD1306_BLACK);
if (currentComponent == HOUR) {
oled.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
} else {
oled.setTextColor(SSD1306_WHITE);
}
oled.print(selectedHour);
oled.print(':');
if (currentComponent == MINUTE) {
oled.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
} else {
oled.setTextColor(SSD1306_WHITE);
}
oled.print(selectedMinute);
oled.print(':');
if (currentComponent == SECOND) {
oled.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
} else {
oled.setTextColor(SSD1306_WHITE);
}
oled.print(selectedSecond);
oled.setCursor(0, 35);
if (currentComponent == MONTH) {
oled.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
} else {
oled.setTextColor(SSD1306_WHITE);
}
oled.print(selectedMonth);
oled.print('/');
if (currentComponent == DAY) {
oled.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
} else {
oled.setTextColor(SSD1306_WHITE);
}
oled.print(selectedDay);
oled.print('/');
if (currentComponent == YEAR) {
oled.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
} else {
oled.setTextColor(SSD1306_WHITE);
}
oled.print(selectedYear);
oled.setTextSize(1);
oled.setCursor(0, 55);
if (currentComponent == EXIT) {
oled.setTextColor(SSD1306_BLACK, SSD1306_WHITE);
} else {
oled.setTextColor(SSD1306_WHITE);
}
oled.println("EXIT");
oled.display();
while (millis() - lastUserInputMillis > IDLE_TIMEOUT) {
oled.clearDisplay();
drawAnimation();
delay(500);
}
}
}
eventDateTime.year = selectedYear;
eventDateTime.month = selectedMonth;
eventDateTime.day = selectedDay;
eventDateTime.hour = selectedHour;
eventDateTime.minute = selectedMinute;
eventDateTime.second = selectedSecond;
if (rtmode == 1) {
startTime.year = rselectedYear;
startTime.month = rselectedMonth;
startTime.day = rselectedDay;
startTime.hour = rselectedHour;
startTime.minute = rselectedMinute;
startTime.second = rselectedSecond;
EEPROM.write(10, 0);
rtmode = 0;
} else {
eventTime.year = eventDateTime.year;
eventTime.month = eventDateTime.month;
eventTime.day = eventDateTime.day;
eventTime.hour = eventDateTime.hour;
eventTime.minute = eventDateTime.minute;
eventTime.second = eventDateTime.second;
serializeDateTime(startTime, EEPROM_ADDRESS_SECOND_DATE);
}
if (isBefore(startTime, eventTime)) {
oled.clearDisplay();
oled.setFont(&FreeSerifBoldItalic12pt7b);
oled.setTextSize(2);
oled.setTextColor(SSD1306_WHITE);
oled.setCursor(0, 40);
oled.print("Error");
oled.display();
delay(1000);
eventmode = 1;
currentComponent = YEAR;
setevent();
}
}
void updateSelectedDateTime() {
//buttonState = digitalRead(encoderPress);
int newValue = encoderValue;
if ((millis() - lastDebounceTime) > debounceDelay) {
if (newValue != lastValue) {
lastDebounceTime = millis();
switch (currentComponent) {
case SECOND:
if (rtmode == 1) {
if (newValue > lastValue) {
rselectedSecond++;
} else {
rselectedSecond--;
}
} else {
if (newValue > lastValue) {
selectedSecond++;
} else {
selectedSecond--;
}
}
break;
case MINUTE:
if (rtmode == 1) {
if (newValue > lastValue) {
rselectedMinute++;
} else {
rselectedMinute--;
}
} else {
if (newValue > lastValue) {
selectedMinute++;
} else {
selectedMinute--;
}
}
break;
case HOUR:
if (rtmode == 1) {
if (newValue > lastValue) {
rselectedHour++;
} else {
rselectedHour--;
}
} else {
if (newValue > lastValue) {
selectedHour++;
} else {
selectedHour--;
}
}
break;
case DAY:
if (rtmode == 1) {
if (newValue > lastValue) {
rselectedDay++;
} else {
rselectedDay--;
}
} else {
if (newValue > lastValue) {
selectedDay++;
} else {
selectedDay--;
}
}
break;
case MONTH:
if (rtmode == 1) {
if (newValue > lastValue) {
rselectedMonth++;
} else {
rselectedMonth--;
}
} else {
if (newValue > lastValue) {
selectedMonth++;
} else {
selectedMonth--;
}
}
break;
case YEAR:
if (rtmode == 1) {
if (newValue > lastValue) {
rselectedYear++;
} else {
rselectedYear--;
}
} else {
if (newValue > lastValue) {
selectedYear++;
} else {
selectedYear--;
}
}
break;
case EXIT:
currentComponent = HOUR; // Change to the first component after exiting
break;
}
//Serial.println(newValue);
//Serial.println(selectedHour);
// Constrain the values to their valid ranges
selectedYear = constrain(selectedYear, 0, 9999);
selectedMonth = constrain(selectedMonth, 1, 12);
selectedDay = constrain(selectedDay, 1, dayInMonth(selectedYear, selectedMonth));
selectedHour = constrain(selectedHour, 0, 23);
selectedMinute = constrain(selectedMinute, 0, 59);
selectedSecond = constrain(selectedSecond, 0, 59);
// Real time mode variables constraints
rselectedYear = constrain(rselectedYear, 0, 9999);
rselectedMonth = constrain(rselectedMonth, 1, 12);
rselectedDay = constrain(rselectedDay, 1, dayInMonth(rselectedYear, rselectedMonth));
rselectedHour = constrain(rselectedHour, 0, 23);
rselectedMinute = constrain(rselectedMinute, 0, 59);
rselectedSecond = constrain(rselectedSecond, 0, 59);
}
}
lastValue = newValue;
}
int dayInMonth(int year, int month) {
if (month == 2) {
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)) {
return 29;
} else {
return 28;
}
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
return 30;
} else {
return 31;
}
}
void incrementSecond(DateTime &dt) {
dt.second++;
if (dt.second >= 60) {
dt.second = 0;
dt.minute++;
if (dt.minute >= 60) {
dt.minute = 0;
dt.hour++;
if (dt.hour >= 24) {
dt.hour = 0;
dt.day++;
int daysInMonth = dayInMonth(dt.year, dt.month);
if (dt.day > daysInMonth) {
dt.day = 1;
dt.month++;
if (dt.month > 12) {
dt.month = 1;
dt.year++;
}
}
}
}
}
}
DateTime subtractDateTime(DateTime dt1, DateTime dt2) {
DateTime result;
if (dt1.second < dt2.second) {
dt1.second += 60;
dt1.minute--;
}
result.second = dt1.second - dt2.second;
if (dt1.minute < dt2.minute) {
dt1.minute += 60;
dt1.hour--;
}
result.minute = dt1.minute - dt2.minute;
if (dt1.hour < dt2.hour) {
dt1.hour += 24;
dt1.day--;
}
result.hour = dt1.hour - dt2.hour;
if (dt1.day < dt2.day) {
int daysInMonth = dayInMonth(dt1.year, dt1.month);
dt1.day += daysInMonth;
dt1.month--;
}
result.day = dt1.day - dt2.day;
if (dt1.month < dt2.month) {
dt1.month += 12;
dt1.year--;
}
result.month = dt1.month - dt2.month;
result.year = dt1.year - dt2.year;
return result;
}
bool isLeapYear(int year) {
return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
}
int daysInYear(int year) {
return isLeapYear(year) ? 366 : 365;
}
int dayOfYear(DateTime date) {
int days = 0;
for (int month = 1; month < date.month; month++) {
days += dayInMonth(date.year, month);
}
days += date.day;
return days;
}
unsigned long int calculateTotalDays(DateTime start, DateTime end) {
unsigned long int totalDays = 0;
// Calculate the total number of days for each year between start and end
for (int year = start.year; year < end.year; year++) {
totalDays += daysInYear(year);
}
// Calculate the remaining days in the start year
totalDays += dayOfYear(end) - dayOfYear(start);
return totalDays;
}
void displayElapsedTimeOption1() {
DateTime difference = subtractDateTime(startTime,eventTime);
int years = difference.year;
int months = difference.month;
int days = difference.day;
int hours = difference.hour;
int minutes = difference.minute;
int seconds = difference.second;
if (seconds < 0) {
seconds += 60;
minutes--;
}
if (minutes < 0) {
minutes += 60;
hours--;
}
if (hours < 0) {
hours += 24;
days--;
}
int daysInMonth = dayInMonth(eventTime.year, eventTime.month);
if (days < 0) {
days += daysInMonth;
months--;
}
if(months < 0) {
months += 12;
years--;
}
oled.setFont(&FreeSerifBoldItalic12pt7b);
oled.clearDisplay();
oled.setTextSize(1);
oled.setTextColor(WHITE);
oled.setCursor(0, 15);
oled.print("Together for");
oled.setFont(&FreeSerifBoldItalic9pt7b);
oled.setTextSize(1);
oled.setTextColor(WHITE,SSD1306_BLACK);
oled.setCursor(0, 40);
// oled.setCursor(0, 60);
oled.print(years);
oled.print("Y ");
oled.print(" / ");
oled.print(months);
oled.print("M ");
oled.print(" / ");
oled.print(days);
oled.print("D");
oled.print(" ");
oled.print(hours);
oled.print("h ");
oled.print(" : ");
oled.print(minutes);
oled.print(" m ");
oled.print(" : ");
oled.print(seconds);
oled.print("s");
oled.display();
screen2=0;
}
void displayElapsedTimeOption2() {
//static int screen2option = 0;
static unsigned long lastDebounceTime = 0;
unsigned long currentMillis = millis();
if (currentMillis - lastButtonPress >= debounceDelay) {
lastButtonPress = currentMillis;
unsigned long int totalDays = calculateTotalDays(eventTime, startTime);
oled.setFont(&FreeSerifBoldItalic12pt7b);
oled.clearDisplay();
oled.setTextSize(1);
oled.setTextColor(WHITE);
oled.setCursor(0, 15);
oled.print("Together for");
if (digitalRead(encoderPress) == LOW) {
screen2option++;
if (screen2option > 1) {
screen2option = 0;
}
lastScreenChangeTime = currentMillis; // Record the time of screen change
}
switch (screen2option) {
case 0:
if (totalDays >= 1000000) {
oled.setTextColor(WHITE);
oled.setCursor(0, 45);
oled.println("Million days");
} else {
oled.setCursor(0, 45);
oled.print(totalDays);
oled.println(" Days");
}
break;
case 1:
if (currentMillis - lastScreenChangeTime >= delayBetweenScreens) {
toggle2++;// screen2option = 0; // Switch back to case 0 after delayBetweenScreens
lastScreenChangeTime = currentMillis; // Record the time of screen change
}
if(toggle2==0)
{
oled.setCursor(0, 40);
oled.print(totalDays / 7);
oled.print(" Weeks ");
//oled.print(totalDays % 7);
//oled.println(" Days");
}
else if(toggle2==1)
{
oled.setCursor(0, 40);
//oled.print(totalDays / 365);
//oled.print(" Y ");
oled.print(totalDays / 30);
oled.println(" Months ");
}
else
{
toggle2=0;
screen2option=0;
}
break;
}
oled.display();
}
screen2 = 1;
}
///////////////////
void displayElapsedTimeOption3() {
oled.clearDisplay();
oled.setFont(&FreeSerifBoldItalic9pt7b);
oled.setTextSize(1);
oled.setTextColor(WHITE);
oled.setCursor(0, 30);
oled.println("Andre & Wendy");
oled.display();
screen2=0;
}
//////////////////
//////////////////////
void displayElapsedTimeOption4() {
oled.clearDisplay();
oled.setFont(&FreeSerifBoldItalic9pt7b);
oled.setTextSize(1);
oled.setTextColor(WHITE);
oled.setCursor(0, 15);
oled.println("Today, I choose");
oled.setCursor(0, 35);
oled.println("to love you with");
oled.setCursor(0, 55);
oled.println("my very best self");
oled.display();
screen2=0;
}
void handleEncoder()
{
int newClk = digitalRead(encoderPinA);
if (newClk != lastClk) {
// There was a change on the CLK pin
lastClk = newClk;
int dtValue = digitalRead(encoderPinB);
if (newClk == LOW && dtValue == HIGH) {
//Serial.println("Rotated clockwise");
option++;
encoderValue++;
if(option>3)
option=0;
//Serial.print("Option=");
// Serial.println(option);
}
if (newClk == LOW && dtValue == LOW) {
//Serial.println("Rotated counterclockwise ");
option--;
encoderValue--;
if(option<0)
option=3;
//Serial.print("Option=");
// Serial.println(option);
}
}
lastUserInputMillis = millis();
}
unsigned long int m=0;
ISR(TIMER1_COMPA_vect) {
incrementSecond(startTime);
}
void setup() {
pinMode(encoderPinA, INPUT_PULLUP);
pinMode(encoderPinB, INPUT_PULLUP);
pinMode(encoderPress, INPUT_PULLUP);
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(encoderPinA), handleEncoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(encoderPinB), handleEncoder, CHANGE);
attachInterrupt(digitalPinToInterrupt(encoderPress), handle, FALLING);
m=EEPROM.read(10);
if(m==255) {
DateTime startTime = {2024, 2, 8, 0, 0, 0}; // Example start time
DateTime eventTime = {2024, 2, 8, 0, 0, 0}; // Example end time
} else {
deserializeDateTime(startTime, EEPROM_ADDRESS_FIRST_DATE);
deserializeDateTime(eventTime, EEPROM_ADDRESS_SECOND_DATE);
}
if (!oled.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed"));
while (true);
}
cli(); // Disable interrupts
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 15624; // 1 Hz (16000000/1024)
TCCR1B |= (1 << WGM12); // CTC mode
TCCR1B |= (1 << CS12) | (1 << CS10); // 1024 prescaler
TIMSK1 |= (1 << OCIE1A); // Enable Timer1 compare interrupt
sei(); // Enable interrupts
}
void loop() {
if(option==0){
displayElapsedTimeOption3();
} else if (option==1) {
displayElapsedTimeOption1();
}
else if (option==2) {
displayElapsedTimeOption2();
}
else if (option==3) {
displayElapsedTimeOption4();
}
if(mode==1 && screen2==0)
{
delay(500);
if(digitalRead(encoderPress)==HIGH)
{
mode=0;
showrealtime();
}
else
{
mode=0;
eventmode=1;
setevent();
}
}
currentMillis=millis();
if (currentMillis - previousMillis >= 1800000) {
DateTime currentTime = startTime;
serializeDateTime(currentTime, EEPROM_ADDRESS_FIRST_DATE);
previousMillis = currentMillis;
}
while (millis() - lastUserInputMillis > IDLE_TIMEOUT) {
oled.clearDisplay();
drawAnimation();
delay(500);
}
}