#include "math.h"
#include <TM1637Display.h>
#include <TimeLib.h>
#include <DS1307RTC.h>
#include "Button.h"
//#define OUR_latitude 24.931011110330267 //55.769222 // 55.751244
//#define OUR_longitude 67.14689472156097 // 12.507237 //37.618423
//#define OUR_timezone 300
//#define OUR_latitude 53.52155 //55.769222 // 55.751244
//#define OUR_longitude -113.51785 // 12.507237 //37.618423
//#define OUR_timezone -420
double OUR_latitude;
double OUR_longitude;
int OUR_timezone;
// lahore, karachi, cop, edm
double latitude_of[4] = {31.5204, 24.931011, 55.769222, 53.52155};
double longitude_of[4] = {74.3587, 67.146894, 12.507237, -113.51785};
int timezone_of[4] = {300, 300, 60, -420};
#define fajr_angle 18
#define isha_angle 18
#define asr_l 2
#define CLK 7
#define DIO 8
#define CLK2 6
#define DIO2 5
#define buzzer A3
Button Set(A2); // Connect your button between pin 2 and GND
Button Incr(A1); // Connect your button between pin 3 and GND
Button Decr(A0); // Connect your button between pin 4 and GND
bool Hour12Format = true;
bool pre_beeped = false;
bool post_beeped = false;
bool colonState = 0;
int DST = 0;
byte city = 1;
TM1637Display display(CLK, DIO);
TM1637Display display2(CLK2, DIO2);
tmElements_t tm;
time_t current_time;
const uint8_t SEG_DST [] = {
SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // d
SEG_A | SEG_C | SEG_D | SEG_F | SEG_G, // S
SEG_D | SEG_G | SEG_E | SEG_F, // t
};
const uint8_t SEG_On [] = {
SEG_A | SEG_D | SEG_B | SEG_C | SEG_E | SEG_F, // O
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F, // n
};
const uint8_t SEG_Off [] = {
SEG_A | SEG_D | SEG_B | SEG_C | SEG_E | SEG_F, // O
SEG_A | SEG_E | SEG_F | SEG_G, // F
SEG_A | SEG_E | SEG_F | SEG_G, // F
};
const uint8_t SEG_city [] = {
SEG_A | SEG_D | SEG_E | SEG_F, // C
SEG_B | SEG_C, // I
SEG_D | SEG_G | SEG_E | SEG_F, // t
SEG_B | SEG_C | SEG_D | SEG_F | SEG_G, // y
};
const uint8_t SEG_allcities [] = {
SEG_D | SEG_E | SEG_F, // L
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // A
SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // H
SEG_D | SEG_E | SEG_F | SEG_G, // K
SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // H
SEG_B | SEG_C, // I
SEG_A | SEG_D | SEG_E | SEG_F, // C
SEG_A | SEG_D | SEG_B | SEG_C | SEG_E | SEG_F, // O
SEG_A | SEG_E | SEG_F | SEG_G | SEG_B, // P
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G, // E
SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // d
SEG_A | SEG_B | SEG_C | SEG_D | SEG_G, // 3
};
const uint8_t SEG_year[] = {
SEG_B | SEG_C | SEG_D | SEG_F | SEG_G, // y
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G, // E
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // A
SEG_E | SEG_G // r
};
const uint8_t SEG_allmonths [] = {
SEG_B | SEG_C | SEG_D, // J
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // A
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F, // n
SEG_A | SEG_E | SEG_F | SEG_G, // F
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G, // E
SEG_F | SEG_C | SEG_D | SEG_E | SEG_G, // b
SEG_A | SEG_B | SEG_C | SEG_D | SEG_G, // 3
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // A
SEG_E | SEG_G, // r
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // A
SEG_A | SEG_E | SEG_F | SEG_G | SEG_B, // P
SEG_E | SEG_G, // r
SEG_A | SEG_B | SEG_C | SEG_D | SEG_G, // 3
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // A
SEG_B | SEG_C | SEG_D | SEG_F | SEG_G, // y
SEG_B | SEG_C | SEG_D, // J
SEG_D | SEG_B | SEG_C | SEG_E | SEG_F, // U
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F, // n
SEG_B | SEG_C | SEG_D, // J
SEG_D | SEG_B | SEG_C | SEG_E | SEG_F, // U
SEG_D | SEG_E | SEG_F, // L
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // A
SEG_D | SEG_B | SEG_C | SEG_E | SEG_F, // U
SEG_D | SEG_C | SEG_E | SEG_F | SEG_A, // G
SEG_A | SEG_C | SEG_D | SEG_F | SEG_G, // S
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G, // E
SEG_A | SEG_E | SEG_F | SEG_G | SEG_B, // P
SEG_A | SEG_D | SEG_B | SEG_C | SEG_E | SEG_F, // O
SEG_A | SEG_D | SEG_E | SEG_F, // C
SEG_D | SEG_G | SEG_E | SEG_F, // t
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F, // n
SEG_A | SEG_D | SEG_B | SEG_C | SEG_E | SEG_F, // O
SEG_D | SEG_B | SEG_C | SEG_E | SEG_F, // U
SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // d
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G, // E
SEG_A | SEG_D | SEG_E | SEG_F // C
};
const uint8_t SEG_day[3] = {
SEG_B | SEG_C | SEG_D | SEG_E | SEG_G, // d
SEG_A | SEG_B | SEG_C | SEG_E | SEG_F | SEG_G, // A
SEG_B | SEG_C | SEG_D | SEG_F | SEG_G // y
};
const uint8_t SEG_hh[] = {
SEG_C | SEG_E | SEG_F | SEG_G, // h
SEG_C | SEG_E | SEG_D | SEG_G, // o
SEG_C | SEG_E | SEG_D, // u
SEG_E | SEG_G, // r
};
const uint8_t SEG_min[] = {
SEG_A | SEG_B | SEG_E | SEG_F, // m
SEG_A | SEG_B | SEG_C | SEG_F, // m
SEG_C | SEG_B, // i
SEG_C | SEG_E | SEG_A | SEG_F | SEG_B // n
};
const uint8_t SEG_sec[] = {
SEG_A | SEG_C | SEG_D | SEG_F | SEG_G, // S
SEG_A | SEG_D | SEG_E | SEG_F | SEG_G, // E
SEG_A | SEG_D | SEG_E | SEG_F // C
};
const uint8_t allOFF[] = {0x00, 0x00, 0x00, 0x00};
void setup() {
Serial.begin(9600);
display.setBrightness(10);
display2.setBrightness(10);
pinMode(A0, INPUT_PULLUP);
pinMode(A1, INPUT_PULLUP);
pinMode(A2, INPUT_PULLUP);
Set.begin();
Set.set_repeat(500, -1);
Incr.begin();
Incr.set_repeat(500, 200);
Decr.begin();
Decr.set_repeat(500, 200);
OUR_latitude = latitude_of[4];
OUR_longitude = longitude_of[4];
OUR_timezone = timezone_of[4] + DST;
RTC.read(tm);
if (tm.Year < CalendarYrToTm(2023)){
tm.Year = setYear();
tm.Month = setMonth();
tm.Day = setDay();
tm.Hour = setHour();
tm.Minute = setMinutes();
tm.Second = setSeconds();
OUR_latitude = latitude_of[2];
OUR_longitude = longitude_of[2];
OUR_timezone = timezone_of[2] + DST;
RTC.write(tm);
}
}
int prayer_times[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int rem_t, elapsed_t, minutes_now;
byte today = 0;
void loop() {
if (RTC.read(tm)){
current_time = makeTime(tm);
show_time_on_7_seg_1(current_time);
minutes_now = minute(current_time) + hour(current_time)*60 ;
colonState = second(current_time) % 2 ;
int day_of_year = calc_day_of_year(current_time);
if (tm.Day != today){
calc_prayer_times_for(day_of_year);
today = tm.Day;
}
byte i = 0;
while (minutes_now > prayer_times[i]) { i = i + 1; }
rem_t = minutes_now - prayer_times[i];
elapsed_t = minutes_now - prayer_times[i-1];
if (rem_t > -60 && rem_t < 0) {
display2.showNumberDecEx(rem_t);
if (pre_beeped == false) { beep_beep(1); pre_beeped = true;}
}
else if (rem_t == 0) {
show_on_7_seg_2(prayer_times[i]);
if (post_beeped == false) { beep_beep(2); post_beeped = true;}
}
else if (elapsed_t < 30 && elapsed_t > 0) {
display2.showNumberDecEx(elapsed_t);
pre_beeped = false;
post_beeped = false;
}
else {
show_on_7_seg_2(prayer_times[i]);
}
if (Set.pressed()) {
bool longPress = Set.repeat_count() > 0;
if (longPress) {
tm.Year = setYear();
tm.Month = setMonth();
tm.Day = setDay();
tm.Hour = setHour();
tm.Minute = setMinutes();
tm.Second = setSeconds();
city = setCity();
DST = setDST();
OUR_latitude = latitude_of[city];
OUR_longitude = longitude_of[city];
OUR_timezone = timezone_of[city] + DST;
Serial.println(OUR_timezone);
Serial.println(OUR_latitude);
Serial.println(OUR_longitude);
RTC.write(tm);
}
else {
show_date_on_7_seg_1(current_time);
}
}
}
}
int setCity () {
display2.setSegments(allOFF);
display2.setSegments(SEG_city , 4,0);
int city_no = 120;
uint8_t SEG_myCity[] = {SEG_allcities[0],SEG_allcities[1],SEG_allcities[2]};
while (Set.pressed() == false) {
display.setSegments(SEG_myCity, 3 ,1);
if (Incr.pressed()) {
city_no = city_no + 1;
SEG_myCity[0] = SEG_allcities[(city_no%4)*3];
SEG_myCity[1] = SEG_allcities[((city_no%4)*3)+1];
SEG_myCity[2] = SEG_allcities[((city_no%4)*3)+2];
}
if (Decr.pressed()) {
city_no = city_no - 1;
SEG_myCity[0] = SEG_allcities[(city_no%4)*3];
SEG_myCity[1] = SEG_allcities[((city_no%4)*3)+1];
SEG_myCity[2] = SEG_allcities[((city_no%4)*3)+2];
}
}
//Serial.println(longitude_of[city_no%4]);
return abs(city_no%4);
}
int setDST () {
bool dst = 0;
display2.setSegments(allOFF);
display2.setSegments(SEG_DST , 3,1);
display.setSegments(SEG_Off , 3,1);
while (Set.pressed() == false) {
if (Incr.pressed()) {
dst = !dst;
display.setSegments(allOFF);
display.setSegments(SEG_On , 2,2);
}
if (Decr.pressed()) {
dst = !dst;
display.setSegments(allOFF);
display.setSegments(SEG_Off , 3,1);
}
}
return 60*dst;
}
int setYear () {
int set_year = 2023;
display2.setSegments(allOFF);
display2.setSegments(SEG_year , 4,0);
while (Set.pressed() == false) {
display.showNumberDecEx(set_year, 0, false);
if (Incr.pressed()) {
set_year = set_year + 1;
}
if (Decr.pressed()) {
set_year = set_year - 1;
}
}
return CalendarYrToTm(set_year);
}
int setMonth () {
int set_month = 120;
uint8_t SEG_month[] = {SEG_allmonths[0],SEG_allmonths[1],SEG_allmonths[2]};
display2.setSegments(allOFF);
while (Set.pressed() == false) {
display.showNumberDecEx((set_month%12)+1, 0, false);
display2.setSegments(SEG_month, 3, 1);
if (Incr.pressed()) {
set_month = set_month + 1;
SEG_month[0] = SEG_allmonths[(set_month%12)*3];
SEG_month[1] = SEG_allmonths[((set_month%12)*3)+1];
SEG_month[2] = SEG_allmonths[((set_month%12)*3)+2];
}
if (Decr.pressed()) {
set_month = set_month - 1;
SEG_month[0] = SEG_allmonths[(set_month%12)*3];
SEG_month[1] = SEG_allmonths[((set_month%12)*3)+1];
SEG_month[2] = SEG_allmonths[((set_month%12)*3)+2];
}
}
set_month = abs(set_month%12) + 1;
return set_month;
}
int setDay () {
int set_day = 3100;
display2.setSegments(allOFF);
display2.setSegments(SEG_day, 3, 1);
while (Set.pressed() == false) {
display.showNumberDecEx(abs(set_day%31) + 1, 0, false);
if (Incr.pressed()) {
set_day = set_day + 1;
}
if (Decr.pressed()) {
set_day = set_day - 1;
}
}
set_day = abs(set_day%31) + 1;
return set_day;
}
int setHour () {
int set_hour = 12;
display.showNumberDecEx(set_hour, 0, false);
display2.setSegments(allOFF);
display2.setSegments(SEG_hh, 4, 0);
while (Set.pressed() == false) {
display.showNumberDecEx(abs(set_hour), 0, false);
if (Incr.pressed()) {
set_hour = (set_hour + 1) % 24 ;
}
if (Decr.pressed()) {
set_hour = (set_hour + 23) % 24 ;
}
}
set_hour = abs(set_hour);
return set_hour;
}
int setMinutes () {
int set_minutes = 0;
display2.setSegments(allOFF);
display2.setSegments(SEG_min, 4, 0);
while (Set.pressed() == false) {
display.showNumberDecEx(abs(set_minutes), 0, false);
if (Incr.pressed()) {
set_minutes = (set_minutes + 1) % 60;
}
if (Decr.pressed()) {
set_minutes = (59 + set_minutes) % 60;
}
}
set_minutes = abs(set_minutes);
return set_minutes;
}
int setSeconds () {
int set_seconds = 0;
display2.setSegments(allOFF);
display2.setSegments(SEG_sec, 3, 1);
while (Set.pressed() == false) {
display.showNumberDecEx(abs(set_seconds), 0, false);
if (Incr.pressed()) {
set_seconds = (set_seconds + 1) % 60 ;
}
if (Decr.pressed()) {
set_seconds = (59 + set_seconds) % 60 ;
}
}
set_seconds = abs(set_seconds);
return set_seconds;
}
void calc_prayer_times_for(int DOY){
float psi, eqtime, decl,psi_tomorrow, eqtime_tomorrow, decl_tomorrow, ha, fajr_tomorrow, snoon_tomorrow,fajr, sunrise, snoon, asr, sunset, isha;
float sinLD, cosLD ,tanL_D,sincottanL_D;
int totalDaysThisYear = 365;
if (isLeapYear(tmYearToCalendar(tm.Year))){
totalDaysThisYear = 366;
}
else{
totalDaysThisYear = 365;
}
psi = 2 * (M_PI/totalDaysThisYear) * DOY;
eqtime = 229.18* (0.000075 + 0.001868 * cos(psi) - 0.032077*sin(psi) - 0.014615*cos(2*psi) - 0.040849*sin(2*psi) );
decl = 0.006918-0.399912*cos(psi) + 0.070257*sin(psi)-0.006758*cos(2*psi) + 0.000907*sin(2*psi) - 0.002697*cos(3*psi) + 0.00148*sin (3*psi);
ha = acos((cos(deg2rad(90.833))/(cos(deg2rad(OUR_latitude))*cos(decl)))- (tan(deg2rad(OUR_latitude))*tan(decl)))*180/M_PI;
sinLD = sin(deg2rad(OUR_latitude))*sin(decl);
cosLD = cos(deg2rad(OUR_latitude))*cos(decl);
tanL_D = tan(deg2rad(OUR_latitude) - decl);
sincottanL_D = sin(atan(1/(asr_l + tanL_D)));
sunrise = (720 - 4*(OUR_longitude + ha) - eqtime) + OUR_timezone;
snoon = 720 - 4*OUR_longitude - eqtime + OUR_timezone;
asr = snoon + 4*rad2deg(acos((sincottanL_D - sinLD)/(cosLD)));
sunset = (720 - 4*(OUR_longitude - ha) - eqtime) + OUR_timezone;
fajr = snoon - 4*rad2deg(acos((-sin(deg2rad(fajr_angle))-(sin(deg2rad(OUR_latitude))*sin(decl)))/(cos(deg2rad(OUR_latitude))*cos(decl))));
isha = snoon + 4*rad2deg(acos((-sin(deg2rad(isha_angle))-(sin(deg2rad(OUR_latitude))*sin(decl)))/(cos(deg2rad(OUR_latitude))*cos(decl))));
psi_tomorrow = 2 * (M_PI/totalDaysThisYear) * (DOY + 1);
eqtime_tomorrow = 229.18* (0.000075 + 0.001868 * cos(psi_tomorrow) - 0.032077*sin(psi_tomorrow) - 0.014615*cos(2*psi_tomorrow) - 0.040849*sin(2*psi_tomorrow) );
decl_tomorrow = 0.006918-0.399912*cos(psi_tomorrow) + 0.070257*sin(psi_tomorrow)-0.006758*cos(2*psi_tomorrow) + 0.000907*sin(2*psi_tomorrow) - 0.002697*cos(3*psi_tomorrow) + 0.00148*sin (3*psi_tomorrow);
snoon_tomorrow = 720 - 4*OUR_longitude - eqtime_tomorrow + OUR_timezone;
fajr_tomorrow = snoon_tomorrow - 4*rad2deg(acos((-sin(deg2rad(fajr_angle))-(sin(deg2rad(OUR_latitude))*sin(decl_tomorrow)))/(cos(deg2rad(OUR_latitude))*cos(decl_tomorrow))));
prayer_times[0] = isha - 24*60 + 0.5;
prayer_times[1] = fajr + 0.5;
prayer_times[2] = sunrise + 0.5;
prayer_times[3] = snoon + 0.5;
prayer_times[4] = asr + 0.5;
prayer_times[5] = sunset + 0.5;
prayer_times[6] = isha + 0.5;
prayer_times[7] = fajr_tomorrow + 24*60 + 0.5;
}
int calc_day_of_year(time_t tt){
int days_of_year = 0;
int daysInMonth[12] = {31,29,31,30,31,30,31,31,30,31,30,31};
for (int j = 0; j < month(tt) -1; j++){
days_of_year += daysInMonth[j];
}
days_of_year += day(tt);
return days_of_year;
}
void show_time_on_7_seg_1 (time_t tt_t) {
int d_t;
d_t = sevenSegFormat(tt_t);
display.showNumberDecEx(d_t, colonState*64, false);
}
void show_on_7_seg_2 (int minutes) {
display2.showNumberDecEx(sevenSegFormat(minutes), 64, false);
}
unsigned int sevenSegFormat(time_t tt_t) {
int d_t;
if (Hour12Format) {
d_t = changeTo12hour(hour(tt_t))*100 + minute(tt_t);
}
else {
d_t = hour(tt_t)*100 + minute(tt_t);
}
return d_t;
}
unsigned int sevenSegFormat(int minutes) {
int d_t;
if (Hour12Format) {
d_t = changeTo12hour(floor(minutes/60))*100 + minutes%60;
}
else {
d_t = (floor(minutes/60))*100 + minutes%60;
}
return d_t;
}
void show_date_on_7_seg_1 (time_t tt_t) {
int d_t;
d_t = day(tt_t)*100 + month(tt_t);
display.setSegments(allOFF);
display.showNumberDecEx(d_t, 0, false);
display2.setSegments(allOFF);
display2.showNumberDecEx(year(tt_t), 0, false);
delay(2500);
}
int changeTo12hour (int hh) {
if (hh > 24) {hh = hh - 24;}
else if (hh > 12) {hh = hh - 12;}
else if (hh == 0) {hh = 12;}
else { }
return hh;
}
float deg2rad (float deg){
return deg*M_PI/180;
}
float rad2deg (float rad)
{
return rad*180/M_PI;
}
void beep_beep (byte num) {
for (int x=0; x<num; x++) {
tone(buzzer, 2000); delay(100);
noTone(buzzer); delay(100);
tone(buzzer, 2000); delay(100);
noTone(buzzer);
delay(500);
}
}
void setColonState () {
//colonState = colonState ? 0 : 1;
}
bool isLeapYear(int year){
bool leapYear;
year%4==0 ? leapYear = true : leapYear = false;
return leapYear;
}