import machine
import ssd1306
import ds1307 # Библиотека часов (файл ds1307.py остается без изменений!)
import time
# 1. Инициализация I2C для ESP32 (Стандартные аппаратные пины: SDA=21, SCL=22)
i2c = machine.I2C(0, scl=machine.Pin(22), sda=machine.Pin(21))
oled = ssd1306.SSD1306_I2C(128, 64, i2c)
# 2. Инициализация модуля часов реального времени DS1307
rtc = ds1307.DS1307(i2c)
# НАСТРОЙКА ВРЕМЕНИ (Раскомментировать при первом запуске, если нужно выставить время):
# Формат: (Год, Месяц, Число, День_недели, Часы, Минуты, Секунды, 0)
# rtc.datetime((2026, 9, 6, 7, 14, 10, 0, 0))
# 3. Переназначение ВСЕХ 6 кнопок под пины ESP32 (0 - нажата, 1 - отпущена)
btn_up = machine.Pin(13, machine.Pin.IN, machine.Pin.PULL_UP)
btn_down = machine.Pin(12, machine.Pin.IN, machine.Pin.PULL_UP)
btn_ok = machine.Pin(14, machine.Pin.IN, machine.Pin.PULL_UP)
btn_left = machine.Pin(27, machine.Pin.IN, machine.Pin.PULL_UP)
btn_right = machine.Pin(26, machine.Pin.IN, machine.Pin.PULL_UP)
btn_back = machine.Pin(25, machine.Pin.IN, machine.Pin.PULL_UP)
# Переменные калькулятора, квеста и меню
calc_stage = 0
num1_tens = num1_ones = num2_tens = num2_ones = 0
calc_digit_sel = 0
operation = "+"
calc_scroll = 0
quest_step = "START"
quest_select = 0
hp = 100
eng = 100
water = 3
apps = ["1. Clock", "2. Notes", "3. Games", "4. Calculator"]
current_select = 0
current_screen = "MENU"
note_page = 0
def draw_menu():
oled.fill(0)
oled.text("EMERGENCY", 0, 0)
# Вывод времени в верхний угол
try:
t = rtc.datetime()
time_str = "{:02d}:{:02d}".format(t[4], t[5])
oled.text(time_str, 88, 0)
except:
oled.text("??:??", 88, 0)
for i, app in enumerate(apps):
pointer = "> " if i == current_select else " "
oled.text(pointer + app, 0, 16 + (i * 12))
oled.show()
def run_app():
global current_screen
if current_select == 0: current_screen = "CLOCK"
elif current_select == 1: current_screen = "NOTES"
elif current_select == 2: current_screen = "GAMES"
elif current_select == 3: current_screen = "CALC"
# Главный цикл ОС
while True:
current_up = btn_up.value()
current_down = btn_down.value()
current_ok = btn_ok.value()
current_left = btn_left.value()
current_right = btn_right.value()
current_back = btn_back.value()
# Глобальный НАЗАД
if current_back == 0 and current_screen != "MENU":
current_screen = "MENU"
note_page = 0
while btn_back.value() == 0: time.sleep(0.01)
# 1. ГЛАВНОЕ МЕНЮ
if current_screen == "MENU":
draw_menu()
if current_down == 0:
current_select = (current_select + 1) % len(apps)
while btn_down.value() == 0: time.sleep(0.01)
elif current_up == 0:
current_select = (current_select - 1) % len(apps)
while btn_up.value() == 0: time.sleep(0.01)
elif current_ok == 0:
run_app()
while btn_ok.value() == 0: time.sleep(0.01)
# 2. ПРИЛОЖЕНИЕ: ЧАСЫ
elif current_screen == "CLOCK":
oled.fill(0)
oled.text("--- TIME ---", 20, 0)
try:
t = rtc.datetime()
live_time = "{:02d}:{:02d}:{:02d}".format(t[4], t[5], t[6])
oled.text(live_time, 32, 28)
except:
oled.text("RTC ERROR", 28, 28)
oled.text("[BACK] to Exit", 8, 54)
oled.show()
# 3. ПРИЛОЖЕНИЕ: ЗАМЕТКИ
elif current_screen == "NOTES":
pages = [
"--- NOTES (1/3) ---\nSOS Radio: 145.5MHz\nAM Radio: 104.3MHz\nStatus: All good\n[Up/Dn] Flip pages",
"--- NOTES (2/3) ---\nFirst Aid Kit:\n- Bandage (x3)\n- Antiseptic\n- Painkillers",
"--- NOTES (3/3) ---\nWater: 10 Liters\nFood: 5 Days\nBatteries: AA (x8)\nFlashlight: OK"
]
oled.fill(0)
lines = pages[note_page].split("\n")
for idx, line in enumerate(lines):
oled.text(line, 0, idx * 12)
oled.show()
if current_down == 0:
if note_page < len(pages) - 1: note_page += 1
while btn_down.value() == 0: time.sleep(0.01)
elif current_up == 0:
if note_page > 0: note_page -= 1
while btn_up.value() == 0: time.sleep(0.01)
# 4. ПРИЛОЖЕНИЕ: ИГРЫ
elif current_screen == "GAMES":
oled.fill(0)
if current_back == 0:
quest_step = "START"; quest_select = 0; hp = 100; eng = 100; water = 3
oled.text(f"H:{hp} E:{eng} W:{water}", 0, 0)
oled.hline(0, 10, 128, 1)
if hp <= 0:
oled.text(" GAME OVER! ", 16, 24); oled.text("You died...", 20, 36); oled.text("[OK] to Retry", 12, 54)
if current_ok == 0:
quest_step = "START"; hp = 100; eng = 100; water = 3; quest_select = 0
while btn_ok.value() == 0: time.sleep(0.01)
oled.show()
continue
elif quest_step == "WIN":
oled.text(" VICTORY! ", 16, 20); oled.text("You survived!", 12, 32); oled.text("Rescuers arrived", 0, 44)
if current_ok == 0:
quest_step = "START"; hp = 100; eng = 100; water = 3; quest_select = 0
while btn_ok.value() == 0: time.sleep(0.01)
oled.show()
continue
text = ""; opt1 = ""; opt2 = ""; next_step1 = ""; next_step2 = ""
eff1 = [0, 0, 0]
eff2 = [0, 0, 0]
if quest_step == "START":
text = "Power is out.\nCity is dark.\nWhat to do?"
opt1 = "1. Stay home"; opt2 = "2. Go outside"
next_step1 = "HOME"; next_step2 = "STREET"
eff1 = [0, -10, 0]; eff2 = [-10, -20, 0]
elif quest_step == "HOME":
text = "You are safe.\nThirst grows.\nDrink water?"
opt1 = "1. Yes (-1 H2O)"; opt2 = "2. No (Save it)"
next_step1 = "RADIO"; next_step2 = "DEHYDR"
eff1 = [0, +20, -1]; eff2 = [-20, -10, 0]
elif quest_step == "DEHYDR":
text = "Weakness...\nYou hear noise\nat the door."
opt1 = "1. Open door"; opt2 = "2. Ignore it"
next_step1 = "BAD_END"; next_step2 = "WIN"
eff1 = [-100, 0, 0]; eff2 = [0, 0, 0]
elif quest_step == "STREET":
text = "It's freezing.\nYou see a car.\nBreak window?"
opt1 = "1. Yes (Get heat)"; opt2 = "2. No (Walk on)"
next_step1 = "CAR_WARM"; next_step2 = "FROZEN"
eff1 = [0, +30, 0]; eff2 = [-40, -20, 0]
elif quest_step == "RADIO" or quest_step == "CAR_WARM":
text = "Radio says:\n'Help comes to\nthe City Park!'"
opt1 = "1. Go to Park"; opt2 = "2. Wait inside"
next_step1 = "WIN"; next_step2 = "FROZEN"
eff1 = [0, -30, 0]; eff2 = [-50, 0, 0]
elif quest_step == "FROZEN" or quest_step == "BAD_END":
hp = 0
continue
lines = text.split("\n")
for idx, line in enumerate(lines): oled.text(line, 0, 14 + (idx * 10))
p1 = "> " if quest_select == 0 else " "
p2 = "> " if quest_select == 1 else " "
oled.text(p1 + opt1, 0, 44); oled.text(p2 + opt2, 0, 54)
oled.show()
if current_down == 0 or current_up == 0:
quest_select = 1 if quest_select == 0 else 0
while btn_down.value() == 0 or btn_up.value() == 0: time.sleep(0.01)
elif current_ok == 0:
if quest_select == 0:
hp += eff1[0]; eng += eff1[1]; water += eff1[2]
quest_step = next_step1
else:
hp += eff2[0]; eng += eff2[1]; water += eff2[2]
quest_step = next_step2
hp = max(0, min(100, hp)); eng = max(0, min(100, eng))
quest_select = 0
while btn_ok.value() == 0: time.sleep(0.01)
# 5. ПРИЛОЖЕНИЕ: КАЛЬКУЛЯТОР
elif current_screen == "CALC":
oled.fill(0)
oled.text("--- CALC ---", 16, 0)
if current_back == 0:
calc_stage = 0
num1_tens = num1_ones = num2_tens = num2_ones = 0
calc_digit_sel = 0
if calc_stage == 0:
oled.text("Enter Num 1:", 0, 16)
oled.text(f"Value: {num1_tens}{num1_ones}", 0, 32)
arrow_pos = 72 if calc_digit_sel == 0 else 80
oled.text("^", arrow_pos, 42)
if current_left == 0:
calc_digit_sel = 0
while btn_left.value() == 0: time.sleep(0.01)
elif current_right == 0:
calc_digit_sel = 1
while btn_right.value() == 0: time.sleep(0.01)
elif current_up == 0:
if calc_digit_sel == 0: num1_tens = (num1_tens + 1) % 10
else: num1_ones = (num1_ones + 1) % 10
while btn_up.value() == 0: time.sleep(0.01)
elif current_down == 0:
if calc_digit_sel == 0: num1_tens = (num1_tens - 1) % 10
else: num1_ones = (num1_ones - 1) % 10
while btn_down.value() == 0: time.sleep(0.01)
elif current_ok == 0:
calc_stage = 1
calc_scroll = 0
while btn_ok.value() == 0: time.sleep(0.01)