//******************************************************************************
// RTC ALARM
//******************************************************************************
#include <RTClib.h>
RTC_DS1307 rtc; // no (SDA, SCL) arguments

// AM feeding time
int amFeedHour   = 10;
int amFeedMinute = 00;

// PM feeding time
int pmFeedHour   = 16;
int pmFeedMinute = 20;

// indicator if AM or PM feeding time
bool ampm = 0;

// char weekDays[][10] = { // removed LCD clutter
//   "SUN",
//   "MON",
//   "TUE",
//   "WED",
//   "THU",
//   "FRI",
//   "SAT"
// };

//******************************************************************************
// LCD
//******************************************************************************
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 4, 5, 6, 7); // 12 RS, 11 E, 4 D4, 5 D5, 6 D6, 7 D7

char line1[] = "@username"; // this will be centered on the LCD
char line2[] = "Pet Feeder!"; // this will be centered on the LCD

//******************************************************************************
// SERVO
//******************************************************************************
#include <Servo.h>
Servo myServo; // create instance of Servo class to control the servo

int servoPin = 3;
int position  = 0; // starting position of the servo (adjustable)
int direction = 1; // servo direction of travel
int speed = 5; // speed of servo arm. larger value is faster movement

void setup() {
  //******************************************************************************
  // GENERAL SETUP
  //******************************************************************************
  Serial.begin(115200); // Serial monitor for debugging

  //******************************************************************************
  // LCD SETUP
  //******************************************************************************
  lcd.begin(16, 2); // start the LCD
  welcome(); // the welcome screen

  //******************************************************************************
  // SERVO SETUP
  //******************************************************************************
  myServo.attach(servoPin); // attach servo to pwm pin

  //******************************************************************************
  // RTC SETUP
  //******************************************************************************
  if (! rtc.begin()) { // start rtc
    Serial.println("Couldn't find RTC"); // failed to start
    Serial.flush(); // wait for previous Serial.print(); to finish
    while (1); // stops sketch here.
  }
  // this will set RTC Date/Time from PC at compile time. COMMENT-OUT after setting
  // rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));

  // this will set RTC with bespoke Date/Time
  // rtc.adjust(DateTime(2023, 3, 14, 12, 30, 0));  // March 14, 2023 at 12:30am
}

void loop() {
  DateTime now = rtc.now(); // set "now" to the RTC time

  if ((now.hour() >= pmFeedHour) && (now.hour() < amFeedHour)) { // compare hour to now/RTC for "next"
    ampm = 0; // before mid-day
    displayNextFeed(ampm, amFeedHour, amFeedMinute); // display next feed time
  } else {
    ampm = 1; // after mid-day
    displayNextFeed(ampm, pmFeedHour, pmFeedMinute); // display next feed time
  }

  //******************************************************************************
  // AM FEED THE CAT
  //******************************************************************************
  if ((now.hour() == amFeedHour && now.minute() == amFeedMinute) && now.second() < 10) {
    feedServo(); // feed now
  }

  //******************************************************************************
  // PM FEED THE CAT
  //******************************************************************************
  if ((now.hour() == pmFeedHour && now.minute() == pmFeedMinute) && now.second() < 10) {
    feedServo(); // feed now
  }

  //******************************************************************************
  // displayDate()
  //******************************************************************************
  lcd.setCursor(0, 0);
  lcd.print(now.year(), DEC);
  lcd.print('/');
  if (now.month() < 10) lcd.print("0");
  lcd.print(now.month(), DEC);
  lcd.print('/');
  if (now.day() < 10) lcd.print("0");
  lcd.print(now.day(), DEC);

  //******************************************************************************
  // displayDayOfWeek() // too much data for 16x02 LCD
  //******************************************************************************
  // lcd.print(" ");
  // lcd.setCursor(0, 1);
  // lcd.print(weekDays[now.dayOfTheWeek()]);
  // lcd.print(" ");

  //******************************************************************************
  // displayTime()
  //******************************************************************************
  lcd.setCursor(0, 1);
  if (now.hour() < 10) lcd.print("0"); // pad single digit with "0"
  lcd.print(now.hour(), DEC);
  lcd.print(':');
  if (now.minute() < 10) lcd.print("0"); // pad single digit with "0"
  lcd.print(now.minute(), DEC);
  lcd.print('.');
  if (now.second() < 10) lcd.print("0"); // pad single digit with "0"
  lcd.print(now.second(), DEC);
}

//******************************************************************************
// Welcome screen LCD and Serial Monitor
//******************************************************************************
void welcome() {
  lcd.setCursor(8 - (sizeof(line1) / 2 - 1), 0); // center line1 of the title
  lcd.print(line1);
  lcd.setCursor(8 - (sizeof(line2) / 2 - 1), 1); // center line 2 of the title
  lcd.print(line2);
  delay(1000);
  lcd.clear();
  lcd.setCursor(11, 0);
  lcd.print("Next:");

  Serial.println("Edit feeding times in the RTC ALARM section");
}

//******************************************************************************
// FEED THE CAT
//******************************************************************************
void feedServo() {
  myServo.write(0);  // set positions of servo arm
  position += direction * speed; // calculate new position
  delay(500); // delay between movements. smaller value is faster movement
  myServo.write(90); // set position of servo arm
}

//******************************************************************************
// NEXT FEEDING TIME
//******************************************************************************
void displayNextFeed(int ampm, int nextHour, int nextMinute) { // display next feeding time
  lcd.setCursor(9, 1);
  lcd.print(nextHour);
  lcd.print(":");
  if (nextMinute < 10)
    lcd.print("0");
  lcd.print(nextMinute);

  lcd.setCursor(14, 1);
  if (ampm) // the "1" or "0" from above for AM or PM
    lcd.print("PM"); // next feed
  else
    lcd.print("AM"); // next feed
}

void displayTime() {
  // move the display-time code from void-loop() to here
}

void displayDate() {
  // move the display-date code from void-loop() to here
}
GND5VSDASCLSQWRTCDS1307+