FoenixMCP/src/dev/rtc.c
2021-10-05 15:51:53 -04:00

227 lines
6.3 KiB
C

/*
* Definitions for access the bq4802LY real time clock
*/
#include "log.h"
#include "interrupt.h"
#include "rtc.h"
#include "rtc_reg.h"
#include "simpleio.h"
static long rtc_ticks;
/*
* Interrupt handler for the real time clock
*/
void rtc_handle_int() {
unsigned char flags;
flags = *RTC_FLAGS;
if (flags | RTC_PF) {
/* Peridic interrupt: increment the ticks counter */
rtc_ticks++;
}
}
/*
* Initialize the RTC
*/
void rtc_init() {
unsigned char rates;
unsigned char enables;
// int_disable(INT_RTC);
//
// /* Reset the ticks counter */
// rtc_ticks = 0;
//
// /* Set the periodic interrupt to 976.5625 microseconds */
// *RTC_RATES = (*RTC_RATES & RTC_RATES_WD) | RTC_RATE_976us;
//
// /* Enable the periodic interrupt */
*RTC_RATES = 0;
*RTC_ENABLES = 0; // RTC_PIE;
/* Make sure the RTC is on */
*RTC_CTRL = RTC_STOP;
/* Register our interrupt handler and clear out any pending interrupts */
// int_register(INT_RTC, rtc_handle_int);
// int_clear(INT_RTC);
// int_enable(INT_RTC);
}
/*
* Set the time on the RTC
*
* Inputs:
* time = pointer to a t_time record containing the correct time
*/
void rtc_set_time(p_time time) {
unsigned char ctrl;
unsigned char century_bcd, year_bcd, month_bcd, day_bcd;
unsigned char hour_bcd, minute_bcd, second_bcd;
unsigned short century;
unsigned short year;
century = time->year / 100;
year = time->year - (century * 100);
/* Compute the BCD values for the time */
century_bcd = i_to_bcd(century);
year_bcd = i_to_bcd(year);
month_bcd = i_to_bcd(time->month);
day_bcd = i_to_bcd(time->day);
hour_bcd = i_to_bcd(time->hour);
minute_bcd = i_to_bcd(time->minute);
second_bcd = i_to_bcd(time->second);
log_num(LOG_INFO, "Century: ", century_bcd);
log_num(LOG_INFO, "Year: ", year_bcd);
log_num(LOG_INFO, "Month: ", month_bcd);
log_num(LOG_INFO, "Day: ", day_bcd);
log_num(LOG_INFO, "Hour: ", hour_bcd);
log_num(LOG_INFO, "Minute: ", minute_bcd);
log_num(LOG_INFO, "Second: ", second_bcd);
if (time->is_24hours) {
if (time->is_pm) {
hour_bcd = hour_bcd | 0x80;
}
}
minute_bcd = i_to_bcd(time->minute);
second_bcd = i_to_bcd(time->second);
/* Temporarily disable updates to the clock */
ctrl = *RTC_CTRL;
*RTC_CTRL = ctrl | RTC_UTI;
log(LOG_INFO, "RTC Disabled");
log_num(LOG_INFO, "RTC Rates: ", *RTC_RATES);
log_num(LOG_INFO, "RTC Enables: ", *RTC_ENABLES);
log_num(LOG_INFO, "RTC Flags: ", *RTC_FLAGS);
log_num(LOG_INFO, "RTC Control: ", *RTC_CTRL);
/* Set the time in the RTC */
*RTC_CENTURY = century_bcd;
*RTC_YEAR = year_bcd;
*RTC_MONTH = month_bcd;
*RTC_DAY = day_bcd;
*RTC_HOUR = hour_bcd;
*RTC_MIN = minute_bcd;
*RTC_SEC = second_bcd;
/* Verify */
century_bcd = *RTC_CENTURY;
year_bcd = *RTC_YEAR;
month_bcd = *RTC_MONTH;
day_bcd = *RTC_DAY;
hour_bcd = *RTC_HOUR;
minute_bcd = *RTC_MIN;
second_bcd = *RTC_SEC;
log_num(LOG_INFO, "REG Century: ", century_bcd);
log_num(LOG_INFO, "REG Year: ", year_bcd);
log_num(LOG_INFO, "REG Month: ", month_bcd);
log_num(LOG_INFO, "REG Day: ", day_bcd);
log_num(LOG_INFO, "REG Hour: ", hour_bcd);
log_num(LOG_INFO, "REG Minute: ", minute_bcd);
log_num(LOG_INFO, "REG Second: ", second_bcd);
/* Set the 24/12 hour control bit if needed */
if (time->is_24hours) {
ctrl = ctrl | RTC_2412;
}
/* Re-enable updates to the clock */
*RTC_CTRL = (ctrl & 0x7f) | RTC_STOP;
log(LOG_INFO, "RTC Enabled");
log_num(LOG_INFO, "RTC Rates: ", *RTC_RATES);
log_num(LOG_INFO, "RTC Enables: ", *RTC_ENABLES);
log_num(LOG_INFO, "RTC Flags: ", *RTC_FLAGS);
log_num(LOG_INFO, "RTC Control: ", *RTC_CTRL);
}
/*
* Get the time on the RTC
*
* Inputs:
* time = pointer to a t_time record in which to put the current time
*/
void rtc_get_time(p_time time) {
unsigned char ctrl;
unsigned char century_bcd, year_bcd, month_bcd, day_bcd;
unsigned char hour_bcd, minute_bcd, second_bcd;
/* Temporarily disable updates to the clock */
ctrl = *RTC_CTRL;
*RTC_CTRL = ctrl | RTC_UTI;
log(LOG_INFO, "RTC Disabled");
log_num(LOG_INFO, "RTC Rates: ", *RTC_RATES);
log_num(LOG_INFO, "RTC Enables: ", *RTC_ENABLES);
log_num(LOG_INFO, "RTC Flags: ", *RTC_FLAGS);
log_num(LOG_INFO, "RTC Control: ", *RTC_CTRL);
if (*RTC_CTRL & RTC_2412) {
time->is_24hours = 1;
} else {
time->is_24hours = 0;
}
century_bcd = *RTC_CENTURY;
year_bcd = *RTC_YEAR;
month_bcd = *RTC_MONTH;
day_bcd = *RTC_DAY;
hour_bcd = *RTC_HOUR;
minute_bcd = *RTC_MIN;
second_bcd = *RTC_SEC;
/* Re-enable updates to the clock */
*RTC_CTRL = ctrl;
log(LOG_INFO, "RTC Enabled");
log_num(LOG_INFO, "RTC Rates: ", *RTC_RATES);
log_num(LOG_INFO, "RTC Enables: ", *RTC_ENABLES);
log_num(LOG_INFO, "RTC Flags: ", *RTC_FLAGS);
log_num(LOG_INFO, "RTC Control: ", *RTC_CTRL);
log_num(LOG_INFO, "Century: ", century_bcd);
log_num(LOG_INFO, "Year: ", year_bcd);
log_num(LOG_INFO, "Month: ", month_bcd);
log_num(LOG_INFO, "Day: ", day_bcd);
log_num(LOG_INFO, "Hour: ", hour_bcd);
log_num(LOG_INFO, "Minute: ", minute_bcd);
log_num(LOG_INFO, "Second: ", second_bcd);
/* Fill out the time record */
time->year = bcd_to_i(century_bcd) * 100 + bcd_to_i(year_bcd);
time->month = bcd_to_i(month_bcd);
time->day = bcd_to_i(day_bcd);
time->hour = bcd_to_i(hour_bcd & 0x7f);
time->is_pm = ((hour_bcd & 0x80) == 0x80) ? 1 : 0;
time->minute = bcd_to_i(minute_bcd);
time->second = bcd_to_i(second_bcd);
}
/*
* Get the number of ticks since the system last booted.
*
* NOTE: a tick is almost, but not quite, 1ms. The RTC periodic interrupt
* period does not line up with a 1ms timer, but it comes close.
* Therefore, a tick will be 976.5625 microseconds... a little faster
* than 1ms.
*
* Returns:
* the number of ticks since the last reset
*/
long rtc_get_ticks() {
long result = 0;
int_disable(INT_RTC); /* Make sure we aren't changing the tick counter during the query */
result = rtc_ticks;
int_enable(INT_RTC);
return rtc_ticks;
}