mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
[ion] Add RTC subsystem
This commit is contained in:
@@ -25,6 +25,7 @@ apps_src += $(addprefix apps/,\
|
|||||||
backlight_dimming_timer.cpp \
|
backlight_dimming_timer.cpp \
|
||||||
battery_timer.cpp \
|
battery_timer.cpp \
|
||||||
battery_view.cpp \
|
battery_view.cpp \
|
||||||
|
clock_timer.cpp \
|
||||||
empty_battery_window.cpp \
|
empty_battery_window.cpp \
|
||||||
exam_pop_up_controller.cpp \
|
exam_pop_up_controller.cpp \
|
||||||
exam_mode_configuration_official.cpp:+official \
|
exam_mode_configuration_official.cpp:+official \
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ AppsContainer::AppsContainer() :
|
|||||||
m_batteryTimer(),
|
m_batteryTimer(),
|
||||||
m_suspendTimer(),
|
m_suspendTimer(),
|
||||||
m_backlightDimmingTimer(),
|
m_backlightDimmingTimer(),
|
||||||
|
m_clockTimer(ClockTimer(this)),
|
||||||
m_homeSnapshot(),
|
m_homeSnapshot(),
|
||||||
m_onBoardingSnapshot(),
|
m_onBoardingSnapshot(),
|
||||||
m_hardwareTestSnapshot(),
|
m_hardwareTestSnapshot(),
|
||||||
@@ -304,6 +305,10 @@ void AppsContainer::run() {
|
|||||||
switchTo(nullptr);
|
switchTo(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AppsContainer::updateClock() {
|
||||||
|
return m_window.updateClock();
|
||||||
|
}
|
||||||
|
|
||||||
bool AppsContainer::updateBatteryState() {
|
bool AppsContainer::updateBatteryState() {
|
||||||
bool batteryLevelUpdated = m_window.updateBatteryLevel();
|
bool batteryLevelUpdated = m_window.updateBatteryLevel();
|
||||||
bool pluggedStateUpdated = m_window.updatePluggedState();
|
bool pluggedStateUpdated = m_window.updatePluggedState();
|
||||||
@@ -409,11 +414,11 @@ Window * AppsContainer::window() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int AppsContainer::numberOfContainerTimers() {
|
int AppsContainer::numberOfContainerTimers() {
|
||||||
return 3;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
Timer * AppsContainer::containerTimerAtIndex(int i) {
|
Timer * AppsContainer::containerTimerAtIndex(int i) {
|
||||||
Timer * timers[3] = {&m_batteryTimer, &m_suspendTimer, &m_backlightDimmingTimer};
|
Timer * timers[4] = {&m_batteryTimer, &m_suspendTimer, &m_backlightDimmingTimer, &m_clockTimer};
|
||||||
return timers[i];
|
return timers[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "backlight_dimming_timer.h"
|
#include "backlight_dimming_timer.h"
|
||||||
#include "shared/global_context.h"
|
#include "shared/global_context.h"
|
||||||
#include "on_boarding/pop_up_controller.h"
|
#include "on_boarding/pop_up_controller.h"
|
||||||
|
#include "clock_timer.h"
|
||||||
|
|
||||||
#include <ion/events.h>
|
#include <ion/events.h>
|
||||||
|
|
||||||
@@ -39,6 +40,7 @@ public:
|
|||||||
bool dispatchEvent(Ion::Events::Event event) override;
|
bool dispatchEvent(Ion::Events::Event event) override;
|
||||||
bool switchTo(App::Snapshot * snapshot) override;
|
bool switchTo(App::Snapshot * snapshot) override;
|
||||||
void run() override;
|
void run() override;
|
||||||
|
bool updateClock();
|
||||||
bool updateBatteryState();
|
bool updateBatteryState();
|
||||||
void refreshPreferences();
|
void refreshPreferences();
|
||||||
void reloadTitleBarView();
|
void reloadTitleBarView();
|
||||||
@@ -76,6 +78,7 @@ private:
|
|||||||
BatteryTimer m_batteryTimer;
|
BatteryTimer m_batteryTimer;
|
||||||
SuspendTimer m_suspendTimer;
|
SuspendTimer m_suspendTimer;
|
||||||
BacklightDimmingTimer m_backlightDimmingTimer;
|
BacklightDimmingTimer m_backlightDimmingTimer;
|
||||||
|
ClockTimer m_clockTimer;
|
||||||
Home::App::Snapshot m_homeSnapshot;
|
Home::App::Snapshot m_homeSnapshot;
|
||||||
OnBoarding::App::Snapshot m_onBoardingSnapshot;
|
OnBoarding::App::Snapshot m_onBoardingSnapshot;
|
||||||
HardwareTest::App::Snapshot m_hardwareTestSnapshot;
|
HardwareTest::App::Snapshot m_hardwareTestSnapshot;
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
}
|
}
|
||||||
|
#include <ion/rtc.h>
|
||||||
|
|
||||||
AppsWindow::AppsWindow() :
|
AppsWindow::AppsWindow() :
|
||||||
Window(),
|
Window(),
|
||||||
@@ -19,6 +20,11 @@ bool AppsWindow::updateBatteryLevel() {
|
|||||||
return m_titleBarView.setChargeState(Ion::Battery::level());
|
return m_titleBarView.setChargeState(Ion::Battery::level());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool AppsWindow::updateClock() {
|
||||||
|
Ion::RTC::DateTime dateTime = Ion::RTC::dateTime();
|
||||||
|
return m_titleBarView.setClock(dateTime.tm_hour, dateTime.tm_min);
|
||||||
|
}
|
||||||
|
|
||||||
bool AppsWindow::updateIsChargingState() {
|
bool AppsWindow::updateIsChargingState() {
|
||||||
return m_titleBarView.setIsCharging(Ion::Battery::isCharging());
|
return m_titleBarView.setIsCharging(Ion::Battery::isCharging());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ public:
|
|||||||
AppsWindow();
|
AppsWindow();
|
||||||
void setTitle(I18n::Message title);
|
void setTitle(I18n::Message title);
|
||||||
bool updateBatteryLevel();
|
bool updateBatteryLevel();
|
||||||
|
bool updateClock();
|
||||||
bool updateIsChargingState();
|
bool updateIsChargingState();
|
||||||
bool updatePluggedState();
|
bool updatePluggedState();
|
||||||
void refreshPreferences();
|
void refreshPreferences();
|
||||||
|
|||||||
12
apps/clock_timer.cpp
Normal file
12
apps/clock_timer.cpp
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#include "clock_timer.h"
|
||||||
|
#include "apps_container.h"
|
||||||
|
|
||||||
|
ClockTimer::ClockTimer(AppsContainer * container) :
|
||||||
|
Timer(1),
|
||||||
|
m_container(container)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClockTimer::fire() {
|
||||||
|
return m_container->updateClock();
|
||||||
|
}
|
||||||
16
apps/clock_timer.h
Normal file
16
apps/clock_timer.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef APPS_CLOCK_TIMER_H
|
||||||
|
#define APPS_CLOCK_TIMER_H
|
||||||
|
|
||||||
|
#include <escher.h>
|
||||||
|
|
||||||
|
class AppsContainer;
|
||||||
|
|
||||||
|
class ClockTimer : public Timer {
|
||||||
|
public:
|
||||||
|
ClockTimer(AppsContainer * container);
|
||||||
|
private:
|
||||||
|
bool fire() override;
|
||||||
|
AppsContainer * m_container;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -10,8 +10,12 @@ using namespace Poincare;
|
|||||||
TitleBarView::TitleBarView() :
|
TitleBarView::TitleBarView() :
|
||||||
View(),
|
View(),
|
||||||
m_titleView(KDFont::SmallFont, I18n::Message::Default, 0.5f, 0.5f, Palette::ToolbarText, Palette::Toolbar),
|
m_titleView(KDFont::SmallFont, I18n::Message::Default, 0.5f, 0.5f, Palette::ToolbarText, Palette::Toolbar),
|
||||||
m_preferenceView(KDFont::SmallFont, 1.0f, 0.5, Palette::ToolbarText, Palette::Toolbar)
|
m_preferenceView(KDFont::SmallFont, 1.0f, 0.5, Palette::ToolbarText, Palette::Toolbar),
|
||||||
|
m_clockView(KDFont::SmallFont, 0.5f, 0.5f, Palette::ToolbarText, Palette::Toolbar),
|
||||||
|
m_hours(-1),
|
||||||
|
m_mins(-1)
|
||||||
{
|
{
|
||||||
|
setClock(0, 0);
|
||||||
m_examModeIconView.setImage(ImageStore::ExamIcon);
|
m_examModeIconView.setImage(ImageStore::ExamIcon);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,6 +29,25 @@ void TitleBarView::setTitle(I18n::Message title) {
|
|||||||
m_titleView.setMessage(title);
|
m_titleView.setMessage(title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TitleBarView::setClock(int hours, int mins) {
|
||||||
|
if (m_hours != hours || m_mins != mins) {
|
||||||
|
char buf[6], *ptr = buf;
|
||||||
|
*ptr++ = (hours / 10) + '0';
|
||||||
|
*ptr++ = (hours % 10) + '0';
|
||||||
|
*ptr++ = ':';
|
||||||
|
*ptr++ = (mins / 10) + '0';
|
||||||
|
*ptr++ = (mins % 10) + '0';
|
||||||
|
*ptr = '\0';
|
||||||
|
m_clockView.setText(buf);
|
||||||
|
|
||||||
|
m_hours = hours;
|
||||||
|
m_mins = mins;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool TitleBarView::setChargeState(Ion::Battery::Charge chargeState) {
|
bool TitleBarView::setChargeState(Ion::Battery::Charge chargeState) {
|
||||||
return m_batteryView.setChargeState(chargeState);
|
return m_batteryView.setChargeState(chargeState);
|
||||||
}
|
}
|
||||||
@@ -42,7 +65,7 @@ bool TitleBarView::setShiftAlphaLockStatus(Ion::Events::ShiftAlphaStatus status)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int TitleBarView::numberOfSubviews() const {
|
int TitleBarView::numberOfSubviews() const {
|
||||||
return 5;
|
return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
View * TitleBarView::subviewAtIndex(int index) {
|
View * TitleBarView::subviewAtIndex(int index) {
|
||||||
@@ -58,6 +81,9 @@ View * TitleBarView::subviewAtIndex(int index) {
|
|||||||
if (index == 3) {
|
if (index == 3) {
|
||||||
return &m_shiftAlphaLockView;
|
return &m_shiftAlphaLockView;
|
||||||
}
|
}
|
||||||
|
if (index == 4) {
|
||||||
|
return &m_clockView;
|
||||||
|
}
|
||||||
return &m_batteryView;
|
return &m_batteryView;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -69,19 +95,21 @@ void TitleBarView::layoutSubviews(bool force) {
|
|||||||
* translate the frame of the title downwards.*/
|
* translate the frame of the title downwards.*/
|
||||||
m_titleView.setFrame(KDRect(0, 2, bounds().width(), bounds().height()-2), force);
|
m_titleView.setFrame(KDRect(0, 2, bounds().width(), bounds().height()-2), force);
|
||||||
m_preferenceView.setFrame(KDRect(Metric::TitleBarExternHorizontalMargin, 0, m_preferenceView.minimalSizeForOptimalDisplay().width(), bounds().height()), force);
|
m_preferenceView.setFrame(KDRect(Metric::TitleBarExternHorizontalMargin, 0, m_preferenceView.minimalSizeForOptimalDisplay().width(), bounds().height()), force);
|
||||||
|
KDSize clockSize = m_clockView.minimalSizeForOptimalDisplay();
|
||||||
|
m_clockView.setFrame(KDRect(bounds().width() - clockSize.width() - Metric::TitleBarExternHorizontalMargin, (bounds().height()- clockSize.height())/2, clockSize), force);
|
||||||
KDSize batterySize = m_batteryView.minimalSizeForOptimalDisplay();
|
KDSize batterySize = m_batteryView.minimalSizeForOptimalDisplay();
|
||||||
m_batteryView.setFrame(KDRect(bounds().width() - batterySize.width() - Metric::TitleBarExternHorizontalMargin, (bounds().height()- batterySize.height())/2, batterySize), force);
|
m_batteryView.setFrame(KDRect(bounds().width() - clockSize.width() - batterySize.width() - Metric::TitleBarExternHorizontalMargin, (bounds().height()- batterySize.height())/2, batterySize), force);
|
||||||
if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
|
if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
|
||||||
m_examModeIconView.setFrame(KDRect(bounds().width() - batterySize.width() - k_examIconWidth - k_alphaRightMargin - Metric::TitleBarExternHorizontalMargin, (bounds().height() - k_examIconHeight)/2, k_examIconWidth, k_examIconHeight), force);
|
m_examModeIconView.setFrame(KDRect(bounds().width() - clockSize.width() - batterySize.width() - k_examIconWidth - k_alphaRightMargin - Metric::TitleBarExternHorizontalMargin, (bounds().height() - k_examIconHeight)/2, k_examIconWidth, k_examIconHeight), force);
|
||||||
} else {
|
} else {
|
||||||
m_examModeIconView.setFrame(KDRectZero, force);
|
m_examModeIconView.setFrame(KDRectZero, force);
|
||||||
}
|
}
|
||||||
KDSize shiftAlphaLockSize = m_shiftAlphaLockView.minimalSizeForOptimalDisplay();
|
KDSize shiftAlphaLockSize = m_shiftAlphaLockView.minimalSizeForOptimalDisplay();
|
||||||
if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
|
if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
|
||||||
// The Shift/Alpha frame is shifted when examination mode is active
|
// The Shift/Alpha frame is shifted when examination mode is active
|
||||||
m_shiftAlphaLockView.setFrame(KDRect(bounds().width()-batterySize.width()-k_examIconWidth-Metric::TitleBarExternHorizontalMargin-2*k_alphaRightMargin-shiftAlphaLockSize.width(), (bounds().height()- shiftAlphaLockSize.height())/2, shiftAlphaLockSize), force);
|
m_shiftAlphaLockView.setFrame(KDRect(bounds().width()-clockSize.width()-batterySize.width()-k_examIconWidth-Metric::TitleBarExternHorizontalMargin-2*k_alphaRightMargin-shiftAlphaLockSize.width(), (bounds().height()- shiftAlphaLockSize.height())/2, shiftAlphaLockSize), force);
|
||||||
} else {
|
} else {
|
||||||
m_shiftAlphaLockView.setFrame(KDRect(bounds().width()-batterySize.width()-Metric::TitleBarExternHorizontalMargin-k_alphaRightMargin-shiftAlphaLockSize.width(), (bounds().height()- shiftAlphaLockSize.height())/2, shiftAlphaLockSize), force);
|
m_shiftAlphaLockView.setFrame(KDRect(bounds().width()-clockSize.width()-batterySize.width()-Metric::TitleBarExternHorizontalMargin-k_alphaRightMargin-shiftAlphaLockSize.width(), (bounds().height()- shiftAlphaLockSize.height())/2, shiftAlphaLockSize), force);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ public:
|
|||||||
TitleBarView();
|
TitleBarView();
|
||||||
void drawRect(KDContext * ctx, KDRect rect) const override;
|
void drawRect(KDContext * ctx, KDRect rect) const override;
|
||||||
void setTitle(I18n::Message title);
|
void setTitle(I18n::Message title);
|
||||||
|
bool setClock(int hours, int mins);
|
||||||
bool setChargeState(Ion::Battery::Charge chargeState);
|
bool setChargeState(Ion::Battery::Charge chargeState);
|
||||||
bool setIsCharging(bool isCharging);
|
bool setIsCharging(bool isCharging);
|
||||||
bool setIsPlugged(bool isPlugged);
|
bool setIsPlugged(bool isPlugged);
|
||||||
@@ -30,6 +31,9 @@ private:
|
|||||||
ShiftAlphaLockView m_shiftAlphaLockView;
|
ShiftAlphaLockView m_shiftAlphaLockView;
|
||||||
BufferTextView m_preferenceView;
|
BufferTextView m_preferenceView;
|
||||||
ImageView m_examModeIconView;
|
ImageView m_examModeIconView;
|
||||||
|
BufferTextView m_clockView;
|
||||||
|
int m_hours;
|
||||||
|
int m_mins;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ ion_src += $(addprefix ion/src/shared/, \
|
|||||||
events_keyboard.cpp \
|
events_keyboard.cpp \
|
||||||
events_modifier.cpp \
|
events_modifier.cpp \
|
||||||
platform_info.cpp \
|
platform_info.cpp \
|
||||||
|
rtc.cpp \
|
||||||
storage.cpp \
|
storage.cpp \
|
||||||
unicode/utf8_decoder.cpp\
|
unicode/utf8_decoder.cpp\
|
||||||
unicode/utf8_helper.cpp\
|
unicode/utf8_helper.cpp\
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <ion/keyboard.h>
|
#include <ion/keyboard.h>
|
||||||
#include <ion/led.h>
|
#include <ion/led.h>
|
||||||
#include <ion/power.h>
|
#include <ion/power.h>
|
||||||
|
#include <ion/rtc.h>
|
||||||
#include <ion/storage.h>
|
#include <ion/storage.h>
|
||||||
#include <ion/timing.h>
|
#include <ion/timing.h>
|
||||||
#include <ion/usb.h>
|
#include <ion/usb.h>
|
||||||
|
|||||||
38
ion/include/ion/rtc.h
Normal file
38
ion/include/ion/rtc.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#ifndef ION_RTC_H
|
||||||
|
#define ION_RTC_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
namespace Ion {
|
||||||
|
namespace RTC {
|
||||||
|
|
||||||
|
struct DateTime {
|
||||||
|
int tm_sec;
|
||||||
|
int tm_min;
|
||||||
|
int tm_hour; // 0-23
|
||||||
|
int tm_mday; // 1-31
|
||||||
|
int tm_mon; // 1-12
|
||||||
|
int tm_year;
|
||||||
|
int tm_wday; // 0-6, 0 is Monday
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class Mode {
|
||||||
|
Disabled = 0,
|
||||||
|
LSI = 1,
|
||||||
|
HSE = 2,
|
||||||
|
} ;
|
||||||
|
|
||||||
|
void setMode(Mode mode);
|
||||||
|
Mode mode();
|
||||||
|
void setDateTime(DateTime dateTime);
|
||||||
|
DateTime dateTime();
|
||||||
|
|
||||||
|
bool parseDate(const char * text, DateTime & target);
|
||||||
|
bool parseTime(const char * text, DateTime & target);
|
||||||
|
void toStringDate(DateTime dateTime, char *text);
|
||||||
|
void toStringTime(DateTime dateTime, char *text);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -15,6 +15,7 @@ ion_src += $(addprefix ion/src/shared/, \
|
|||||||
timing.cpp \
|
timing.cpp \
|
||||||
dummy/backlight.cpp \
|
dummy/backlight.cpp \
|
||||||
dummy/battery.cpp \
|
dummy/battery.cpp \
|
||||||
|
dummy/rtc.cpp \
|
||||||
dummy/display.cpp \
|
dummy/display.cpp \
|
||||||
dummy/events_modifier.cpp \
|
dummy/events_modifier.cpp \
|
||||||
dummy/exam_mode.cpp \
|
dummy/exam_mode.cpp \
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ void initClocks() {
|
|||||||
// We're using TIM3 for the LEDs
|
// We're using TIM3 for the LEDs
|
||||||
RCC.APB1ENR()->setTIM3EN(true);
|
RCC.APB1ENR()->setTIM3EN(true);
|
||||||
RCC.APB1ENR()->setPWREN(true);
|
RCC.APB1ENR()->setPWREN(true);
|
||||||
|
RCC.APB1ENR()->setRTCAPB(true);
|
||||||
|
|
||||||
// APB2 bus
|
// APB2 bus
|
||||||
class RCC::APB2ENR apb2enr(0x00008000); // Reset value
|
class RCC::APB2ENR apb2enr(0x00008000); // Reset value
|
||||||
|
|||||||
@@ -251,6 +251,8 @@ void initClocks() {
|
|||||||
// APB1 bus
|
// APB1 bus
|
||||||
// We're using TIM3 for the LEDs
|
// We're using TIM3 for the LEDs
|
||||||
RCC.APB1ENR()->setTIM3EN(true);
|
RCC.APB1ENR()->setTIM3EN(true);
|
||||||
|
RCC.APB1ENR()->setPWREN(true);
|
||||||
|
RCC.APB1ENR()->setRTCAPB(true);
|
||||||
|
|
||||||
// APB2 bus
|
// APB2 bus
|
||||||
class RCC::APB2ENR apb2enr(0); // Reset value
|
class RCC::APB2ENR apb2enr(0); // Reset value
|
||||||
|
|||||||
33
ion/src/device/regs/pwr.h
Normal file
33
ion/src/device/regs/pwr.h
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#ifndef REGS_PWR_H
|
||||||
|
#define REGS_PWR_H
|
||||||
|
|
||||||
|
#include "register.h"
|
||||||
|
|
||||||
|
class PWR {
|
||||||
|
public:
|
||||||
|
class CR : Register32 {
|
||||||
|
public:
|
||||||
|
REGS_BOOL_FIELD(LPDS, 0);
|
||||||
|
REGS_BOOL_FIELD(PPDS, 1);
|
||||||
|
REGS_BOOL_FIELD(DBP, 8);
|
||||||
|
REGS_BOOL_FIELD(FPDS, 9);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSR : Register32 {
|
||||||
|
public:
|
||||||
|
REGS_BOOL_FIELD(BRE, 9);
|
||||||
|
REGS_BOOL_FIELD_R(BRR, 3);
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr PWR() {};
|
||||||
|
REGS_REGISTER_AT(CR, 0x00);
|
||||||
|
REGS_REGISTER_AT(CSR, 0x04);
|
||||||
|
private:
|
||||||
|
constexpr uint32_t Base() const {
|
||||||
|
return 0x40007000;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr PWR PWR;
|
||||||
|
|
||||||
|
#endif
|
||||||
133
ion/src/device/regs/rcc.h
Normal file
133
ion/src/device/regs/rcc.h
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
#ifndef REGS_RCC_H
|
||||||
|
#define REGS_RCC_H
|
||||||
|
|
||||||
|
#include "register.h"
|
||||||
|
|
||||||
|
class RCC {
|
||||||
|
public:
|
||||||
|
class CR : public Register32 {
|
||||||
|
public:
|
||||||
|
REGS_BOOL_FIELD(PLLRDY, 25);
|
||||||
|
REGS_BOOL_FIELD(PLLON, 24);
|
||||||
|
};
|
||||||
|
|
||||||
|
class PLLCFGR : public Register32 {
|
||||||
|
public:
|
||||||
|
REGS_FIELD(PLLM, uint8_t, 5, 0);
|
||||||
|
REGS_FIELD(PLLN, uint16_t, 14, 6);
|
||||||
|
REGS_FIELD(PLLP, uint8_t, 17, 16);
|
||||||
|
enum class PLLSRC {
|
||||||
|
HSI = 0,
|
||||||
|
HSE = 1
|
||||||
|
};
|
||||||
|
void setPLLSRC(PLLSRC s) volatile { setBitRange(22, 22, (uint8_t)s); }
|
||||||
|
REGS_FIELD(PLLQ, uint8_t, 27, 24);
|
||||||
|
REGS_FIELD(PLLR, uint8_t, 30, 28);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CFGR : public Register32 {
|
||||||
|
public:
|
||||||
|
enum class SW {
|
||||||
|
HSI = 0,
|
||||||
|
HSE = 1,
|
||||||
|
PLL = 2
|
||||||
|
};
|
||||||
|
void setSW(SW s) volatile { setBitRange(1, 0, (uint8_t)s); }
|
||||||
|
SW getSWS() volatile { return (SW)getBitRange(3,2); }
|
||||||
|
enum class AHBRatio {
|
||||||
|
One = 0,
|
||||||
|
DivideBy2 = 4,
|
||||||
|
DivideBy4 = 5,
|
||||||
|
DivideBy8 = 6,
|
||||||
|
DivideBy16 = 7
|
||||||
|
};
|
||||||
|
void setPPRE1(AHBRatio r) volatile { setBitRange(12, 10, (uint32_t)r); }
|
||||||
|
};
|
||||||
|
|
||||||
|
class AHB1ENR : public Register32 {
|
||||||
|
public:
|
||||||
|
using Register32::Register32;
|
||||||
|
REGS_BOOL_FIELD(GPIOAEN, 0);
|
||||||
|
REGS_BOOL_FIELD(GPIOBEN, 1);
|
||||||
|
REGS_BOOL_FIELD(GPIOCEN, 2);
|
||||||
|
REGS_BOOL_FIELD(GPIODEN, 3);
|
||||||
|
REGS_BOOL_FIELD(GPIOEEN, 4);
|
||||||
|
REGS_BOOL_FIELD(GPIOFEN, 5);
|
||||||
|
REGS_BOOL_FIELD(GPIOGEN, 6);
|
||||||
|
REGS_BOOL_FIELD(GPIOHEN, 7);
|
||||||
|
REGS_BOOL_FIELD(CRCEN, 12);
|
||||||
|
REGS_BOOL_FIELD(DMA1EN, 21);
|
||||||
|
REGS_BOOL_FIELD(DMA2EN, 22);
|
||||||
|
};
|
||||||
|
|
||||||
|
class AHB2ENR : Register32 {
|
||||||
|
public:
|
||||||
|
REGS_BOOL_FIELD(RNGEN, 6);
|
||||||
|
};
|
||||||
|
|
||||||
|
class AHB3ENR : Register32 {
|
||||||
|
public:
|
||||||
|
REGS_BOOL_FIELD(FSMCEN, 0);
|
||||||
|
REGS_BOOL_FIELD(QSPIEN, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
class APB1ENR : public Register32 {
|
||||||
|
public:
|
||||||
|
using Register32::Register32;
|
||||||
|
REGS_BOOL_FIELD(TIM3EN, 1);
|
||||||
|
REGS_BOOL_FIELD(RTCAPB, 10);
|
||||||
|
REGS_BOOL_FIELD(SPI3EN, 15);
|
||||||
|
REGS_BOOL_FIELD(USART3EN, 18);
|
||||||
|
REGS_BOOL_FIELD(PWREN, 28);
|
||||||
|
};
|
||||||
|
|
||||||
|
class APB2ENR : public Register32 {
|
||||||
|
public:
|
||||||
|
using Register32::Register32;
|
||||||
|
REGS_BOOL_FIELD(TIM1EN, 0);
|
||||||
|
REGS_BOOL_FIELD(USART1EN, 4);
|
||||||
|
REGS_BOOL_FIELD(ADC1EN, 8);
|
||||||
|
REGS_BOOL_FIELD(SDIOEN, 11);
|
||||||
|
REGS_BOOL_FIELD(SYSCFGEN, 14);
|
||||||
|
};
|
||||||
|
|
||||||
|
class BDCR : public Register32 {
|
||||||
|
public:
|
||||||
|
REGS_BOOL_FIELD(BDRST, 16);
|
||||||
|
REGS_BOOL_FIELD(RTCEN, 15);
|
||||||
|
REGS_FIELD(RTCSEL, uint8_t, 9, 8);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSR : public Register32 {
|
||||||
|
public:
|
||||||
|
REGS_BOOL_FIELD(LSION, 0);
|
||||||
|
REGS_BOOL_FIELD_R(LSIRDY, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
class DCKCFGR2 : Register32 {
|
||||||
|
public:
|
||||||
|
REGS_BOOL_FIELD(CK48MSEL, 27);
|
||||||
|
REGS_BOOL_FIELD(CKSDIOSEL, 28);
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr RCC() {};
|
||||||
|
REGS_REGISTER_AT(CR, 0x00);
|
||||||
|
REGS_REGISTER_AT(PLLCFGR, 0x04);
|
||||||
|
REGS_REGISTER_AT(CFGR, 0x08);
|
||||||
|
REGS_REGISTER_AT(AHB1ENR, 0x30);
|
||||||
|
REGS_REGISTER_AT(AHB2ENR, 0x34);
|
||||||
|
REGS_REGISTER_AT(AHB3ENR, 0x38);
|
||||||
|
REGS_REGISTER_AT(APB1ENR, 0x40);
|
||||||
|
REGS_REGISTER_AT(APB2ENR, 0x44);
|
||||||
|
REGS_REGISTER_AT(BDCR, 0x70);
|
||||||
|
REGS_REGISTER_AT(CSR, 0x74);
|
||||||
|
REGS_REGISTER_AT(DCKCFGR2, 0x94);
|
||||||
|
private:
|
||||||
|
constexpr uint32_t Base() const {
|
||||||
|
return 0x40023800;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr RCC RCC;
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <ion.h>
|
#include <ion.h>
|
||||||
#include "../drivers/board.h"
|
#include "../drivers/board.h"
|
||||||
|
#include "../drivers/rtc.h"
|
||||||
#include "../drivers/reset.h"
|
#include "../drivers/reset.h"
|
||||||
#include "../drivers/timing.h"
|
#include "../drivers/timing.h"
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ ion_device_src += $(addprefix ion/src/device/shared/drivers/, \
|
|||||||
power.cpp\
|
power.cpp\
|
||||||
random.cpp\
|
random.cpp\
|
||||||
reset.cpp \
|
reset.cpp \
|
||||||
|
rtc.cpp \
|
||||||
serial_number.cpp \
|
serial_number.cpp \
|
||||||
swd.cpp \
|
swd.cpp \
|
||||||
timing.cpp \
|
timing.cpp \
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include <drivers/external_flash.h>
|
#include <drivers/external_flash.h>
|
||||||
#include <drivers/keyboard.h>
|
#include <drivers/keyboard.h>
|
||||||
#include <drivers/led.h>
|
#include <drivers/led.h>
|
||||||
|
#include <drivers/rtc.h>
|
||||||
#include <drivers/swd.h>
|
#include <drivers/swd.h>
|
||||||
#include <drivers/timing.h>
|
#include <drivers/timing.h>
|
||||||
#include <drivers/usb.h>
|
#include <drivers/usb.h>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <ion/battery.h>
|
#include <ion/battery.h>
|
||||||
#include <ion/keyboard.h>
|
#include <ion/keyboard.h>
|
||||||
#include <ion/led.h>
|
#include <ion/led.h>
|
||||||
|
#include <ion/rtc.h>
|
||||||
#include <ion/usb.h>
|
#include <ion/usb.h>
|
||||||
#include <drivers/board.h>
|
#include <drivers/board.h>
|
||||||
#include <drivers/battery.h>
|
#include <drivers/battery.h>
|
||||||
@@ -39,7 +40,7 @@ void suspend(bool checkIfOnOffKeyReleased) {
|
|||||||
isLEDActive = LED::updateColorWithPlugAndCharge() != KDColorBlack;
|
isLEDActive = LED::updateColorWithPlugAndCharge() != KDColorBlack;
|
||||||
|
|
||||||
// Configure low-power mode
|
// Configure low-power mode
|
||||||
if (isLEDActive) {
|
if (isLEDActive || Ion::RTC::mode() == Ion::RTC::Mode::HSE) {
|
||||||
Device::Power::sleepConfiguration();
|
Device::Power::sleepConfiguration();
|
||||||
} else {
|
} else {
|
||||||
Device::Power::stopConfiguration();
|
Device::Power::stopConfiguration();
|
||||||
|
|||||||
169
ion/src/device/shared/drivers/rtc.cpp
Normal file
169
ion/src/device/shared/drivers/rtc.cpp
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
#include <ion/rtc.h>
|
||||||
|
#include <ion/timing.h>
|
||||||
|
#include <drivers/rtc.h>
|
||||||
|
#include <drivers/config/clocks.h>
|
||||||
|
#include "regs/regs.h"
|
||||||
|
|
||||||
|
constexpr int yearEpoch = 2000;
|
||||||
|
|
||||||
|
static int bcdToBinary(int tens, int units) {
|
||||||
|
return tens * 10 + units;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dayOfWeek(int y, int m, int d)
|
||||||
|
{
|
||||||
|
const static int t[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
|
||||||
|
y -= m < 3;
|
||||||
|
return ((y + y/4 - y/100 + y/400 + t[m-1] + (d-1)) % 7) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Public Ion methods
|
||||||
|
|
||||||
|
namespace Ion {
|
||||||
|
namespace RTC {
|
||||||
|
|
||||||
|
static void rtcSetWriteEnable(bool status) {
|
||||||
|
if (status) {
|
||||||
|
Device::Regs::PWR.CR()->setDBP(true);
|
||||||
|
Device::Regs::RTC.WPR()->setKEY(0xCA);
|
||||||
|
Device::Regs::RTC.WPR()->setKEY(0x53);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Device::Regs::RTC.WPR()->setKEY(0xFF);
|
||||||
|
Device::Regs::PWR.CR()->setDBP(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setMode(Mode mode) {
|
||||||
|
DateTime prevDateTime = dateTime();
|
||||||
|
Ion::Device::RTC::init(mode != Mode::Disabled, mode == Mode::HSE);
|
||||||
|
setDateTime(prevDateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mode mode() {
|
||||||
|
if (!Ion::Device::Regs::RCC.BDCR()->getRTCEN()) {
|
||||||
|
return Mode::Disabled;
|
||||||
|
}
|
||||||
|
if (Ion::Device::Regs::RCC.BDCR()->getRTCSEL() == 0x3) {
|
||||||
|
return Mode::HSE;
|
||||||
|
}
|
||||||
|
return Mode::LSI;
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime dateTime() {
|
||||||
|
if (mode() == Mode::Disabled) {
|
||||||
|
return DateTime { 0, 0, 0, 1, 1, 2000, 6 };
|
||||||
|
}
|
||||||
|
|
||||||
|
Device::Regs::RTC.ISR()->setRSF(false);
|
||||||
|
for (int cpt = 0; cpt < 100; cpt++) {
|
||||||
|
if (Device::Regs::RTC.ISR()->getRSF() == true)
|
||||||
|
break;
|
||||||
|
Ion::Timing::usleep(5);
|
||||||
|
}
|
||||||
|
|
||||||
|
return DateTime {
|
||||||
|
bcdToBinary(Device::Regs::RTC.TR()->getST(), Device::Regs::RTC.TR()->getSU()),
|
||||||
|
bcdToBinary(Device::Regs::RTC.TR()->getMNT(), Device::Regs::RTC.TR()->getMNU()),
|
||||||
|
bcdToBinary(Device::Regs::RTC.TR()->getHT(), Device::Regs::RTC.TR()->getHU()),
|
||||||
|
bcdToBinary(Device::Regs::RTC.DR()->getDT(), Device::Regs::RTC.DR()->getDU()),
|
||||||
|
bcdToBinary(Device::Regs::RTC.DR()->getMT(), Device::Regs::RTC.DR()->getMU()),
|
||||||
|
bcdToBinary(Device::Regs::RTC.DR()->getYT(), Device::Regs::RTC.DR()->getYU()) + yearEpoch,
|
||||||
|
Device::Regs::RTC.DR()->getWDU() - 1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDateTime(DateTime dateTime) {
|
||||||
|
if (mode() == Mode::Disabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
rtcSetWriteEnable(true);
|
||||||
|
|
||||||
|
Device::Regs::RTC.ISR()->setINIT(true);
|
||||||
|
for (int cpt = 0; cpt < 100; cpt++) {
|
||||||
|
if (Device::Regs::RTC.ISR()->getINITF() == true)
|
||||||
|
break;
|
||||||
|
Ion::Timing::usleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Ion::Device::Regs::RCC.BDCR()->getRTCSEL() == 0x2) {
|
||||||
|
// LSI is ~32 kHz
|
||||||
|
Device::Regs::RTC.PRER()->setPREDIV_S(249);
|
||||||
|
Device::Regs::RTC.PRER()->setPREDIV_A(127);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// HSE's divided down to 1 MHz
|
||||||
|
Device::Regs::RTC.PRER()->setPREDIV_S(7999);
|
||||||
|
Device::Regs::RTC.PRER()->setPREDIV_A(124);
|
||||||
|
}
|
||||||
|
Device::Regs::RTC.CR()->setFMT(false);
|
||||||
|
|
||||||
|
class Device::Regs::RTC::TR tr(0);
|
||||||
|
tr.setPM(false);
|
||||||
|
tr.setHT(dateTime.tm_hour / 10);
|
||||||
|
tr.setHU(dateTime.tm_hour % 10);
|
||||||
|
tr.setMNT(dateTime.tm_min / 10);
|
||||||
|
tr.setMNU(dateTime.tm_min % 10);
|
||||||
|
tr.setST(dateTime.tm_sec / 10);
|
||||||
|
tr.setSU(dateTime.tm_sec % 10);
|
||||||
|
Device::Regs::RTC.TR()->set(tr);
|
||||||
|
|
||||||
|
class Device::Regs::RTC::DR dr(0);
|
||||||
|
dr.setYT((dateTime.tm_year - yearEpoch) / 10);
|
||||||
|
dr.setYU((dateTime.tm_year - yearEpoch) % 10);
|
||||||
|
dr.setWDU(dayOfWeek(dateTime.tm_year, dateTime.tm_mon, dateTime.tm_mday));
|
||||||
|
dr.setMT(dateTime.tm_mon / 10);
|
||||||
|
dr.setMU(dateTime.tm_mon % 10);
|
||||||
|
dr.setDT(dateTime.tm_mday / 10);
|
||||||
|
dr.setDU(dateTime.tm_mday % 10);
|
||||||
|
Device::Regs::RTC.DR()->set(dr);
|
||||||
|
|
||||||
|
Device::Regs::RTC.ISR()->setINIT(true);
|
||||||
|
rtcSetWriteEnable(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Private Ion::Device::RTC methods
|
||||||
|
|
||||||
|
namespace Ion {
|
||||||
|
namespace Device {
|
||||||
|
namespace RTC {
|
||||||
|
|
||||||
|
void init(bool enable, bool useHighPrecisionClock) {
|
||||||
|
const int rtcSource = useHighPrecisionClock ? 0x3 : 0x2;
|
||||||
|
|
||||||
|
Ion::Device::Regs::RCC.CFGR()->setRTCPRE(Ion::Device::Clocks::Config::HSE);
|
||||||
|
|
||||||
|
Ion::RTC::rtcSetWriteEnable(true);
|
||||||
|
|
||||||
|
if (Ion::Device::Regs::RCC.BDCR()->getRTCSEL() != rtcSource) {
|
||||||
|
// Initialize backup domain for RTC
|
||||||
|
Ion::Device::Regs::RCC.BDCR()->setBDRST(true);
|
||||||
|
Ion::Timing::usleep(250);
|
||||||
|
Ion::Device::Regs::RCC.BDCR()->setBDRST(false);
|
||||||
|
Ion::Timing::usleep(250);
|
||||||
|
|
||||||
|
Ion::RTC::rtcSetWriteEnable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ion::Device::Regs::RCC.BDCR()->setRTCSEL(rtcSource);
|
||||||
|
Ion::Device::Regs::RCC.BDCR()->setRTCEN(enable);
|
||||||
|
|
||||||
|
// Enable/disable LSI clock
|
||||||
|
if (enable && useHighPrecisionClock) {
|
||||||
|
Ion::Device::Regs::RCC.CSR()->setLSION(false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Ion::Device::Regs::RCC.CSR()->setLSION(true);
|
||||||
|
while (Ion::Device::Regs::RCC.CSR()->getLSIRDY() != true);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ion::RTC::rtcSetWriteEnable(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
ion/src/device/shared/drivers/rtc.h
Normal file
16
ion/src/device/shared/drivers/rtc.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#ifndef ION_DEVICE_RTC_H
|
||||||
|
#define ION_DEVICE_RTC_H
|
||||||
|
|
||||||
|
#include "regs/regs.h"
|
||||||
|
|
||||||
|
namespace Ion {
|
||||||
|
namespace Device {
|
||||||
|
namespace RTC {
|
||||||
|
|
||||||
|
void init(bool enabled, bool useHighPrecisionClock);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -15,6 +15,7 @@ public:
|
|||||||
REGS_BOOL_FIELD(LPDS, 0);
|
REGS_BOOL_FIELD(LPDS, 0);
|
||||||
REGS_BOOL_FIELD(PPDS, 1);
|
REGS_BOOL_FIELD(PPDS, 1);
|
||||||
REGS_BOOL_FIELD(CSBF, 3);
|
REGS_BOOL_FIELD(CSBF, 3);
|
||||||
|
REGS_BOOL_FIELD(DBP, 8);
|
||||||
REGS_BOOL_FIELD(FPDS, 9);
|
REGS_BOOL_FIELD(FPDS, 9);
|
||||||
REGS_BOOL_FIELD(LPUDS, 10); // Called LPLVDS in N0100
|
REGS_BOOL_FIELD(LPUDS, 10); // Called LPLVDS in N0100
|
||||||
REGS_BOOL_FIELD(MRUDS, 11); // Called MRLVDS in N100
|
REGS_BOOL_FIELD(MRUDS, 11); // Called MRLVDS in N100
|
||||||
@@ -39,6 +40,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
REGS_BOOL_FIELD_R(WUIF, 0);
|
REGS_BOOL_FIELD_R(WUIF, 0);
|
||||||
REGS_BOOL_FIELD_R(SBF, 1);
|
REGS_BOOL_FIELD_R(SBF, 1);
|
||||||
|
REGS_BOOL_FIELD_R(BRR, 3);
|
||||||
REGS_BOOL_FIELD_W(EIWUP, 8);
|
REGS_BOOL_FIELD_W(EIWUP, 8);
|
||||||
REGS_BOOL_FIELD_W(BRE, 9);
|
REGS_BOOL_FIELD_W(BRE, 9);
|
||||||
REGS_BOOL_FIELD_R(VOSRDY, 14);
|
REGS_BOOL_FIELD_R(VOSRDY, 14);
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ public:
|
|||||||
};
|
};
|
||||||
void setPPRE1(APBPrescaler r) volatile { setBitRange(12, 10, (uint32_t)r); }
|
void setPPRE1(APBPrescaler r) volatile { setBitRange(12, 10, (uint32_t)r); }
|
||||||
void setPPRE2(APBPrescaler r) volatile { setBitRange(15, 13, (uint32_t)r); }
|
void setPPRE2(APBPrescaler r) volatile { setBitRange(15, 13, (uint32_t)r); }
|
||||||
|
REGS_FIELD(RTCPRE, uint8_t, 20, 16);
|
||||||
};
|
};
|
||||||
|
|
||||||
class AHB3RSTR : Register32 {
|
class AHB3RSTR : Register32 {
|
||||||
@@ -111,6 +112,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
using Register32::Register32;
|
using Register32::Register32;
|
||||||
REGS_BOOL_FIELD(TIM3EN, 1);
|
REGS_BOOL_FIELD(TIM3EN, 1);
|
||||||
|
REGS_BOOL_FIELD(RTCAPB, 10);
|
||||||
REGS_BOOL_FIELD(SPI3EN, 15);
|
REGS_BOOL_FIELD(SPI3EN, 15);
|
||||||
REGS_BOOL_FIELD(USART3EN, 18);
|
REGS_BOOL_FIELD(USART3EN, 18);
|
||||||
REGS_BOOL_FIELD(PWREN, 28);
|
REGS_BOOL_FIELD(PWREN, 28);
|
||||||
@@ -264,6 +266,19 @@ public:
|
|||||||
REGS_BOOL_FIELD(SSCGEN, 31);
|
REGS_BOOL_FIELD(SSCGEN, 31);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class BDCR : public Register32 {
|
||||||
|
public:
|
||||||
|
REGS_BOOL_FIELD(BDRST, 16);
|
||||||
|
REGS_BOOL_FIELD(RTCEN, 15);
|
||||||
|
REGS_FIELD(RTCSEL, uint8_t, 9, 8);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CSR : public Register32 {
|
||||||
|
public:
|
||||||
|
REGS_BOOL_FIELD(LSION, 0);
|
||||||
|
REGS_BOOL_FIELD_R(LSIRDY, 1);
|
||||||
|
};
|
||||||
|
|
||||||
class DCKCFGR2 : Register32 {
|
class DCKCFGR2 : Register32 {
|
||||||
public:
|
public:
|
||||||
REGS_BOOL_FIELD(CK48MSEL, 27);
|
REGS_BOOL_FIELD(CK48MSEL, 27);
|
||||||
@@ -285,6 +300,8 @@ public:
|
|||||||
REGS_REGISTER_AT(AHB3LPENR, 0x58);
|
REGS_REGISTER_AT(AHB3LPENR, 0x58);
|
||||||
REGS_REGISTER_AT(APB1LPENR, 0x60);
|
REGS_REGISTER_AT(APB1LPENR, 0x60);
|
||||||
REGS_REGISTER_AT(APB2LPENR, 0x64);
|
REGS_REGISTER_AT(APB2LPENR, 0x64);
|
||||||
|
REGS_REGISTER_AT(BDCR, 0x70);
|
||||||
|
REGS_REGISTER_AT(CSR, 0x74);
|
||||||
REGS_REGISTER_AT(SSCGR, 0x80);
|
REGS_REGISTER_AT(SSCGR, 0x80);
|
||||||
REGS_REGISTER_AT(DCKCFGR2, 0x94);
|
REGS_REGISTER_AT(DCKCFGR2, 0x94);
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include "rng.h"
|
#include "rng.h"
|
||||||
#include "otg.h"
|
#include "otg.h"
|
||||||
#include "quadspi.h"
|
#include "quadspi.h"
|
||||||
|
#include "rtc.h"
|
||||||
#include "sdio.h"
|
#include "sdio.h"
|
||||||
#include "spi.h"
|
#include "spi.h"
|
||||||
#include "syscfg.h"
|
#include "syscfg.h"
|
||||||
|
|||||||
99
ion/src/device/shared/regs/rtc.h
Normal file
99
ion/src/device/shared/regs/rtc.h
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
#ifndef REGS_RTC_H
|
||||||
|
#define REGS_RTC_H
|
||||||
|
|
||||||
|
#include "register.h"
|
||||||
|
|
||||||
|
namespace Ion {
|
||||||
|
namespace Device {
|
||||||
|
namespace Regs {
|
||||||
|
|
||||||
|
class RTC {
|
||||||
|
public:
|
||||||
|
class TR : public Register32 {
|
||||||
|
public:
|
||||||
|
using Register32::Register32;
|
||||||
|
REGS_BOOL_FIELD(PM, 22);
|
||||||
|
REGS_FIELD(HT, uint8_t, 21, 20);
|
||||||
|
REGS_FIELD(HU, uint8_t, 19, 16);
|
||||||
|
REGS_FIELD(MNT, uint8_t, 14, 12);
|
||||||
|
REGS_FIELD(MNU, uint8_t, 11, 8);
|
||||||
|
REGS_FIELD(ST, uint8_t, 6, 4);
|
||||||
|
REGS_FIELD(SU, uint8_t, 3, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
class DR : public Register32 {
|
||||||
|
public:
|
||||||
|
using Register32::Register32;
|
||||||
|
REGS_FIELD(YT, uint8_t, 23, 20);
|
||||||
|
REGS_FIELD(YU, uint8_t, 19, 16);
|
||||||
|
REGS_FIELD(WDU, uint8_t, 15, 13);
|
||||||
|
REGS_FIELD(MT, uint8_t, 12, 12);
|
||||||
|
REGS_FIELD(MU, uint8_t, 11, 8);
|
||||||
|
REGS_FIELD(DT, uint8_t, 5, 4);
|
||||||
|
REGS_FIELD(DU, uint8_t, 3, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CR : Register32 {
|
||||||
|
public:
|
||||||
|
REGS_BOOL_FIELD(COE, 23);
|
||||||
|
REGS_FIELD(OSEL, uint8_t, 22, 21);
|
||||||
|
REGS_BOOL_FIELD(POL, 20);
|
||||||
|
REGS_BOOL_FIELD(COSEL, 19);
|
||||||
|
REGS_BOOL_FIELD(BKP, 18);
|
||||||
|
REGS_BOOL_FIELD_W(SUB1H, 17);
|
||||||
|
REGS_BOOL_FIELD_W(ADD1H, 16);
|
||||||
|
REGS_BOOL_FIELD(TSIE, 15);
|
||||||
|
REGS_BOOL_FIELD(WUTIE, 14);
|
||||||
|
REGS_BOOL_FIELD(ALRBIE, 13);
|
||||||
|
REGS_BOOL_FIELD(ALRAIE, 12);
|
||||||
|
REGS_BOOL_FIELD(TSE, 11);
|
||||||
|
REGS_BOOL_FIELD(WUTE, 10);
|
||||||
|
REGS_BOOL_FIELD(ALRBE, 9);
|
||||||
|
REGS_BOOL_FIELD(ALRAE, 8);
|
||||||
|
REGS_BOOL_FIELD(DCE, 7);
|
||||||
|
REGS_BOOL_FIELD(FMT, 6);
|
||||||
|
REGS_BOOL_FIELD(BYPSHAD, 5);
|
||||||
|
REGS_BOOL_FIELD(REFCKON, 4);
|
||||||
|
REGS_BOOL_FIELD(TSEDGE, 3);
|
||||||
|
REGS_FIELD(WUCKSEL, uint8_t, 2, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ISR : Register32 {
|
||||||
|
public:
|
||||||
|
REGS_BOOL_FIELD(INIT, 7);
|
||||||
|
REGS_BOOL_FIELD_R(INITF, 6);
|
||||||
|
REGS_BOOL_FIELD(RSF, 5);
|
||||||
|
REGS_BOOL_FIELD_R(INITS, 4);
|
||||||
|
};
|
||||||
|
|
||||||
|
class PRER : Register32 {
|
||||||
|
public:
|
||||||
|
REGS_FIELD(PREDIV_A, uint8_t, 22, 16);
|
||||||
|
REGS_FIELD(PREDIV_S, uint16_t, 14, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
class WPR : Register32 {
|
||||||
|
public:
|
||||||
|
REGS_FIELD_W(KEY, uint8_t, 7, 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr RTC() {}
|
||||||
|
REGS_REGISTER_AT(TR, 0x00);
|
||||||
|
REGS_REGISTER_AT(DR, 0x04);
|
||||||
|
REGS_REGISTER_AT(CR, 0x08);
|
||||||
|
REGS_REGISTER_AT(ISR, 0x0C);
|
||||||
|
REGS_REGISTER_AT(PRER, 0x10);
|
||||||
|
REGS_REGISTER_AT(WPR, 0x24);
|
||||||
|
private:
|
||||||
|
constexpr uint32_t Base() const {
|
||||||
|
return 0x40002800;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr RTC RTC;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
18
ion/src/shared/dummy/rtc.cpp
Normal file
18
ion/src/shared/dummy/rtc.cpp
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#include <ion/rtc.h>
|
||||||
|
|
||||||
|
static Ion::RTC::Mode s_mode = Ion::RTC::Mode::HSE;
|
||||||
|
|
||||||
|
void Ion::RTC::setMode(Ion::RTC::Mode mode) {
|
||||||
|
s_mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ion::RTC::Mode Ion::RTC::mode() {
|
||||||
|
return s_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ion::RTC::setDateTime(Ion::RTC::DateTime dateTime) {
|
||||||
|
}
|
||||||
|
|
||||||
|
Ion::RTC::DateTime Ion::RTC::dateTime() {
|
||||||
|
return Ion::RTC::DateTime { 0, 0, 0, 1, 1, 2000, 6 };
|
||||||
|
}
|
||||||
89
ion/src/shared/rtc.cpp
Normal file
89
ion/src/shared/rtc.cpp
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
#include <ion/rtc.h>
|
||||||
|
|
||||||
|
namespace Ion {
|
||||||
|
namespace RTC {
|
||||||
|
|
||||||
|
static bool consumeDigit(char text, int & target)
|
||||||
|
{
|
||||||
|
if (text < '0' || text > '9') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
target = target * 10 + (text - '0');
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parseDate(const char * text, DateTime & target)
|
||||||
|
{
|
||||||
|
target.tm_mday = 0;
|
||||||
|
target.tm_mon = 0;
|
||||||
|
target.tm_year = 0;
|
||||||
|
|
||||||
|
if (!consumeDigit(*text++, target.tm_mday)) return false;
|
||||||
|
if (*text != '/') {
|
||||||
|
if (!consumeDigit(*text++, target.tm_mday)) return false;
|
||||||
|
}
|
||||||
|
if (*text++ != '/') return false;
|
||||||
|
if (!consumeDigit(*text++, target.tm_mon)) return false;
|
||||||
|
if (*text != '/') {
|
||||||
|
if (!consumeDigit(*text++, target.tm_mon)) return false;
|
||||||
|
}
|
||||||
|
if (*text++ != '/') return false;
|
||||||
|
if (!consumeDigit(*text++, target.tm_year)) return false;
|
||||||
|
if (!consumeDigit(*text++, target.tm_year)) return false;
|
||||||
|
if (!consumeDigit(*text++, target.tm_year)) return false;
|
||||||
|
if (!consumeDigit(*text++, target.tm_year)) return false;
|
||||||
|
if (*text++ != '\0') return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool parseTime(const char * text, DateTime & target)
|
||||||
|
{
|
||||||
|
target.tm_sec = 0;
|
||||||
|
target.tm_min = 0;
|
||||||
|
target.tm_hour = 0;
|
||||||
|
|
||||||
|
if (!consumeDigit(*text++, target.tm_hour)) return false;
|
||||||
|
if (!consumeDigit(*text++, target.tm_hour)) return false;
|
||||||
|
if (*text++ != ':') return false;
|
||||||
|
if (!consumeDigit(*text++, target.tm_min)) return false;
|
||||||
|
if (!consumeDigit(*text++, target.tm_min)) return false;
|
||||||
|
if (*text == '\0') return true;
|
||||||
|
if (*text++ != ':') return false;
|
||||||
|
if (!consumeDigit(*text++, target.tm_sec)) return false;
|
||||||
|
if (!consumeDigit(*text++, target.tm_sec)) return false;
|
||||||
|
if (*text++ != '\0') return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toStringDate(DateTime dateTime, char *text)
|
||||||
|
{
|
||||||
|
*text++ = ((dateTime.tm_mday / 10) % 10) + '0';
|
||||||
|
*text++ = ((dateTime.tm_mday / 1) % 10) + '0';
|
||||||
|
*text++ = '/';
|
||||||
|
*text++ = ((dateTime.tm_mon / 10) % 10) + '0';
|
||||||
|
*text++ = ((dateTime.tm_mon / 1) % 10) + '0';
|
||||||
|
*text++ = '/';
|
||||||
|
*text++ = ((dateTime.tm_year / 1000) % 10) + '0';
|
||||||
|
*text++ = ((dateTime.tm_year / 100) % 10) + '0';
|
||||||
|
*text++ = ((dateTime.tm_year / 10) % 10) + '0';
|
||||||
|
*text++ = ((dateTime.tm_year / 1) % 10) + '0';
|
||||||
|
*text++ = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
void toStringTime(DateTime dateTime, char *text)
|
||||||
|
{
|
||||||
|
*text++ = ((dateTime.tm_hour / 10) % 10) + '0';
|
||||||
|
*text++ = ((dateTime.tm_hour / 1) % 10) + '0';
|
||||||
|
*text++ = ':';
|
||||||
|
*text++ = ((dateTime.tm_min / 10) % 10) + '0';
|
||||||
|
*text++ = ((dateTime.tm_min / 1) % 10) + '0';
|
||||||
|
*text++ = ':';
|
||||||
|
*text++ = ((dateTime.tm_sec / 10) % 10) + '0';
|
||||||
|
*text++ = ((dateTime.tm_sec / 1) % 10) + '0';
|
||||||
|
*text++ = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ ion_src += $(addprefix ion/src/simulator/shared/, \
|
|||||||
dummy/stack.cpp \
|
dummy/stack.cpp \
|
||||||
dummy/usb.cpp \
|
dummy/usb.cpp \
|
||||||
console_stdio.cpp:-consoledisplay \
|
console_stdio.cpp:-consoledisplay \
|
||||||
|
rtc.cpp \
|
||||||
crc32.cpp \
|
crc32.cpp \
|
||||||
display.cpp:-headless \
|
display.cpp:-headless \
|
||||||
events_keyboard.cpp:-headless \
|
events_keyboard.cpp:-headless \
|
||||||
|
|||||||
32
ion/src/simulator/shared/rtc.cpp
Normal file
32
ion/src/simulator/shared/rtc.cpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#include <ion/rtc.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
static Ion::RTC::Mode s_mode = Ion::RTC::Mode::HSE;
|
||||||
|
|
||||||
|
void Ion::RTC::setMode(Ion::RTC::Mode mode) {
|
||||||
|
s_mode = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
Ion::RTC::Mode Ion::RTC::mode() {
|
||||||
|
return s_mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Ion::RTC::setDateTime(Ion::RTC::DateTime dateTime) {
|
||||||
|
printf("Ion::RTC::setDateTime(%02d:%02d:%02d %02d/%02d/%04d)\n", dateTime.tm_hour, dateTime.tm_min, dateTime.tm_sec, dateTime.tm_mday, dateTime.tm_mon, dateTime.tm_year);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ion::RTC::DateTime Ion::RTC::dateTime() {
|
||||||
|
time_t localTime = time(nullptr);
|
||||||
|
struct tm *localTm = localtime(&localTime);
|
||||||
|
|
||||||
|
return DateTime {
|
||||||
|
localTm->tm_sec,
|
||||||
|
localTm->tm_min,
|
||||||
|
localTm->tm_hour,
|
||||||
|
localTm->tm_mday,
|
||||||
|
localTm->tm_mon + 1,
|
||||||
|
localTm->tm_year + 1900,
|
||||||
|
localTm->tm_wday != 0 ? localTm->tm_wday - 1 : 6,
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user