from machine import Pin, Timer
from utime import sleep, ticks_ms
# Define helper functions
def init_pins(start_id: int, count: int, mode: int, **kwargs) -> list:
"""Initialize a range of GPIO pins."""
return [Pin(start_id + i, mode, **kwargs) for i in range(count)]
def init_irq(pins: list, callback, trigger: int = Pin.IRQ_RISING) -> None:
"""Attach an interrupt request (IRQ) handler to a list of pins."""
for pin in pins:
pin.irq(trigger=trigger, handler=callback)
def zfill(s: str, width: int) -> str:
"""Pad a string with leading zeros to match the specified width."""
if len(s) >= width:
return s
return '0' * (width - len(s)) + s
def decimal_to_binary(decimal_num: int, length: int = 0) -> str:
"""Convert a decimal integer (Base 10) to a binary string (Base 2)."""
binary_str = bin(decimal_num)[2:] # Convert to binary and remove '0b' prefix
return zfill(binary_str, length) if length > 0 else binary_str or "0"
# Define global variables/constants
LEDS_START_ID = 7
LEDS_COUNT = 9
leds = init_pins(LEDS_START_ID, LEDS_COUNT, Pin.OUT)
BUTTONS_START_ID = 16
BUTTONS_COUNT = 3
buttons = init_pins(BUTTONS_START_ID, BUTTONS_COUNT, Pin.IN, pull=Pin.PULL_DOWN)
SELECTORS_START_ID = 27
SELECTORS_COUNT = 2
selectors = init_pins(SELECTORS_START_ID, SELECTORS_COUNT, Pin.OUT)
PASSWORD = "021"
selected_led_id = None # Updated in the main function
input_password = ""
last_press = 0
def interrupt_callback(pin):
global last_press
global input_password
current_press = ticks_ms()
if (current_press - last_press) > 200: # Debounce guard of 200ms
button_index = buttons.index(pin)
input_password += str(button_index)
print(f"Pressed Button: {button_index}")
last_press = current_press
# Check if input is long enough
if len(input_password) >= len(PASSWORD):
if input_password == PASSWORD:
print("Correct password.")
if selected_led_id < len(leds):
print(f"--- Toggled LED: {selected_led_id} ---")
leds[selected_led_id].toggle()
else:
print("---Failed to toggle LED---")
print(f"--> Error: out of range LED *{selected_led_id}*")
print(f"--> valid range is [0-{len(leds) - 1}], please try again.")
else:
print("Incorrect password, please try again.")
input_password = "" # Reset after length of password is exceeded
def clear_input(timer):
global input_password
if ticks_ms() - last_press > 5000 and input_password:
input_password = "" # Clear
print("-- Your input has been cleared due to inactivity --")
def main():
# Add interrupt handlers to buttons
init_irq(pins=buttons, callback=interrupt_callback)
# Every 2s, i.e.
# Max delay of 2s
input_timer = Timer()
input_timer.init(mode=Timer.PERIODIC, period=2000, callback=clear_input)
# Initialize the mux input pin
mux_in = Pin(26, Pin.IN, Pin.PULL_DOWN)
upper_bound = 2 ** len(selectors)
global selected_led_id
while True:
output = 0
# Iterate over the mux inputs
for i in range(upper_bound):
binary = decimal_to_binary(i, length=len(selectors))
for selector_index in range(len(selectors)):
# Set selector output
selectors[selector_index].value(int(binary[selector_index]))
output += mux_in.value() * (2 ** i)
if output != selected_led_id:
print(f"Selected LED: {output}")
selected_led_id = output
sleep(0.2) # short delay
print("hello ,welcome to the embedded input reader")
sleep(1.5)
print("set switches to represent a decimal from 0-8")
sleep(1.5)
print("write the correct passcode to toggle the selected led:")
sleep(1)
if __name__ == "__main__":
main()