Defines | Typedefs | Functions | Variables

xpal_power.h File Reference

Power Management System for the eXPal Prototype A. More...

#include <avr/io.h>
#include "cb_list.h"

Go to the source code of this file.

Defines

#define HL_PWR_ON   1
 Parameter to switch things on.
#define HL_PWR_OFF   0
 Parameter to switch things off.
#define HL_PWR_FAIL   -1
 Return value to indicate error conditions.
#define HL_PWR_USB_ACTIVE   0x01
 Power from USB is available.
#define HL_PWR_3V3_ACTIVE   0x02
 3.3V is active
#define HL_PWR_5V_ACTIVE   0x04
 5V regulator is active
#define HL_PWR_LCD_ACTIVE   0x08
 LCD High Voltage is active.
#define HL_PWR_ST_RUNNING   0x00
 PowerState 1 Running at full speed, no sleep at all allowed.
#define HL_PWR_ST_IDLE   0x10
 PowerState 2 Go into idle mode only.
#define HL_PWR_ST_33SLEEP   0x20
 PowerState 3 Go into power save mode but keep 3.3V ON.
#define HL_PWR_ST_SLEEP   0x40
 PowerState 3 Go into power save mode and switch 3.3V off.
#define HL_PWR_ST_OFF   0x80
 PowerState 3 Go into sleep mode.
#define HL_PWR_ALLOW_NOSAVE   0x0000
 No power saving allowed.
#define HL_PWR_ALLOW_IDLE   0x0010
 Power Down allowed.
#define HL_PWR_ALLOW_33SLEEP   0x0020
 Sleep Allowed but 3.3V untouched.
#define HL_PWR_ALLOW_SLEEP   0x0040
 Sleep Allowed.
#define HL_PWR_ALLOW_OFF   0x0080
 Power Off allowed.
#define HL_PWR_OFF_TIME   600
 inactivity seconds until power off
#define HL_PWR_WAKE_BY_KEY   0x01
 Key in COL0..2.
#define HL_PWR_WAKE_BY_PWR_KEY   0x02
 Key in COL3.
#define HL_PWR_WAKE_BY_SYS_TMR   0x04
 Timer2 COMPA.
#define HL_PWR_WAKE_BY_1S_TMR   0x08
 Timer2 OV.
#define HL_PWR_WAKE_BY_EX232   0x10
 USART 3.
#define HL_PWR_WAKE_BY_MOD232   0x20
 USART 2.
#define HL_PWR_WAKE_BY_ADC   0x40
 ADC.
#define HL_PWR_WAKE_NO_SOURCE   0x00
 Unknown Source or system was not in sleep (_NOSAVE).

Typedefs

typedef int8_t hl_pwr_state_t
typedef int8_t pwr_info_t

Functions

void hl_pwr_InitBoard (void)
 Primary Hardware Init Function.
void hl_pwr_InitPwrMan (void)
 Init power management system.
uint8_t hl_pwr_EnterSleep (void)
 Try to switch system in the deepest allowed sleep mode.
void hl_pwr_SetWakeSource (uint8_t ws)
 To be called in ISR to set wake-up source.
uint8_t hl_pwr_GetWakeSource (void)
 return Wake-up source
void hl_pwr_AppBusy (void)
 Keep System On.
void hl_pwr_OffNow (void)
 Set off timer to zero.
uint16_t hl_pwr_GetOffTime (void)
 Return the off timer value.
uint16_t hl_pwr_fast (void *)
 fast system timer call (20ms)
uint16_t hl_pwr_slow (void *)
 slow system timer call (1sec)
void hl_pwr_3V3reg (hl_pwr_state_t state)
 Control the 3.3V regulator.
void hl_pwr_5Vreg (hl_pwr_state_t state)
 Control the 5V regulator.
void hl_pwr_LCDreg (hl_pwr_state_t state)
 Control the 15V regulator.
hl_pwr_state_t hl_pwr_GetState (void)
 Return complete power state to application.
void hl_RegisterPwrCb (cb_function_t fkt2call, void *PwrStAllowed)
 Register a call back function to request power down in higher SW layers.

