void hw_enter_lowpower_mode(uint8_t mode)
{
    switch(mode)
    {
	case 0:
	{
	    EMU_EnterEM1();
	    break;	    
	}
	case 1:
	{
	    EMU_EnterEM2(true);
	    break;
	}
	case 2:
	{
	    EMU_EnterEM3(true);
	    break;
	}
	case 4:
	{
	    EMU_EnterEM4();
	    break;
	}
	default:
	{
	    assert(0);
	}
    }
}
Example #2
0
/**************************************************************************//**
 * @brief  Check if PB0 is pushed and EM4 entry is due.
 *****************************************************************************/
static void CheckEM4Entry( void )
{
  if ( enterEM4 )
  {
    enterEM4 = false;

    printf( "\f\n\n Ready to enter"
            "\n energy mode"
            "\n EM4"
            "\n\n Push PB0 to"
            "\n enter EM4"
            "\n\n Wakeup from"
            "\n EM4 by pushing"
            "\n PB1 or the"
            "\n reset button" );

    while ( enterEM4 == false );
    enterEM4 = false;

    /* Disable the RTC and PCNT. */
    printf( "\f" );
    displayEnabled = false;
    NVIC_DisableIRQ( RTC_IRQn );
    NVIC_DisableIRQ( PCNT0_IRQn );

    /* Power down the display. */
    displayDevice.pDisplayPowerOn( &displayDevice, false );

    /* Enable wakeup from EM4 on PB1 GPIO pin. */
    GPIO_EM4EnablePinWakeup( GPIO_EM4WUEN_EM4WUEN_C9, 0 );
    EMU_EnterEM4();
  }
}
Example #3
0
enum lpm_mode lpm_arch_set(enum lpm_mode target)
{
    switch (target) {
        case LPM_ON:
            /* nothing to do */
            break;
        case LPM_IDLE:
            /* wait for next event or interrupt */
            EMU_EnterEM1();
            break;
        case LPM_SLEEP:
            /* after exiting EM2, clocks are restored */
            EMU_EnterEM2(true);
            break;
        case LPM_POWERDOWN:
            /* after exiting EM3, clocks are restored */
            EMU_EnterEM3(true);
            break;
        case LPM_OFF:
            /* only a reset can wake up from EM4 */
            EMU_EnterEM4();
            break;

        /* do nothing here */
        case LPM_UNKNOWN:
        default:
            break;
    }

    /* no matter which case was selected, instructions executed in EM0 only */
    return LPM_ON;
}
Example #4
0
/**************************************************************************//**
 * @brief Sleeps in EM4 until reset
 *****************************************************************************/
void EM4Sleep(void)
{
  /* Tell AEM we're in EM4 */
  BSP_EnergyModeSet(4);
  EMU_EnterEM4();
  /* we will never wake up again here - reset required */
}
ERROR_CODE Statemachine::startApplication( STATUS_BLOCK *statusBlock )
{
	callingStatusBlock = currentStatusBlock;
	currentStatusBlock = statusBlock;

	if(!setupDone)
		return FSM_NotInitialized;


	// Run the FSM until the execution is stopped by the Application-Code.
	// The State-Function is called within the WHILE-STATEMENT !!!!
	while( ( *(stateDefinition)[statusBlock->nextState] )() )
	{
		// Is the State-Function, which is selected for execution in the next step a valid one?
		if( currentStatusBlock->nextState < maxNumberOfStates )
		{
			// Does the MCU have to enter a sleep-mode?
			if( currentStatusBlock->wantToSleep )
			{
				// Which sleep-mode has to be entered?
				switch( currentStatusBlock->sleepMode )
				{
				case 0:
					break;
				case 1:
					EMU_EnterEM1();
					break;
				case 2:
					EMU_EnterEM2( currentStatusBlock->restoreClockSetting );
					break;
				case 3:
					EMU_EnterEM3( currentStatusBlock->restoreClockSetting );
					break;
				case 4:
					EMU_EnterEM4();
				default:
					return EM_invalid; // Invalid sleep-mode!!!
				}
			}
		}

		else
			return StateID_Invalid; // Invalid State-Function number!!!
	}

	currentStatusBlock = callingStatusBlock;

	return FSM_finalized; // FSM-execution successfully finalized!!!
}
/**************************************************************************//**
 * @brief  Main function
 *****************************************************************************/
