# BEAPER Pico I/O Test Project
# October 13, 2024

# Functionality test program for on-board BEAPER Pico I/O devices. Press
# each pushbutton to light LEDs. SW3 makes tones. Analog values converted
# from the ambient light sensor and potentiometers are displayed in the shell.

# Import machine and time functions
from machine import Pin, PWM, ADC
import time

# Configure Educational Starter I/O devices
SW2 = Pin(0, Pin.IN, Pin.PULL_UP)
SW3 = Pin(1, Pin.IN, Pin.PULL_UP)
SW4 = Pin(2, Pin.IN, Pin.PULL_UP)
SW5 = Pin(3, Pin.IN, Pin.PULL_UP)
LED2 = Pin(10, Pin.OUT)
LED3 = Pin(11, Pin.OUT)
LED4 = Pin(12, Pin.OUT)
LED5 = Pin(13, Pin.OUT)
BEEPER = Pin(14, Pin.OUT)

# Configure analog input devices
Q1 = Q4 = ADC(0)
Q2 = RV1 = ADC(1)
Q3 = RV2 = ADC(2)
temp_sensor = ADC(4)

# Define toggle button variables
SW4IsPressed = False
LED4State = 0

# Tone functions
def tone(frequency, duration = None):
    beeperPin = PWM(Pin(14), duty_u16 = 32768)
    beeperPin.freq(frequency)
    if duration is not None:
        time.sleep(duration)
        noTone()

def noTone(duration = None):
    beeperPin = PWM(Pin(14))
    beeperPin.deinit()
    if duration is not None:
        time.sleep(duration)

# Start-up sound
tone(4000,0.1)

while True:
    # Chase LEDs
    if SW2.value() == 0:
        LED2.value(1)
        time.sleep(0.1)
        LED3.value(1)
        time.sleep(0.1)
        LED4.value(1)
        time.sleep(0.1)
        LED5.value(1)
        time.sleep(0.1)
        
        LED2.value(0)
        time.sleep(0.1)
        LED3.value(0)
        time.sleep(0.1)
        LED4.value(0)
        time.sleep(0.1)
        LED5.value(0)
        time.sleep(0.1)

    # Beep, boop, with momentary button
    if SW3.value() == 0:
        LED3.value(1)
        tone(700, 0.16)
        noTone(0.05)
        tone(600, 0.16)
        noTone()
        while SW3.value() == 0:
            time.sleep_ms(10)
    else:
        LED3.value(0)
    
    # Toggle button
    if SW4.value() == 0 and SW4IsPressed == False:
        SW4IsPressed = True
        if LED4State == 0:
            LED4State = 1
        else:
            LED4State = 0
            
    LED4.value(LED4State)
    
    if SW4.value() == 1:
        SW4IsPressed = False
    
    # Brighten and dim LED D5 using PWM
    if SW5.value() == 0:
        # Fade-up LED5
        pwmLED = PWM(Pin(13), freq=1000)
        for brightness in range(0, 65535, 1024):
            pwmLED.duty_u16(brightness)
            time.sleep_ms(10)
        # Fade-out LED5
        for brightness in range(65535, 0, -1024):
            pwmLED.duty_u16(brightness)
            time.sleep_ms(10)
        pwmLED.deinit()
        # Reset pin as digital output
        LED5 = Pin(13, Pin.OUT)
    
    # Display analog input levels
    lightLevel = Q4.read_u16()
    pos1 = RV1.read_u16()
    pos2 = RV2.read_u16()
    raw_temp = temp_sensor.read_u16()
    print("Light level: ", lightLevel)
    print("RV1 position: ", pos1)
    print("RV2 position: ", pos2)
    print("Raw temp: ", raw_temp)
    print("")

    time.sleep_ms(20)
