diff --git a/kernel/include/kernel/RTC.h b/kernel/include/kernel/RTC.h new file mode 100644 index 00000000..32f9e7c3 --- /dev/null +++ b/kernel/include/kernel/RTC.h @@ -0,0 +1,20 @@ +#pragma once + +#include + +namespace RTC +{ + + struct Time + { + uint8_t second; + uint8_t minute; + uint8_t hour; + uint8_t day; + uint8_t month; + int year; + }; + + Time GetCurrentTime(); + +} \ No newline at end of file diff --git a/kernel/kernel/RTC.cpp b/kernel/kernel/RTC.cpp new file mode 100644 index 00000000..46d4b8ec --- /dev/null +++ b/kernel/kernel/RTC.cpp @@ -0,0 +1,88 @@ +#include +#include + +#include + +#define CURRENT_YEAR 2022 + +#define CMOS_ADDRESS 0x70 +#define CMOS_DATA 0x71 + +#define CMOS_REGISTER_SECOND 0x00 +#define CMOS_REGISTER_MINUTE 0x02 +#define CMOS_REGISTER_HOUR 0x04 +#define CMOS_REGISTER_WEEK_DAY 0x06 +#define CMOS_REGISTER_DAY 0x07 +#define CMOS_REGISTER_MONTH 0x08 +#define CMOS_REGISTER_YEAR 0x09 +#define CMOS_REGISTER_STATUS_1 0x0A +#define CMOS_REGISTER_STATUS_2 0x0B + +namespace RTC +{ + + static bool get_update_in_progress() + { + IO::outb(CMOS_ADDRESS, CMOS_REGISTER_STATUS_1); + return IO::inb(CMOS_DATA) & 0x80; + } + + static uint8_t get_rtc_register(uint8_t reg) + { + IO::outb(CMOS_ADDRESS, reg); + return IO::inb(CMOS_DATA); + } + + static void get_time(Time& out) + { + out.second = get_rtc_register(CMOS_REGISTER_SECOND); + out.minute = get_rtc_register(CMOS_REGISTER_MINUTE); + out.hour = get_rtc_register(CMOS_REGISTER_HOUR); + out.day = get_rtc_register(CMOS_REGISTER_DAY); + out.month = get_rtc_register(CMOS_REGISTER_MONTH); + out.year = get_rtc_register(CMOS_REGISTER_YEAR); + } + + Time GetCurrentTime() + { + Time last_time = {}; + Time time = {}; + + while (get_update_in_progress()) + continue; + + get_time(time); + last_time.second = time.second + 1; + + while (memcmp(&last_time, &time, sizeof(Time))) + { + last_time = time; + get_time(time); + } + + uint8_t regB = get_rtc_register(0x0B); + + // Convert BCD to binary values if necessary + if (!(regB & 0x04)) + { + time.second = (time.second & 0x0F) + ((time.second / 16) * 10); + time.minute = (time.minute & 0x0F) + ((time.minute / 16) * 10); + time.hour = ((time.hour & 0x0F) + (((time.hour & 0x70) / 16) * 10) ) | (time.hour & 0x80); + time.day = (time.day & 0x0F) + ((time.day / 16) * 10); + time.month = (time.month & 0x0F) + ((time.month / 16) * 10); + time.year = (time.year & 0x0F) + ((time.year / 16) * 10); + } + + // Convert 12 hour clock to 24 hour clock if necessary + if (!(regB & 0x02) && (time.hour & 0x80)) + time.hour = ((time.hour & 0x7F) + 12) % 24; + + // Calculate the full 4 digit year + time.year += (CURRENT_YEAR / 100) * 100; + if (time.year < CURRENT_YEAR) + time.year += 100; + + return time; + } + +} \ No newline at end of file diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index 40d4603f..bd969a0a 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -63,9 +64,10 @@ void kernel_main(multiboot_info_t* mbi, uint32_t magic) PIT::initialize(); Keyboard::initialize(on_key_press); - kprintln("Hello from the kernel!"); + auto time = RTC::GetCurrentTime(); + kprintln("Today is {2}:{2}:{2} {2}.{2}.{4}", time.hour, time.minute, time.second, time.day, time.month, time.year); - kprint("HHHHHHHHHHHHHHHHHHHHHHHHHHHHH\e[20D.\e[3K"); + kprintln("Hello from the kernel!"); ENABLE_INTERRUPTS();