int main(void)
{
  /* Initialize chip */
  CHIP_Init();
  
  setupSWO();

  BSP_LedsInit();

  /* Enable clock for GPIO module */
  CMU_ClockEnable(cmuClock_GPIO, true);

  /* Configure interrupt for Push Button 0 */
  GPIO_PinModeSet(PB0_PORT, PB0_PIN, gpioModeInput, 1);
#if defined(_EFM32_GIANT_FAMILY)
  NVIC_EnableIRQ(GPIO_ODD_IRQn);
#else
  NVIC_EnableIRQ(GPIO_EVEN_IRQn);
#endif
  GPIO_IntConfig(PB0_PORT, PB0_PIN, false, true, true);

  /* By turning on retention in EM4, the state of the GPIO pins
   * can be retained in all energy modes */
  GPIO->CTRL = GPIO_CTRL_EM4RET;

  /* Uncomment to drive LED in all energy modes */
  /* BSP_LedSet(0);*/

  while (1)
  {
    switch (STATE)
    {
    case EM0:
      break;
    case EM1:
      EMU_EnterEM1();
      break;
    case EM2:
      EMU_EnterEM2(true);
      break;
    case EM3:
      EMU_EnterEM3(true);
    case EM4:
      EMU_EnterEM4();
      break;
    }
  }
}
Example #7
0
/***************************************************************************//**
 * @brief
 *   Call the callbacks and enter the requested energy mode.
 *
 * @details
 *   This function is not part of the API, therefore it shall not be called by
 *   the user directly as it doesn not have any checks if the system is ready
 *   for sleep!
 *
 * @note
 *   The EM4 wakeup callback is not being called from this function because
 *   waking up from EM4 causes a reset.
 *   If SLEEP_EM4_WAKEUP_CALLBACK_ENABLED is set to true, SLEEP_Init() function
 *   checks for the cause of the reset and calls the wakeup callback if the
 *   reset was a wakeup from EM4.
 ******************************************************************************/
static void SLEEP_EnterEMx(SLEEP_EnergyMode_t eMode)
{
  EFM_ASSERT((eMode > sleepEM0) && (eMode <= sleepEM4));

  /* Call sleepCallback() before going to sleep. */
  if (NULL != sleepCallback)
  {
    /* Call the callback before going to sleep. */
    sleepCallback(eMode);
  }

  /* Enter the requested energy mode. */
  switch (eMode)
  {
  case sleepEM1:
  {
    EMU_EnterEM1();
  } break;

  case sleepEM2:
  {
    EMU_EnterEM2(true);
  } break;

  case sleepEM3:
  {
    EMU_EnterEM3(true);
  } break;

  case sleepEM4:
  {
    EMU_EnterEM4();
  } break;

  default:
  {
    /* Don't do anything, stay in EM0. */
  } break;
  }

  /* Call the callback after waking up from sleep. */
  if (NULL != wakeUpCallback)
  {
    wakeUpCallback(eMode);
  }
}
Example #8
0
/**************************************************************************//**
 * @brief  Main function
 *****************************************************************************/