Variables

volatile uint8_t WakeUpSource
 Bitmap variable to indicate the wake-up source.
volatile uint16_t PowerOffTimer
 Second timer until power off.
volatile hl_pwr_state_t hl_pwr_state
 System power state (current setting).
volatile hl_pwr_state_t hl_pwr_info
 Power States,the system is allowed to use.

Detailed Description

Power Management System for the eXPal Prototype A.


Define Documentation

#define HL_PWR_ST_33SLEEP   0x20

PowerState 3 Go into power save mode but keep 3.3V ON.

This power state can be used when the system does not have to react on any communicatin channel. The system will wake up on any key interrupt or from the 1 sec interrupt and return from hl_pwr_EnterSleep(). After a key interrupt, the key scan module will keep the system in IDLE state until the key input is completed.

Power State with CPU in power save mode.

  • CPU Power-Save Mode, IOclk off
  • wake on Timer2 and all Key Interrupts
  • 3.3V Supply to stay on of already on

In this mode the CPU can not wake up from USART (no GPS operation possible)

  • System can still access the SD Card
    • Display HV on
    • not entered when running on USB
    • RS232 driver off
    • 19.53ms timer off
    • 1sec timer on
#define HL_PWR_ST_IDLE   0x10

PowerState 2 Go into idle mode only.

This power state is intended to be used when the system is waiting for GPS or other external data. Every timer, USART or key iterrupt will cause the return from hl_pwr_EnterSleep().

Power State with CPU Idle mode.

  • CPU Idle Mode, IOclk running, wake on UART and all other sources
  • 3.3V Supply state will stay as is
  • Display HV on
  • not entered when running on USB
  • RS232 driver state will stay as is
  • 19.53ms timer will stay on
#define HL_PWR_ST_OFF   0x80

PowerState 3 Go into sleep mode.

This state is the soft power off state with maximum power reduction, but the system time is still updated every second. The clock speed is reduced below 1MHz, the 5V regulator is off and the system will run on battery voltage. The wake-up procedure will take ~1ms to start the crystal, ramp the voltage up to 5V and start running at full speed again. The 1s ISR code is executed at low CPU speed. This has to be taken into account when functions like delay() are used.

Soft Power off state

  • CPU Power-Save Mode, IOclk off
  • wake on Timer2 and PowerKey Interrupts
  • 3.3V Supply off
  • Display HV off
  • not entered when running on USB
  • RS232 driver off
  • 19.53ms timer off
  • 1sec timer on, but will only run ISR code and not return back from hl_pwr_EnterSleep()

System will only return from hl_pwr_EnterSleep() after a powerKey Interrupt (COL3)

#define HL_PWR_ST_RUNNING   0x00

PowerState 1 Running at full speed, no sleep at all allowed.

The system will operate without sleep and return immediately from from hl_pwr_EnterSleep(). This power state can be used to get the fastest main loop turn around time. This power state is default when powered from USB.

#define HL_PWR_ST_SLEEP   0x40

PowerState 3 Go into power save mode and switch 3.3V off.

This power state can be used when the system does not have to react on any communicatin channel. The system will wake up on any key interrupt or from the 1 sec interrupt and return from hl_pwr_EnterSleep(). After a key interrupt, the key scan module will keep the system in IDLE state until the key input is completed.

Power State with CPU in power save mode.

  • CPU Power-Save Mode, IOclk off
  • wake on Timer2 and all Key Interrupts
  • 3.3V Supply off

In this mode the CPU can not wake up from USART (no GPS operation possible)

  • System must stay in idle or 33SLEEP mode to access the SD Card
    • Display HV on
    • not entered when running on USB
    • RS232 driver off
    • 19.53ms timer off
    • 1sec timer on

Function Documentation

void hl_pwr_3V3reg ( hl_pwr_state_t  state  ) 

Control the 3.3V regulator.

The function can be used to switch the 3.3V source ON or Off

Parameters:
[in] state HL_PWR_ON/HL_PWR_OFF

