forked from nneves/MBED-NXP-LPC1768-LWIP
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrtc_cal.c
105 lines (84 loc) · 3.4 KB
/
rtc_cal.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/* Martin Thomas, 7/2010, 3BSD license */
#include "lpc17xx_rtc.h"
#include "rtc_cal.h"
/* # of bits used in the Calibration value */
#define CALIBRATION_VALUE_SIZE 17
/* If the actual frequency is within +/- of this value,
calibration should be disabled because of overflow */
#define MAX_DELTA_FREQUENCY_VALUE (RTC_IDEAL_FREQ / ((1 << CALIBRATION_VALUE_SIZE) - 1))
/*****************************************************************************
** Function name: rtc_cal_config
**
** Descriptions: Function calculates the required calibration value and
** direction values for the calibration register.
** If the actual_rtc_frequency is within
** +/- (32.768kHz / (2^17 - 1)) == +/- 0.250 Hz, then disable
** the auto calibration due to RTCAL overflow.
** Else, save the proper RTC calibration value and direction.
**
** parameters: The actual RTC oscillating frequency should be passed
** in mHz (milli Hz).
**
** Returned value: None
**
*******************************************************************************/
/* This code is from NXP's example-code for application note AN10849.
* Copyright(C) 2008(?), NXP Semiconductor, 2009(?).05.28 version 1.00 preliminary version"
* For further information please read the AppNote available from nxp.com.
* Adapted for the NXP driver-library and this project by Martin Thomas 7/2010 */
void rtc_cal_config(uint32_t actual_rtc_frequency)
{
uint32_t calibration_value;
int32_t rtc_frequency_delta;
rtc_frequency_delta = (RTC_IDEAL_FREQ - actual_rtc_frequency);
RTC_CalibCounterCmd(LPC_RTC, DISABLE);
/* Check for valid RTC frequency */
/* Disable calibration if the correction value is +/- .250Hz offset
It would otherwise cause an overflow in RTCCAL */
if ((rtc_frequency_delta <= MAX_DELTA_FREQUENCY_VALUE)
&& (rtc_frequency_delta >= -MAX_DELTA_FREQUENCY_VALUE)) {
RTC_CalibCounterCmd(LPC_RTC, DISABLE);
/* Determine the calibration direction CALDIR and CALVAL*/
} else if (rtc_frequency_delta > MAX_DELTA_FREQUENCY_VALUE) {
/* Forward direction */
calibration_value = RTC_IDEAL_FREQ / (RTC_IDEAL_FREQ - actual_rtc_frequency);
RTC_CalibConfig(LPC_RTC, calibration_value, RTC_CALIB_DIR_FORWARD);
RTC_CalibCounterCmd(LPC_RTC, ENABLE);
} else {
/* Backward direction */
calibration_value = RTC_IDEAL_FREQ / (actual_rtc_frequency - RTC_IDEAL_FREQ);
RTC_CalibConfig(LPC_RTC, calibration_value, RTC_CALIB_DIR_BACKWARD);
RTC_CalibCounterCmd(LPC_RTC, ENABLE);
}
return;
}
void rtc_cal_init(RTC_TIME_Type *pFullTime)
{
RTC_Init(LPC_RTC);
LPC_RTC->RTC_AUX = RTC_AUX_RTC_OSCF;
rtc_cal_config(RTC_ACTUAL_FREQ);
RTC_SetFullTime(LPC_RTC, pFullTime);
RTC_Cmd(LPC_RTC, ENABLE);
}
void rtc_cal_settime(RTC_TIME_Type *pFullTime)
{
RTC_Cmd(LPC_RTC, DISABLE);
RTC_SetFullTime(LPC_RTC, pFullTime);
RTC_Cmd(LPC_RTC, ENABLE);
}
uint8_t rtc_cal_gettime(RTC_TIME_Type *pFullTime)
{
uint32_t ct0, ct1;
// adapted from ChaN's FatFs LPC23xx example:
do {
ct0 = LPC_RTC->CTIME0;
ct1 = LPC_RTC->CTIME1;
} while (ct0 != LPC_RTC->CTIME0 || ct1 != LPC_RTC->CTIME1);
pFullTime->SEC = ct0 & 63;;
pFullTime->MIN = (ct0 >> 8) & 63;;
pFullTime->HOUR = (ct0 >> 16) & 31;
pFullTime->DOM = ct1 & 31;
pFullTime->MONTH = (ct1 >> 8) & 15;;
pFullTime->YEAR = (ct1 >> 16) & 4095;
return (LPC_RTC->RTC_AUX & RTC_AUX_RTC_OSCF) ? 1 : 0;
}