mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-03-18 21:30:38 +01:00
Merge branch 'rtc_part1' of https://github.com/boricj/epsilon into exam_mode_boricj
This commit is contained in:
@@ -22,7 +22,6 @@ app_objs += $(addprefix apps/,\
|
||||
exam_pop_up_controller.o\
|
||||
global_preferences.o\
|
||||
i18n.o\
|
||||
led_timer.o\
|
||||
lock_view.o\
|
||||
main.o\
|
||||
math_toolbox.o\
|
||||
|
||||
@@ -16,7 +16,6 @@ AppsContainer::AppsContainer() :
|
||||
m_variableBoxController(&m_globalContext),
|
||||
m_examPopUpController(this),
|
||||
m_updateController(),
|
||||
m_ledTimer(LedTimer()),
|
||||
m_batteryTimer(BatteryTimer(this)),
|
||||
m_suspendTimer(SuspendTimer(this)),
|
||||
m_backlightDimmingTimer(),
|
||||
@@ -230,11 +229,11 @@ Window * AppsContainer::window() {
|
||||
}
|
||||
|
||||
int AppsContainer::numberOfContainerTimers() {
|
||||
return 3+(GlobalPreferences::sharedGlobalPreferences()->examMode() == GlobalPreferences::ExamMode::Activate);
|
||||
return 3;
|
||||
}
|
||||
|
||||
Timer * AppsContainer::containerTimerAtIndex(int i) {
|
||||
Timer * timers[4] = {&m_batteryTimer, &m_suspendTimer, &m_backlightDimmingTimer, &m_ledTimer};
|
||||
Timer * timers[3] = {&m_batteryTimer, &m_suspendTimer, &m_backlightDimmingTimer};
|
||||
return timers[i];
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "variable_box_controller.h"
|
||||
#include "exam_pop_up_controller.h"
|
||||
#include "exam_pop_up_controller_delegate.h"
|
||||
#include "led_timer.h"
|
||||
#include "battery_timer.h"
|
||||
#include "suspend_timer.h"
|
||||
#include "backlight_dimming_timer.h"
|
||||
@@ -69,7 +68,6 @@ private:
|
||||
VariableBoxController m_variableBoxController;
|
||||
ExamPopUpController m_examPopUpController;
|
||||
OnBoarding::UpdateController m_updateController;
|
||||
LedTimer m_ledTimer;
|
||||
BatteryTimer m_batteryTimer;
|
||||
SuspendTimer m_suspendTimer;
|
||||
BacklightDimmingTimer m_backlightDimmingTimer;
|
||||
|
||||
@@ -58,7 +58,10 @@ ExamPopUpController::ContentView::ContentView(Responder * parentResponder) :
|
||||
AppsContainer * container = (AppsContainer *)controller->app()->container();
|
||||
if (controller->isActivatingExamMode()) {
|
||||
container->reset();
|
||||
Ion::LED::setBlinking(0.5, true, false, false);
|
||||
Ion::LED::setLockState(true);
|
||||
} else {
|
||||
Ion::LED::setLockState(false);
|
||||
Ion::LED::setColor(KDColorBlack);
|
||||
}
|
||||
container->refreshPreferences();
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#include "led_timer.h"
|
||||
|
||||
LedTimer::LedTimer() :
|
||||
Timer(1),
|
||||
m_on(false)
|
||||
{
|
||||
}
|
||||
|
||||
bool LedTimer::fire() {
|
||||
m_on = !m_on;
|
||||
KDColor ledColor = m_on ? KDColorRed : KDColorBlack;
|
||||
Ion::LED::setColor(ledColor);
|
||||
return false;
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
#ifndef APPS_LED_TIMER_H
|
||||
#define APPS_LED_TIMER_H
|
||||
|
||||
#include <escher.h>
|
||||
|
||||
class LedTimer : public Timer {
|
||||
public:
|
||||
LedTimer();
|
||||
private:
|
||||
bool fire() override;
|
||||
bool m_on;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -7,6 +7,7 @@ EPSILON_VERSION ?= 1.6.0
|
||||
EPSILON_ONBOARDING_APP ?= 1
|
||||
EPSILON_SOFTWARE_UPDATE_PROMPT ?= 1
|
||||
EPSILON_APPS ?= calculation graph code statistics probability solver sequence regression settings
|
||||
EPSILON_LED_WHILE_CHARGING = 1
|
||||
EPSILON_I18N ?= en fr es de pt
|
||||
EPSILON_GETOPT ?= 0
|
||||
|
||||
@@ -24,3 +25,4 @@ SFLAGS += -DDEBUG=$(DEBUG)
|
||||
SFLAGS += -DEPSILON_ONBOARDING_APP=$(EPSILON_ONBOARDING_APP)
|
||||
SFLAGS += -DEPSILON_SOFTWARE_UPDATE_PROMPT=$(EPSILON_SOFTWARE_UPDATE_PROMPT)
|
||||
SFLAGS += -DEPSILON_GETOPT=$(EPSILON_GETOPT)
|
||||
SFLAGS += -DEPSILON_LED_WHILE_CHARGING=$(EPSILON_LED_WHILE_CHARGING)
|
||||
|
||||
@@ -7,6 +7,15 @@ namespace Ion {
|
||||
namespace LED {
|
||||
|
||||
void setColor(KDColor c);
|
||||
void setBlinking(float blinkLength, bool red, bool green, bool blue);
|
||||
void setCharging(bool isPluggedIn, bool isCharging);
|
||||
|
||||
/*
|
||||
* This is just a flag to see if we should mess with the LEDs on our own.
|
||||
* Especially useful for keeping the LED blinking while in exam mode.
|
||||
*/
|
||||
bool getLockState();
|
||||
void setLockState(bool state);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,15 +20,20 @@ extern "C" {
|
||||
|
||||
// Public Ion methods
|
||||
|
||||
/* TODO: The delay methods 'msleep' and 'usleep' are currently dependent on the
|
||||
* optimizations chosen by the compiler. To prevent that and to gain in
|
||||
* precision, we could use the controller cycle counter (Systick). */
|
||||
|
||||
void Ion::msleep(long ms) {
|
||||
for (volatile long i=0; i<8852*ms; i++) {
|
||||
__asm volatile("nop");
|
||||
}
|
||||
// We need a frequency high enough to not overflow the prescaler,
|
||||
// which is 16 bits wide.
|
||||
constexpr int TIM6_FREQ = 4*1000;
|
||||
|
||||
Ion::Device::waitTIM6(Ion::Device::SYSBUS_FREQ / TIM6_FREQ, ms * TIM6_FREQ / 1000);
|
||||
}
|
||||
|
||||
/* TODO: The delay method 'usleep' is currently dependent on the optimizations
|
||||
* chosen by the compiler. To prevent that and to gain in precision, we could
|
||||
* use the controller cycle counter (Systick). We can't use a regular timer
|
||||
* (like TIM6) for this since setting it up takes a significant amount of time
|
||||
* in these timescales.
|
||||
*/
|
||||
void Ion::usleep(long us) {
|
||||
for (volatile long i=0; i<9*us; i++) {
|
||||
__asm volatile("nop");
|
||||
@@ -265,8 +270,10 @@ void initClocks() {
|
||||
RCC.AHB3ENR()->setFSMCEN(true);
|
||||
|
||||
// APB1 bus
|
||||
// We're using TIM3
|
||||
// We're using TIM3 for the LEDs
|
||||
RCC.APB1ENR()->setTIM3EN(true);
|
||||
// We're using TIM6 for sleeping
|
||||
RCC.APB1ENR()->setTIM6EN(true);
|
||||
RCC.APB1ENR()->setPWREN(true);
|
||||
|
||||
// APB2 bus
|
||||
@@ -283,8 +290,9 @@ void shutdownClocks() {
|
||||
// APB2 bus
|
||||
RCC.APB2ENR()->set(0x00008000); // Reset value
|
||||
|
||||
// AHB1
|
||||
RCC.APB1ENR()->set(0x00000400);
|
||||
// APB1
|
||||
RCC.APB1ENR()->set(0x00000402);
|
||||
RCC.APB1LPENR()->setTIM3LPEN(true); // Keep the LED going
|
||||
|
||||
// AHB1 bus
|
||||
RCC.AHB1ENR()->set(0); // Reset value
|
||||
@@ -292,5 +300,31 @@ void shutdownClocks() {
|
||||
RCC.AHB3ENR()->setFSMCEN(false);
|
||||
}
|
||||
|
||||
void waitTIM6(unsigned short prescaler, long cycles) {
|
||||
while (cycles > 0) {
|
||||
// TIM6 counts up to 2^16-1, make sure we won't overflow the counter.
|
||||
uint16_t iterCycles = (cycles > 0xFFFF ? 0xFFFF : cycles);
|
||||
|
||||
// Initialize TIM6
|
||||
TIM6.PSC()->set(prescaler);
|
||||
TIM6.CNT()->set(0);
|
||||
TIM6.ARR()->set(iterCycles);
|
||||
TIM6.EGR()->setUG(true);
|
||||
TIM6.SR()->setUIF(false);
|
||||
TIM6.CR1()->setCEN(true);
|
||||
|
||||
// Wait until the timer elapses
|
||||
do {
|
||||
// TODO: Use interrupts instead of busy-waiting
|
||||
__asm volatile("nop");
|
||||
} while (TIM6.SR()->getUIF() == false);
|
||||
|
||||
// Stop TIM6
|
||||
TIM6.CR1()->setCEN(false);
|
||||
|
||||
cycles -= iterCycles;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
namespace Ion {
|
||||
namespace Device {
|
||||
|
||||
constexpr int SYSBUS_FREQ = 96*1000*1000;
|
||||
|
||||
void init();
|
||||
void shutdown();
|
||||
|
||||
@@ -23,6 +25,45 @@ void shutdownClocks();
|
||||
constexpr static int SerialNumberLength = 16;
|
||||
void copySerialNumber(char * buffer);
|
||||
|
||||
void waitTIM6(unsigned short prescaler, long cycles);
|
||||
|
||||
/* Pin | Role | Mode | Function
|
||||
* -----+-------------------+-----------------------+----------
|
||||
* PA0 | Battery sensing | |
|
||||
* PA2 | LCD D4 | Alternate Function 12 | FMSC_D4
|
||||
* PA3 | LCD D5 | Alternate Function 12 | FSMC_D5
|
||||
* PA4 | LCD D6 | Alternate Function 12 | FSMC_D6
|
||||
* PA5 | LCD D7 | Alternate Function 12 | FSMC_D7
|
||||
* PA6 | LED red | Alternate Function XX | TIM3_CH1
|
||||
* PA7 | LED green | Alternate Function XX | TIM3_CH2
|
||||
* PA9 | USB VBUS prob | Input, pulled down |
|
||||
* PB0 | LED blue | Alternate Function XX | TIM3_CH3
|
||||
* PB1 | Keyboard row A | Output, open-drain |
|
||||
* PB2 | Keyboard row B | Output, open-drain |
|
||||
* PB3 | Keyboard row C | Output, open-drain |
|
||||
* PB4 | Keyboard row D | Output, open-drain |
|
||||
* PB5 | Keyboard row E | Output, open-drain |
|
||||
* PB6 | Keyboard row F | Output, open-drain |
|
||||
* PB7 | Keyboard row G | Output, open-drain |
|
||||
* PB8 | Keyboard row H | Output, open-drain |
|
||||
* PB9 | Keyboard row I | Output, open-drain |
|
||||
* PB10 | Keyboard row J | Output, open-drain |
|
||||
* PB14 | LCD D0 | Alternate Function 12 | FSMC_D0
|
||||
* PC0 | Keyboard column 1 | Input, pulled-up |
|
||||
* PC1 | Keyboard column 2 | Input, pulled-up |
|
||||
* PC3 | LCD data/command | Alternate Function 12 | FSMC_A0
|
||||
* PC4 | LCD chip select | Alternate Function 12 | FSMC_NE4
|
||||
* PC5 | LCD read signal | Alternate Function 12 | FSMC_NOE
|
||||
* PC6 | LCD D1 | Alternate Function 12 | FSMC_D7
|
||||
* PC9 | LCD backlight | Alternate Function 12 | TIM3_CH4
|
||||
* PC11 | LCD D2 | Alternate Function 12 | FSMC_D2
|
||||
* PC12 | LCD D3 | Alternate Function 12 | FSMC_D3
|
||||
* PC13 | Keyboard column 3 | Input, pulled-up |
|
||||
* PC14 | Keyboard column 4 | Input, pulled-up |
|
||||
* PC15 | Keyboard column 5 | Input, pulled-up |
|
||||
* PD2 | LCD write signal | Alternate Function 12 | FSMC_NWE
|
||||
*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +1,63 @@
|
||||
#include <ion/led.h>
|
||||
#include <ion/display.h>
|
||||
#include "device.h"
|
||||
#include "led.h"
|
||||
#include "regs/regs.h"
|
||||
|
||||
// Public Ion::LED methods
|
||||
|
||||
void Ion::LED::setColor(KDColor c) {
|
||||
if (getLockState()) {
|
||||
return;
|
||||
}
|
||||
|
||||
initTimer(Ion::LED::Device::Mode::PWM);
|
||||
|
||||
Ion::LED::Device::setColorStatus(Ion::LED::Device::Color::RED, true);
|
||||
Ion::LED::Device::setColorStatus(Ion::LED::Device::Color::GREEN, true);
|
||||
Ion::LED::Device::setColorStatus(Ion::LED::Device::Color::BLUE, true);
|
||||
|
||||
TIM3.CCR2()->set(Device::dutyCycleForUInt8(c.red()));
|
||||
TIM3.CCR3()->set(Device::dutyCycleForUInt8(c.blue()));
|
||||
TIM3.CCR4()->set(Device::dutyCycleForUInt8(c.green()));
|
||||
}
|
||||
|
||||
void Ion::LED::setBlinking(float blinkPeriod, bool red, bool green, bool blue) {
|
||||
if (getLockState()) {
|
||||
return;
|
||||
}
|
||||
|
||||
initTimer(Ion::LED::Device::Mode::BLINK, blinkPeriod);
|
||||
|
||||
Ion::LED::Device::setColorStatus(Ion::LED::Device::Color::RED, red);
|
||||
Ion::LED::Device::setColorStatus(Ion::LED::Device::Color::GREEN, green);
|
||||
Ion::LED::Device::setColorStatus(Ion::LED::Device::Color::BLUE, blue);
|
||||
}
|
||||
|
||||
void Ion::LED::setCharging(bool isPluggedIn, bool isCharging) {
|
||||
if (!isPluggedIn) {
|
||||
Ion::LED::setColor(KDColorBlack);
|
||||
}
|
||||
else {
|
||||
if (isCharging) {
|
||||
Ion::LED::setColor(KDColorRed);
|
||||
}
|
||||
else {
|
||||
Ion::LED::setColor(KDColorGreen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool lockState = false;
|
||||
|
||||
bool Ion::LED::getLockState() {
|
||||
return lockState;
|
||||
}
|
||||
|
||||
void Ion::LED::setLockState(bool state) {
|
||||
lockState = state;
|
||||
}
|
||||
|
||||
// Private Ion::Device::LED methods
|
||||
|
||||
namespace Ion {
|
||||
@@ -19,12 +66,9 @@ namespace Device {
|
||||
|
||||
void init() {
|
||||
initGPIO();
|
||||
initTimer();
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
shutdownTimer();
|
||||
shutdownGPIO();
|
||||
}
|
||||
|
||||
void initGPIO() {
|
||||
@@ -44,7 +88,56 @@ void shutdownGPIO() {
|
||||
}
|
||||
}
|
||||
|
||||
void initTimer() {
|
||||
void initTimer(Mode mode, float blinkPeriod) {
|
||||
constexpr int TIM3_FREQ = 4*1000;
|
||||
|
||||
/* Pulse width modulation mode allows you to generate a signal with a
|
||||
* frequency determined by the value of the TIMx_ARR register and a duty cycle
|
||||
* determined by the value of the TIMx_CCRx register. */
|
||||
switch (mode) {
|
||||
case Ion::LED::Device::Mode::PWM:
|
||||
/* Let's set the prescaler to 1. Increasing the prescaler would slow down the
|
||||
* modulation, which can be useful when debugging. */
|
||||
TIM3.PSC()->set(1);
|
||||
TIM3.ARR()->set(PWMPeriod);
|
||||
TIM3.CCR2()->set(0);
|
||||
TIM3.CCR3()->set(0);
|
||||
TIM3.CCR4()->set(0);
|
||||
break;
|
||||
case Ion::LED::Device::Mode::BLINK:
|
||||
/* We still want to do PWM, but at a rate slow enough to blink. */
|
||||
TIM3.PSC()->set(Ion::Device::SYSBUS_FREQ / TIM3_FREQ);
|
||||
TIM3.ARR()->set(blinkPeriod * TIM3_FREQ);
|
||||
TIM3.CCR2()->set(blinkPeriod * TIM3_FREQ / 2);
|
||||
TIM3.CCR3()->set(blinkPeriod * TIM3_FREQ / 2);
|
||||
TIM3.CCR4()->set(blinkPeriod * TIM3_FREQ / 2);
|
||||
break;
|
||||
}
|
||||
|
||||
// Set Channels 2-4 as outputs, PWM mode 1
|
||||
TIM3.CCMR()->setOC2M(TIM<Register16>::CCMR::OCM::PWM1);
|
||||
TIM3.CCMR()->setOC3M(TIM<Register16>::CCMR::OCM::PWM1);
|
||||
TIM3.CCMR()->setOC4M(TIM<Register16>::CCMR::OCM::PWM1);
|
||||
|
||||
// Output preload enable for channels 2-4
|
||||
TIM3.CCMR()->setOC2PE(true);
|
||||
TIM3.CCMR()->setOC3PE(true);
|
||||
TIM3.CCMR()->setOC4PE(true);
|
||||
|
||||
// Auto-reload preload enable
|
||||
TIM3.CR1()->setARPE(true);
|
||||
|
||||
// Enable Capture/Compare for channel 2 to 4
|
||||
TIM3.CCER()->setCC2E(true);
|
||||
TIM3.CCER()->setCC3E(true);
|
||||
TIM3.CCER()->setCC4E(true);
|
||||
|
||||
TIM3.BDTR()->setMOE(true);
|
||||
|
||||
TIM3.CR1()->setCEN(true);
|
||||
}
|
||||
|
||||
void initTimerColor() {
|
||||
/* Let's set the prescaler to 1. Increasing the prescaler would slow down the
|
||||
* modulation, which can be useful when debugging. */
|
||||
TIM3.PSC()->set(1);
|
||||
@@ -57,11 +150,6 @@ void initTimer() {
|
||||
TIM3.CCR3()->set(0);
|
||||
TIM3.CCR4()->set(0);
|
||||
|
||||
// Set Channels 2-4 as outputs, PWM mode 1
|
||||
TIM3.CCMR()->setOC2M(TIM::CCMR::OCM::PWM1);
|
||||
TIM3.CCMR()->setOC3M(TIM::CCMR::OCM::PWM1);
|
||||
TIM3.CCMR()->setOC4M(TIM::CCMR::OCM::PWM1);
|
||||
|
||||
// Output preload enable for channels 2-4
|
||||
TIM3.CCMR()->setOC2PE(true);
|
||||
TIM3.CCMR()->setOC3PE(true);
|
||||
@@ -81,9 +169,23 @@ void initTimer() {
|
||||
}
|
||||
|
||||
void shutdownTimer() {
|
||||
TIM3.CCMR()->setOC2M(TIM::CCMR::OCM::ForceInactive);
|
||||
TIM3.CCMR()->setOC3M(TIM::CCMR::OCM::ForceInactive);
|
||||
TIM3.CCMR()->setOC4M(TIM::CCMR::OCM::ForceInactive);
|
||||
setColorStatus(Ion::LED::Device::Color::RED, false);
|
||||
setColorStatus(Ion::LED::Device::Color::GREEN, false);
|
||||
setColorStatus(Ion::LED::Device::Color::BLUE, false);
|
||||
}
|
||||
|
||||
void setColorStatus(Color color, bool enable) {
|
||||
switch (color) {
|
||||
case Ion::LED::Device::Color::RED:
|
||||
TIM3.CCMR()->setOC2M(enable ? TIM<Register16>::CCMR::OCM::PWM1 : TIM<Register16>::CCMR::OCM::ForceInactive);
|
||||
break;
|
||||
case Ion::LED::Device::Color::GREEN:
|
||||
TIM3.CCMR()->setOC4M(enable ? TIM<Register16>::CCMR::OCM::PWM1 : TIM<Register16>::CCMR::OCM::ForceInactive);
|
||||
break;
|
||||
case Ion::LED::Device::Color::BLUE:
|
||||
TIM3.CCMR()->setOC3M(enable ? TIM<Register16>::CCMR::OCM::PWM1 : TIM<Register16>::CCMR::OCM::ForceInactive);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void enforceState(bool red, bool green, bool blue) {
|
||||
|
||||
@@ -14,14 +14,26 @@ namespace Device {
|
||||
* PC7 | LED red | Alternate Function 2 | TIM3_CH2
|
||||
*/
|
||||
|
||||
enum Mode {
|
||||
PWM,
|
||||
BLINK
|
||||
} ;
|
||||
|
||||
enum Color {
|
||||
RED,
|
||||
GREEN,
|
||||
BLUE
|
||||
} ;
|
||||
|
||||
void init();
|
||||
void shutdown();
|
||||
void setColorStatus(Color color, bool enable);
|
||||
/* This call bypasses the timer, and immediately enforces a given LED state. */
|
||||
void enforceState(bool red, bool green, bool blue);
|
||||
|
||||
void initGPIO();
|
||||
void shutdownGPIO();
|
||||
void initTimer();
|
||||
void initTimer(Mode mode, float blinkPeriod = 0);
|
||||
void shutdownTimer();
|
||||
|
||||
constexpr static GPIOPin RGBPins[] = {
|
||||
|
||||
@@ -21,22 +21,22 @@ void Ion::Power::suspend(bool checkIfPowerKeyReleased) {
|
||||
|
||||
PWR.CR()->setLPDS(true); // Turn the regulator off. Takes longer to wake up.
|
||||
PWR.CR()->setFPDS(true); // Put the flash to sleep. Takes longer to wake up.
|
||||
CM4.SCR()->setSLEEPDEEP(true);
|
||||
CM4.SCR()->setSLEEPDEEP(!Ion::LED::getLockState());
|
||||
|
||||
WakeUp::Device::onUSBPlugging();
|
||||
#if LED_WHILE_CHARGING
|
||||
WakeUp::Device::onChargingEvent();
|
||||
#endif
|
||||
while (1) {
|
||||
#if LED_WHILE_CHARGING
|
||||
#if EPSILON_LED_WHILE_CHARGING
|
||||
/* Update LEDS
|
||||
* if the standby mode was stopped due to a "stop charging" event, we wait
|
||||
* a while to be sure that the plug state of the USB is up-to-date. */
|
||||
msleep(200);
|
||||
LED::Device::enforceState(Battery::isCharging(), USB::isPlugged(), false);
|
||||
Ion::LED::setCharging(Ion::USB::isPlugged(), Ion::Battery::isCharging());
|
||||
#endif
|
||||
|
||||
WakeUp::Device::onPowerKeyDown();
|
||||
WakeUp::Device::onUSBPlugging();
|
||||
#if EPSILON_LED_WHILE_CHARGING
|
||||
WakeUp::Device::onChargingEvent();
|
||||
#endif
|
||||
|
||||
Device::shutdownClocks();
|
||||
|
||||
@@ -47,7 +47,7 @@ void Ion::Power::suspend(bool checkIfPowerKeyReleased) {
|
||||
* to clear it, and then a second WFE to wait for a _new_ event. */
|
||||
asm("sev");
|
||||
asm("wfe");
|
||||
msleep(1);
|
||||
asm("nop");
|
||||
asm("wfe");
|
||||
|
||||
Device::initClocks();
|
||||
|
||||
@@ -9,11 +9,19 @@ public:
|
||||
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;
|
||||
|
||||
@@ -7,11 +7,16 @@ class RCC {
|
||||
public:
|
||||
class CR : public Register32 {
|
||||
public:
|
||||
REGS_BOOL_FIELD(HSION, 0);
|
||||
REGS_BOOL_FIELD(HSEON, 16);
|
||||
REGS_BOOL_FIELD(HSERDY, 17);
|
||||
REGS_BOOL_FIELD(PLLON, 24);
|
||||
REGS_BOOL_FIELD_R(PLLI2SRDY, 27);
|
||||
REGS_BOOL_FIELD(PLLI2SON, 26);
|
||||
REGS_BOOL_FIELD(PLLRDY, 25);
|
||||
REGS_BOOL_FIELD(PLLON, 24);
|
||||
REGS_BOOL_FIELD(CSSON, 19);
|
||||
REGS_BOOL_FIELD(HSEBYP, 18);
|
||||
REGS_BOOL_FIELD_R(HSERDY, 17);
|
||||
REGS_BOOL_FIELD(HSEON, 16);
|
||||
REGS_BOOL_FIELD_R(HSIRDY, 1);
|
||||
REGS_BOOL_FIELD(HSION, 0);
|
||||
};
|
||||
|
||||
class PLLCFGR : public Register32 {
|
||||
@@ -56,7 +61,9 @@ public:
|
||||
AHBDividedBy8 = 6,
|
||||
AHBDividedBy16 = 7
|
||||
};
|
||||
void setPPRE1(APBPrescaler p) volatile { setBitRange(12, 10, (uint32_t)p); }
|
||||
void setPPRE2(APBPrescaler r) volatile { setBitRange(15, 13, (uint32_t)r); }
|
||||
void setPPRE1(APBPrescaler r) volatile { setBitRange(12, 10, (uint32_t)r); }
|
||||
REGS_FIELD(RTCPRE, uint8_t, 4, 0);
|
||||
};
|
||||
|
||||
class AHB1ENR : public Register32 {
|
||||
@@ -90,7 +97,16 @@ public:
|
||||
class APB1ENR : public Register32 {
|
||||
public:
|
||||
using Register32::Register32;
|
||||
REGS_BOOL_FIELD(TIM2EN, 0);
|
||||
REGS_BOOL_FIELD(TIM3EN, 1);
|
||||
REGS_BOOL_FIELD(TIM4EN, 2);
|
||||
REGS_BOOL_FIELD(TIM5EN, 3);
|
||||
REGS_BOOL_FIELD(TIM6EN, 4);
|
||||
REGS_BOOL_FIELD(TIM7EN, 5);
|
||||
REGS_BOOL_FIELD(TIM12EN, 6);
|
||||
REGS_BOOL_FIELD(TIM13EN, 7);
|
||||
REGS_BOOL_FIELD(TIM14EN, 8);
|
||||
REGS_BOOL_FIELD(RTCAPB, 10);
|
||||
REGS_BOOL_FIELD(SPI3EN, 15);
|
||||
REGS_BOOL_FIELD(USART3EN, 18);
|
||||
REGS_BOOL_FIELD(PWREN, 28);
|
||||
@@ -100,11 +116,52 @@ public:
|
||||
public:
|
||||
using Register32::Register32;
|
||||
REGS_BOOL_FIELD(TIM1EN, 0);
|
||||
REGS_BOOL_FIELD(TIM8EN, 1);
|
||||
REGS_BOOL_FIELD(USART1EN, 4);
|
||||
REGS_BOOL_FIELD(ADC1EN, 8);
|
||||
REGS_BOOL_FIELD(SDIOEN, 11);
|
||||
REGS_BOOL_FIELD(SPI1EN, 12);
|
||||
REGS_BOOL_FIELD(SYSCFGEN, 14);
|
||||
REGS_BOOL_FIELD(TIM9EN, 16);
|
||||
REGS_BOOL_FIELD(TIM10EN, 17);
|
||||
REGS_BOOL_FIELD(TIM11EN, 18);
|
||||
};
|
||||
|
||||
class APB1LPENR : public Register32 {
|
||||
public:
|
||||
using Register32::Register32;
|
||||
REGS_BOOL_FIELD(TIM2LPEN, 0);
|
||||
REGS_BOOL_FIELD(TIM3LPEN, 1);
|
||||
REGS_BOOL_FIELD(TIM4LPEN, 2);
|
||||
REGS_BOOL_FIELD(TIM5LPEN, 3);
|
||||
REGS_BOOL_FIELD(TIM6LPEN, 4);
|
||||
REGS_BOOL_FIELD(TIM7LPEN, 5);
|
||||
REGS_BOOL_FIELD(TIM12LPEN, 6);
|
||||
REGS_BOOL_FIELD(TIM13LPEN, 7);
|
||||
REGS_BOOL_FIELD(TIM14LPEN, 8);
|
||||
REGS_BOOL_FIELD(RTCAPBEN, 10);
|
||||
REGS_BOOL_FIELD(SPI3LPEN, 15);
|
||||
REGS_BOOL_FIELD(USART3LPEN, 18);
|
||||
REGS_BOOL_FIELD(PWRLPEN, 28);
|
||||
};
|
||||
|
||||
class BDCR : public Register32 {
|
||||
public:
|
||||
REGS_BOOL_FIELD(BDRST, 16);
|
||||
REGS_BOOL_FIELD(RTCEN, 15);
|
||||
enum class RTCSel {
|
||||
RTC_NoClock = 0,
|
||||
RTC_LSEClock = 1,
|
||||
RTC_LSIClock = 2,
|
||||
RTC_HSEClock = 3
|
||||
};
|
||||
void setRTCSel(RTCSel s) volatile { setBitRange(9, 8, (uint32_t)s); }
|
||||
};
|
||||
|
||||
class CSR : public Register32 {
|
||||
public:
|
||||
REGS_BOOL_FIELD(LSION, 0);
|
||||
REGS_BOOL_FIELD_R(LSIRDY, 1);
|
||||
};
|
||||
|
||||
class DCKCFGR2 : Register32 {
|
||||
@@ -122,6 +179,9 @@ public:
|
||||
REGS_REGISTER_AT(AHB3ENR, 0x38);
|
||||
REGS_REGISTER_AT(APB1ENR, 0x40);
|
||||
REGS_REGISTER_AT(APB2ENR, 0x44);
|
||||
REGS_REGISTER_AT(APB1LPENR, 0x60);
|
||||
REGS_REGISTER_AT(BDCR, 0x70);
|
||||
REGS_REGISTER_AT(CSR, 0x74);
|
||||
REGS_REGISTER_AT(DCKCFGR2, 0x94);
|
||||
private:
|
||||
constexpr uint32_t Base() const {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "rcc.h"
|
||||
#include "rng.h"
|
||||
#include "otg.h"
|
||||
#include "rtc.h"
|
||||
#include "sdio.h"
|
||||
#include "spi.h"
|
||||
#include "syscfg.h"
|
||||
|
||||
99
ion/src/device/regs/rtc.h
Normal file
99
ion/src/device/regs/rtc.h
Normal file
@@ -0,0 +1,99 @@
|
||||
#ifndef REGS_RTC_H
|
||||
#define REGS_RTC_H
|
||||
|
||||
#include "register.h"
|
||||
|
||||
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_R(RECALPF, 16);
|
||||
REGS_BOOL_FIELD(INIT, 7);
|
||||
REGS_BOOL_FIELD_R(INITF, 6);
|
||||
REGS_BOOL_FIELD(RSF, 5);
|
||||
REGS_BOOL_FIELD_R(INITS, 4);
|
||||
};
|
||||
|
||||
class PRER : public Register32 {
|
||||
public:
|
||||
using Register32::Register32;
|
||||
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);
|
||||
};
|
||||
|
||||
class CALR : Register32 {
|
||||
public:
|
||||
REGS_FIELD(CALM, uint8_t, 8, 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);
|
||||
REGS_REGISTER_AT(CALR, 0x3C);
|
||||
private:
|
||||
constexpr uint32_t Base() const {
|
||||
return 0x40002800;
|
||||
};
|
||||
};
|
||||
|
||||
constexpr RTC RTC;
|
||||
|
||||
#endif
|
||||
@@ -3,14 +3,40 @@
|
||||
|
||||
#include "register.h"
|
||||
|
||||
template <typename RegisterWidth>
|
||||
class TIM {
|
||||
public:
|
||||
class CR1 : Register16 {
|
||||
public:
|
||||
REGS_BOOL_FIELD(CEN, 0);
|
||||
REGS_BOOL_FIELD(URS, 1);
|
||||
REGS_BOOL_FIELD(UDIS, 1);
|
||||
REGS_BOOL_FIELD(ARPE, 7);
|
||||
};
|
||||
|
||||
class SR : Register16 {
|
||||
public:
|
||||
REGS_BOOL_FIELD(CC4OF, 12);
|
||||
REGS_BOOL_FIELD(CC3OF, 11);
|
||||
REGS_BOOL_FIELD(CC2OF, 10);
|
||||
REGS_BOOL_FIELD(CC1OF, 9);
|
||||
REGS_BOOL_FIELD(CC4IF, 4);
|
||||
REGS_BOOL_FIELD(CC3IF, 3);
|
||||
REGS_BOOL_FIELD(CC2IF, 2);
|
||||
REGS_BOOL_FIELD(CC1IF, 1);
|
||||
REGS_BOOL_FIELD(UIF, 0);
|
||||
};
|
||||
|
||||
class EGR : Register16 {
|
||||
public:
|
||||
REGS_BOOL_FIELD(UG, 0);
|
||||
};
|
||||
|
||||
class DIER : Register16 {
|
||||
public:
|
||||
REGS_BOOL_FIELD(UIE, 0);
|
||||
};
|
||||
|
||||
class CCMR : Register64 {
|
||||
/* We're declaring CCMR as a 64 bits register. CCMR doesn't exsist per se,
|
||||
* it is in fact the consolidation of CCMR1 and CCMR2. Both are 16 bits
|
||||
@@ -24,6 +50,12 @@ public:
|
||||
INPUT_TI1 = 2,
|
||||
INPUT_TRC = 3
|
||||
};
|
||||
enum class CC4S : uint8_t {
|
||||
OUTPUT = 0,
|
||||
INPUT_TI4 = 1,
|
||||
INPUT_TI3 = 2,
|
||||
INPUT_TRC = 3
|
||||
};
|
||||
enum class OCM : uint8_t {
|
||||
Frozen = 0,
|
||||
ActiveOnMatch = 1,
|
||||
@@ -44,6 +76,8 @@ public:
|
||||
REGS_TYPE_FIELD(OC2M, 14, 12);
|
||||
REGS_BOOL_FIELD(OC3PE, 35);
|
||||
REGS_TYPE_FIELD(OC3M, 38, 36);
|
||||
REGS_TYPE_FIELD(CC4S, 41, 40);
|
||||
REGS_FIELD(IC4PSC, uint8_t, 43, 42);
|
||||
REGS_BOOL_FIELD(OC4PE, 43);
|
||||
REGS_TYPE_FIELD(OC4M, 46, 44);
|
||||
};
|
||||
@@ -61,17 +95,33 @@ public:
|
||||
REGS_BOOL_FIELD(MOE, 15);
|
||||
};
|
||||
|
||||
class CNT : public RegisterWidth {};
|
||||
class PSC : public Register16 {};
|
||||
class ARR : public Register16 {};
|
||||
class CCR1 : public Register16 {};
|
||||
class CCR2 : public Register16 {};
|
||||
class CCR3 : public Register16 {};
|
||||
class CCR4 : public Register16 {};
|
||||
class ARR : public RegisterWidth {};
|
||||
class CCR1 : public RegisterWidth {};
|
||||
class CCR2 : public RegisterWidth {};
|
||||
class CCR3 : public RegisterWidth {};
|
||||
class CCR4 : public RegisterWidth {};
|
||||
|
||||
class OR : Register16 {
|
||||
public:
|
||||
enum class TI4_RMP {
|
||||
GPIO = 0,
|
||||
LSI = 1,
|
||||
LSE = 2,
|
||||
WAKEUP = 3
|
||||
};
|
||||
void setTI4RMP(TI4_RMP r) volatile { setBitRange(7, 6, (uint32_t)r); }
|
||||
};
|
||||
|
||||
constexpr TIM(int i) : m_index(i) {}
|
||||
REGS_REGISTER_AT(CR1, 0x0);
|
||||
REGS_REGISTER_AT(DIER, 0xC);
|
||||
REGS_REGISTER_AT(SR, 0x10);
|
||||
REGS_REGISTER_AT(EGR, 0x14);
|
||||
REGS_REGISTER_AT(CCMR, 0x18);
|
||||
REGS_REGISTER_AT(CCER, 0x20);
|
||||
REGS_REGISTER_AT(CNT, 0x24);
|
||||
REGS_REGISTER_AT(PSC, 0x28);
|
||||
REGS_REGISTER_AT(ARR, 0x2C);
|
||||
REGS_REGISTER_AT(CCR1, 0x34);
|
||||
@@ -79,14 +129,35 @@ public:
|
||||
REGS_REGISTER_AT(CCR3, 0x3C);
|
||||
REGS_REGISTER_AT(CCR4, 0x40);
|
||||
REGS_REGISTER_AT(BDTR, 0x44);
|
||||
REGS_REGISTER_AT(OR, 0x50);
|
||||
private:
|
||||
constexpr uint32_t Base() const {
|
||||
return (m_index == 1 ? 0x40010000 : 0x40000000 + 0x400*(m_index-2));
|
||||
};
|
||||
return (m_index == 1 ? 0x40010000 :
|
||||
(m_index <= 7 ? 0x40000000 + 0x400*(m_index-2) :
|
||||
(m_index == 8 ? 0x40010400 :
|
||||
(m_index <= 11 ? 0x40014000 + 0x400*(m_index-9) :
|
||||
0x40001800 + 0x400*(m_index-12)
|
||||
)
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
int m_index;
|
||||
};
|
||||
|
||||
constexpr TIM TIM1(1);
|
||||
constexpr TIM TIM3(3);
|
||||
constexpr TIM<Register16> TIM1(1);
|
||||
constexpr TIM<Register32> TIM2(2);
|
||||
constexpr TIM<Register16> TIM3(3);
|
||||
constexpr TIM<Register16> TIM4(4);
|
||||
constexpr TIM<Register32> TIM5(5);
|
||||
constexpr TIM<Register16> TIM6(6);
|
||||
constexpr TIM<Register16> TIM7(7);
|
||||
constexpr TIM<Register16> TIM8(8);
|
||||
constexpr TIM<Register16> TIM9(9);
|
||||
constexpr TIM<Register16> TIM10(10);
|
||||
constexpr TIM<Register16> TIM11(11);
|
||||
constexpr TIM<Register16> TIM12(12);
|
||||
constexpr TIM<Register16> TIM13(13);
|
||||
constexpr TIM<Register16> TIM14(14);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -31,7 +31,7 @@ void onUSBPlugging() {
|
||||
SYSCFG.EXTICR3()->setEXTI(USB::Device::VbusPin.pin(), USB::Device::VbusPin.group());
|
||||
|
||||
EXTI.EMR()->set(USB::Device::VbusPin.pin(), true);
|
||||
#if LED_WHILE_CHARGING
|
||||
#if EPSILON_LED_WHILE_CHARGING
|
||||
EXTI.FTSR()->set(USB::Device::VbusPin.pin(), true);
|
||||
#endif
|
||||
EXTI.RTSR()->set(USB::Device::VbusPin.pin(), true);
|
||||
|
||||
@@ -2,3 +2,16 @@
|
||||
|
||||
void Ion::LED::setColor(KDColor c) {
|
||||
}
|
||||
|
||||
void Ion::LED::setBlinking(float blinkPeriod, bool red, bool green, bool blue) {
|
||||
}
|
||||
|
||||
void Ion::LED::setCharging(bool isPlugged, bool isCharging) {
|
||||
}
|
||||
|
||||
bool Ion::LED::getLockState() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Ion::LED::setLockState(bool state) {
|
||||
}
|
||||
|
||||
@@ -3,4 +3,15 @@
|
||||
void Ion::LED::setColor(KDColor c) {
|
||||
}
|
||||
|
||||
void Ion::LED::setBlinking(float blinkPeriod, bool red, bool green, bool blue) {
|
||||
}
|
||||
|
||||
void Ion::LED::setCharging(bool isPlugged, bool isCharging) {
|
||||
}
|
||||
|
||||
bool Ion::LED::getLockState() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void Ion::LED::setLockState(bool state) {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user