160 lines
4.1 KiB
C
160 lines
4.1 KiB
C
#include <arm/NXP/LPC17xx/LPC17xx.h>
|
|
#include <arm/bits.h>
|
|
#include "config.h"
|
|
#include "rtc.h"
|
|
#include "uart.h"
|
|
#include "timer.h"
|
|
#include "power.h"
|
|
|
|
rtcstate_t rtc_state;
|
|
|
|
#define CLKEN 0
|
|
#define CTCRST 1
|
|
|
|
uint8_t rtc_isvalid( void )
|
|
{
|
|
if ( LPC_RTC->GPREG0 == RTC_MAGIC )
|
|
{
|
|
return RTC_OK;
|
|
}
|
|
|
|
return RTC_INVALID;
|
|
}
|
|
|
|
void rtc_init( void )
|
|
{
|
|
if ( LPC_RTC->CCR & BV( CLKEN ) )
|
|
{
|
|
rtc_state = RTC_OK;
|
|
}
|
|
else
|
|
{
|
|
rtc_state = RTC_INVALID;
|
|
}
|
|
}
|
|
|
|
void read_rtc( struct tm *time )
|
|
{
|
|
do
|
|
{
|
|
time->tm_sec = LPC_RTC->SEC;
|
|
time->tm_min = LPC_RTC->MIN;
|
|
time->tm_hour = LPC_RTC->HOUR;
|
|
time->tm_mday = LPC_RTC->DOM;
|
|
time->tm_mon = LPC_RTC->MONTH;
|
|
time->tm_year = LPC_RTC->YEAR;
|
|
time->tm_wday = LPC_RTC->DOW;
|
|
}
|
|
while ( time->tm_sec != LPC_RTC->SEC );
|
|
}
|
|
|
|
uint8_t calc_weekday( struct tm *time )
|
|
{
|
|
int month = time->tm_mon;
|
|
int year = time->tm_year;
|
|
int day = time->tm_mday;
|
|
|
|
/* Variation of Sillke for the Gregorian calendar.
|
|
* http://www.mathematik.uni-bielefeld.de/~sillke/ALGORITHMS/calendar/weekday.c */
|
|
if ( month <= 2 )
|
|
{
|
|
month += 10;
|
|
year--;
|
|
}
|
|
else
|
|
{
|
|
month -= 2;
|
|
}
|
|
|
|
return ( 83 * month / 32 + day + year + year / 4 - year / 100 + year / 400 ) % 7;
|
|
}
|
|
|
|
void set_rtc( struct tm *time )
|
|
{
|
|
LPC_RTC->CCR = BV( CTCRST );
|
|
LPC_RTC->SEC = time->tm_sec;
|
|
LPC_RTC->MIN = time->tm_min;
|
|
LPC_RTC->HOUR = time->tm_hour;
|
|
LPC_RTC->DOM = time->tm_mday;
|
|
LPC_RTC->MONTH = time->tm_mon;
|
|
LPC_RTC->YEAR = time->tm_year;
|
|
LPC_RTC->DOW = calc_weekday( time );
|
|
LPC_RTC->CCR = BV( CLKEN );
|
|
LPC_RTC->GPREG0 = RTC_MAGIC;
|
|
}
|
|
|
|
void invalidate_rtc()
|
|
{
|
|
LPC_RTC->GPREG0 = 0;
|
|
}
|
|
|
|
uint32_t get_fattime( void )
|
|
{
|
|
struct tm time;
|
|
|
|
read_rtc( &time );
|
|
return ( ( uint32_t )time.tm_year - 1980 ) << 25 |
|
|
( ( uint32_t )time.tm_mon ) << 21 |
|
|
( ( uint32_t )time.tm_mday ) << 16 |
|
|
( ( uint32_t )time.tm_hour ) << 11 |
|
|
( ( uint32_t )time.tm_min ) << 5 |
|
|
( ( uint32_t )time.tm_sec ) >> 1;
|
|
}
|
|
|
|
uint64_t get_bcdtime( void )
|
|
{
|
|
struct tm time;
|
|
read_rtc( &time );
|
|
uint16_t year = time.tm_year;
|
|
|
|
return ( ( uint64_t )( time.tm_wday % 7 ) << 56 )
|
|
| ( ( uint64_t )( ( year / 1000 ) % 10 ) << 52 )
|
|
| ( ( uint64_t )( ( year / 100 ) % 10 ) << 48 )
|
|
| ( ( uint64_t )( ( year / 10 ) % 10 ) << 44 )
|
|
| ( ( uint64_t )( year % 10 ) << 40 )
|
|
| ( ( uint64_t )( time.tm_mon / 10 ) << 36 )
|
|
| ( ( uint64_t )( time.tm_mon % 10 ) << 32 )
|
|
| ( ( time.tm_mday / 10 ) << 28 )
|
|
| ( ( time.tm_mday % 10 ) << 24 )
|
|
| ( ( time.tm_hour / 10 ) << 20 )
|
|
| ( ( time.tm_hour % 10 ) << 16 )
|
|
| ( ( time.tm_min / 10 ) << 12 )
|
|
| ( ( time.tm_min % 10 ) << 8 )
|
|
| ( ( time.tm_sec / 10 ) << 4 )
|
|
| ( time.tm_sec % 10 );
|
|
}
|
|
|
|
void set_bcdtime( uint64_t btime )
|
|
{
|
|
struct tm time;
|
|
time.tm_sec = ( btime & 0xf ) + ( ( btime >> 4 ) & 0xf ) * 10;
|
|
time.tm_min = ( ( btime >> 8 ) & 0xf ) + ( ( btime >> 12 ) & 0xf ) * 10;
|
|
time.tm_hour = ( ( btime >> 16 ) & 0xf ) + ( ( btime >> 20 ) & 0xf ) * 10;
|
|
time.tm_mday = ( ( btime >> 24 ) & 0xf ) + ( ( btime >> 28 ) & 0xf ) * 10;
|
|
time.tm_mon = ( ( btime >> 32 ) & 0xf ) + ( ( btime >> 36 ) & 0xf ) * 10;
|
|
time.tm_year = ( ( btime >> 40 ) & 0xf ) + ( ( btime >> 44 ) & 0xf ) * 10
|
|
+ ( ( btime >> 48 ) & 0xf ) * 100 + ( ( btime >> 52 ) & 0xf ) * 1000;
|
|
printtime( &time );
|
|
set_rtc( &time );
|
|
}
|
|
|
|
void printtime( struct tm *time )
|
|
{
|
|
printf( "%04d-%02d-%02d %02d:%02d:%02d\n", time->tm_year, time->tm_mon,
|
|
time->tm_mday, time->tm_hour, time->tm_min, time->tm_sec );
|
|
}
|
|
|
|
void testbattery()
|
|
{
|
|
printf( "%lx\n", LPC_RTC->GPREG0 );
|
|
LPC_RTC->GPREG0 = RTC_MAGIC;
|
|
printf( "%lx\n", LPC_RTC->GPREG0 );
|
|
LPC_RTC->CCR = 0;
|
|
BITBAND( LPC_SC->PCONP, PCRTC ) = 0;
|
|
delay_ms( 20000 );
|
|
BITBAND( LPC_SC->PCONP, PCRTC ) = 1;
|
|
printf( "%lx\n", LPC_RTC->GPREG0 );
|
|
delay_ms( 20 );
|
|
LPC_RTC->CCR = BV( CLKEN );
|
|
}
|