227 lines
6.3 KiB
C
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;
|
||
|
}
|