from machine import Pin
import time, utime
# Shift Register Pins
SD = Pin(0, Pin.OUT) # Serial Data (SD) - Sends bit values to the shift register
ST_CP = Pin(1, Pin.OUT) # Store Clock (ST_CP) - Latches data to output pins
SH_CP = Pin(2, Pin.OUT) # Shift Clock (SH_CP) - Shifts bits into the register
# Push-Button Inputs
push_button_HIGH = Pin(21, Pin.IN, Pin.PULL_DOWN) # Push-button for HIGH (1) input
push_button_LOW = Pin(20, Pin.IN, Pin.PULL_DOWN) # Push-button for LOW (0) input
# Global Variables
magic_key = 0xF0 # Expected pattern: 11110000
bits_entered = 0 # Keeps track of total button presses
pattern = 0 # Stores entered bits from button presses
# Debounce Timing Variables
last_press_high = 0 # Time of the last high button event
last_press_low = 0 # Time of the last low button event
debounce_interval = 200 # Minimum delay between button presses (in ms)
def send_shift_register_data(data):
""" Function to send an 8-bit pattern to the 74HC595 shift register.
Each bit is shifted sequentially, and the final state is latched to output pins. """
for i in range(8):
bit_value = (data >> (7 - i)) & 1 # Extract individual bit
SD.value(bit_value) # Send bit to Serial Data
# Pulse Shift Clock to move data
SH_CP.low()
time.sleep_ms(5)
SH_CP.high()
# Latch Data to output pins
ST_CP.low()
time.sleep_ms(5)
ST_CP.high()
def check_pattern():
""" Checks pattern, prints result, and activates LEDs"""
print(f"Checking pattern: {bin(pattern)}")
if pattern == magic_key:
print("SUCCESS! Activating GREEN LED.")
send_shift_register_data(0b00000010) # Green LED at Q1 0b10
else:
print("FAIL! Activating RED LED.")
send_shift_register_data(0b00000100) # Red LED at Q2 0b100
reset_bits()
def reset_bits():
""" Resets system for new input sequence"""
global pattern, bits_entered
pattern = 0
bits_entered = 0
send_shift_register_data(0b00000000) # Clear all shift register outputs
print("\nEnter new input:")
def push_button_HIGH_interrupt_handler(pin):
""" Handles HIGH button presses"""
global last_press_high, bits_entered, pattern
# Check debounce timing
current_time = utime.ticks_ms()
if utime.ticks_diff(current_time, last_press_high) < debounce_interval:
return
last_press_high = current_time # Store the latest button press time
# Process button press if not already entered 8 bits
if bits_entered < 8:
pattern = (pattern << 1) | 1 # Shift left and add HIGH bit (1)
bits_entered += 1
# Print updated pattern after modification
print(f"Button HIGH pressed! Pattern: {bin(pattern)} Bits: {bits_entered}")
if bits_entered == 8: # If 8 bits have been entered, check the pattern
check_pattern()
def push_button_LOW_interrupt_handler(pin):
""" Handles LOW button presses"""
global last_press_low, bits_entered, pattern
# Check debounce timing
current_time = utime.ticks_ms()
if utime.ticks_diff(current_time, last_press_low) < debounce_interval:
return
last_press_low = current_time # Store the latest button press time
# Process button press if not already entered 8 bits
if bits_entered < 8:
pattern = (pattern << 1) # Shift left and add LOW bit (0)
bits_entered += 1
# Print updated pattern after modification
print(f"Button LOW pressed! Pattern: {bin(pattern)} Bits: {bits_entered}")
# If 8 bits have been entered, check the pattern
if bits_entered == 8:
check_pattern()
# Register Interrupts
push_button_HIGH.irq(trigger=Pin.IRQ_RISING, handler=push_button_HIGH_interrupt_handler)
push_button_LOW.irq(trigger=Pin.IRQ_RISING, handler=push_button_LOW_interrupt_handler)
print("Enter input:")
while True: # Keep the script running to allow interrupts to be handled
time.sleep(1)