#define HALT while(true);
#define STATE_NORMAL 0
#define STATE_SHORT 1
#define STATE_LONG 2
const int LED = 13;
// Button input related values
static const byte BUTTON_PIN = 3;
//static const int STATE_NORMAL = 0; // no button activity
//static const int STATE_SHORT = 1; // short button press
//static const int STATE_LONG = 2; // long button press
volatile int resultButton = 0; // global value set by checkButton()
////////////////////////Clock////////////////////////////////////////////
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include "RTClib.h"
RTC_DS1307 rtc;
RTC_DS1307 rtcM;
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define SCREEN_WIDTH 128
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
// Global State
volatile int state = 0;
volatile int short_press_flag = 0; // 0 idle, 1 event pressed
// feature flags
volatile bool sw_flag = true; // stopwatch start or stop
volatile bool sw_alarm = false; // alarm start or stop
// enum of states
enum states {
CLOCK,
STPWATCH,
//ALARM
};
enum states clockStates;
const float pi = 3.14159267 ;
const int clock_center_x = 32;
const int clock_center_y = 32;
int o = 1;
// variables used to calculate coordinates of points on the circle
int x;
int y;
int x1;
int y1;
// variables to store previous values read off RTC module
int second = 0;
int minute;
int hour;
int RTC;
//string time="A";
int m = 0;
int h = 0;
int s = 0 ;
int j = 1;
///////////////////////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(9600);
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
Serial.println(F("Initializing Button pin"));
pinMode(BUTTON_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), checkButton, CHANGE);
Serial.println(F("Button pin initialized"));
/////////////////////////clock void stup///////////////////////////
Serial.begin(9600);
Serial.setTimeout(1000);
if (! rtc.begin()) {
Serial.println("Couldn't find RTC");
Serial.flush();
abort();
}
if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for (;;);
}
if (rtc.isrunning()) {
Serial.println("let's set the time!");
Serial.println("Set the time [hour:min;seconds]: ");
while (j != 0) {
while (Serial.available() == 0) {}
String timeStr = Serial.readString();
int seperatorIndex1 = timeStr.indexOf(":");
int seperatorIndex2 = timeStr.indexOf(":", seperatorIndex1);
h = timeStr.substring(0, seperatorIndex1).toInt(); // every charactors until : from the begining
m = timeStr.substring((seperatorIndex1 + 1), seperatorIndex2).toInt();
s = timeStr.substring(seperatorIndex2 + 1).toInt();
j = 0;
}
Serial.println(h);
Serial.println(m);
Serial.println(s);
rtc.adjust(DateTime(2022, 9, 25, h, m, s));
}
// Show initial display buffer contents on the screen --
// the library initializes this with an Adafruit splash screen.
//display.display();
delay(2000); // Pause for 2 seconds
// Clear the buffer
display.clearDisplay();
draw_clock_face();
display.display();
//////////////////////////////////////////////////////////////////
}
void loop() {
int longButton = 0;
int count = 0;
while (true) {
switch (state) { // was: resultButton
// case STATE_NORMAL: {
// Serial.print(".");
// count++;
// count = count % 10;
// clockState();
// if (count==0) Serial.println("");
// break;
// }
// case STATE_SHORT: {
// Serial.println("Short press has been detected");
// digitalWrite(LED,HIGH);
// delay(1000);
// digitalWrite(LED,LOW);
// resultButton=STATE_NORMAL;
// break;
// }
// case STATE_LONG: {
// Serial.println("Button was pressed for long time");
// digitalWrite(LED,HIGH);
// delay(3000);
// digitalWrite(LED,LOW);
// longButton++;
// resultButton=STATE_NORMAL;
// break;
// }
case CLOCK:
clockState();
if(short_press_flag > 0){
short_press_flag = 0;
}
break;
case STPWATCH:
if(short_press_flag > 0){
sw_flag = !sw_flag;
short_press_flag = 0; // clear the short press flag
}
stopWatch(sw_flag);
//delay(500);
break;
}
if (longButton == 5) {
Serial.println("Halting");
HALT;
}
}
}
//*****************************************************************
void checkButton() {
/*
This function implements software debouncing for a two-state button.
It responds to a short press and a long press and identifies between
the two states. Your sketch can continue processing while the button
function is driven by pin changes.
*/
const unsigned long LONG_DELTA = 1000ul; // hold seconds for a long press
const unsigned long DEBOUNCE_DELTA = 30ul; // debounce time
static int lastButtonStatus = HIGH; // HIGH indicates the button is NOT pressed
int buttonStatus; // button atate Pressed/LOW; Open/HIGH
static unsigned long longTime = 0ul, shortTime = 0ul; // future times to determine is button has been poressed a short or long time
boolean Released = true, Transition = false; // various button states
boolean timeoutShort = false, timeoutLong = false; // flags for the state of the presses
buttonStatus = digitalRead(BUTTON_PIN); // read the button state on the pin "BUTTON_PIN"
timeoutShort = (millis() > shortTime); // calculate the current time states for the button presses
timeoutLong = (millis() > longTime);
if (buttonStatus != lastButtonStatus) { // reset the timeouts if the button state changed
shortTime = millis() + DEBOUNCE_DELTA;
longTime = millis() + LONG_DELTA;
}
Transition = (buttonStatus != lastButtonStatus); // has the button changed state
Released = (Transition && (buttonStatus == HIGH)); // for input pullup circuit
lastButtonStatus = buttonStatus; // save the button status
if ( ! Transition) { //without a transition, there's no change in input
// if there has not been a transition, don't change the previous result
resultButton = STATE_NORMAL | resultButton;
return;
}
if (timeoutLong && Released) { // long timeout has occurred and the button was just released
resultButton = STATE_LONG | resultButton; // ensure the button result reflects a long press
state = (state + 1) % 2;
} else if (timeoutShort && Released) { // short timeout has occurred (and not long timeout) and button was just released
resultButton = STATE_SHORT | resultButton; // ensure the button result reflects a short press
short_press_flag = 1; // only two states required in any mode (clck, stpwatch or alarm)
} else { // else there is no change in status, return the normal state
resultButton = STATE_NORMAL | resultButton; // with no change in status, ensure no change in button status
}
}
//////////////////////////////////////////////kjnjininjknj/////////////////////////////////
void draw_second(int second, int mode) {
y = (24 * cos(pi - (2 * pi) / 60 * second)) + clock_center_y;
x = (24 * sin(pi - (2 * pi) / 60 * second)) + clock_center_x;
if (mode == 1) {
display.drawCircle(x, y, 2, SSD1306_WHITE);
}
if (mode == 0) {
display.drawCircle(x, y, 2, SSD1306_BLACK);
}
}
void draw_hour(int hour, int minute, int mode) {
y = (18 * cos(pi - (2 * pi) / 12 * hour - (2 * PI) / 720 * minute)) + clock_center_y;
x = (18 * sin(pi - (2 * pi) / 12 * hour - (2 * PI) / 720 * minute)) + clock_center_x;
y1 = (18 * cos(pi - (2 * pi) / 12 * hour - (2 * PI) / 720 * minute)) + clock_center_y + 1;
x1 = (18 * sin(pi - (2 * pi) / 12 * hour - (2 * PI) / 720 * minute)) + clock_center_x + 1;
if (mode == 1) {
display.drawLine(clock_center_x, clock_center_y, x, y, SSD1306_WHITE);
display.drawLine(clock_center_x + 1, clock_center_y + 1, x1, y1, SSD1306_WHITE);
}
else {
display.drawLine(clock_center_x, clock_center_y, x, y, SSD1306_BLACK);
display.drawLine(clock_center_x + 1, clock_center_y + 1, x1, y1, SSD1306_BLACK);
}
}
void draw_minute(int minute, int mode) {
y = (24 * cos(pi - (2 * pi) / 60 * minute)) + clock_center_y;
x = (24 * sin(pi - (2 * pi) / 60 * minute)) + clock_center_x;
if (mode == 1)display.drawLine(clock_center_x, clock_center_y, x, y, SSD1306_WHITE); else display.drawLine(clock_center_x, clock_center_y, x, y, SSD1306_BLACK);
}
void draw_clock_face(void) {
// draw the center of the clock
display.drawCircle(clock_center_x, clock_center_y, 3, SSD1306_WHITE);
display.fillCircle(clock_center_x, clock_center_y, 3, SSD1306_WHITE);
// draw hour pointers around the face of a clock
for (int i = 0; i < 12; i++) {
y = (32 * cos(pi - (2 * pi) / 12 * i)) + clock_center_y;
x = (32 * sin(pi - (2 * pi) / 12 * i)) + clock_center_x;
y1 = (28 * cos(pi - (2 * pi) / 12 * i)) + clock_center_y;
x1 = (28 * sin(pi - (2 * pi) / 12 * i)) + clock_center_x;
display.drawLine(x1, y1, x, y, SSD1306_WHITE);
}
// print string "12" at the top of the face of the clock
display.drawCircle(26 * sin(pi) + clock_center_x, (26 * cos(pi)) + clock_center_y, 6, SSD1306_BLACK);
display.fillCircle(26 * sin(pi) + clock_center_x, (26 * cos(pi)) + clock_center_y, 5, SSD1306_BLACK);
display.setTextSize(1); // Normal 1:1 pixel scale
display.setTextColor(SSD1306_WHITE); // Draw white text
display.setCursor(clock_center_x - 3, 0); // Start at top-left corner
display.println(F("12"));
}
void redraw_clock_face_elements(void) {
display.drawCircle(clock_center_x, clock_center_y, 3, SSD1306_WHITE);
display.fillCircle(clock_center_x, clock_center_y, 3, SSD1306_WHITE);
display.setCursor(clock_center_x - 3, 0);
display.println(F("12"));
}
void clockState() {
DateTime RTC = rtc.now();
if (RTC.second() != second) {
draw_second(second, 0);
draw_minute(minute, 0);
draw_hour(hour, minute, 0);
draw_second(RTC.second(), 1);
draw_minute(RTC.minute(), 1);
draw_hour(RTC.hour(), RTC.minute(), 1);
display.display();
antiDigiClock(second, minute, hour);
redraw_clock_face_elements();
second = RTC.second();
minute = RTC.minute();
hour = RTC.hour();
digiClock(second, minute, hour);
redraw_clock_face_elements();
display.display();
}
}
void digiClock(int second, int minute, int hour) {
int x = 72;
int y = 10;
//display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(x, y);
display.println(hour);
// display.display(); // Show initial text
//display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(x + 14, y);
display.println(":");
//display.display(); // Show initial text
//display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(x + 20, y);
display.println(minute);
// display.display();
//display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(x + 34, y);
display.println(":");
//display.display(); // Show initial text
//display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(x + 40, y);
display.println(second);
//display.display();
}
void antiDigiClock(int second, int minute, int hour) {
int x = 72;
int y = 10;
//display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(BLACK);
display.setCursor(x, y);
display.println(hour);
// display.display(); // Show initial text
//display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(BLACK);
display.setCursor(x + 14, y);
display.println(":");
//display.display(); // Show initial text
//display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(BLACK);
display.setCursor(x + 20, y);
display.println(minute);
// display.display();
//display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(BLACK);
display.setCursor(x + 34, y);
display.println(":");
//display.display(); // Show initial text
//display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(BLACK);
display.setCursor(x + 40, y);
display.println(second);
//display.display();
}
void stopWatch(bool flag) {
display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(20, 5);
display.println(F("Stop Watch"));
display.setCursor(20, 25);
int l=0;
int h=0,s=0,m;
if(flag){
//display.println("On");
display.println("Onfgfhjf");
rtcM.adjust(DateTime(2022, 9, 25, 0, 0, 0));
if(flag){
display.println("On");
DateTime rtcK=rtcM.now();
stopWatch_start(s,m,h,0);
stopWatch_start(rtcK.second(),rtcK.minute(),rtcK.hour(),1);
s=rtcK.second();
m=rtcK.minute();
h=rtcK.hour();
display.display();
//}
}
}else{
display.println("off");
display.println("off");
display.clearDisplay();
l=1;
}
display.display();
}
void setAlarm(bool flag) {
display.clearDisplay();
display.setTextSize(1); // Draw 2X-scale text
display.setTextColor(WHITE);
display.setCursor(20, 5);
display.println(F("ALARM"));
display.setCursor(20, 25);
int l=0;
int h=0,s=0,m;
if(flag){
display.println("Onfgfhjf");
//rtcM.adjust(DateTime(2022, 9, 25, 0, 0, 0));
while(l != 1){
display.println("On");
DateTime rtcK=rtcM.now();
stopWatch_start(s,m,h,0);
stopWatch_start(rtcK.second(),rtcK.minute(),rtcK.hour(),1);
s=rtcK.second();
m=rtcK.minute();
h=rtcK.hour();
display.display();
}
}else{
display.println("off");
display.clearDisplay();
l=1;
}
display.display();
}
void stopWatch_start(int second, int minute, int hour, int mode) {
int x = 8;
int y = 35;
if (mode == 0) {
//display.clearDisplay();
mode = BLACK; /// to erase previous time
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(mode);
display.setCursor(x, y);
display.println(hour);
// display.display(); // Show initial text
//display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(mode);
display.setCursor(x + 14, y);
display.println(":");
//display.display(); // Show initial text
//display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(mode);
display.setCursor(x + 20, y);
display.println(minute);
// display.display();
//display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(mode);
display.setCursor(x + 34, y);
display.println(":");
//display.display(); // Show initial text
//display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(mode);
display.setCursor(x + 40, y);
display.println(second);
//display.display();
}
if (mode == 1) {
//display.clearDisplay();
mode = WHITE; /// to display current time
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(mode);
display.setCursor(x, y);
display.println(hour);
// display.display(); // Show initial text
//display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(mode);
display.setCursor(x + 14, y);
display.println(":");
//display.display(); // Show initial text
//display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(mode);
display.setCursor(x + 20, y);
display.println(minute);
// display.display();
//display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(mode);
display.setCursor(x + 34, y);
display.println(":");
//display.display(); // Show initial text
//display.clearDisplay();
display.setTextSize(2); // Draw 2X-scale text
display.setTextColor(mode);
display.setCursor(x + 40, y);
display.println(second);
//display.display();
}
}