Control the 3.3V regulator.

Switch the 3.3V reg. on or off

Parameters:
[in] desired state, HL_PWR_ON / HL_PWR_OFF

                                        {
        if (state == HL_PWR_OFF){
                /* power down 3.3 */
                HL_PWR_VCC33_PORT &= ~(_BV(HL_PWR_VCC33));
                hl_pwr_state &= ~HL_PWR_3V3_ACTIVE;     
        }else{
                /* power up 3.3 */
                HL_PWR_VCC33_PORT |= _BV(HL_PWR_VCC33); 
                hl_pwr_state |= HL_PWR_3V3_ACTIVE;      
        }
}

void hl_pwr_5Vreg ( hl_pwr_state_t  state  ) 

Control the 5V regulator.

The function can be used to switch the 5V source ON or Off When OFF, the Controller will run on Battery voltage minus ~0.2V.

Parameters:
[in] state HL_PWR_ON/HL_PWR_OFF

Control the 5V regulator.

Switch the 5V reg. on or off

Parameters:
[in] desired state, HL_PWR_ON / HL_PWR_OFF

                                       {
        if (state == HL_PWR_OFF){
                /* power down 3.3 */
                HL_PWR_VCC5_PORT &= ~(_BV(HL_PWR_VCC5));                
                hl_pwr_state &= ~HL_PWR_5V_ACTIVE;      
        }else{
                /* power up 3.3 */
                HL_PWR_VCC5_PORT |= _BV(HL_PWR_VCC5);   
                hl_pwr_state |= HL_PWR_5V_ACTIVE;       
        }
}

void hl_pwr_AppBusy ( void   )  [inline]

Keep System On.

The App has to call this function to avoid automatic power off otherwise the system will enter HL_PWR_ST_OFF when allowed and the timer has reached Zero

                                {
        PowerOffTimer = HL_PWR_OFF_TIME;
}

uint8_t hl_pwr_EnterSleep ( void   ) 

Try to switch system in the deepest allowed sleep mode.

Function to enter "PwrState". If a sleep power state is entered, the Control will stay within this function until wake-up

Returns:
wake-up source
Note:
This function must be called outside of an ISR, or special care must be taken to ensure the system wake-up, since inside of an ISR the global IRQ is disabled.

