#!/usr/bin/env python3 """ RTC (Real-Time Clock) Demo. Demonstrates PCF8523 RTC functionality: - Read current date/time - Set RTC time - Sync with system time - Set and monitor alarms - Display continuous time updates This example requires actual PCF8523 RTC hardware connected via I2C. """ import asyncio import sys import os import time # Add src to path sys.path.insert(0, os.path.join(os.path.dirname(__file__), '../src')) from dreader_hal import EReaderDisplayHAL def format_time(t: time.struct_time) -> str: """Format struct_time as readable string.""" return time.strftime("%Y-%m-%d %H:%M:%S %A", t) async def display_current_time(hal: EReaderDisplayHAL): """Display current RTC time continuously.""" print("\nDisplaying current time (Ctrl+C to stop)...\n") try: while True: current = await hal.get_datetime() if current: print(f"\rCurrent time: {format_time(current)}", end="", flush=True) else: print("\rRTC not available", end="", flush=True) await asyncio.sleep(1.0) except KeyboardInterrupt: print("\n") async def set_time_demo(hal: EReaderDisplayHAL): """Demonstrate setting RTC time.""" print("\n=== Setting RTC Time ===") # Show current time current = await hal.get_datetime() if current: print(f"Current RTC time: {format_time(current)}") # Set to system time print("\nSetting RTC to current system time...") system_time = time.localtime() await hal.set_datetime(system_time) print(f"System time: {format_time(system_time)}") # Verify await asyncio.sleep(0.5) new_time = await hal.get_datetime() if new_time: print(f"New RTC time: {format_time(new_time)}") print("✓ Time updated successfully!") async def alarm_demo(hal: EReaderDisplayHAL): """Demonstrate RTC alarm functionality.""" print("\n=== RTC Alarm Demo ===") # Get current time current = await hal.get_datetime() if not current: print("Error: RTC not available") return print(f"Current time: {format_time(current)}") # Set alarm for 2 minutes from now alarm_minute = (current.tm_min + 2) % 60 alarm_hour = current.tm_hour if alarm_minute < current.tm_min: alarm_hour = (alarm_hour + 1) % 24 print(f"\nSetting alarm for {alarm_hour:02d}:{alarm_minute:02d}...") await hal.set_alarm(hour=alarm_hour, minute=alarm_minute) print("✓ Alarm set!") print("\nNote: Alarm functionality requires checking alarm status") print("via the low-level RTC driver (hal.rtc.check_alarm())") async def interactive_menu(hal: EReaderDisplayHAL): """Interactive menu for RTC operations.""" while True: print("\n" + "="*50) print("RTC Demo Menu") print("="*50) print("1. Display current time") print("2. Set time to system time") print("3. Set custom time") print("4. Set alarm") print("5. Display time continuously") print("6. Exit") print("="*50) choice = input("\nEnter choice (1-6): ").strip() if choice == "1": current = await hal.get_datetime() if current: print(f"\nCurrent RTC time: {format_time(current)}") else: print("\nRTC not available") elif choice == "2": await set_time_demo(hal) elif choice == "3": print("\nEnter date/time (or press Enter to cancel):") year = input("Year (YYYY): ").strip() if not year: continue try: year = int(year) month = int(input("Month (1-12): ")) day = int(input("Day (1-31): ")) hour = int(input("Hour (0-23): ")) minute = int(input("Minute (0-59): ")) second = int(input("Second (0-59): ")) # Create struct_time (weekday and yearday are calculated) custom_time = time.struct_time(( year, month, day, hour, minute, second, 0, 0, -1 )) print(f"\nSetting RTC to: {format_time(custom_time)}") await hal.set_datetime(custom_time) # Verify await asyncio.sleep(0.5) new_time = await hal.get_datetime() if new_time: print(f"Verified: {format_time(new_time)}") print("✓ Time updated successfully!") except (ValueError, OverflowError) as e: print(f"\nError: Invalid date/time - {e}") elif choice == "4": await alarm_demo(hal) elif choice == "5": await display_current_time(hal) elif choice == "6": print("\nExiting...") break else: print("\nInvalid choice. Please enter 1-6.") async def main(): """Main example function.""" # Create HAL with RTC enabled hal = EReaderDisplayHAL( width=800, height=1200, virtual_display=True, # Virtual display for testing enable_orientation=False, enable_rtc=True, # Enable RTC enable_power_monitor=False, ) print("="*50) print("DReader HAL - RTC Demo") print("="*50) print("\nInitializing HAL with RTC...") try: await hal.initialize() print("✓ HAL initialized!") if not hal.rtc: print("\n⚠️ Warning: RTC not available!") print("\nThis example requires PCF8523 RTC hardware on I2C bus.") print("RTC should be at address 0x68 on I2C bus 1.") print("\nCheck connections:") print(" - VCC → 3.3V (Pin 1)") print(" - GND → GND (Pin 6)") print(" - SDA → GPIO2 (Pin 3)") print(" - SCL → GPIO3 (Pin 5)") print("\nVerify with: i2cdetect -y 1") return print("✓ RTC initialized!") # Show initial time current = await hal.get_datetime() if current: print(f"\nCurrent RTC time: {format_time(current)}") system_time = time.localtime() print(f"System time: {format_time(system_time)}") # Check if times differ time_diff = abs(time.mktime(current) - time.mktime(system_time)) if time_diff > 2: # More than 2 seconds difference print(f"\n⚠️ RTC differs from system time by {time_diff:.0f} seconds") # Run interactive menu await interactive_menu(hal) except RuntimeError as e: print(f"\n❌ Error: {e}") print("\nNote: This example requires PCF8523 RTC hardware on I2C bus.") return except KeyboardInterrupt: print("\n\nInterrupted by user") finally: # Cleanup print("\nCleaning up...") await hal.cleanup() print("Done!") if __name__ == "__main__": try: asyncio.run(main()) except KeyboardInterrupt: print("\nExiting...")