🕐 hal::rtc

Real-Time Clock - Tarih/Saat Yönetimi

379 lines ~12 function Low-Power

📖 Overview

RTC (Real-Time Clock) modülü, düşük güç tüketimli tarih ve saat tutma işlevi sağlar. Batarya destekli çalışma, alarm ve takvim özellikleri sunar.

🔑 Key Features

🚀 Quick Start

import hal::rtc

// Initialize RTC
let rtc_handle = rtc.init(do
    hour_format: rtc.FORMAT_24H,
    async_prediv: 127,
    sync_prediv: 255
end)

// Set time
rtc.set_time(rtc_handle, do
    hours: 14,
    minutes: 30,
    seconds: 0
end)

// Set date
rtc.set_date(rtc_handle, do
    year: 2024,
    month: 12,
    day: 25,
    weekday: rtc.WEDNESDAY
end)

// Read time
let time = rtc.get_time(rtc_handle)
io.println("{:02}:{:02}:{:02}".formatla(time.hours, time.minutes, time.seconds))

💡 Example: Digital Clock Display

import hal::rtc, hal::core

struct DateTime do
    year: int,
    month: int,
    day: int,
    hours: int,
    minutes: int,
    seconds: int,
    weekday: int
end

function weekday_name(day: int) -> str do
    return match day do
        1 => "Pazartesi",
        2 => "Salı",
        3 => "Çarşamba",
        4 => "Perşembe",
        5 => "Cuma",
        6 => "Cumartesi",
        7 => "Pazar",
        _ => "Bilinmeyen"
    end
end

function ana() do
    core.system_init()
    
    // Initialize RTC
    let rtc_handle = rtc.init(do
        hour_format: rtc.FORMAT_24H
    end)
    
    // Set initial time (2024-12-25 14:30:00 Wednesday)
    rtc.set_date(rtc_handle, do
        year: 2024,
        month: 12,
        day: 25,
        weekday: rtc.WEDNESDAY
    end)
    
    rtc.set_time(rtc_handle, do
        hours: 14,
        minutes: 30,
        seconds: 0
    end)
    
    loop do
        // Read current time
        let time = rtc.get_time(rtc_handle)
        let date = rtc.get_date(rtc_handle)
        
        // Display
        io.print("\r")  // Carriage return
        io.print("{:02}/{:02}/{} {} {:02}:{:02}:{:02}".formatla(
            date.day,
            date.month,
            date.year,
            weekday_name(date.weekday),
            time.hours,
            time.minutes,
            time.seconds
        ))
        
        core.delay_ms(1000)
    end
end

💡 Example: Alarm Clock

import hal::rtc

let alarm_triggered = false

function alarm_callback() do
    alarm_triggered = true
    io.println("\n🔔 ALARM! Wake up!")
end

function set_alarm(rtc_handle: rtc.Handle, hours: int, minutes: int) do
    rtc.set_alarm(rtc_handle, rtc.ALARM_A, do
        hours: hours,
        minutes: minutes,
        seconds: 0,
        alarm_mask: rtc.MASK_SECONDS,  // Ignore seconds
        callback: alarm_callback
    end)
    
    io.println("Alarm set for {:02}:{:02}".formatla(hours, minutes))
end

function ana() do
    let rtc_handle = rtc.init(do
        hour_format: rtc.FORMAT_24H
    end)
    
    // Set current time: 07:58:00
    rtc.set_time(rtc_handle, do
        hours: 7,
        minutes: 58,
        seconds: 0
    end)
    
    // Set alarm for 08:00
    set_alarm(rtc_handle, 8, 0)
    
    loop do
        let time = rtc.get_time(rtc_handle)
        io.print("\r{:02}:{:02}:{:02}".formatla(
            time.hours, time.minutes, time.seconds
        ))
        
        if alarm_triggered ise do
            alarm_triggered = false
            // Snooze for 5 minutes
            set_alarm(rtc_handle, time.hours, time.minutes + 5)
        end
        
        core.delay_ms(1000)
    end
end

💡 Example: Wakeup Timer (Auto-Wakeup from Standby)

import hal::rtc, hal::core

function periodic_wakeup() do
    let rtc_handle = rtc.init(do
        hour_format: rtc.FORMAT_24H
    end)
    
    // Configure wakeup every 10 seconds
    rtc.set_wakeup(rtc_handle, do
        prescaler: rtc.WAKEUP_DIV_16,  // 16Hz clock
        counter: 160  // 160 / 16Hz = 10 seconds
    end)
    
    io.println("Entering standby, wakeup in 10s...")
    core.delay_ms(100)  // Flush UART
    
    // Enter standby mode (lowest power)
    core.standby()
    
    // After wakeup, system resets
    io.println("Woke up from standby!")
    
    // Check wakeup flag
    if rtc.was_wakeup_flag_set() ise do
        io.println("Wakeup timer triggered")
        rtc.clear_wakeup_flag()
    end
end

