from machine import Pin, I2C, PWM
from ssd1306 import SSD1306_I2C
from time import sleep, ticks_ms, ticks_diff

# Pin Definitions
SERVO_PIN = 18
BUTTON_PINS = [12, 13, 14, 27]  # GPIO5, GPIO4, GPIO14, GPIO12
I2C_SCL_PIN = 22
I2C_SDA_PIN = 21
RED_LED_PIN = 17
GREEN_LED_PIN = 16
BUZZER_PIN = 26

# Initialize components connection
servo = PWM(Pin(SERVO_PIN), freq=50, duty=77)  # 77 is the duty cycle for 0 degrees
i2c = I2C(0, scl=Pin(I2C_SCL_PIN), sda=Pin(I2C_SDA_PIN), freq=100000)
oled = SSD1306_I2C(128, 64, i2c)
red_led = Pin(RED_LED_PIN, Pin.OUT)
green_led = Pin(GREEN_LED_PIN, Pin.OUT)
buzzer = PWM(Pin(BUZZER_PIN), freq=1000, duty=0)  # Start with the buzzer off

# Function to move the servo to a specific angle
def move_servo(angle):
    duty_cycle = int(((angle / -180) * 77) + 77)
    servo.duty(duty_cycle)
    sleep(0.5)  # Give time for the servo to move

# Function to control LEDs and buzzer based on motor operation
def control_outputs(status):
    if status == "running":
        red_led.on()
        green_led.off()
        buzzer.duty(0)  # Turn off the buzzer when the motor is running
    elif status == "complete":
        red_led.off()
        green_led.on()
        buzzer.duty(512)  # Turn on the buzzer when the motor is complete

# Function to display a message on the OLED screen
def display_message(message):
    oled.fill(1) #Make OLED White background 
    oled.text(message, 10, 30, 0)
    oled.show()

# Main Loop
while True:
    display_message("PRESS A BUTTON")
    button_pressed = False
    
    for i, button_pin in enumerate(BUTTON_PINS):
        button = Pin(button_pin, Pin.IN, Pin.PULL_UP)
        if button.value() == 0:
            button_pressed = True
            if i == 0:
                angle = 30
                message = "5ml Dispensed"
            elif i == 1:
                angle = 60
                message = "10ml Dispensed"
            elif i == 2:
                angle = 90
                message = "15ml Dispensed"
            elif i == 3:
                angle = 120
                message = "20ml Dispensed"
             

            volume = (i + 1) * 5  # Calculate volume based on button press
            display_message(message)
            control_outputs("running")  # Turn on the red LED and turn off the buzzer indicating motor is running
            move_servo(angle)
            sleep(0.5)  # Debounce delay
            control_outputs("complete")  # Turn on the green LED and turn on the buzzer indicating motor is complete
            display_message("")

    if not button_pressed:
        buzzer.duty(0)  # Turn off the buzzer if no button is pressed

    sleep(0.1)