// https://forum.arduino.cc/t/new-project-ships-clock/1339379
// https://en.wikipedia.org/wiki/Ship%27s_bell

/*
  // Calculating ships bells

  void setup() {
  Serial.begin(115200);
  for (int hour = 0; hour <= 24; hour ++) { // count the hours
    Serial.print(hour);
    Serial.print(" = ");
    if (hour && !(hour % 4)) // greater than zero and evenly divisible by 4
      Serial.print(4); // four double bells
    else
      Serial.print(hour % 4); // remainder of hour division by 4
    Serial.print(" double bells");
    Serial.println();
  }
  }

  void loop() {}
*/

#include <RTClib.h>
RTC_DS1307 rtc;
DateTime now;

char daysOfTheWeek[7][4] = {"SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
bool onetime;
byte buzzerPin = 2;

void setup () {
  Serial.begin(115200);
  rtc.begin();

  // rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // system time
  // January 21, 2021, 10:23.24pm
  // rtc.adjust(DateTime(2021, 1, 21, 22, 23, 24)); // set any time
  // rtc.adjust(DateTime(2025, 1, 6, 0, 29, 55)); // set any time 5 seconds before one bell
  rtc.adjust(DateTime(2025, 1, 6, 7, 59, 55)); // set any time 5 seconds before eight bells
}

void loop () {
  now = rtc.now();
  // double bells: minutes are 00 or 30 and greater than zero and evenly divisible by 4, or remainder of (hour mod 4)
  int doublebell = ((!now.minute() || now.minute() == 30) && now.hour() && !(now.hour() % 4)) ? 4 : now.hour() % 4;

  // single bells: half hours
  int singlebell = now.minute() == 30;

  Serial.print(doublebell);
  for (int i = 0; i < doublebell; i++)
    bell();
  Serial.print(" ");
  Serial.print(singlebell);
  if (singlebell && !onetime)
    bell();
  Serial.println();
  delay(250);
}

void bell() {
  onetime = 1; // set onetime flag to only visit one time
  digitalWrite(buzzerPin, HIGH);
  digitalWrite(buzzerPin, LOW);
  Serial.print("ding");
}

void humantime() {
  onetime = 1; // set onetime flag to only visit one time
  Serial.print("Current time: ");
  Serial.print(now.year(), DEC);
  Serial.print('/');
  pad(now.month());
  Serial.print(now.month(), DEC);
  Serial.print('/');
  pad(now.day());
  Serial.print(now.day(), DEC);
  Serial.print(" (");
  Serial.print(daysOfTheWeek[now.dayOfTheWeek()]);
  Serial.print(") ");
  pad(now.hour());
  Serial.print(now.hour(), DEC);
  Serial.print(':');
  pad(now.minute());
  Serial.print(now.minute(), DEC);
  Serial.print(':');
  pad(now.second());
  Serial.print(now.second(), DEC);
  Serial.println();
}

void pad(int value) {
  if (value < 10) // pad single digits
    Serial.print("0");
}
GND5VSDASCLSQWRTCDS1307+