# Import necessary modules
import machine
import time
import utime
from utime import sleep
from machine import Timer
# Constants for pin numbers
BUTTON_START_ID = 16
LED_GPIO_START = 7
INPUT_COUNT = 4
BUTTON_COUNT = 3 # Define the number of buttons
LED_COUNT = 9
# Initialize global variables
last_button_time_stamp = 0
key_presses = []
# Define the selector pins
s0 = machine.Pin(27, machine.Pin.OUT)
s1 = machine.Pin(28, machine.Pin.OUT)
mux_in = machine.Pin(26, machine.Pin.IN, machine.Pin.PULL_DOWN)
prev_binary_code = 0
# Define timeout interval
timeout_interval = 3
def PinId(pin):
# Pin(GPIO17, mode=IN, pull=PULL_DOWN)
# the pin value is in the format above
# and the pin id, i.e. 7 or 17, can be single or double digit
# So, we filter the characters 8-10,
# which would be '7,' or '17' depending on the pin,
# then, we remove any ',' character at the end
# and we are left with the numeric value of the pin, i.e. 7 or 17
return int(str(pin)[8:11].rstrip(","))
# This function is called when the reset button is pressed. It resets the LEDs.
def resetLeds(pin):
global reset_last_button_press_time
# Get the current time in milliseconds
cur_time = utime.ticks_ms()
# Calculate the time difference since the last button press
button_time_diff = utime.ticks_diff(cur_time, reset_last_button_press_time)
# Calculate the time difference since the last button press
if button_time_diff >= debounce_interval:
reset_last_button_press_time = cur_time
print("Resetting")
# Turn off each LED
for led in leds:
led.value(0)
# This function is called when there is no activity
#for a certain period of time. It clears the entered sequence.
def clearEntered(pin):
global key_presses
# If there are key presses, clear them
if key_presses:
print("Clearing entered sequence due to inactivity...")
utime.sleep(0.75)
# Reset the key presses
key_presses = []
utime.sleep(0.2)
# Create a timer that calls the clearEntered function after a timeout interval
timeout = Timer(period=(timeout_interval*1000), mode=Timer.ONE_SHOT, callback=clearEntered)
# This function is called when a button is pressed. It adds the button press to the sequence.
def interrupt_callback(pin):
global last_button_time_stamp
# Get the current time in milliseconds
cur_button_ts = time.ticks_ms()
# Calculate the time difference since the last button press
button_press_delta = cur_button_ts - last_button_time_stamp
# If the time difference is greater than 200 ms, add the button press to the sequence
if button_press_delta > 200:
last_button_time_stamp = cur_button_ts
key_presses.append(pin)
#print the key pre
print(f'key press: {PinId(pin) - BUTTON_START_ID}')
#resrt the timer
timeout.init(period=(timeout_interval * 1000), mode=Timer.ONE_SHOT, callback=clearEntered)
def main():
global key_presses
global last_button_time_stamp
PASSCODE_LENGTH = 0
# Initialize buttons
buttons = []
for btn_idx in range(0, BUTTON_COUNT):
buttons.append(machine.Pin(BUTTON_START_ID + btn_idx, machine.Pin.IN, machine.Pin.PULL_DOWN))
buttons[-1].irq(trigger=machine.Pin.IRQ_FALLING, handler=interrupt_callback)
# Define the passcode
PASS_CODE = [buttons[0], buttons[2], buttons[1]]
PASSCODE_LENGTH = len(PASS_CODE)
# Initialize LED pins
out_pins = []
for out_id in range(0, LED_COUNT):
out_pins.append(machine.Pin(LED_GPIO_START + out_id, machine.Pin.OUT))
last_dev = -1
while True:
# Initialize binary code to 0
binary_code = 0
# Loop over the range of input count
for selector_val in range(INPUT_COUNT):
# Set the values of s0 and s1 based on the selector value
s0.value(selector_val % 2)
s1.value(selector_val // 2)
# Wait for 0.02 seconds
sleep(0.02)
# Update the binary code based on the value of mux_in
binary_code += (pow(2, selector_val) * mux_in.value())
# If the last device is not equal to the binary code
if last_dev != binary_code:
# Update the last device to the binary code
last_dev = binary_code
# Print the selected output
print(f'selected output: {last_dev}')
sleep(0.1)
# If the length of key presses is greater than or equal to the passcode length
if len(key_presses) >= PASSCODE_LENGTH:
# If the key presses match the passcode
if key_presses[:PASSCODE_LENGTH] == PASS_CODE:
print('correct passcode')
# If the binary code is less than the LED count
if binary_code < LED_COUNT:
print(f'toggling: {binary_code}')
# Toggle the output pin
out_pins[binary_code].toggle()
else:
print(f'invalid output: {binary_code}, ' + \
f'valid range: 0-{len(out_pins) - 1}, doing nothing')
else:
# Print a message for wrong passcode
print('wrong passcode')
print('')
key_presses = key_presses[PASSCODE_LENGTH:]
if __name__ == "__main__":
main()