luxos/kernel/clock/time.c

143 lines
4.4 KiB
C

#ifndef __TIME_C
#define __TIME_C
#include "cmos.h"
static const char* clock_months[] = {0,
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"};
static const char* clock_weekdays[] = {0,
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
byte clock_months_len[] = {
0,
31, // January
28, // February
31, // March
30, // April
31, // May
30, // June
31, // July
31, // August
30, // September
31, // October
30, // November
31 // December
};
typedef struct {
byte seconds;
byte minutes;
byte hours;
byte weekday;
byte day;
byte month;
byte year;
byte century;
byte am_pm;
} TIME;
volatile static TIME clock;
void RTC_get_time()
{
cmos_read();
if ((cmos_data[0x0b]&4)==0) // BCD = true;
{
clock.seconds = (cmos_data[0x00]%16) + 10*(cmos_data[0x00]/16);
clock.minutes = (cmos_data[0x02]%16) + 10*(cmos_data[0x02]/16);
if ((cmos_data[0x0b]&2)==0) { // AM/PM
if (cmos_data[0x04]&80) { // pm
clock.hours = ((cmos_data[0x04]-0x80)%16) + 10*((cmos_data[0x04]-0x80)/16);
clock.am_pm = 1;
}
else { // am
clock.hours = (cmos_data[0x04]%16) + 10*(cmos_data[0x04]/16);
clock.am_pm = 0;
}
}
else { // 24 hours
clock.hours = (cmos_data[0x04]%16) + 10*(cmos_data[0x04]/16);
if (clock.hours > 12) {
clock.am_pm = 1;
clock.hours -= 12;
}
else clock.am_pm = 0;
}
clock.weekday = (cmos_data[0x06]%16) + 10*(cmos_data[0x06]/16);
clock.day = (cmos_data[0x07]%16) + 10*(cmos_data[0x07]/16);
clock.month = (cmos_data[0x08]%16) + 10*(cmos_data[0x08]/16);
clock.year = (cmos_data[0x09]%16) + 10*(cmos_data[0x09]/16);
clock.century = (cmos_data[0x32]%16) + 10*(cmos_data[0x32]/16);
}
else {//BCD = false;
clock.seconds = cmos_data[0x00];
clock.minutes = cmos_data[0x02];
if ((cmos_data[0x0b]&2)==0) { // AM/PM
if (cmos_data[0x04]&80) { // pm
clock.hours = cmos_data[0x04]-0x80;
clock.am_pm = 1;
}
else { // am
clock.hours = cmos_data[0x04];
clock.am_pm = 0;
}
}
else { // 24 hours
clock.hours = cmos_data[0x02];
if (clock.hours > 12) {
clock.am_pm = 1;
clock.hours -= 12;
}
else clock.am_pm = 0;
}
clock.weekday = cmos_data[0x06];
clock.day = cmos_data[0x07];
clock.month = cmos_data[0x08];
clock.year = cmos_data[0x09];
clock.century = cmos_data[0x32];
}
// Leap years
if (clock.year % 4 == 0) clock_months_len[2]=29;
}
void clock_inc()
{
// New minute
if (++clock.seconds > 59) {
clock.seconds = 0;
// New hour
if (++clock.minutes > 59) {
clock.minutes = 0;
clock.hours++;
if (clock.hours == 12 && clock.am_pm == 1) { // 11:59pm -> 0:00am
clock.hours = 0; clock.am_pm = 0;
// New day
clock.weekday = 1+(clock.weekday%7);
// New month
if (++clock.day > clock_months_len[clock.month]) {
clock.day = 1;
// New year
if (++clock.month>12) {
clock.month = 1;
// New century
if (++clock.year > 99) {
clock.year = 0;
clock.century++;
}
}
}
}
else if (clock.hours == 12 && clock.am_pm == 0) // 11:59am -> 12:00pm
clock.am_pm = 1;
else if (clock.hours == 13 && clock.am_pm == 1) // 12:59pm -> 1:59pm
clock.hours = 1;
}
}
}
#endif