ZZZzzz...

                               {

        // *************************************************************************
        // Do OperatingSystem idle operations

        // Update battery display
        uint8_t BatState = hl_bat_GetBatStatus();
        if((BatState & HL_BAT_NEWSTAT) != 0){
                hl_stb_BattState(Empty + (BatState & HL_BAT_ST_MASK));
        }

        // *************************************************************************
        // Check what sleep mode is allowed
        uint16_t allowed_pwr_mode = 0xffff;

        // ask applications what's possible
        allowed_pwr_mode = callback_iterate_and_until0 (cbListPowerFirst);

/*      if(hl_pwr_state & HL_PWR_USB_ACTIVE){   
                // USB is active, stay in full on
                allowed_pwr_mode = HL_PWR_ALLOW_NOSAVE;
        }
*/
        // reset system power state for update below
        hl_pwr_state &= ~(HL_PWR_ST_RUNNING | HL_PWR_ST_IDLE | HL_PWR_ST_33SLEEP | HL_PWR_ST_SLEEP | HL_PWR_ST_OFF);

        // *************************************************************************
        // prepare for the individual sleep modes
        if ((allowed_pwr_mode & HL_PWR_ALLOW_OFF) && (PowerOffTimer == 0)){
                // All registered applications did allow power off
                // and the shut off timer is zero too

                // Display status symbol
                hl_stb_PwrState(SLEEPsymbol);

                // update power state
                hl_pwr_state |= HL_PWR_ST_OFF;

                // for off use pwr-save to allow wake up from async timer
                set_sleep_mode (SLEEP_MODE_PWR_SAVE);

                // switch power sources off
                hl_pwr_LCDreg(HL_PWR_OFF);
                hl_pwr_3V3reg(HL_PWR_OFF);

                // LCD Controller off
                HL_LCD_PowerOff();

                // enable wake up for power key
                hlRow3KeyWakeup();              

                // RAM interface disable and deselect RAM
                // ExtMemDisable();

                // stop fast system timer
                hl_asyn_StopSysTimer();

                // Stop ADC as well
                hl_adc_off();

                // reduce clock and switch 5V reg off
                clock_prescale_set( clock_div_16 );
                hl_pwr_5Vreg(HL_PWR_OFF);

        }else if (allowed_pwr_mode & HL_PWR_ALLOW_SLEEP){
        
                // Display status symbol
                hl_stb_PwrState(SLEEPsymbol);

                // All registered applications did allow sleep
                hl_pwr_state |= HL_PWR_ST_SLEEP;

                // for off use pwr-save to allow wake up from async timer
                set_sleep_mode (SLEEP_MODE_PWR_SAVE);

                // switch power sources off
                hl_pwr_3V3reg(HL_PWR_OFF);

                // enable wake up for power key
                hlAllKeyWakeup();

                // RAM interface disable and deselect RAM
                // ExtMemDisable();

                // stop fast system timer
                hl_asyn_StopSysTimer();

                // Stop ADC as well
                // ADC result will not be evaluated when SysTimer is off
                hl_adc_off();

        }else if (allowed_pwr_mode & HL_PWR_ALLOW_33SLEEP){
        
                // Display status symbol
                hl_stb_PwrState(SLEEPsymbol);

                // All registered applications did allow sleep
                hl_pwr_state |= HL_PWR_ST_33SLEEP;

                // for off use pwr-save to allow wake up from async timer
                set_sleep_mode (SLEEP_MODE_PWR_SAVE);

                // enable wake up for power key
                hlAllKeyWakeup();

                // RAM interface disable and deselect RAM
                // ExtMemDisable();

                // stop fast system timer
                hl_asyn_StopSysTimer();

                // Stop ADC as well
                // ADC result will not be evaluated when SysTimer is off
                hl_adc_off();

        }else if (allowed_pwr_mode & HL_PWR_ALLOW_IDLE){

                // Display status symbol
                hl_stb_PwrState(IDLEsymbol);

                // All registered applications did allow idle
                hl_pwr_state |= HL_PWR_ST_IDLE;

                // Only idle mode to react on all sources
                set_sleep_mode (SLEEP_MODE_IDLE);       
        }

        // *************************************************************************
        // enter sleep mode
        if (allowed_pwr_mode != 0){

                do{ // loop to stay in sleep for 1s timer in OFF mode

                        WakeUpSource = HL_PWR_WAKE_NO_SOURCE;

                        // Enter sleep mode
                        sleep_enable ();
                    sleep_cpu ();   
                        sleep_disable ();

                        // Wait for ISR to set wake source if not done yet
                        // while (WakeUpSource == HL_PWR_WAKE_NO_SOURCE);
                        // we expect the ISR to be completed when WakeUpSource is set

                }while((WakeUpSource & HL_PWR_WAKE_BY_1S_TMR) && (hl_pwr_state & HL_PWR_ST_OFF));

                // *************************************************************************
                // manage wake up

                // System clock speed up when start from off
                if(hl_pwr_state & HL_PWR_ST_OFF){

                        hl_pwr_5Vreg(HL_PWR_ON);
                        hl_pwr_LCDreg(HL_PWR_ON);
                        HL_LCD_PowerOn();

                        // wait for 5V to rise
                        //
                        // While the voltage is rising up to 5V, the system is still running with 
                        // reduced speed. Since the delay time calculation works for 14.7456MHz,
                        // the actual time had to be adjusted. In case of 1/16 of the original
                        // clock, the value of 70us caused a delay of ~1.2ms.
                        _delay_us (70); 

                        // Full speed ahead
                        clock_prescale_set( clock_div_1 );
                }

                // enable in case it was off or stay on
                // ExtMemEnable(); 

                // do sys timer start in case it's off
                // hl_asyn_StartSysTimer();

        }else{
                // System is required to stay ON, 
                // no sleep function called, 
                // return without wakeup

                // Display status symbol
                if(hl_pwr_state & HL_PWR_USB_ACTIVE){
                        hl_stb_PwrState(USBsymbol);
                }else{
                        hl_stb_PwrState(RUNsymbol);
                }

                WakeUpSource = HL_PWR_WAKE_NO_SOURCE;
                hl_pwr_state |= HL_PWR_ST_RUNNING;
        }
        return WakeUpSource;
}

