CMOS: Difference between revisions
Replaced "read all RTC time and date" example code
[unchecked revision] | [unchecked revision] |
m (Century determination when no century register is present) |
(Replaced "read all RTC time and date" example code) |
||
Line 246:
</source>
=== Reading All RTC Time and Date Registers ===
<source lang="
#define CURRENT_YEAR 2011 // Change this each year!
int century_register = 0x00; // Set by ACPI table parsing code if possible
unsigned char second;
unsigned char minute;
unsigned char hour;
unsigned char day;
unsigned char month;
unsigned int year;
void out_byte(int port, int value);
int in_byte(int port);
enum {
cmos_address = 0x70,
cmos_data = 0x71
};
int get_update_in_progress_flag() {
out_byte(cmos_address, 0x0A);
return (in_byte(cmos_data) & 0x80);
}
unsigned char get_RTC_register(int register) {
out_byte(cmos_address, register);
return in_byte(cmos_data);
}
void read_rtc() {
unsigned char century;
unsigned char last_second;
unsigned char last_minute;
unsigned char last_hour;
unsigned char last_day;
unsigned char last_month;
unsigned char last_year;
unsigned char last_century;
unsigned char registerB;
// Note: This uses the "read registers until you get the same values twice in a row" technique
// to avoid getting dodgy/inconsistent values due to RTC updates
while (get_update_in_progress_flag()); // Make sure an update isn't in progress
second = get_RTC_register(0x00);
minute = get_RTC_register(0x02);
hour = get_RTC_register(0x04);
day = get_RTC_register(0x07);
month = get_RTC_register(0x08);
year = get_RTC_register(0x09);
if(century_register != 0) {
century = get_RTC_register(century_register);
}
do {
last_second = second;
last_minute = minute;
last_hour = hour;
last_day = day;
last_month = month;
last_year = year;
last_century = century;
while (get_update_in_progress_flag()); // Make sure an update isn't in progress
second = get_RTC_register(0x00);
minute = get_RTC_register(0x02);
hour = get_RTC_register(0x04);
day = get_RTC_register(0x07);
month = get_RTC_register(0x08);
temp_year = get_RTC_register(0x09);
if(century_register != 0) {
century = get_RTC_register(century_register);
}
} while( (last_second == second) && (last_minute == minute) && (last_hour == hour) &&
(last_day == day) && (last_month == month) && (last_year == year) &&
(last_century == century) );
registerB = get_RTC_register(0x0B);
// Convert BCD to binary values if necessary
if (!(registerB & 0x04)) {
second = (second & 0x0F) + ((second / 16) * 10);
minute = (minute & 0x0F) + ((minute / 16) * 10);
hour = ( (hour & 0x0F) + (((hour & 0x70) / 16) * 10) ) | (hour & 0x80);
day = (day & 0x0F) + ((day / 16) * 10);
month = (month & 0x0F) + ((month / 16) * 10);
temp_year = (year & 0x0F) + ((year / 16) * 10);
if(century_register != 0) {
century = (century & 0x0F) + ((century / 16) * 10);
}
}
// Convert 12 hour clock to 24 hour clock if necessary
if (!(registerB & 0x02) && (time[2] & 0x80)) {
time[2] = ((time[2] & 0x7F) + 12) % 24;
}
// Calculate the full (4-digit) year
if(century_register != 0) {
year += century * 100;
} else {
year += (CURRENT_YEAR / 100) * 100;
if(year < CURRENT_YEAR) year += 100;
}
}
</source>
|