From 3177b26f306d08eb7e308f4c085369fa35c7a304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89milie=20Feral?= Date: Mon, 27 Aug 2018 09:52:17 +0200 Subject: [PATCH] [ion] Clean LED API --- apps/exam_pop_up_controller.cpp | 2 +- ion/include/ion/led.h | 2 +- ion/src/device/device.cpp | 24 +++------ ion/src/device/device.h | 2 - ion/src/device/led.cpp | 95 +++++++++++---------------------- ion/src/device/led.h | 17 +++--- ion/src/shared/dummy/led.cpp | 2 +- 7 files changed, 46 insertions(+), 98 deletions(-) diff --git a/apps/exam_pop_up_controller.cpp b/apps/exam_pop_up_controller.cpp index 7e8736a74..c0c935bf9 100644 --- a/apps/exam_pop_up_controller.cpp +++ b/apps/exam_pop_up_controller.cpp @@ -59,7 +59,7 @@ ExamPopUpController::ContentView::ContentView(Responder * parentResponder) : if (controller->isActivatingExamMode()) { container->reset(); Ion::LED::setColor(KDColorRed); - Ion::LED::setBlinking(1.0f, 0.1f); + Ion::LED::setBlinking(1000, 0.1f); } else { Ion::LED::setColor(KDColorBlack); } diff --git a/ion/include/ion/led.h b/ion/include/ion/led.h index dfb69c420..2d4475eab 100644 --- a/ion/include/ion/led.h +++ b/ion/include/ion/led.h @@ -8,7 +8,7 @@ namespace LED { KDColor getColor(); void setColor(KDColor c); -void setBlinking(float period, float dutyCycle); +void setBlinking(uint16_t periodInMilliseconds, float dutyCycle); } } diff --git a/ion/src/device/device.cpp b/ion/src/device/device.cpp index d23dd35d9..53de95726 100644 --- a/ion/src/device/device.cpp +++ b/ion/src/device/device.cpp @@ -285,29 +285,17 @@ void shutdownClocks(bool keepLEDAwake) { // APB2 bus RCC.APB2ENR()->set(0x00008000); // Reset value + // APB1 + class RCC::APB1ENR apb1enr(0x00000400); // Reset value + // AHB1 bus + class RCC::AHB1ENR ahb1enr(0); // Reset value if (keepLEDAwake) { - /* TODO: enter sleep mode even if the LED is used and enable LED in low - * power mode. */ - // Keep the LED going: peripheral clock enable in low power mode register - /*RCC.APB1LPENR()->setTIM3LPEN(true); - RCC.AHB1LPENR()->setGPIOBLPEN(true); - RCC.AHB1LPENR()->setGPIOCLPEN(true);*/ - - // APB1 - class RCC::APB1ENR apb1enr(0x00000400); apb1enr.setTIM3EN(true); - RCC.APB1ENR()->set(apb1enr); - // AHB1 bus - class RCC::AHB1ENR ahb1enr(0); // Reset value ahb1enr.setGPIOBEN(true); ahb1enr.setGPIOCEN(true); - RCC.AHB1ENR()->set(ahb1enr); - } else { - // APB1 - RCC.APB1ENR()->set(0x00000400); - // AHB1 bus - RCC.AHB1ENR()->set(0); // Reset value } + RCC.APB1ENR()->set(apb1enr); + RCC.AHB1ENR()->set(ahb1enr); RCC.AHB3ENR()->setFSMCEN(false); } diff --git a/ion/src/device/device.h b/ion/src/device/device.h index a95bf85e7..c3332fd77 100644 --- a/ion/src/device/device.h +++ b/ion/src/device/device.h @@ -4,8 +4,6 @@ namespace Ion { namespace Device { -constexpr int SYSBUS_FREQ = 96*1000*1000; - void init(); void shutdown(); diff --git a/ion/src/device/led.cpp b/ion/src/device/led.cpp index 566eb67df..028e8e846 100644 --- a/ion/src/device/led.cpp +++ b/ion/src/device/led.cpp @@ -15,41 +15,28 @@ KDColor Ion::LED::getColor() { void Ion::LED::setColor(KDColor c) { sLedColor = c; - /* Active RGB colors */ - 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); + /* Active all RGB colors */ + TIM3.CCMR()->setOC2M(TIM::CCMR::OCM::PWM1); + TIM3.CCMR()->setOC4M(TIM::CCMR::OCM::PWM1); + TIM3.CCMR()->setOC3M(TIM::CCMR::OCM::PWM1); /* Set the PWM duty cycles to display the right color */ constexpr float maxColorValue = (float)((1 << 8) -1); Device::setPeriodAndDutyCycles(Device::Mode::PWM, c.red()/maxColorValue, c.green()/maxColorValue, c.blue()/maxColorValue); } -void Ion::LED::setBlinking(float period, float dutyCycle) { +void Ion::LED::setBlinking(uint16_t period, float dutyCycle) { /* We want to use the PWM at a slow rate to display a seeable blink. - * Consequently, we do not use PWM to display the right color anymore. - * Instead we 'project the color on 3 bits' : RED LED is active or not etc. */ - Ion::LED::Device::setColorStatus(Ion::LED::Device::Color::RED, sLedColor.red() > 0); - Ion::LED::Device::setColorStatus(Ion::LED::Device::Color::GREEN, sLedColor.green() > 0); - Ion::LED::Device::setColorStatus(Ion::LED::Device::Color::BLUE, sLedColor.blue() > 0); + * Consequently, we do not use PWM to display the right color anymore but to + * blink. We cannot use the PWM to display the exact color so we 'project the + * color on 3 bits' : all colors have 2 states - active or not. */ + TIM3.CCMR()->setOC2M(sLedColor.red() > 0 ? TIM::CCMR::OCM::PWM1 : TIM::CCMR::OCM::ForceInactive); + TIM3.CCMR()->setOC4M(sLedColor.green() > 0 ? TIM::CCMR::OCM::PWM1 : TIM::CCMR::OCM::ForceInactive); + TIM3.CCMR()->setOC3M(sLedColor.blue() > 0 ? TIM::CCMR::OCM::PWM1 : TIM::CCMR::OCM::ForceInactive); - Device::setPeriodAndDutyCycles(Device::Mode::BLINK, dutyCycle, dutyCycle, dutyCycle, period); + Device::setPeriodAndDutyCycles(Device::Mode::Blink, dutyCycle, dutyCycle, dutyCycle, period); } -/*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); - } - } -}*/ - // Private Ion::Device::LED methods namespace Ion { @@ -103,30 +90,36 @@ void initTimer() { } void shutdownTimer() { - setColorStatus(Ion::LED::Device::Color::RED, false); - setColorStatus(Ion::LED::Device::Color::GREEN, false); - setColorStatus(Ion::LED::Device::Color::BLUE, false); + TIM3.CCMR()->setOC2M(TIM::CCMR::OCM::ForceInactive); + TIM3.CCMR()->setOC4M(TIM::CCMR::OCM::ForceInactive); + TIM3.CCMR()->setOC3M(TIM::CCMR::OCM::ForceInactive); } /* 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. */ -void setPeriodAndDutyCycles(Mode mode, float dutyCycleRed, float dutyCycleGreen, float dutyCycleBlue, float period) { - constexpr int TIM3_FREQ = 4*1000; +void setPeriodAndDutyCycles(Mode mode, float dutyCycleRed, float dutyCycleGreen, float dutyCycleBlue, uint16_t period) { switch (mode) { case Mode::PWM: - /* Let's set the prescaler to 1. Increasing the prescaler would slow down the - * modulation, which can be useful when debugging. */ + /* Let's set the prescaler to 1. Increasing the prescaler would slow down + * the modulation, which can be useful when debugging or when we want an + * actual blinking. */ TIM3.PSC()->set(1); TIM3.ARR()->set(PWMPeriod); period = PWMPeriod; break; - case 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(period * TIM3_FREQ); - period *= TIM3_FREQ; // as we pre-scaled, we update the period + case Mode::Blink: + int systemClockFreq = 96; + /* We still want to do PWM, but at a rate slow enough to blink. Ideally, + * we want to pre-scale the period to be able to set it in milliseconds; + * however, as the prescaler is cap by 2^16-1, we divide it by a factor + * and correct the period consequently. */ + int factor = 2; + // TODO: explain the 2 ? + TIM3.PSC()->set(systemClockFreq*1000/factor); + period *= factor; + TIM3.ARR()->set(period); break; } @@ -135,34 +128,6 @@ void setPeriodAndDutyCycles(Mode mode, float dutyCycleRed, float dutyCycleGreen, TIM3.CCR4()->set(dutyCycleGreen*period); } -void setColorStatus(Color color, bool enable) { - switch (color) { - case Ion::LED::Device::Color::RED: - TIM3.CCMR()->setOC2M(enable ? TIM::CCMR::OCM::PWM1 : TIM::CCMR::OCM::ForceInactive); - break; - case Ion::LED::Device::Color::GREEN: - TIM3.CCMR()->setOC4M(enable ? TIM::CCMR::OCM::PWM1 : TIM::CCMR::OCM::ForceInactive); - break; - case Ion::LED::Device::Color::BLUE: - TIM3.CCMR()->setOC3M(enable ? TIM::CCMR::OCM::PWM1 : TIM::CCMR::OCM::ForceInactive); - break; - } -} - -/*void enforceState(bool red, bool green, bool blue) { - bool states[3] = {red, green, blue}; - for (int i=0; i<3; i++) { - GPIOPin p = RGBPins[i]; - if (states[i]) { - p.group().MODER()->setMode(p.pin(), GPIO::MODER::Mode::Output); - p.group().ODR()->set(p.pin(), true); - } else { - p.group().MODER()->setMode(p.pin(), GPIO::MODER::Mode::Analog); - p.group().PUPDR()->setPull(p.pin(), GPIO::PUPDR::Pull::None); - } - } -}*/ - } } } diff --git a/ion/src/device/led.h b/ion/src/device/led.h index 426ce9607..fe46994d9 100644 --- a/ion/src/device/led.h +++ b/ion/src/device/led.h @@ -14,23 +14,20 @@ namespace Device { * PC7 | LED red | Alternate Function 2 | TIM3_CH2 */ -enum Mode { +enum class Mode { PWM, - BLINK + Blink }; -enum Color { - RED, - GREEN, - BLUE +enum class Color { + Red, + Green, + Blue }; void init(); void shutdown(); -void setPeriodAndDutyCycles(Mode mode, float dutyCycleRed, float dutyCycleGreen, float dutyCycleBlue, float period = 0.0f); -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 setPeriodAndDutyCycles(Mode mode, float dutyCycleRed, float dutyCycleGreen, float dutyCycleBlue, uint16_t period = 0); void initGPIO(); void shutdownGPIO(); diff --git a/ion/src/shared/dummy/led.cpp b/ion/src/shared/dummy/led.cpp index d317c207d..097aff116 100644 --- a/ion/src/shared/dummy/led.cpp +++ b/ion/src/shared/dummy/led.cpp @@ -9,7 +9,7 @@ KDColor getColor() { void setColor(KDColor c) {} -void setBlinking(float period, float dutyCycle) {} +void setBlinking(uint16_t period, float dutyCycle) {} } }