from machine import Pin, ADC, Timer
import time

# Segment pins A to DP → GP0–GP7
segment_pins = [Pin(i, Pin.OUT) for i in range(8)]

# Digit control pins DIG1 → DIG4 = GP11 → GP8
digit_pins = [Pin(11, Pin.OUT), Pin(10, Pin.OUT), Pin(9, Pin.OUT), Pin(8, Pin.OUT)]

# ADC input on GP26
adc = ADC(26)

# Button with interrupt and pull-up on GP16
button = Pin(16, Pin.IN, Pin.PULL_UP)

# Digit patterns (active low)
digits = {
    '0': 0b11000000,
    '1': 0b11111001,
    '2': 0b10100100,
    '3': 0b10110000,
    '4': 0b10011001,
    '5': 0b10010010,
    '6': 0b10000010,
    '7': 0b11111000,
    '8': 0b10000000,
    '9': 0b10011000,
    ' ': 0b11111111,
    '-': 0b10111111
}

# Global flags and timer for debouncing
button_pressed = False
debounce_timer = Timer()

def clear_display():
    for seg in segment_pins:
        seg.value(1)
    for dig in digit_pins:
        dig.value(0)

def show_char(ch, digit_index, show_dp=False):
    pattern = digits.get(ch, digits[' '])
    if show_dp:
        pattern &= 0b01111111  # Turn on decimal point (bit 7 LOW = ON)
    for i in range(8):
        segment_pins[i].value((pattern >> i) & 1)
    digit_pins[digit_index].value(1)
    time.sleep(0.003)
    digit_pins[digit_index].value(0)

def mv_to_str(mv):
    if mv < 1000:
        return f"0.{mv:03d}"
    else:
        volts = mv // 1000
        mvolts = mv % 1000
        return f"{volts}.{mvolts:03d}"

# Interrupt handler
def button_irq_handler(pin):
    global button_pressed
    if not button_pressed:
        button_pressed = True
        debounce_timer.init(mode=Timer.ONE_SHOT, period=200, callback=lambda t: None)

# Attach interrupt
button.irq(trigger=Pin.IRQ_FALLING, handler=button_irq_handler)

# Display voltage for 2 seconds
def display_voltage(mv):
    value_str = mv_to_str(mv)
    digits_to_show = list(value_str)
    start = time.ticks_ms()
    while time.ticks_diff(time.ticks_ms(), start) < 2000:
        i = 0
        digit_pos = 0
        while digit_pos < 4:
            ch = digits_to_show[i]
            if ch == '.':
                i += 1
                continue
            dp = (i + 1 < len(digits_to_show)) and digits_to_show[i + 1] == '.'
            show_char(ch, digit_pos, show_dp=dp)
            i += 1
            digit_pos += 1
        clear_display()

# Main loop
print("System ready. Press button to read voltage.")
while True:
    if button_pressed:
        button_pressed = False
        raw = adc.read_u16()
        voltage_mv = (raw * 3300) // 65535
        print("Voltage:", mv_to_str(voltage_mv), "V")
        display_voltage(voltage_mv)
$abcdeabcde151015202530354045505560fghijfghij
BOOTSELLED1239USBRaspberryPiPico©2020RP2-8020/21P64M15.00TTT