int main(void)
{
  const int msDelay = 100;

  /* Chip errata */
  CHIP_Init();

  /* If first word of user data page is non-zero, enable eA Profiler trace */
  BSP_TraceProfilerSetup();

    /* Power down special RAM blocks to reduce current consumption with some nA. */
  CMU_ClockEnable(cmuClock_CORELE, true);
  LESENSE->POWERDOWN = LESENSE_POWERDOWN_RAM;
  CMU_ClockEnable(cmuClock_CORELE, false);

  /* Configure push button interrupts */
  gpioSetup();

  /* Setup SysTick Timer for 1 msec interrupts  */
  if (SysTick_Config(SystemCoreClockGet() / 1000)) while (1) ;

  /* Initialize LCD controller */
  SegmentLCD_Init(false);

  /* Run countdown for user to select energy mode */
  msCountDown = 4000; /* milliseconds */
  while (msCountDown > 0)
  {
    switch (eMode)
    {
    case 0:
      SegmentLCD_Write("EM0 32M");
      break;
    case 1:
      SegmentLCD_Write("EM1 32M");
      break;
    case 2:
      SegmentLCD_Write("EM2 32K");
      break;
    case 3:
      SegmentLCD_Write("EM3");
      break;
    case 4:
      SegmentLCD_Write("EM4");
      break;
    case 5:
      SegmentLCD_Write("EM2+RTC");
      break;
    case 6:
      SegmentLCD_Write("RTC+LCD");
      break;
    case 7:
      SegmentLCD_Write("EM3+RTC");
      break;
    case 8:
      SegmentLCD_Write("USER");
      break;
    }
    SegmentLCD_Number(msCountDown);
    Delay(msDelay);
    msCountDown -= msDelay;
  }
  /* Disable components, reenable when needed */
  SegmentLCD_Disable();
  RTC_Enable(false);

  /* GPIO->ROUTE = 0x00000000; */

  /* Go to energy mode and wait for reset */
  switch (eMode)
  {
  case 0:
    /* Disable pin input */
    GPIO_PinModeSet(gpioPortB, 10, gpioModeDisabled, 1);

    /* Disable systick timer */
    SysTick->CTRL = 0;

    /* 32Mhz primes demo - running off HFXO */
    CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO);
    /* Disable HFRCO, LFRCO and all unwanted clocks */
    CMU->OSCENCMD     = CMU_OSCENCMD_HFRCODIS;
    CMU->OSCENCMD     = CMU_OSCENCMD_LFRCODIS;
    CMU->HFPERCLKEN0  = 0x00000000;
    CMU->HFCORECLKEN0 = 0x00000000;
    CMU->LFACLKEN0    = 0x00000000;
    CMU->LFBCLKEN0    = 0x00000000;
    CMU->LFCLKSEL     = 0x00000000;
    /* Supress Conditional Branch Target Prefetch */
    MSC->READCTRL = MSC_READCTRL_MODE_WS1SCBTP;
    {
      #define PRIM_NUMS    64
      uint32_t i, d, n;
      uint32_t primes[PRIM_NUMS];

      /* Find prime numbers forever */
      while (1)
      {
        primes[0] = 1;
        for (i = 1; i < PRIM_NUMS;)
        {
          for (n = primes[i - 1] + 1;; n++)
          {
            for (d = 2; d <= n; d++)
            {
              if (n == d)
              {
                primes[i] = n;
                goto nexti;
              }
              if (n % d == 0) break;
            }
          }
 nexti:
          i++;
        }
      }
    }
  case 1:
    /* Disable pin input */
    GPIO_PinModeSet(gpioPortB, 10, gpioModeDisabled, 1);

    /* Disable systick timer */
    SysTick->CTRL = 0;

    CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO);
    /* Disable HFRCO, LFRCO and all unwanted clocks */
    CMU->OSCENCMD     = CMU_OSCENCMD_HFRCODIS;
    CMU->OSCENCMD     = CMU_OSCENCMD_LFRCODIS;
    CMU->HFPERCLKEN0  = 0x00000000;
    CMU->HFCORECLKEN0 = 0x00000000;
    CMU->LFACLKEN0    = 0x00000000;
    CMU->LFBCLKEN0    = 0x00000000;
    CMU->LFCLKSEL     = 0x00000000;
    EMU_EnterEM1();
    break;
  case 2:
    /* Enable LFRCO */
    CMU->OSCENCMD = CMU_OSCENCMD_LFRCOEN;
    /* Disable everything else */
    CMU->OSCENCMD     = CMU_OSCENCMD_LFXODIS;
    CMU->HFPERCLKEN0  = 0x00000000;
    CMU->HFCORECLKEN0 = 0x00000000;
    CMU->LFACLKEN0    = 0x00000000;
    CMU->LFBCLKEN0    = 0x00000000;
    /* Disable LFB clock select */
    CMU->LFCLKSEL     = 0x00000000;
    EMU_EnterEM2(false);
    break;
  case 3:
    /* Disable all clocks */
    CMU->OSCENCMD     = CMU_OSCENCMD_LFXODIS;
    CMU->OSCENCMD     = CMU_OSCENCMD_LFRCODIS;
    CMU->HFPERCLKEN0  = 0x00000000;
    CMU->HFCORECLKEN0 = 0x00000000;
    CMU->LFACLKEN0    = 0x00000000;
    CMU->LFBCLKEN0    = 0x00000000;
    CMU->LFCLKSEL     = 0x00000000;
    EMU_EnterEM3(false);
    break;
  case 4:
    /* Go straight down to EM4 */
    EMU_EnterEM4();
    break;
  case 5:
    /* EM2 + RTC - only briefly wake up to reconfigure every 2 seconds */
    /* Disable LFB clock select */
    CMU->LFCLKSEL     &= ~(_CMU_LFCLKSEL_LFB_MASK);
    RTCDRV_Setup(cmuSelect_LFRCO, cmuClkDiv_32);
    while (1)
    {
      RTCDRV_Trigger(2000, NULL);
      EMU_EnterEM2(false);
    }
  case 6:
    /* EM2 + RTC + LCD (if battery slips below 3V vboost should be enabled) */
    /* Disable LFB clock select */
    CMU->LFCLKSEL     &= ~(_CMU_LFCLKSEL_LFB_MASK);
    SegmentLCD_Init(false);
    RTCDRV_Setup(cmuSelect_LFRCO, cmuClkDiv_32);
    while (1)
    {
      SegmentLCD_Write("Silicon");
      /* Sleep in EM2 */
      RTCDRV_Trigger(2000, NULL);
      EMU_EnterEM2(false);

      SegmentLCD_Write(" Labs");
      /* Sleep in EM2 */
      RTCDRV_Trigger(2000, NULL);
      EMU_EnterEM2(false);
    }
  case 7:
    /* EM3 + RTC - only briefly wake up to reconfigure every ~5 seconds */
    while (1)
    {
      /* Disable LFB clock select */
      CMU->LFCLKSEL     &= ~(_CMU_LFCLKSEL_LFB_MASK);
      /* This RTCDRV_Setup will configure LFCLK A as ULFRCO */
      RTCDRV_Setup(cmuSelect_ULFRCO, cmuClkDiv_1);
      RTCDRV_Trigger(5000, NULL);
      /* Sleep in EM3, wake up on RTC trigger */
      EMU_EnterEM3(false);
      /* SegmentLCD_Init will configure LFCLK A as LFRCO */
      SegmentLCD_Init(false);
      SegmentLCD_Write("ULFRCO");
      Delay(1000);
      SegmentLCD_Disable();
    }
  case 8:
  default:
    /* User defined */
    break;
  }

  return 0;
}
Example #9
0
/**************************************************************************//**
 * @brief Energy Mode 4 demonstration
 *****************************************************************************/
