Blame view

epsilon-master/ion/src/device/power.cpp 2.1 KB
6663b6c9   adorian   projet complet av...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
  #include <ion.h>
  #include "battery.h"
  #include "device.h"
  #include "display.h"
  #include "keyboard.h"
  #include "led.h"
  #include "usb.h"
  #include "wakeup.h"
  #include "regs/regs.h"
  
  void Ion::Power::suspend(bool checkIfPowerKeyReleased) {
    bool isLEDActive = Ion::LED::getColor() != KDColorBlack;
    if (checkIfPowerKeyReleased) {
      /* Wait until power is released to avoid restarting just after suspending */
      bool isPowerDown = true;
      while (isPowerDown) {
        Keyboard::State scan = Keyboard::scan();
        isPowerDown = scan.keyDown(Keyboard::Key::B2);
      }
    }
    Device::shutdownPeripherals(isLEDActive);
  
    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(!isLEDActive);
  
    while (1) {
  #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);
      //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(isLEDActive);
  
     /* To enter sleep, we need to issue a WFE instruction, which waits for the
     * event flag to be set and then clears it. However, the event flag might
     * already be on. So the safest way to make sure we actually wait for a new
     * event is to force the event flag to on (SEV instruction), use a first WFE
     * to clear it, and then a second WFE to wait for a _new_ event. */
      asm("sev");
      asm("wfe");
      asm("nop");
      asm("wfe");
  
      Device::initClocks();
  
      Keyboard::Device::init();
      Keyboard::State scan = Keyboard::scan();
      Keyboard::Device::shutdown();
  
      Ion::Keyboard::State OnlyPowerKeyDown = Keyboard::State(Keyboard::Key::B2);
      if (scan == OnlyPowerKeyDown || USB::isPlugged()) {
        // Wake up
        break;
      }
    }
    Device::initClocks();
  
    Device::initPeripherals();
  }