Files
@ 7f3f8f2d539f
Branch filter:
Location: FeatherHAB/wsprhab/src/rtc.c - annotation
7f3f8f2d539f
4.0 KiB
text/plain
Add support for RTC-based full unix timestamp with subsecond support
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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 | bb703e19f242 bb703e19f242 bb703e19f242 bb703e19f242 bb703e19f242 bb703e19f242 af5348c12bda bb703e19f242 bb703e19f242 bb703e19f242 bb703e19f242 bb703e19f242 bb703e19f242 af6b7df096c5 af5348c12bda af5348c12bda af5348c12bda af5348c12bda af5348c12bda af5348c12bda bb703e19f242 bb703e19f242 bb703e19f242 bb703e19f242 bb703e19f242 ddbcfaffc98a bb703e19f242 bb703e19f242 30ab6b66325f 30ab6b66325f 30ab6b66325f bb703e19f242 af5348c12bda af5348c12bda 30ab6b66325f 30ab6b66325f 7f3f8f2d539f 7f3f8f2d539f 30ab6b66325f af5348c12bda 30ab6b66325f ddbcfaffc98a 30ab6b66325f 30ab6b66325f 30ab6b66325f 30ab6b66325f bb703e19f242 30ab6b66325f 30ab6b66325f 30ab6b66325f 30ab6b66325f 30ab6b66325f 30ab6b66325f 30ab6b66325f 30ab6b66325f 30ab6b66325f bb703e19f242 30ab6b66325f 30ab6b66325f af5348c12bda af5348c12bda bb703e19f242 30ab6b66325f 30ab6b66325f 30ab6b66325f 30ab6b66325f bb703e19f242 ddbcfaffc98a 30ab6b66325f 30ab6b66325f 30ab6b66325f 30ab6b66325f 30ab6b66325f 30ab6b66325f 30ab6b66325f 30ab6b66325f ddbcfaffc98a 30ab6b66325f af5348c12bda f2f8cb2bebfa 30ab6b66325f af5348c12bda 30ab6b66325f af5348c12bda 30ab6b66325f 30ab6b66325f 30ab6b66325f bb703e19f242 30ab6b66325f 30ab6b66325f af5348c12bda af5348c12bda af5348c12bda af5348c12bda bb703e19f242 ddbcfaffc98a f2f8cb2bebfa f2f8cb2bebfa f2f8cb2bebfa f2f8cb2bebfa f2f8cb2bebfa f2f8cb2bebfa f2f8cb2bebfa f2f8cb2bebfa 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f 7f3f8f2d539f f2f8cb2bebfa ddbcfaffc98a ddbcfaffc98a ddbcfaffc98a ddbcfaffc98a ddbcfaffc98a ddbcfaffc98a ddbcfaffc98a ddbcfaffc98a ddbcfaffc98a ddbcfaffc98a ddbcfaffc98a | //
// RTC: configure real-time clock
//
#include "stm32f0xx_hal.h"
#include "rtc.h"
#include "gpio.h"
RTC_HandleTypeDef hrtc;
static void Error_Handler(void)
{
volatile uint8_t crap = 1;
for(uint16_t i=0; i<300; i++)
{
HAL_GPIO_TogglePin(LED_BLUE);
HAL_Delay(100);
}
}
// Initialize RTC
void rtc_init(void)
{
__HAL_RCC_RTC_ENABLE();
RTC_TimeTypeDef sTime;
RTC_DateTypeDef sDate;
RTC_AlarmTypeDef sAlarm;
HAL_PWR_EnableBkUpAccess();
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127; // Note that both these dividers actually divide by their value + 1
hrtc.Init.SynchPrediv = 311; // About 1Hz with 40kHz LSI
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
sTime.Hours = 0x0;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
sDate.WeekDay = RTC_WEEKDAY_MONDAY;
sDate.Month = RTC_MONTH_JANUARY;
sDate.Date = 0x01;
sDate.Year = 0x19;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
/**Enable the Alarm A
*/
sAlarm.AlarmTime.Hours = 0x0;
sAlarm.AlarmTime.Minutes = 0x0;
sAlarm.AlarmTime.Seconds = 0x0;
sAlarm.AlarmTime.SubSeconds = 0x0;
sAlarm.AlarmTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sAlarm.AlarmTime.StoreOperation = RTC_STOREOPERATION_RESET;
// Alarm will trigger on the Xth second of every minute
sAlarm.AlarmMask = RTC_ALARMMASK_ALL; // Trigger every second for now
sAlarm.AlarmSubSecondMask = RTC_ALARMSUBSECONDMASK_SS14; //RTC_ALARMSUBSECONDMASK_ALL;
sAlarm.AlarmDateWeekDaySel = RTC_ALARMDATEWEEKDAYSEL_DATE;
sAlarm.AlarmDateWeekDay = RTC_WEEKDAY_MONDAY;
sAlarm.Alarm = RTC_ALARM_A;
if (HAL_RTC_SetAlarm_IT(&hrtc, &sAlarm, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
HAL_NVIC_SetPriority(RTC_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(RTC_IRQn);
HAL_RTC_WaitForSynchro(&hrtc);
}
RTC_TimeTypeDef time_last = {0};
RTC_TimeTypeDef* rtc_time(void)
{
HAL_RTC_GetTime(&hrtc, &time_last, RTC_FORMAT_BCD);
return &time_last;
}
uint16_t __rtc_millis(uint32_t sub_seconds)
{
// Subsecond counter counts down from SynchPrediv value to zero
return (hrtc.Init.SynchPrediv - sub_seconds) * 999 / hrtc.Init.SynchPrediv; // 0 - 999 mS
}
#define JULIAN_DATE_BASE 2440588 // Unix epoch time in Julian calendar (UnixTime = 00:00:00 01.01.1970 => JDN = 2440588)
uint64_t rtc_timestamp(void)
{
RTC_TimeTypeDef time = {0};
RTC_DateTypeDef date = {0};
HAL_RTC_GetTime(&hrtc, &time, RTC_FORMAT_BCD);
HAL_RTC_GetDate(&hrtc, &date, RTC_FORMAT_BCD);
// Thanks to LonelyWolf: https://github.com/LonelyWolf/stm32/blob/master/stm32l-dosfs/RTC.c
// Convert Date/Time structures to epoch time
uint8_t a;
uint16_t y;
uint8_t m;
uint64_t JDN;
// These hardcore math's are taken from http://en.wikipedia.org/wiki/Julian_day
// Calculate some coefficients
a = (14 - date.Month) / 12;
y = (date.Year + 2000) + 4800 - a; // years since 1 March, 4801 BC
m = date.Month + (12 * a) - 3; // since 1 March, 4801 BC
// Gregorian calendar date compute
JDN = date.Date;
JDN += (153 * m + 2) / 5;
JDN += 365 * y;
JDN += y / 4;
JDN += -y / 100;
JDN += y / 400;
JDN = JDN - 32045;
JDN = JDN - JULIAN_DATE_BASE; // Calculate from base date
JDN *= 86400; // Days to seconds
JDN += time.Hours * 3600; // ... and today seconds
JDN += time.Minutes * 60;
JDN += time.Seconds;
JDN *= 1000; // Prepare to add ms
JDN += __rtc_millis(time.SubSeconds);
return JDN;
}
void rtc_cal(void)
{
// Do something with hrtc.Instance->CALR; // this has a plus and minus component, see refman
}
RTC_HandleTypeDef* rtc_gethandle(void)
{
return &hrtc;
}
|