Enable buttons and the display.

Kind-of-sort-of usable-ish.
This commit is contained in:
2019-06-06 22:30:27 -07:00
parent 1cc2f7adf4
commit 125ddfb687
19 changed files with 937 additions and 196 deletions

View File

@@ -21,6 +21,7 @@
#include "RtcDriver.h"
#include "macros.h"
#include <new>
namespace BSP {
@@ -29,6 +30,13 @@ using Common::time_t;
RtcDriver::RtcSystemTimer RtcDriver::m_sys_timer;
ReturnCode RtcDriver::init()
{
init_hw();
return ReturnCode::OK;
}
void RtcDriver::enable_rtc_write()
{
/*<! Disable write protection */
@@ -48,7 +56,7 @@ void RtcDriver::enable_periodic_alarm()
SET(RTC->ALRMAR, RTC_ALRMAR_MSK4 | RTC_ALRMAR_MSK3 | RTC_ALRMAR_MSK2 | RTC_ALRMAR_MSK1);
// Only calculate alarms when second rolls over
SET_TO(RTC->ALRMASSR, RTC_ALRMASSR_MASKSS, 0);
SET_TO(RTC->ALRMASSR, RTC_ALRMASSR_MASKSS, RTC_ALRMASSR_MASKSS);
SET(RTC->CR, RTC_CR_ALRAE | RTC_CR_ALRAIE);
SET(EXTI->IMR, EXTI_IMR_IM17);
@@ -84,7 +92,8 @@ ReturnCode RtcDriver::init_hw()
/*<! Set the Clock Prescalers (32.768kHz / 1 / 32768 = 1Hz */
/*<! Set the Async prescaler to the Maximum (divide the clock by 128) */
SET_TO(RTC->PRER, RTC_PRER_PREDIV_A, 0);
// XXX reset to 0, this is to enable easier debugging
SET_TO(RTC->PRER, RTC_PRER_PREDIV_A, 0);
/*<! Set the Syncronous scaler so the RTC updates at 1Hz */
SET_TO(RTC->PRER, RTC_PRER_PREDIV_S, (LSE_CLOCK_FREQ - 1));
@@ -121,32 +130,60 @@ ReturnCode RtcDriver::init_hw()
return ReturnCode::OK;
}
ReturnCode RtcDriver::get_time(time_bcd &tm_bcd)
ReturnCode RtcDriver::get_time(Common::WallClockTime &wall_time)
{
/*<! The value of TR in the shadow register is locked when SSR is
read (by the system timer), until the date register is read. We're
not using the date here, but we do need to clear the stale value. */
(void) RTC->DR;
// TODO: reread TR + PM for consistency
uint32_t time = RTC->TR;
unsigned int hours = 0, minutes = 0, seconds = 0;
tm_bcd.hour_tens = STM32_GET_FIELD(time, RTC_TR_HT);
tm_bcd.hour_ones = STM32_GET_FIELD(time, RTC_TR_HU);
hours += 10 * STM32_GET_FIELD(time, RTC_TR_HT);
hours += STM32_GET_FIELD(time, RTC_TR_HU);
tm_bcd.minute_tens = STM32_GET_FIELD(time, RTC_TR_MNT);
tm_bcd.minute_ones = STM32_GET_FIELD(time, RTC_TR_MNU);
minutes += 10 * STM32_GET_FIELD(time, RTC_TR_MNT);
minutes += STM32_GET_FIELD(time, RTC_TR_MNU);
tm_bcd.second_tens = STM32_GET_FIELD(time, RTC_TR_ST);
tm_bcd.second_ones = STM32_GET_FIELD(time, RTC_TR_SU);
seconds += 10 * STM32_GET_FIELD(time, RTC_TR_ST);
seconds += STM32_GET_FIELD(time, RTC_TR_SU);
tm_bcd.pm = STM32_GET_FIELD(time, RTC_TR_PM);
if (STM32_GET_FIELD(time, RTC_TR_PM)) {
hours += 12;
}
new (&wall_time) Common::WallClockTime(hours, minutes, seconds);
return ReturnCode::OK;
}
ReturnCode RtcDriver::init()
ReturnCode RtcDriver::set_time(const Common::WallClockTime &wall_time)
{
init_hw();
enable_rtc_write();
RTC->ISR = RTC_ISR_INIT;
while (!(RTC->ISR & RTC_ISR_INITF)) {}
/*<! Load initial date and time */
// 12-Hour format
SET(RTC->CR, RTC_CR_FMT);
uint32_t time = 0;
SET_TO(time, RTC_TR_PM, wall_time.get_is_pm() << RTC_TR_PM_Pos);
SET_TO(time, RTC_TR_HT, wall_time.get_hours_12_tens() << RTC_TR_HT_Pos);
SET_TO(time, RTC_TR_HU, wall_time.get_hours_12_ones() << RTC_TR_HU_Pos);
SET_TO(time, RTC_TR_MNT, wall_time.get_minutes_tens() << RTC_TR_MNT_Pos);
SET_TO(time, RTC_TR_MNU, wall_time.get_minutes_ones() << RTC_TR_MNU_Pos);
SET_TO(time, RTC_TR_ST, wall_time.get_seconds_tens() << RTC_TR_ST_Pos);
SET_TO(time, RTC_TR_SU, wall_time.get_seconds_tens() << RTC_TR_SU_Pos);
RTC->TR = time;
CLR(RTC->ISR, RTC_ISR_INIT);
disable_rtc_write();
return ReturnCode::OK;
}
@@ -156,7 +193,8 @@ ReturnCode RtcDriver::set_wakeup_in(Common::time_t wakeup_delay)
/*<! 2^64 / (1000000 * 32768) / 60 / 60 / 24 / 365 = ~17.85 This
value will only overflow for wakeup_delays > 17.85 years, so
this is fine. */
uint64_t delay_cycles = Common::Time::to_micros(wakeup_delay) * LSE_CLOCK_FREQ / Common::Time::MICROS_PER_SEC;
uint64_t delay_cycles = Common::Time::to_micros(wakeup_delay) * LSE_CLOCK_FREQ /
Common::Time::MICROS_PER_SEC;
enable_rtc_write();
@@ -203,23 +241,24 @@ ReturnCode RtcDriver::set_wakeup_in(Common::time_t wakeup_delay)
return ReturnCode::OK;
}
Common::time_t RtcDriver::RtcSystemTimer::get_time()
{
uint32_t new_secs, old_secs, ssr, subsecond;
do {
old_secs = m_seconds;
ssr = RTC->SSR & 0xFFFF;
new_secs = m_seconds;
} while (new_secs != old_secs);
Common::time_t RtcDriver::RtcSystemTimer::get_time()
{
uint32_t new_secs, old_secs, ssr, subsecond;
do {
old_secs = m_seconds;
ssr = RTC->SSR & 0xFFFF;
new_secs = m_seconds;
} while (new_secs != old_secs);
new_secs = new_secs * LSE_CLOCK_FREQ;
/** SSR is a countdown register */
subsecond = (new_secs + LSE_CLOCK_FREQ - 1 - ssr) * Common::Time::MILLIS_PER_SEC / LSE_CLOCK_FREQ;
return Common::Time::millis(subsecond);
new_secs = new_secs * LSE_CLOCK_FREQ;
/** SSR is a countdown register */
subsecond = (new_secs + LSE_CLOCK_FREQ - 1 - ssr) * Common::Time::MILLIS_PER_SEC / LSE_CLOCK_FREQ;
return Common::Time::millis(subsecond);
}
void RtcDriver::RtcSystemTimer::increment_seconds()
{
/** TODO: Atomic increment */
m_seconds++;
}