diff --git a/pico_2026/rate.py b/pico_2026/rate.py index b140903..437f4e0 100644 --- a/pico_2026/rate.py +++ b/pico_2026/rate.py @@ -14,6 +14,12 @@ BUTTON_SEND = None RATE_BUTTONS = [] DISPLAY = None +# Variables for Interrupt (ISR) handling and Debouncing +pending_rate_button = -1 +pending_send_button = False +last_interrupt_time = 0 +DEBOUNCE_MS = 250 # Ignore button presses within 250ms of each other + # Helper to update display based on state def refresh_display(message=None): if not DISPLAY: @@ -26,10 +32,9 @@ def refresh_display(message=None): DISPLAY.text(message, 10, 30) elif CURRENT_STATE == STATE_USER_ID: # 1. User ID Mode - DISPLAY.text("Inchometer", 25, 0) + DISPLAY.text("User ID Mode", 15, 0) # Display binary representation: _ _ _ _ _ - # Bit 4 is leftmost button, Bit 0 is rightmost binary_str = "" for i in range(5): bit_pos = 4 - i @@ -49,8 +54,6 @@ def refresh_display(message=None): else: rating_text = str(RATING) - # Draw "big" text (simulated with scale if supported, or just centered) - # Standard ssd1306 doesn't have big fonts, so we just center it DISPLAY.text(rating_text, 60, 30) DISPLAY.show() @@ -60,30 +63,35 @@ def initialize_pin(pin_number:int): button = Pin(pin_number, Pin.IN, Pin.PULL_DOWN) return button -# activates send pin -def activate_sendPin() -> None: - BUTTON_SEND.irq(trigger=Pin.IRQ_RISING, handler=sendButton_pressed) - -# deactivates send pin -def deactivate_sendPin() -> None: - BUTTON_SEND.irq(handler=None) - -# rate button is pressed +# Hardware Interrupt: rate button is pressed def rate_button_pressed(pin:Pin) -> None: - global USER_ID, RATING, CURRENT_STATE, RATE_BUTTONS - - # Find which button index was pressed - button_index = -1 - for i, button in enumerate(RATE_BUTTONS): - if button == pin: - button_index = i - break + global pending_rate_button, last_interrupt_time - if button_index == -1: - return + current_time = time.ticks_ms() + # Simple software debounce + if time.ticks_diff(current_time, last_interrupt_time) > DEBOUNCE_MS: + # Find which button index was pressed + for i, button in enumerate(RATE_BUTTONS): + if button == pin: + pending_rate_button = i + break + last_interrupt_time = current_time +# Hardware Interrupt: Send/Confirm button is pressed +def sendButton_pressed(pin:Pin) -> None: + global pending_send_button, last_interrupt_time + + current_time = time.ticks_ms() + if time.ticks_diff(current_time, last_interrupt_time) > DEBOUNCE_MS: + pending_send_button = True + last_interrupt_time = current_time + +# Process the rate button press (Called from the main loop) +def process_rate_button(button_index: int): + global USER_ID, RATING, CURRENT_STATE + if CURRENT_STATE == STATE_USER_ID: - bit_pos = len(RATE_BUTTONS) - 1 - button_index + bit_pos = 4 - button_index USER_ID ^= (1 << bit_pos) print(f"Current User ID: {USER_ID}") @@ -92,12 +100,10 @@ def rate_button_pressed(pin:Pin) -> None: print(f"Current Rating selected: {RATING}") refresh_display() - activate_sendPin() -# Send/Confirm button is pressed -def sendButton_pressed(pin) -> None: +# Process the send button press (Called from the main loop) +def process_send_button(): global CURRENT_STATE, USER_ID, RATING - deactivate_sendPin() if CURRENT_STATE == STATE_USER_ID: # 2. Confirmed ID display @@ -109,8 +115,7 @@ def sendButton_pressed(pin) -> None: elif CURRENT_STATE == STATE_RATING: if RATING == 0: - activate_sendPin() - return + return # Don't send if no rating is selected yet # 4. Sending / Success / Error refresh_display("Sending...") @@ -122,7 +127,7 @@ def sendButton_pressed(pin) -> None: else: refresh_display("Error") - time.sleep(5) # Display status for 5 seconds + time.sleep(3) # Display status for 3 seconds # Reset for next rating USER_ID = 0 @@ -133,21 +138,32 @@ def sendButton_pressed(pin) -> None: # start the rating program def start_rating(rate_button_pins:list, button_send_pin:int, oled_display=None) -> None: global RATE_BUTTONS, BUTTON_SEND, DISPLAY + global pending_rate_button, pending_send_button DISPLAY = oled_display - # initialize all pins as buttons and add them to the list + # initialize all pins as buttons and attach interrupts RATE_BUTTONS = [] for pin_num in rate_button_pins: button = initialize_pin(pin_num) button.irq(trigger=Pin.IRQ_RISING, handler=rate_button_pressed) RATE_BUTTONS.append(button) - # initialize send button + # initialize send button and attach interrupt BUTTON_SEND = initialize_pin(button_send_pin) + BUTTON_SEND.irq(trigger=Pin.IRQ_RISING, handler=sendButton_pressed) print("System started.") refresh_display() + # The Main Event Loop - This safely handles the screen updates while True: - time.sleep(1) + if pending_rate_button != -1: + process_rate_button(pending_rate_button) + pending_rate_button = -1 # Reset the flag + + if pending_send_button: + process_send_button() + pending_send_button = False # Reset the flag + + time.sleep_ms(50) # Short delay to save power and avoid choking the CPU