Merge branch 'rtc_part1' of https://github.com/boricj/epsilon into exam_mode_boricj

This commit is contained in:
Émilie Feral
2018-08-22 17:11:19 +02:00
21 changed files with 514 additions and 81 deletions

View File

@@ -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\

View File

@@ -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];
}

View File

@@ -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;

View File

@@ -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();

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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)

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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
*/
}
}

View File

@@ -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) {

View File

@@ -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[] = {

View File

@@ -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();

View File

@@ -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;

View File

@@ -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 {

View File

@@ -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
View 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

View File

@@ -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

View File

@@ -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);

View File

@@ -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) {
}

View File

@@ -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) {
}