function ana() do
    // Count wakeups using backup register
    let wakeup_count = rtc.read_backup(rtc_handle, 0)
    wakeup_count += 1
    rtc.write_backup(rtc_handle, 0, wakeup_count)
    
    io.println("Wakeup count: {}", wakeup_count)
    
    periodic_wakeup()
end

💡 Example: Battery-Backed Data Logger

import hal::rtc

// Store sensor readings in backup registers (survives power loss)
struct LogEntry do
    timestamp: int,  // Unix timestamp
    temp: u16,        // Temperature x100
    humidity: u16     // Humidity x100
end

const MAX_ENTRIES = 20  // 80 bytes / 4 = 20 entries

function log_data(temp: float, humidity: float) do
    let rtc_handle = rtc.init(do hour_format: rtc.FORMAT_24H end)
    
    // Get current index
    let index = rtc.read_backup(rtc_handle, 0)
    if index >= MAX_ENTRIES ise index = 0
    
    // Get timestamp
    let time = rtc.get_time(rtc_handle)
    let date = rtc.get_date(rtc_handle)
    let timestamp = date_to_unix(date, time)
    
    // Store in backup registers (4 bytes per entry)
    let base = 1 + (index * 2)
    rtc.write_backup(rtc_handle, base, timestamp)
    rtc.write_backup(rtc_handle, base + 1, 
        ((temp * 100.0).int() << 16) | (humidity * 100.0).int()
    )
    
    // Update index
    rtc.write_backup(rtc_handle, 0, index + 1)
    
    io.println("Logged: {}°C, {}%RH", temp, humidity)
end

function print_log() do
    let rtc_handle = rtc.init(do hour_format: rtc.FORMAT_24H end)
    let count = rtc.read_backup(rtc_handle, 0).min(MAX_ENTRIES)
    
    io.println("\n=== Data Log ({} entries) ===", count)
    
    each i forde 0..count for do
        let base = 1 + (i * 2)
        let timestamp = rtc.read_backup(rtc_handle, base)
        let data = rtc.read_backup(rtc_handle, base + 1)
        
        let temp = ((data >> 16) & 0xFFFF).float() / 100.0
        let hum = (data & 0xFFFF).float() / 100.0
        
        io.println("{}: {:.1f}°C, {:.1f}%", 
            unix_to_string(timestamp), temp, hum)
    end
end

function date_to_unix(date: rtc.Date, time: rtc.Time) -> int do
    // Simplified unix timestamp calculation
    return (date.year - 1970) * 31536000 + 
           date.month * 2592000 + 
           date.day * 86400 + 
           time.hours * 3600 + 
           time.minutes * 60 + 
           time.seconds
end

function ana() do
    // Simulate sensor readings
    log_data(23.5, 65.2)
    core.delay_ms(5000)
    
    log_data(24.1, 63.8)
    core.delay_ms(5000)
    
    // Print all logged data
    print_log()
end

💡 Example: Timestamp Events (Input Capture)

import hal::rtc, hal::gpio

let event_count = 0

function timestamp_callback() do
    let rtc_handle = rtc.init(do hour_format: rtc.FORMAT_24H end)
    
    // Get timestamp
    let time = rtc.get_timestamp_time(rtc_handle)
    let date = rtc.get_timestamp_date(rtc_handle)
    
    event_count += 1
    
    io.println("Event #{}: {:02}:{:02}:{:02}.{:03}", 
        event_count,
        time.hours, 
        time.minutes, 
        time.seconds,
        time.subseconds
    )
end

function timestamp_input_capture() do
    // Configure PA0 (WKUP pin) as timestamp trigger
    gpio.clock_enable(gpio.PORT_A)
    gpio.pin_init(gpio.PORT_A, 0, do
        mode: gpio.MODE_INPUT,
        pull: gpio.PULL_DOWN
    end)
    
    let rtc_handle = rtc.init(do
        hour_format: rtc.FORMAT_24H
    end)
    
    // Enable timestamp on rising edge
    rtc.enable_timestamp(rtc_handle, do
        edge: rtc.TIMESTAMP_RISING_EDGE,
        pin: rtc.TIMESTAMP_PIN_0,
        callback: timestamp_callback
    end)
    
    io.println("Press button on PA0 to timestamp events...")
    
    loop do
        core.delay_ms(100)
    end
end

function ana() do
    timestamp_input_capture()
end

💡 Example: Multi-Alarm Scheduler

import hal::rtc

struct Task do
    name: str,
    alarm: rtc.Alarm,
    callback: fn()
end

let tasks = []

function task_morning() do
    io.println("🌅 Good morning! Time to wake up!")
end

function task_lunch() do
    io.println("🍽️ Lunch break!")
end

function task_evening() do
    io.println("🌙 Evening reminder: Review tasks")
end

