import machine
import time

# Constants
SEVEN_SEGMENT = 0      # GPIO 0-7 for segments
ANAL_INPUT = 26        # ADC input pin
DIS_COUNT = 4          # 4-digit display
PBUTTON = 28           # Pushbutton GPIO
PRECISION = 3
ADC_MAX = float((2 ** 16) - 1)

# Segment hex codes for 0-9, A-F, blank
DIGITAL_LIST_HEX = [
    0x40, 0x79, 0x24, 0x30, 0x19, 0x12, 0x02, 0x78,
    0x00, 0x10, 0x08, 0x03, 0x46, 0x21, 0x06, 0x0E, 0x7F
]

# Globals
segment_pins = []
displays_pins = []
adc_pin = None
display_timer = None
display_value = 0
current_display_index = 0

# Button state
button_pressed = False
last_press_time = 0
debounce_delay = 200  # ms

def display_digit(digit, index, dot=False):
    if digit < 0 or digit >= len(DIGITAL_LIST_HEX):
        digit = 16  # blank

    for pin in displays_pins:
        pin.value(0)

    mask = DIGITAL_LIST_HEX[digit]
    for i in range(7):
        segment_pins[i].value((mask >> i) & 1)

    segment_pins[7].value(0 if dot else 1)

    if 0 <= index < DIS_COUNT:
        displays_pins[index].value(1)

def scan_display(timer):
    global current_display_index, display_value

    value = display_value
    digits = [0] * DIS_COUNT
    for i in range(DIS_COUNT):
        digits[DIS_COUNT - 1 - i] = value % 10
        value //= 10

    dot = (DIS_COUNT - current_display_index - 1 == PRECISION)
    display_digit(digits[current_display_index], current_display_index, dot)

    current_display_index = (current_display_index + 1) % DIS_COUNT

def read_voltage():
    global display_value
    total = sum(adc_pin.read_u16() for _ in range(16))
    avg = total // 16
    voltage = round((avg / ADC_MAX) * 3.3, PRECISION)
    display_value = int(voltage * (10 ** PRECISION))
    print(f"Voltage: {voltage:.3f} V")

def enable_timer():
    global display_timer
    display_timer.init(freq=250, mode=machine.Timer.PERIODIC, callback=scan_display)

def disable_timer():
    global display_timer
    display_timer.deinit()

def button_handler(pin):
    global button_pressed
    button_pressed = True

def setup():
    global segment_pins, displays_pins, adc_pin, display_timer

    for i in range(SEVEN_SEGMENT, SEVEN_SEGMENT + 8):
        pin = machine.Pin(i, machine.Pin.OUT)
        pin.value(1)
        segment_pins.append(pin)

    for i in range(SEVEN_SEGMENT + 8, SEVEN_SEGMENT + 8 + DIS_COUNT):
        pin = machine.Pin(i, machine.Pin.OUT)
        pin.value(0)
        displays_pins.append(pin)

    adc_pin = machine.ADC(ANAL_INPUT)
    display_timer = machine.Timer()
    enable_timer()

def setup_button():
    button = machine.Pin(PBUTTON, machine.Pin.IN, machine.Pin.PULL_UP)
    button.irq(trigger=machine.Pin.IRQ_FALLING, handler=button_handler)

# Main Program
if __name__ == '__main__':
    setup()
    setup_button()

    last_press_time = time.ticks_ms()

    while True:
        if button_pressed:
            now = time.ticks_ms()
            if time.ticks_diff(now, last_press_time) > debounce_delay:
                read_voltage()
                last_press_time = now
            button_pressed = False

        time.sleep_ms(10)
$abcdeabcde151015202530354045505560fghijfghij
$abcdeabcde151015202530fghijfghij
BOOTSELLED1239USBRaspberryPiPico©2020RP2-8020/21P64M15.00TTT