void Demo_EM4(void)
{
  EMU_EnterEM4();
}
Example #10
0
void main ()
{
  uint32_t lfa_Hz;
  uint16_t reset_cause;
  int sleep_mode = 0;
  uint32_t burtc_ctrl;

  CHIP_Init();
  reset_cause = RMU->RSTCAUSE;
  RMU_ResetCauseClear();
#if ! defined(_EFM32_ZERO_FAMILY)
  BSPACM_CORE_BITBAND_PERIPH(RMU->CTRL, _RMU_CTRL_BURSTEN_SHIFT) = 0;
#endif
  SystemCoreClockUpdate();
  vBSPACMledConfigure();

  setvbuf(stdout, NULL, _IONBF, 0);

  BSPACM_CORE_ENABLE_INTERRUPT();

  printf("\n" __DATE__ " " __TIME__ "\n");
  printf("System clock %lu Hz\n", SystemCoreClock);
  {
    int i = sizeof(xResetCause)/sizeof(*xResetCause);

    printf("Reset cause [%04x]:", reset_cause);
    while (0 <= --i) {
      const sResetCause * const rcp = xResetCause + i;
      if (rcp->value == (reset_cause & rcp->mask)) {
        printf(" %s", rcp->name);
      }
    }
    printf("\nRMU CTRL %lx\n", RMU->CTRL);
  }

  /* Enable low-energy support. */
  CMU_ClockEnable(cmuClock_CORELE, true);
  BURTC_Enable(true);

  if (MAGIC != retained_state->magic) {
    memset(retained_state, 0, sizeof(*retained_state));
    retained_state->magic = MAGIC;
    printf("Resetting retained state\n");
  }
  ++retained_state->boots;
  printf("Boot count %lu\n", retained_state->boots);

  printf("BURTC clock source: ");
#if (WITH_ULFRCO - 0)
  /* Use ULFRCO, which enables EM4 wakeup but is pretty inaccurate. */
  printf("ULFRCO\n");
  /* NB: DIV2 means 1 kHz instead of 2 kHz */
  burtc_ctrl = BURTC_CTRL_CLKSEL_ULFRCO | BURTC_CTRL_PRESC_DIV2;
  CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_ULFRCO);
  lfa_Hz = CMU_ClockFreqGet(cmuClock_LFA);
  {
    EMU_EM4Init_TypeDef cfg = {
      .lockConfig = 1,
      .osc = EMU_EM4CONF_OSC_ULFRCO,
      .buRtcWakeup = 1,
      .vreg = 1,
    };
    EMU_EM4Init(&cfg);
  }