function schedule_daily_tasks() do
    let rtc_handle = rtc.init(do
        hour_format: rtc.FORMAT_24H
    end)
    
    // Set current time (for testing: 06:58)
    rtc.set_time(rtc_handle, do
        hours: 6,
        minutes: 58,
        seconds: 0
    end)
    
    // Alarm A: Morning wakeup (07:00)
    rtc.set_alarm(rtc_handle, rtc.ALARM_A, do
        hours: 7,
        minutes: 0,
        seconds: 0,
        alarm_mask: rtc.MASK_DATEWEEKDAY,  // Daily
        callback: task_morning
    end)
    
    // Alarm B: Lunch (12:00)
    rtc.set_alarm(rtc_handle, rtc.ALARM_B, do
        hours: 12,
        minutes: 0,
        seconds: 0,
        alarm_mask: rtc.MASK_DATEWEEKDAY,
        callback: task_lunch
    end)
    
    io.println("Scheduler started. Waiting for alarms...")
    
    loop do
        let time = rtc.get_time(rtc_handle)
        io.print("\r{:02}:{:02}:{:02}", 
            time.hours, time.minutes, time.seconds)
        
        core.delay_ms(1000)
    end
end

function ana() do
    schedule_daily_tasks()
end

⚙️ RTC structlandırma

// RTC Configuration
struct RTCConfig do
    hour_format: HourFormat,    // 12H or 24H
    async_prediv: int,         // Asynchronous prescaler (7-bit)
    sync_prediv: int,          // Synchronous prescaler (15-bit)
    clock_source: ClockSource   // LSE, LSI, HSE
end

// Hour Format
enum HourFormat {
    FORMAT_12H,  // AM/PM
    FORMAT_24H   // 00:00-23:59
}

// Clock Source
enum ClockSource {
    LSE,  // 32.768kHz external crystal (most accurate)
    LSI,  // 32kHz internal RC (less accurate, ±5%)
    HSE   // High-speed external (rarely used for RTC)
}

// Alarm Configuration
struct AlarmConfig do
    hours: int,
    minutes: int,
    seconds: int,
    alarm_mask: AlarmMask,      // What to match
    callback: fn()              // Interrupt callback
end

// Alarm Mask (what to ignore)
enum AlarmMask {
    MASK_NONE,           // Match all (specific time)
    MASK_DATEWEEKDAY,    // Ignore date (daily alarm)
    MASK_HOURS,          // Every hour
    MASK_MINUTES,        // Every minute
    MASK_SECONDS         // Every second
}

// Wakeup Configuration
struct WakeupConfig do
    prescaler: WakeupPrescaler,
    counter: u16  // 0-65535
end

enum WakeupPrescaler {
    WAKEUP_DIV_16,    // RTC/16 (~2048Hz for 32kHz LSE)
    WAKEUP_DIV_8,     // RTC/8
    WAKEUP_DIV_4,     // RTC/4
    WAKEUP_DIV_2      // RTC/2
}

📚 RTC functionları

// Initialization
function init(config: RTCConfig) -> Handle
function deinit(handle: Handle)

// Time/Date
function set_time(handle: Handle, time: Time)
function get_time(handle: Handle) -> Time
function set_date(handle: Handle, date: Date)
function get_date(handle: Handle) -> Date

// Alarms
function set_alarm(handle: Handle, alarm: Alarm, config: AlarmConfig)
function disable_alarm(handle: Handle, alarm: Alarm)
function get_alarm_flag(handle: Handle, alarm: Alarm) -> bool
function clear_alarm_flag(handle: Handle, alarm: Alarm)

// Wakeup timer
function set_wakeup(handle: Handle, config: WakeupConfig)
function disable_wakeup(handle: Handle)
function was_wakeup_flag_set() -> bool
function clear_wakeup_flag()

// Timestamp
function enable_timestamp(handle: Handle, config: TimestampConfig)
function get_timestamp_time(handle: Handle) -> Time
function get_timestamp_date(handle: Handle) -> Date

// Backup registers
function write_backup(handle: Handle, register: int, value: u32)
function read_backup(handle: Handle, register: int) -> u32

// Calibration
function calibrate(handle: Handle, ppm: float)  // Fine-tune frequency

⚙️ RTC Backup Registers

// Store data that survives reset/power-down
rtc.write_backup(rtc_handle, 0, 0x12345678)
let value = rtc.read_backup(rtc_handle, 0)

// Common use cases:
// - Boot counter
// - Configuration persistence
// - Crash/reset reason
// - Sensor calibration data
// - Short-term data logging (80 bytes total)

// Example: Boot counter
let boot_count = rtc.read_backup(rtc_handle, 0)
boot_count += 1
rtc.write_backup(rtc_handle, 0, boot_count)
io.println("Boot count: {}", boot_count)

📊 RTC Use Cases

Senaryo Özellik Güç Tüketimi Açıklama
Digital Clock Time/Date Active Real-time display
Alarm Clock Alarm A/B Sleep + Interrupt Wake on alarm
Periodic Wakeup Wakeup Timer Standby (~1μA) Ultra-low-power sensor reading
Event Timestamp Timestamp Active Precise event logging
Data Logger Backup Regs VBAT (~1μA) Survive power loss

⚡ Performance Tips

🖥️ Platform Support

⚠️ Important Notes

🔗 Related Modules

📖 References

← HAL Modülleri