# main.py - Código unificado de sistema embebido con Round Robin (sin HC-SR04)
print("¡El script se está ejecutando!")
import time
import math
import random
from machine import Pin, I2C, ADC, Timer, PWM
from ssd1306 import SSD1306_I2C
# from machine import time_pulse_us # ELIMINADO: No necesitamos time_pulse_us sin HC-SR04
# Importar las librerías y módulos.
import dht # Para el sensor DHT22
print("Iniciando script Round Robin (sin HC-SR04)...")
# --- Constantes y Pines ---
WIDTH, HEIGHT = 128, 64 # Dimensiones de la pantalla OLED
# Pines I2C para la pantalla OLED
SCL_PIN = 5
SDA_PIN = 4
# Pines para el Joystick Analógico (No usado en los modos actuales, se mantiene por si acaso)
JOY_X_PIN = 26 # GP26
JOY_Y_PIN = 27 # GP27
# Pines para los Botones (4 Direccionales + 1 Seleccionar + 1 Atrás)
BTN_UP_PIN = 10 # GP10 (Arriba)
BTN_DOWN_PIN = 11 # GP11 (Abajo)
BTN_RIGHT_PIN = 12 # GP12 (Derecha)
BTN_LEFT_PIN = 13 # GP13 (Izquierda)
BTN_ENTER_PIN = 15 # GP15 (Ahora es ENTER/Seleccionar)
BTN_BACK_PIN = 16 # GP16 (NUEVO BOTÓN: ATRÁS)
# Pin para el Buzzer
BUZZER_PIN = 14 # GP14
# Pin para el sensor DHT22
DHT22_PIN = 19 # GP19
# --- Pines para HC-SR04 --- ELIMINADOS
# TRIGGER_PIN = 20 # GPIO20
# ECHO_PIN = 21 # GPIO21
# DISTANCE_THRESHOLD = 5 # cm para apagar OLED
# --- Definición de Modos del Sistema ---
MODE_PRESENTATION = -1 # Un modo inicial para la pantalla de bienvenida
MODE_MENU = 0
MODE_CLOCK = 1
MODE_CHRONOMETER = 2
MODE_ANALOG_CLOCK = 3
MODE_TEMPERATURE = 4
MODE_CALENDAR = 5
# --- Inicialización de Hardware ---
oled_initialized = False
try:
print("Inicializando I2C y OLED...")
i2c = I2C(0, scl=Pin(SCL_PIN), sda=Pin(SDA_PIN), freq=400000)
oled = SSD1306_I2C(WIDTH, HEIGHT, i2c)
oled_initialized = True
print("OLED inicializada exitosamente.")
# Asegurar que la OLED esté encendida y limpia al inicio
oled.poweron()
oled.fill(0)
oled.show()
except Exception as e:
print(f"ERROR: Fallo al inicializar OLED en pines SCL={SCL_PIN}, SDA={SDA_DA}. Mensaje: {e}")
buzzer = PWM(Pin(BUZZER_PIN))
buzzer.freq(1000) # Frecuencia inicial para el buzzer
buzzer.duty_u16(0) # Apagado inicialmente
print("Buzzer inicializado.")
# Inicialización de pines de botones con pull-up interno
btn_up = Pin(BTN_UP_PIN, Pin.IN, Pin.PULL_UP)
btn_down = Pin(BTN_DOWN_PIN, Pin.IN, Pin.PULL_UP)
btn_right = Pin(BTN_RIGHT_PIN, Pin.IN, Pin.PULL_UP)
btn_left = Pin(BTN_LEFT_PIN, Pin.IN, Pin.PULL_UP)
btn_enter = Pin(BTN_ENTER_PIN, Pin.IN, Pin.PULL_UP)
btn_back = Pin(BTN_BACK_PIN, Pin.IN, Pin.PULL_UP)
print("Botones inicializados.")
# Inicialización de ADCs para el joystick (se mantienen aunque no se usen activamente)
joy_x = ADC(JOY_X_PIN)
joy_y = ADC(JOY_Y_PIN)
print("Joystick ADCs inicializados.")
# Inicialización del sensor DHT22
dht_sensor = dht.DHT22(Pin(DHT22_PIN))
print("Sensor DHT22 inicializado (o intento).")
# --- Inicialización del sensor HC-SR04 --- ELIMINADA
# trigger_pin = Pin(TRIGGER_PIN, Pin.OUT)
# echo_pin = Pin(ECHO_PIN, Pin.IN)
# trigger_pin.low()
# print("Sensor HC-SR04 inicializado.")
# --- Variables Globales del Sistema ---
global_current_mode = MODE_PRESENTATION # Estado actual del sistema
# Variables para el reloj digital global (se actualiza cada segundo)
global_h = 0
global_m = 0
global_s = 0
# Variables para el cronómetro
ch = cm = cs = cc = 0
cronometro_activo = False
# Variables para la fecha global
global_day = 1
global_month = 1
global_year = 2025
# Variables temporales de ajuste (para Clock y Calendar)
time_setting_part = 0
current_setting_h = 0
current_setting_m = 0
current_setting_s = 0
clock_setting_active = False
date_setting_part = 0
current_setting_day = 1
current_setting_month = 1
current_setting_year = 2025
calendar_setting_active = False
# Estado de la OLED (ahora siempre encendida, ya que no hay sensor para apagarla)
oled_powered = True
# --- Funciones Auxiliares del Sistema ---
# Control del Buzzer para sonido de clic
def play_click_sound():
if buzzer is not None:
buzzer.duty_u16(5000)
buzzer.freq(2000)
time.sleep_ms(50)
buzzer.duty_u16(0)
button_last_states = {
'up': [True],
'down': [True],
'right': [True],
'left': [True],
'enter': [True],
'back': [True]
}
def check_button_press(button_pin, last_state_var_list):
current_state = button_pin.value()
if not current_state and last_state_var_list[0]:
last_state_var_list[0] = False
play_click_sound()
return True
elif current_state and not last_state_var_list[0]:
last_state_var_list[0] = True
return False
def display_global_clock():
if oled_initialized and oled_powered:
oled.text("{:02}:{:02}".format(global_h, global_m), 80, 0)
def get_days_in_month(month, year):
if month == 2: # Febrero
if (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0): # Año bisiesto
return 29
else:
return 28
elif month in [4, 6, 9, 11]: # Meses con 30 días
return 30
else: # Meses con 31 días
return 31
# --- Funciones de "Tareas" para el Planificador Round Robin ---
def task_update_global_clock():
# Esta función ya no hace nada, el reloj se actualiza por su propio Timer ISR
pass
# --- TAREA: Leer Sensor HC-SR04 y Controlar OLED --- ELIMINADA
# def task_ultrasonic_oled_control():
# global oled_powered, oled_last_check_time
# # Esta función ha sido eliminada. La OLED se asume siempre encendida.
# pass
# --- MODO: Pantalla de Presentación ---
def run_presentation_mode_once():
global global_current_mode
if not oled_initialized or not oled_powered:
print("OLED no inicializada o no encendida. Saltando modo presentación.")
global_current_mode = MODE_MENU
return
oled.fill(0)
for _ in range(2):
buzzer.freq(500)
buzzer.duty_u16(30000)
time.sleep_ms(200)
buzzer.duty_u16(0)
time.sleep_ms(50)
buzzer.freq(1000)
buzzer.duty_u16(30000)
time.sleep_ms(200)
buzzer.duty_u16(0)
time.sleep_ms(50)
buzzer.duty_u16(0)
agumon_bytes = bytearray([
0xff, 0xc0, 0x03, 0xff, 0xff, 0xc0, 0x03, 0xff,
0xff, 0x3f, 0xfc, 0xff, 0xff, 0x3f, 0xfc, 0xff,
0xc0, 0xff, 0x0f, 0x3f, 0xc0, 0xff, 0x0f, 0x3f,
0x3f, 0xff, 0xc3, 0x3f, 0x3f, 0xff, 0xc3, 0x3f,
0x3f, 0xff, 0x03, 0x3f, 0x3f, 0xff, 0x03, 0x3f,
0x3f, 0xc3, 0xff, 0x3f, 0x3f, 0xc3, 0xff, 0x3f,
0xc0, 0x3f, 0xff, 0x3f, 0xc0, 0x3f, 0xff, 0x3f,
0xcf, 0xff, 0x0c, 0xff, 0xcf, 0xff, 0x0c, 0xff,
0xf0, 0x00, 0xfc, 0xff, 0xf0, 0x00, 0xfc, 0xff,
0xfc, 0x3f, 0x0f, 0x3f, 0xfc, 0x3f, 0x0f, 0x3f,
0xf3, 0x3c, 0xfc, 0x3f, 0xf3, 0x3c, 0xfc, 0x3f,
0xf0, 0x3c, 0x0f, 0xc0, 0xf0, 0x3c, 0x0f, 0xc0,
0xff, 0x0f, 0xcc, 0x0c, 0xff, 0x0f, 0xcc, 0x0c,
0xf0, 0xf0, 0x0f, 0xc3, 0xf0, 0xf0, 0x0f, 0xc3,
0xcc, 0xf3, 0x33, 0x33, 0xcc, 0xf3, 0x33, 0x33,
0xc0, 0x03, 0x00, 0x03, 0xc0, 0x03, 0x00, 0x03
])
agumon_fb = framebuf.FrameBuffer(agumon_bytes, 32, 32, framebuf.MONO_HLSB)
oled.blit(agumon_fb, (WIDTH // 2) - 16, 0)
oled.text("Edwin Luis", 20, 40)
oled.text("Garavito Omoya", 5, 50)
oled.show()
time.sleep(3)
oled.fill(0)
oled.show()
global_current_mode = MODE_MENU # Pasar al menú después de la presentación
# --- MODO: Menú Principal con Iconos ---
# Iconos (16x16 píxeles, MONO_HLSB)
icon_clock_bytes = bytearray([
0xff, 0xff, 0xff, 0xff,
0x85, 0xb7, 0xbd, 0xb7,
0xbd, 0xb7, 0xbd, 0xb4,
0x85, 0xb4, 0xf5, 0xb7,
0xf5, 0xb7, 0xf5, 0xb4,
0xf5, 0xb4, 0xf5, 0xb7,
0x85, 0xb7, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff
])
icon_clock_fb = framebuf.FrameBuffer(icon_clock_bytes, 16, 16, framebuf.MONO_HLSB)
icon_chrono_bytes = bytearray([
0xff, 0xff, 0x7f, 0xfc,
0xff, 0xfe, 0x1f, 0xf0,
0xef, 0xef, 0xf7, 0xdf,
0xfb, 0xbf, 0x1b, 0xb1,
0x5b, 0xb5, 0x5b, 0xb5,
0x1b, 0xb1, 0xfb, 0xbf,
0xf7, 0xdf, 0xef, 0xef,
0x1f, 0xf0, 0xff, 0xff
])
icon_chrono_fb = framebuf.FrameBuffer(icon_chrono_bytes, 16, 16, framebuf.MONO_HLSB)
icon_analog_bytes = bytearray([
0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff,
0xff, 0xf7, 0xff, 0xfb,
0xff, 0xfd, 0x7f, 0xfe,
0x7f, 0xfe, 0xbf, 0xff,
0xdf, 0xff, 0xef, 0xff,
0xf7, 0xff, 0xfb, 0xff,
0xfd, 0xff, 0xff, 0xff
])
icon_analog_fb = framebuf.FrameBuffer(icon_analog_bytes, 16, 16, framebuf.MONO_HLSB)
icon_temp_bytes = bytearray([
0xff, 0xff,
0xfe, 0x7f,
0xfd, 0xbf,
0xfd, 0x3f,
0xfd, 0xbf,
0xfd, 0x3f,
0xfd, 0xbf,
0xfd, 0x3f,
0xfb, 0xdf,
0xf7, 0xef,
0xf7, 0xef,
0xf7, 0xef,
0xf8, 0x1f,
0xff, 0xff
])
icon_temp_fb = framebuf.FrameBuffer(icon_temp_bytes, 16, 16, framebuf.MONO_HLSB)
icon_calendar_bytes = bytearray([
0x12, 0x48,
0x12, 0x48,
0x12, 0x48,
0x00, 0x00,
0x00, 0x00,
0xff, 0xff,
0xf7, 0x0f,
0xf7, 0xef,
0xf7, 0xef,
0xf7, 0x0f,
0xf7, 0x7f,
0xf7, 0x7f,
0xf7, 0x7f,
0xf7, 0x0f,
0xff, 0xff,
0xff, 0xff
])
icon_calendar_fb = framebuf.FrameBuffer(icon_calendar_bytes, 16, 16, framebuf.MONO_HLSB)
menu_items = [
("Reloj Digital", icon_clock_fb, MODE_CLOCK),
("Cronometro", icon_chrono_fb, MODE_CHRONOMETER),
("Reloj Analogico", icon_analog_fb, MODE_ANALOG_CLOCK),
("Temperatura", icon_temp_fb, MODE_TEMPERATURE),
("Calendario", icon_calendar_fb, MODE_CALENDAR)
]
current_menu_selection = 0
def run_menu_mode():
global global_current_mode, current_menu_selection
if not oled_initialized or not oled_powered: return
oled.fill(0)
display_offset = 0
if len(menu_items) > 3:
if current_menu_selection >= 2:
display_offset = current_menu_selection - 2
if display_offset > len(menu_items) - 3:
display_offset = len(menu_items) - 3
if display_offset < 0:
display_offset = 0
for i in range(display_offset, min(len(menu_items), display_offset + 3)):
menu_text, menu_icon_fb, _ = menu_items[i]
icon_x = 0
text_x = 20
y_pos = 5 + (i - display_offset) * 20
if i == current_menu_selection:
oled.fill_rect(icon_x, y_pos, WIDTH, 18, 1)
oled.blit(menu_icon_fb, icon_x + 2, y_pos + 1, 0)
oled.text(menu_text, text_x, y_pos + 5, 0)
else:
oled.blit(menu_icon_fb, icon_x + 2, y_pos + 1, 1)
oled.text(menu_text, text_x, y_pos + 5, 1)
display_global_clock()
oled.show()
if check_button_press(btn_up, button_last_states['up']):
current_menu_selection = (current_menu_selection - 1 + len(menu_items)) % len(menu_items)
if check_button_press(btn_down, button_last_states['down']):
current_menu_selection = (current_menu_selection + 1) % len(menu_items)
if check_button_press(btn_enter, button_last_states['enter']):
global_current_mode = menu_items[current_menu_selection][2]
# --- MODO: Reloj Digital (Visualización y Configuración) ---
def show_clock_mode():
global global_current_mode, time_setting_part
global current_setting_h, current_setting_m, current_setting_s, clock_setting_active
global global_h, global_m, global_s
if not oled_initialized or not oled_powered: return
oled.fill(0)
display_global_clock()
if not clock_setting_active:
oled.text("Reloj Digital", 0, 10)
full_time_display = "{:02}:{:02}:{:02}".format(global_h, global_m, global_s)
oled.text(full_time_display, 20, 30)
oled.text("ENTER: Ajustar", 0, 50)
oled.text("BACK: Menu", 0, 40)
oled.show()
if check_button_press(btn_enter, button_last_states['enter']):
clock_setting_active = True
current_setting_h = global_h
current_setting_m = global_m
current_setting_s = global_s
time_setting_part = 0
if check_button_press(btn_back, button_last_states['back']):
global_current_mode = MODE_MENU
else:
oled.text("Ajuste de Hora", 0, 10)
hora_display = "{:02}:{:02}:{:02}".format(current_setting_h, current_setting_m, current_setting_s)
oled.text(hora_display, 20, 30)
if time_setting_part == 0:
oled.rect(20-1, 30+8+1, 2*8+2, 2, 1)
elif time_setting_part == 1:
oled.rect(20+3*8-1, 30+8+1, 2*8+2, 2, 1)
elif time_setting_part == 2:
oled.rect(20+6*8-1, 30+8+1, 2*8+2, 2, 1)
oled.text("UP/DOWN: Ajustar", 0, 40)
oled.text("RIGHT: Siguiente", 0, 50)
oled.show()
if check_button_press(btn_up, button_last_states['up']):
if time_setting_part == 0:
current_setting_h = (current_setting_h + 1) % 24
elif time_setting_part == 1:
current_setting_m = (current_setting_m + 1) % 60
elif time_setting_part == 2:
current_setting_s = (current_setting_s + 1) % 60
if check_button_press(btn_down, button_last_states['down']):
if time_setting_part == 0:
current_setting_h = (current_setting_h - 1 + 24) % 24
elif time_setting_part == 1:
current_setting_m = (current_setting_m - 1 + 60) % 60
elif time_setting_part == 2:
current_setting_s = (current_setting_s - 1 + 60) % 60
if check_button_press(btn_right, button_last_states['right']):
time_setting_part = (time_setting_part + 1) % 3
if check_button_press(btn_enter, button_last_states['enter']):
global_h = current_setting_h
global_m = current_setting_m
global_s = current_setting_s
clock_setting_active = False
if check_button_press(btn_back, button_last_states['back']):
clock_setting_active = False
# --- MODO: Cronómetro ---
def show_chronometer_mode():
global ch, cm, cs, cc, cronometro_activo, global_current_mode
if not oled_initialized or not oled_powered: return
oled.fill(0)
display_global_clock()
oled.text("Cronometro", 0, 10)
t = "{:02}:{:02}:{:02}.{:02}".format(ch, cm, cs, cc)
oled.text(t[0:5], 10, 30)
oled.text(t[6:], 10, 45)
oled.text("{}".format("ON" if cronometro_activo else "PAUSA"), 85, 20)
oled.text("LEFT: Reset", 0, 56)
oled.show()
if cronometro_activo:
cc += 1
if cc >= 100:
cc = 0
cs += 1
if cs >= 60:
cs = 0
cm += 1
if cm >= 60:
cm = 0
ch += 1
if check_button_press(btn_enter, button_last_states['enter']):
cronometro_activo = not cronometro_activo
if check_button_press(btn_left, button_last_states['left']):
ch = cm = cs = cc = 0
cronometro_activo = False
if check_button_press(btn_back, button_last_states['back']):
global_current_mode = MODE_MENU
# --- MODO: Reloj Analógico ---
def show_analog_clock_mode():
global global_current_mode
if not oled_initialized or not oled_powered: return
oled.fill(0)
cx, cy, r = 64, 32, 28
for a in range(0, 360, 30):
x = int(cx + math.cos(math.radians(a)) * r)
y = int(cy + math.sin(math.radians(a)) * r)
oled.pixel(x, y, 1)
ang_s = (global_s / 60) * 360 - 90
ang_m = (global_m / 60) * 360 - 90
ang_h = ((global_h % 12 + global_m / 60) / 12) * 360 - 90
oled.line(cx, cy, int(cx + math.cos(math.radians(ang_s)) * r), int(cy + math.sin(math.radians(ang_s)) * r), 1)
oled.line(cx, cy, int(cx + math.cos(math.radians(ang_m)) * (r - 6)), int(cy + math.sin(math.radians(ang_m)) * (r - 6)), 1)
oled.line(cx, cy, int(cx + math.cos(math.radians(ang_h)) * (r - 12)), int(cy + math.sin(math.radians(ang_h)) * (r - 12)), 1)
oled.text("Analogico", 30, 0)
display_global_clock()
oled.show()
if check_button_press(btn_back, button_last_states['back']):
global_current_mode = MODE_MENU
# --- MODO: Temperatura ---
temp_last_read_time = 0
TEMP_READ_INTERVAL_MS = 2000
def run_temperature_mode():
global global_current_mode, temp_last_read_time
if not oled_initialized or not oled_powered: return
oled.fill(0)
display_global_clock()
oled.text("Modo: Temperatura", 0, 10)
current_time_ms = time.ticks_ms()
if time.ticks_diff(current_time_ms, temp_last_read_time) >= TEMP_READ_INTERVAL_MS:
temp_last_read_time = current_time_ms
try:
dht_sensor.measure()
temperatura = dht_sensor.temperature()
humedad = dht_sensor.humidity()
oled.text("Temp: {:.1f}C".format(temperatura), 0, 30)
oled.text("Hum: {:.1f}%".format(humedad), 0, 45)
except OSError as e:
oled.text("Error DHT22", 0, 30)
oled.text(str(e)[:15], 0, 45)
else:
oled.text("Esperando datos...", 0, 30)
oled.show()
if check_button_press(btn_back, button_last_states['back']):
global_current_mode = MODE_MENU
# --- MODO: Calendario ---
def show_calendar_mode():
global global_current_mode
global current_setting_day, current_setting_month, current_setting_year
global date_setting_part, calendar_setting_active
global global_day, global_month, global_year
if not oled_initialized or not oled_powered: return
oled.fill(0)
display_global_clock()
if not calendar_setting_active:
oled.text("Calendario", 0, 10)
full_date_display = "{:02}/{:02}/{}".format(global_day, global_month, global_year)
oled.text(full_date_display, 20, 30)
oled.text("ENTER: Ajustar", 0, 50)
oled.text("BACK: Menu", 0, 40)
oled.show()
if check_button_press(btn_enter, button_last_states['enter']):
calendar_setting_active = True
current_setting_day = global_day
current_setting_month = global_month
current_setting_year = global_year
date_setting_part = 0
if check_button_press(btn_back, button_last_states['back']):
global_current_mode = MODE_MENU
else:
oled.text("Ajuste de Fecha", 0, 10)
date_display = "{:02}/{:02}/{}".format(current_setting_day, current_setting_month, current_setting_year)
oled.text(date_display, 20, 30)
if date_setting_part == 0:
oled.rect(20-1, 30+8+1, 2*8+2, 2, 1)
elif date_setting_part == 1:
oled.rect(20+3*8-1, 30+8+1, 2*8+2, 2, 1)
elif date_setting_part == 2:
oled.rect(20+6*8-1, 30+8+1, 4*8+2, 2, 1)
oled.text("UP/DOWN: Ajustar", 0, 40)
oled.text("RIGHT: Siguiente", 0, 50)
oled.show()
if check_button_press(btn_up, button_last_states['up']):
if date_setting_part == 0:
max_days = get_days_in_month(current_setting_month, current_setting_year)
current_setting_day = (current_setting_day % max_days) + 1
elif date_setting_part == 1:
current_setting_month = (current_setting_month % 12) + 1
max_days = get_days_in_month(current_setting_month, current_setting_year)
if current_setting_day > max_days:
current_setting_day = max_days
elif date_setting_part == 2:
current_setting_year = (current_setting_year % 2100) + 1 if current_setting_year < 2099 else 2000
if current_setting_month == 2:
max_days = get_days_in_month(current_setting_month, current_setting_year)
if current_setting_day > max_days:
current_setting_day = max_days
if check_button_press(btn_down, button_last_states['down']):
if date_setting_part == 0:
max_days = get_days_in_month(current_setting_month, current_setting_year)
current_setting_day = (current_setting_day - 2 + max_days) % max_days + 1
elif date_setting_part == 1:
current_setting_month = (current_setting_month - 2 + 12) % 12 + 1
max_days = get_days_in_month(current_setting_month, current_setting_year)
if current_setting_day > max_days:
current_setting_day = max_days
elif date_setting_part == 2:
current_setting_year = (current_setting_year - 2001 + 100) % 100 + 2000 if current_setting_year > 2000 else 2099
if current_setting_month == 2:
max_days = get_days_in_month(current_setting_month, current_setting_year)
if current_setting_day > max_days:
current_setting_day = max_days
if check_button_press(btn_right, button_last_states['right']):
date_setting_part = (date_setting_part + 1) % 3
if check_button_press(btn_enter, button_last_states['enter']):
global_day = current_setting_day
global_month = current_setting_month
global_year = current_setting_year
calendar_setting_active = False
if check_button_press(btn_back, button_last_states['back']):
calendar_setting_active = False
# --- Planificador Round Robin con Interrupciones ---
# Eliminada la tarea task_ultrasonic_oled_control de aquí
system_tasks = [
task_update_global_clock
]
mode_to_task_map = {
MODE_MENU: run_menu_mode,
MODE_CLOCK: show_clock_mode,
MODE_CHRONOMETER: show_chronometer_mode,
MODE_ANALOG_CLOCK: show_analog_clock_mode,
MODE_TEMPERATURE: run_temperature_mode,
MODE_CALENDAR: show_calendar_mode,
}
TIME_SLICE_MS = 50
timer_global_reloj = Timer()
timer_global_reloj.init(freq=1, mode=Timer.PERIODIC, callback=lambda t: tick_global_reloj_ISR())
def tick_global_reloj_ISR():
global global_h, global_m, global_s
global_s += 1
if global_s >= 60:
global_s = 0
global_m += 1
if global_m >= 60:
global_m = 0
global_h += 1
if global_h >= 24:
global_h = 0
def scheduler_callback(timer):
global global_current_mode
if global_current_mode == MODE_PRESENTATION:
run_presentation_mode_once()
else:
if global_current_mode in mode_to_task_map:
mode_to_task_map[global_current_mode]()
else:
global_current_mode = MODE_MENU
print(f"AVISO: Modo desconocido '{global_current_mode}', volviendo a menú.")
for sys_task in system_tasks:
sys_task()
rr_timer = Timer(1)
try:
print(f"Inicializando Timer Round Robin con periodo de {TIME_SLICE_MS}ms...")
rr_timer.init(mode=Timer.PERIODIC, period=TIME_SLICE_MS, callback=scheduler_callback)
print("Timer Round Robin inicializado.")
except Exception as e:
print(f"ERROR: Fallo al inicializar el Timer Round Robin. Mensaje: {e}")
# --- Bucle Principal del Sistema ---
def main_loop_scheduler():
print("Entrando al bucle principal del scheduler. Las tareas se ejecutan por interrupciones.")
try:
while True:
time.sleep(1)
except KeyboardInterrupt:
print("Detectado Ctrl+C. Deteniendo timers...")
rr_timer.deinit()
timer_global_reloj.deinit()
print("Timers detenidos. Programa finalizado.")
# --- Ejecución del Programa ---
if __name__ == "__main__":
main_loop_scheduler()