Загрузка данных


from machine import import Pin, I2C
import ssd1306
import time

# ==========================================
# # НАСТРОЙКИ
# ==========================================
OLED_WIDTH = 128
OLED_HEIGHT = 64
OLED_ADDRESS = 0x3C

# Тексты можно менять здесь.
# Стандартный шрифт SSD1306 поддерживает только латинские символы.
START_TEXT = "Najimai lubuiu knopky"

TEXT_BUTTON_1 = "a/(sin a)=b/(sin b)=c/(sin c)=2R|a^2=b^2+c^2-2bc*cosa"
TEXT_BUTTON_2 = "blablabla super puper poleznaya formula"
TEXT_BUTTON_3 = "predstavte budto zdes chtoto ochen vajnoe"
TEXT_BUTTON_4 = "kto prochital tot nigadai"

# Период защиты от дребезга кнопок, миллисекунды
DEBOUNCE_MS = 50

# ==========================================
# # ИНИЦИАЛИЗАЦИЯ OLED
# ==========================================
i2c = I2C(
    0,
    scl=Pin(22),
    sda=Pin(21),
    freq=400000
)

oled = ssd1306.SSD1306_I2C(
    OLED_WIDTH,
    OLED_HEIGHT,
    i2c,
    addr=OLED_ADDRESS
)

# ==========================================
# # ИНИЦИАЛИЗАЦИЯ КНОПОК
# ==========================================
button_pins = [
    Pin(13, Pin.IN, Pin.PULL_UP),
    Pin(14, Pin.IN, Pin.PULL_UP),
    Pin(25, Pin.IN, Pin.PULL_UP),
    Pin(26, Pin.IN, Pin.PULL_UP)
]

button_texts = [
    TEXT_BUTTON_1,
    TEXT_BUTTON_2,
    TEXT_BUTTON_3,
    TEXT_BUTTON_4
]

# Последнее мгновенное состояние кнопок
last_raw_states = [button.value() for button in button_pins]
# Подтвержденное стабильное состояние кнопок
stable_states = last_raw_states[:]
# Время последнего изменения мгновенного состояния
change_times = [time.ticks_ms()] * len(button_pins)

# ==========================================
# # РАБОТА С ТЕКСТОМ
# ==========================================
def split_long_word(word, max_chars):
    """
    Разбивает слишком длинное слово на части,
    чтобы оно помещалось на экран.
    """
    parts = []
    while len(word) > max_chars:
        parts.append(word[:max_chars])
        word = word[max_chars:]
    if word:
        parts.append(word)
    return parts

def wrap_text(text, max_chars=16):
    """
    Переносит текст по словам.
    Для OLED 128x64:
    128 / 8 = 16 символов в строке
    64 / 8 = 8 строк
    """
    words = text.split()
    lines = []
    current_line = ""
    
    for word in words:
        # Если слово само длиннее ширины строки
        if len(word) > max_chars:
            if current_line:
                lines.append(current_line)
                current_line = ""
            long_word_parts = split_long_word(word, max_chars)
            for part in long_word_parts:
                lines.append(part)
        else:
            if current_line == "":
                current_line = word
            elif len(current_line) + 1 + len(word) <= max_chars:
                current_line += " " + word
            else:
                lines.append(current_line)
                current_line = word
                
    if current_line:
        lines.append(current_line)
        
    return lines

def show_text(text):
    """
    Полностью очищает экран и выводит новый текст.
    """
    # Полное стирание буфера OLED
    oled.fill(0)
    
    # Получаем строки с переносом
    lines = wrap_text(text)
    
    # На экране 128x64 помещается максимум 8 строк
    max_lines = OLED_HEIGHT // 8
    
    for line_number, line in enumerate(lines[:max_lines]):
        y = line_number * 8
        oled.text(line, 0, y)
        
    # Передача изображения на OLED
    oled.show()

def clear_screen():
    """
    Полностью очищает дисплей.
    """
    oled.fill(0)
    oled.show()

# ==========================================
# # ЗАПУСК
# ==========================================
clear_screen()
show_text(START_TEXT)

# Небольшая задержка после стартовой надписи
time.sleep_ms(500)

# Переменные для режима часов
show_time_mode = False
last_time_update = 0

# ==========================================
# # ГЛАВНЫЙ ЦИКЛ
# ==========================================
while True:
    now = time.ticks_ms()
    
    for index, button in enumerate(button_pins):
        raw_state = button.value()
        
        # Если мгновенное состояние изменилось, запускаем отсчет защиты от дребезга
        if raw_state != last_raw_states[index]:
            last_raw_states[index] = raw_state
            change_times[index] = now
            
        # Проверяем, сохраняется ли состояние достаточно долго
        elif time.ticks_diff(now, change_times[index]) >= DEBOUNCE_MS:
            # Если стабильное состояние действительно изменилось
            if stable_states[index] != raw_state:
                stable_states[index] = raw_state
                
                # Кнопка нажата: состояние LOW (0)
                if stable_states[index] == 0:
                    if index == 2:  # Если нажата 3-я кнопка (индекс 2)
                        show_time_mode = not show_time_mode  # Переключаем режим часов
                        if not show_time_mode:
                            show_text("Menu closed")  # Надпись при закрытии часов
                    else:
                        show_time_mode = False  # Любая другая кнопка отключает часы
                        show_text(button_texts[index])

    # Динамическое обновление времени каждую секунду
    if show_time_mode and time.ticks_diff(now, last_time_update) >= 1000:
        last_time_update = now
        t = time.localtime()  # Получаем текущее время контроллера
        
        # Форматируем красивое меню с часами
        time_str = "   TIME MENU\n\n    {:02d}:{:02d}:{:02d}".format(t[3], t[4], t[5])
        show_text(time_str)

    # Короткая пауза, чтобы не загружать процессор
    time.sleep_ms(5)