Files @ 7f3f8f2d539f
Branch filter:

Location: FeatherHAB/wsprhab/src/rtc.c - annotation

Ethan Zonca
Add support for RTC-based full unix timestamp with subsecond support
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;
}