######
# LEAVE THESE IMPORTS!
######
from arduinIO import ArduinoController
import functions
import time
######
# config values
######
SERIAL_PORT = '/dev/ttyUSB0'
BAUD_RATE = 9600
######
# arduinIO values
######
ARDIO_PORT = "/dev/ttyACM2"
ARDIO_BAUDRATE = 115200
ARDIO_INPUT_PIN = 2
ARDIO_OUTPUT_PINS = [8, 9, 10, 11] # ok, space, dot, dash
ARDIO_PULSE_DURATION_MS = 300
arduino = ArduinoController(port=ARDIO_PORT, baudrate=ARDIO_BAUDRATE)
arduino.connect()
###
# name, enabled, string to match
###
conditions = [
['rdy', False, "", 'setup_buttons'],
['ok', False, "", 'button_ok'],
['dash', False, "", 'button_dash'],
['spce', False, "", 'button_space'],
['dot', False, "", 'button_dot'],
['check', False, "", 'echo_trigger_state'],
['run', False, "", 'find_code'],
["Flag", True, "TS{", "stop_glitch"],
]
######
# Custom functions
######
def setup_buttons():
version = arduino.get_version()
functions.add_text(f"[INFO] Connected to Arduino: {version}")
# Configure pins
functions.add_text("[INFO] Configuring pin modes...")
arduino.set_mode(ARDIO_INPUT_PIN, "INPUT")
for pin in ARDIO_OUTPUT_PINS:
arduino.set_mode(pin, "OUTPUT")
arduino.set_default(pin, "LOW")
# Display current configuration
pinmap = arduino.get_pinmap()
functions.add_text(f"[INFO] Pin map: {pinmap}")
def button_ok():
# Pulse one output pin
functions.add_text(f"[INFO] Pulsing output pin 8 for {ARDIO_PULSE_DURATION_MS} ms...")
arduino.set_for(8, "HIGH", ARDIO_PULSE_DURATION_MS)
time.sleep(0.5)
def button_dash():
functions.add_text(f"[INFO] Pulsing output pin 11 for {ARDIO_PULSE_DURATION_MS} ms...")
arduino.set_for(11, "HIGH", ARDIO_PULSE_DURATION_MS)
time.sleep(0.5)
def button_space():
functions.add_text(f"[INFO] Pulsing output pin 9 for {ARDIO_PULSE_DURATION_MS} ms...")
arduino.set_for(9, "HIGH", ARDIO_PULSE_DURATION_MS)
time.sleep(0.5)
def button_dot():
functions.add_text(f"[INFO] Pulsing output pin 10 for {ARDIO_PULSE_DURATION_MS} ms...")
arduino.set_for(10, "HIGH", ARDIO_PULSE_DURATION_MS)
time.sleep(0.5)
def echo_trigger_state():
state = arduino.get_state(ARDIO_INPUT_PIN)
functions.add_text(f"[INFO] Input pin {ARDIO_INPUT_PIN} is currently {state}")
def find_code():
candidate_pins = [8, 9, 10, 11] # include pin 8 as a candidate
code_sequence = []
pin_to_symbol = {8: "OK", 9: "*", 10: ".", 11: "-"}
functions.add_text("[INFO] Starting full code discovery sequence")
for digit_index in range(4):
functions.add_text(f"[INFO] Finding digit {digit_index + 1}")
results = {}
for test_pin in candidate_pins:
# Build the sequence: previously found digits + candidate repeated to fill 4 pulses
sequence = code_sequence.copy()
remaining_pulses = 4 - len(sequence)
sequence += [test_pin] * remaining_pulses
symbol_seq = [pin_to_symbol.get(pin, str(pin)) for pin in sequence]
functions.add_text(f"[TEST] Testing candidate pin {test_pin} ({pin_to_symbol.get(test_pin)}), "
f"sequence: {' '.join(symbol_seq)}")
# Send all pulses in the sequence, starting timer immediately before the fourth pulse
for i, pin in enumerate(sequence):
if i == len(sequence) - 1:
# Start timer immediately before sending the fourth pulse
start_time = time.time()
arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS)
# Allow a short interval for the device to react
time.sleep(0.05)
# Wait for the input to go HIGH and capture result
result = arduino.wait_for(ARDIO_INPUT_PIN, "HIGH")
end_time = time.time()
# Safely extract duration from result or compute fallback
if isinstance(result, dict):
duration = result.get("duration_ms",
int((end_time - start_time) * 1000))
else:
duration = int((end_time - start_time) * 1000)
functions.add_text(f"[RESULT] Candidate pin {test_pin} - LOW->HIGH {duration} ms.")
results[test_pin] = duration
else:
arduino.set_for(pin, "HIGH", ARDIO_PULSE_DURATION_MS)
time.sleep(0.5)
# small pause between candidates
time.sleep(0.8)
# Choose the candidate with the longest duration for this digit
correct_pin = max(results, key=results.get)
code_sequence.append(correct_pin)
functions.add_text(f"[INFO] Digit {digit_index + 1} identified (pin): {correct_pin}")
functions.add_text(f"[INFO] Digit {digit_index + 1} identified (symbol): "
f"{pin_to_symbol.get(correct_pin)}")
translated_sequence = [pin_to_symbol.get(pin, str(pin)) for pin in code_sequence]
functions.add_text(f"[INFO] Full code sequence identified (pins): {code_sequence}")
functions.add_text(f"[INFO] Full code sequence identified (symbols): {translated_sequence}")
return code_sequence, translated_sequence
def stop_glitch():
functions.set_uart_switch(False)