#elif (WITH_LFRCO - 0)
  printf("LFRCO/32\n");
  CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFRCO);
  burtc_ctrl = BURTC_CTRL_CLKSEL_LFRCO | BURTC_CTRL_PRESC_DIV32;
  lfa_Hz = CMU_ClockFreqGet(cmuClock_LFA) / 32;
#else
  printf("LFXO/32\n");
  CMU_ClockSelectSet(cmuClock_LFA, cmuSelect_LFXO);
  burtc_ctrl = BURTC_CTRL_CLKSEL_LFXO | BURTC_CTRL_PRESC_DIV32;
  lfa_Hz = CMU_ClockFreqGet(cmuClock_LFA) / 32;
#endif /* LFA source */
  printf("LFA clock at %lu Hz ; wake every %u seconds\n", lfa_Hz, WAKE_INTERVAL_S);

  /* Initialize BURTC. */
  if (! (RMU_RSTCAUSE_EM4WURST & reset_cause)) {
    printf("Initializing BURTC\n");
    BURTC->FREEZE = BURTC_FREEZE_REGFREEZE;
    BURTC->LPMODE = BURTC_LPMODE_LPMODE_DISABLE;
    BURTC->CTRL = burtc_ctrl /* CLKSEL + PRESC */
      | BURTC_CTRL_RSTEN
      | BURTC_CTRL_MODE_EM4EN
      ;
    BURTC->COMP0 = WAKE_INTERVAL_S * lfa_Hz;
    BURTC->IEN = BURTC_IF_COMP0;
    BURTC->CTRL &= ~BURTC_CTRL_RSTEN;
    BURTC->FREEZE = 0;
  } else {
    while (BURTC_SYNCBUSY_COMP0 & BURTC->SYNCBUSY) {
    }
    BURTC->COMP0 += WAKE_INTERVAL_S * lfa_Hz;
  }
  BURTC->IFC = BURTC_IFC_COMP0;
  NVIC_EnableIRQ(BURTC_IRQn);

  printf("BURTC CTRL %lx IEN %lx\n", BURTC->CTRL, BURTC->IEN);
  (void)iBSPACMperiphUARTflush(hBSPACMdefaultUART, eBSPACMperiphUARTfifoState_TX);
  while (1) {
    static const sBSPACMperiphUARTconfiguration cfg = { .speed_baud = 0 };
    printf("Sleeping in mode %u, %lu to %lu rtc_if %x or %lx\n", sleep_mode, BURTC->CNT, BURTC->COMP0, burtc_if, BURTC->IF);
    BSPACM_CORE_DISABLE_INTERRUPT();
    do {
      (void)iBSPACMperiphUARTflush(hBSPACMdefaultUART, eBSPACMperiphUARTfifoState_TX);
      hBSPACMperiphUARTconfigure(hBSPACMdefaultUART, 0);
      switch (sleep_mode) {
        case 0:
          while (! (BURTC_IF_COMP0 & BURTC->IF)) {
          }
          ++sleep_mode;
          break;
        case 1:
          EMU_EnterEM1();
          ++sleep_mode;
          break;
        case 2:
          EMU_EnterEM2(true);

          SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
          if (cmuSelect_ULFRCO == CMU_ClockSelectGet(cmuClock_LFA)) {
            ++sleep_mode;
          } else {
            sleep_mode = 0;
          }
          break;
        case 3:
          EMU_EnterEM3(true);
          SCB->SCR &= ~SCB_SCR_SLEEPDEEP_Msk;
          if (cmuSelect_ULFRCO == CMU_ClockSelectGet(cmuClock_LFA)) {
            ++sleep_mode;
          } else {
            sleep_mode = 0;
          }
          break;
        case 4:
          EMU_EnterEM4();
          sleep_mode = 0;
          break;
      }
    } while (0);
    BSPACM_CORE_ENABLE_INTERRUPT();
    hBSPACMperiphUARTconfigure(hBSPACMdefaultUART, &cfg);
    while (BURTC_SYNCBUSY_COMP0 & BURTC->SYNCBUSY) {
    }
    BURTC->COMP0 += WAKE_INTERVAL_S * lfa_Hz;
    /* Giant Gecko
     *  Source    EM0    EM1    EM2     EM3    EM4
     * ULFRCO    2.5m   1.1m   622n    622n   450n
     */
  }

}
Example #11
0
/**************************************************************************//**
 * @brief Sleeps in EM4 until reset
 *****************************************************************************/
