#include <Wire.h>              // Includes the Wire library for I2C communication
#include <Adafruit_SSD1306.h>  // Includes the Adafruit library for the OLED display
#include <Servo.h>             // Includes the Servo library to control servos

#define SCREEN_WIDTH 128       // OLED display width, in pixels
#define SCREEN_HEIGHT 64       // OLED display height, in pixels

// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
// The pins for I2C are defined by the Wire-library.
// On an Arduino UNO:       A4(SDA), A5(SCL)
// On an Arduino MEGA 2560: 20(SDA), 21(SCL)
// On an Arduino LEONARDO:   2(SDA),  3(SCL), ...
#define OLED_RESET     -1      // Reset pin (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C    // Address for the OLED display; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);  // OLED display instance

// 'logo-1', 128x64px
const unsigned char FAB[] PROGMEM = {
    // Image data for the logo in hexadecimal format
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
    // Continue declaration of the image data for the logo
    // (omitting data here for brevity, but all the logo data would be included)
};

int pos = 90;  // Initializes the servo position to 90 degrees
Servo myservo; // Creates a servo instance

void setup() {
  Serial.begin(9600);  // Starts serial communication at 9600 baud

  myservo.write(pos);  // Moves the servo to the initial position
  myservo.attach(10);  // Attaches the servo to pin 10

  // Starts the OLED display with voltage generated internally from 3.3V
  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
    Serial.println(F("SSD1306 allocation failed"));  // Prints error if initialization fails
    for (;;); // Do not proceed, loop forever
  }
  display.clearDisplay();          // Clears the display
  display.setRotation(2);          // Sets the display rotation
  display.drawBitmap(0, 0, FAB, 128, 64, WHITE); // Draws the logo on the display
  display.display();               // Displays the content on the screen

  delay(2000);  // Waits for 2 seconds

  display.setRotation(2);          // Sets the display rotation
  display.clearDisplay();          // Clears the display
  display.setTextSize(3);          // Sets the text size
  display.setTextColor(WHITE);     // Sets the text color
  display.setCursor(0, 0);         // Sets the cursor to position (0, 0)
  display.println("FAB");          // Displays the text "FAB"
  display.println("ACADEMY");      // Displays the text "ACADEMY"
  display.setTextSize(1);          // Sets the text size to 1
  display.setTextColor(WHITE);     // Sets the text color
  display.println("WEEK 9 OUTPUT");// Displays the text "WEEK 9 OUTPUT"
  display.display();               // Displays the content on the screen
  delay(2000);  // Waits for 2 seconds

  pinMode(4, INPUT);  // Sets pin 4 as input
  pinMode(3, INPUT);  // Sets pin 3 as input
  pinMode(13, OUTPUT); // Sets pin 13 as output
  pinMode(9, OUTPUT);  // Sets pin 9 as output
}

void loop() {
  display.clearDisplay();          // Clears the display
  display.setRotation(2);          // Sets the display rotation
  display.drawBitmap(0, 0, FAB, 110, 45, WHITE); // Draws the logo on the display
  display.display();               // Displays the content on the screen

  if (digitalRead(4) == 1) {       // If pin 4 reads a high value
    digitalWrite(13, HIGH);        // Turns on the LED on pin 13
    if (pos < 180) {               // If the position is less than 180 degrees
      pos += 20;                   // Increases the position by 20 degrees
      myservo.write(pos);          // Moves the servo to the new position
      delay(200);                  // Small delay to avoid bouncing
    }
  }
  if (digitalRead(3) == 1) {       // If pin 3 reads a high value
    digitalWrite(9, HIGH);         // Turns on the LED on pin 9
    if (pos > 0) {                 // If the position is greater than 0 degrees
      pos -= 20;                   // Decreases the position by 20 degrees
      myservo.write(pos);          // Moves the servo to the new position
      delay(200);                  // Small delay to avoid bouncing
    }
  } else {
    digitalWrite(13, LOW);         // Turns off the LED on pin 13
    digitalWrite(9, LOW);          // Turns off the LED on pin 9
  }
}