uint16_t hl_pwr_fast ( void *  p  ) 

fast system timer call (20ms)

fast system timer call (20ms)

Do fast operations for power management:

  • Manage USB power detection
Todo:
Replace the USB polling by a pin change interrupt. This will also make sure, that the voltage can not drop below the limits for 14MHz.

                             {

        // disable 5V reg. if Vusb available
        if ( (HL_USB_PWREN_PIN & _BV(HL_USB_PWREN)) == 0){
                // device configured and active
            // Disable 5V reg.
            HL_PWR_VCC5_PORT &= ~(_BV(HL_PWR_VCC5));
                hl_pwr_state &= ~HL_PWR_5V_ACTIVE;
                hl_pwr_state |= HL_PWR_USB_ACTIVE;
        }else{
            // device not configured or in suspend
            // Enable 5V reg.
            HL_PWR_VCC5_PORT |= (_BV(HL_PWR_VCC5));             
                hl_pwr_state |= HL_PWR_5V_ACTIVE;
                hl_pwr_state &= ~HL_PWR_USB_ACTIVE;
        }
        return 0;
}

uint16_t hl_pwr_GetOffTime ( void   )  [inline]

Return the off timer value.

The App can call this function to find out what time in seconds is left until soft power off.

                                       {
        return PowerOffTimer;
}

hl_pwr_state_t hl_pwr_GetState ( void   )  [inline]

Return complete power state to application.

Returns:
Pwr State Bitmap

                                           { 
        return hl_pwr_state;
};

void hl_pwr_InitBoard ( void   ) 

Primary Hardware Init Function.

This function has to be called as the first action in main() It will ensure the correct setting of all processor IO lines and other board hardware. The function will only set everything in a defined, power saving state and not init any hardware unit to work.

                           {

        /*
                Initialize the ports to avoid floating signals and excessive power
                consumption.
                To be complete it is more obvious to access the ports directly here.
        */
        // Port A
        // can stay as is after reset

        // Port B
        PORTB= 0x80 | _BV(HL_SD_SS);  // USB_RESET inakt, sauberer Pegel für SD Treiber
        DDRB = 0x87; 

        // Port C
        DDRC = 0xFF;  // Addr.Augaenge
        PORTC= 0xC0;  // RAM Disable

        // Port D
        PORTD = 0xFF; // PullUp on for KeyLines

        // Port E
        PORTE = 0xFF; // PullUp on

        // Port F
        PORTF = 0x0F & ~_BV(PF0); // PullUp for unused AD Inputs

        // Port G
        DDRG = 0x07;
        PORTG = 0x07; // RD/WR disable

        // Port H
        PORTH = 0xFF; // PullUp on

        // Port J
        PORTJ = 0xFF; // PullUp on

        // Port K
        PORTK = 0xFF; // PullUp on

        // Port L
        DDRL = 0x07 | _BV(HL_EX232_FRCON) | _BV(HL_EX232_EN);

        // 5V ON, pull up at open pins
        PORTL = _BV(HL_PWR_VCC5) | _BV(PL3)|_BV(PL4)
          | 0*_BV(HL_EX232_FRCON) | 1*_BV(HL_EX232_EN);

        /* set power reduction registers */
        PRR0 = _BV(PRTWI) /* | _BV(PRTIM2)  | _BV(PRTIM0) */
                | _BV(PRTIM1) | _BV(PRSPI) | _BV(PRUSART0)
            | _BV(PRADC)
            ;
        PRR1 = _BV(PRTIM5) | _BV(PRTIM4) | _BV(PRTIM3)
                | _BV(PRUSART3) | _BV(PRUSART2) | _BV(PRUSART1)
            ;

}