void EM4Sleep(void)
{
  EMU_EnterEM4();
  /* we will never wake up again here - reset required */
}
Example #12
0
/**************************************************************************//**
 * @brief  Main function
 *****************************************************************************/
int main(void)
{
  int msCountDown;
  const int msDelay = 100;
  char displayString[8];
  LCD_AnimInit_TypeDef anim = {
    true,
    0x00,
    lcdAnimShiftNone,
    0x03,
    lcdAnimShiftLeft,
    lcdAnimLogicOr
  };
  LCD_FrameCountInit_TypeDef fc = {
    true,
    2, /* Update each 2nd frame */
    lcdFCPrescDiv1,
  };

  /* Chip errata */
  CHIP_Init();

  /* If first word of user data page is non-zero, enable eA Profiler trace */
  BSP_TraceProfilerSetup();

  /* Configure push button interrupts */
  gpioSetup();

  /* Setup SysTick Timer for 1 msec interrupts  */
  if (SysTick_Config(SystemCoreClockGet() / 1000)) while (1) ;

  /* Initialize LCD controller */
  SegmentLCD_Init(false);

  /* Run countdown for user to select energy mode */
  msCountDown = 4000; /* milliseconds */
  while(msCountDown > 0)
  {
    if ( eMode >=3 && eMode<=4) {
      sprintf(displayString, "EM%d", eMode);
      SegmentLCD_Write(displayString);
    }
    switch( eMode )
    {
    case 0:
      SegmentLCD_Write("EM0 32M");
      break;
    case 1:
      SegmentLCD_Write("EM1 32M");
      break;
    case 2:
      SegmentLCD_Write("EM2 32K");
      break;
    case 5:
      SegmentLCD_Write("EM2+RTC");
      break;
    case 6:
      SegmentLCD_Write("RTC+LCD");
      break;
    }
    SegmentLCD_Number(msCountDown);
    Delay(msDelay);
    msCountDown -= msDelay;
  }
  /* Disable components, reenable when needed */
  SegmentLCD_Disable();
  RTC_Enable(false);

  /* Go to energy mode and wait for reset */
  switch(eMode)
  {
  case 0:
    /* Disable pin input */
    GPIO_PinModeSet(gpioPortB, 10, gpioModeDisabled, 1);

    /* Disable systick timer */
    SysTick->CTRL  = 0;

    /* 32Mhz primes demo - running off HFXO */
    CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO);
    /* Disable HFRCO, LFRCO and all unwanted clocks */
    CMU->OSCENCMD = CMU_OSCENCMD_HFRCODIS;
    CMU->OSCENCMD = CMU_OSCENCMD_LFRCODIS;
    CMU->HFPERCLKEN0  = 0x00000000;
    CMU->HFCORECLKEN0 = 0x00000000;
    CMU->LFACLKEN0    = 0x00000000;
    CMU->LFBCLKEN0    = 0x00000000;
    CMU->LFCLKSEL     = 0x00000000;
    /* Supress Conditional Branch Target Prefetch */
    MSC->READCTRL = MSC_READCTRL_MODE_WS1SCBTP;
    {
      #define PRIM_NUMS 64
      uint32_t i, d, n;
      uint32_t primes[PRIM_NUMS];

      /* Find prime numbers forever */
      while (1)
      {
        primes[0] = 1;
        for (i = 1; i < PRIM_NUMS;)
        {
          for (n = primes[i - 1] + 1; ;n++)
          {
            for (d = 2; d <= n; d++)
            {
              if (n == d)
              {
                primes[i] = n;
                goto nexti;
              }
              if (n%d == 0) break;
            }
          }
        nexti:
          i++;
        }
      }
    }
  case 1:
    /* Disable pin input */
    GPIO_PinModeSet(gpioPortB, 10, gpioModeDisabled, 1);

    /* Disable systick timer */
    SysTick->CTRL  = 0;

    CMU_ClockSelectSet(cmuClock_HF, cmuSelect_HFXO);
    /* Disable HFRCO, LFRCO and all unwanted clocks */
    CMU->OSCENCMD = CMU_OSCENCMD_HFRCODIS;
    CMU->OSCENCMD = CMU_OSCENCMD_LFRCODIS;
    CMU->HFPERCLKEN0  = 0x00000000;
    CMU->HFCORECLKEN0 = 0x00000000;
    CMU->LFACLKEN0    = 0x00000000;
    CMU->LFBCLKEN0    = 0x00000000;
    CMU->LFCLKSEL     = 0x00000000;
    EMU_EnterEM1();
    break;
  case 2:
    /* Enable LFRCO */
    CMU->OSCENCMD = CMU_OSCENCMD_LFRCOEN;
    /* Disable everything else */
    CMU->OSCENCMD = CMU_OSCENCMD_LFXODIS;
    CMU->HFPERCLKEN0  = 0x00000000;
    CMU->HFCORECLKEN0 = 0x00000000;
    CMU->LFACLKEN0    = 0x00000000;
    CMU->LFBCLKEN0    = 0x00000000;
    CMU->LFCLKSEL     = 0x00000000;
    EMU_EnterEM2(false);
    break;
  case 3:
    /* Disable all clocks */
    CMU->OSCENCMD = CMU_OSCENCMD_LFXODIS;
    CMU->OSCENCMD = CMU_OSCENCMD_LFRCODIS;
    CMU->HFPERCLKEN0  = 0x00000000;
    CMU->HFCORECLKEN0 = 0x00000000;
    CMU->LFACLKEN0    = 0x00000000;
    CMU->LFBCLKEN0    = 0x00000000;
    EMU_EnterEM3(false);
    break;
  case 4:
    EMU_EnterEM4();
    break;
  case 5:
    /* EM2 + RTC - only briefly wake up to reconfigure each second */
    CMU->LFCLKSEL     = CMU_LFCLKSEL_LFA_LFRCO;
    while(1)
    {
      RTCDRV_Trigger(2000, NULL);
      EMU_EnterEM2(false);
    }
  case 6:
  default:
    /* EM2 + RTC + LCD (if battery slips below 3V vboost should be */
    /* enabled) */
    CMU->LFCLKSEL     = CMU_LFCLKSEL_LFA_LFRCO;
    SegmentLCD_Init(false);
    /* Animate LCD */
    LCD_FrameCountInit(&fc);
    LCD_AnimInit(&anim);
    while(1)
    {
      SegmentLCD_Write("Energy");
      /* Sleep in EM2 */
      RTCDRV_Trigger(2000,NULL);
      EMU_EnterEM2(false);

      SegmentLCD_Write("Micro");
      /* Sleep in EM2 */
      RTCDRV_Trigger(2000,NULL);
      EMU_EnterEM2(false);
    }
  }

  return 0;
}