void hl_pwr_InitPwrMan ( void   ) 

Init power management system.

Initialize

  • Variables
  • Bat Voltage measurement
  • Key interrupts

Initialize

  • Variables
  • Register timer calls

                            {

        hl_pwr_state = HL_PWR_5V_ACTIVE | HL_PWR_ST_RUNNING;
        hl_pwr_info = 0; // Stay in full on
        PowerOffTimer = HL_PWR_OFF_TIME;

        hl_asyn_Register1sTimer( (&hl_pwr_slow), NULL);
        hl_asyn_RegisterFastTimer( (&hl_pwr_fast), NULL);
}

void hl_pwr_LCDreg ( hl_pwr_state_t  state  ) 

Control the 15V regulator.

The function can be used to switch the 15V LCD source ON or Off

Parameters:
[in] state HL_PWR_ON/HL_PWR_OFF

Control the 15V regulator.

Switch the LCD High Voltage (~15V) reg. on or off

Parameters:
[in] desired state, HL_PWR_ON / HL_PWR_OFF

                                        {
        if (state == HL_PWR_OFF){
                /* power down 3.3 */
                HL_PWR_VLCD_PORT &= ~(_BV(HL_PWR_VLCD));                
                hl_pwr_state &= ~HL_PWR_LCD_ACTIVE;     
        }else{
                /* power up 3.3 */
                HL_PWR_VLCD_PORT |= _BV(HL_PWR_VLCD);   
                hl_pwr_state |= HL_PWR_LCD_ACTIVE;      
        }
}

void hl_pwr_OffNow ( void   )  [inline]

Set off timer to zero.

The App has to call this function to set the off timer to Zero. The system will enter HL_PWR_ST_OFF when allowed.

                               {
        PowerOffTimer = 0;
}

void hl_pwr_SetWakeSource ( uint8_t  ws  )  [inline]

To be called in ISR to set wake-up source.

In some cases it might be desired to go back to sleep when the wake-up was caused by a certain source.
Example: Most of the background activities are done within the 20ms timer call. When the control is returned back to the main loop it might be desired to call hl_pwr_EnterSleep immediately.

Parameters:
[in] ws Wake-up source define HL_PWR_WAKE_BY_KEY
HL_PWR_WAKE_BY_PWR_KEY
HL_PWR_WAKE_BY_SYS_TMR
HL_PWR_WAKE_BY_1S_TMR
HL_PWR_WAKE_BY_EX232
HL_PWR_WAKE_BY_MOD232
HL_PWR_WAKE_NO_SOURCE

                                            {

        WakeUpSource |= ws;
}

uint16_t hl_pwr_slow ( void *  p  ) 

slow system timer call (1sec)

slow system timer call (1sec)

Do slow operations for power management:

  • OFF timer count down

                             {

        if (PowerOffTimer > 0){
                PowerOffTimer--;
        }
        return 0;
}

void hl_RegisterPwrCb ( cb_function_t  fkt2call,
void *  PwrStAllowed 
)

Register a call back function to request power down in higher SW layers.

The function will add an entry to the list of functions to be called when the power management tries to enter a lower power state. The new entry is added to the front of the list.

An Application routine can use the call back for the following actions:

  • Check if current states or operations require the system to stay on
  • set the allowed states

The control should be returned as fast as pssible. Do not wait or complete any pending operations within the callback.

Parameters:
[in] fkt2call function pointer
[in] PwrStAllowed pointer to power state bitmap

{
  cb_register_call (&cbListPowerFirst, fkt2call, PwrStAllowed);
}


Variable Documentation

volatile uint16_t PowerOffTimer

Second timer until power off.

If power off is allowed but the timer is not NULL, the system will only enter sleep mode.

volatile uint8_t WakeUpSource

Bitmap variable to indicate the wake-up source.

WakeUpSource is a symmary of system actions that caused the system to wake up. It's cleared before entering sleep, any wake-up ISR will set the individual bit. When checked some time after wake-up, more than one source might be active