leddie/firmware/lib/pm.c

123 lines
1.8 KiB
C

#include "pm.h"
#include <avr/io.h>
#include <util/delay.h>
#include <avr/sleep.h>
#include <avr/interrupt.h>
void pm_reset()
{
DDRB = 0;
DDRC = 0;
DDRD = 0;
PORTB = 0;
PORTC = 0;
PORTD = 0;
GICR = 0;
// Reset to bootloader
WDTCR = (1 << WDE) | (1 << WDP2);
while(1);
/*
// Reset to application
asm("ldi R16,0x00");
asm("push R16");
asm("push R16");
asm("push R16");
asm("push R16");
asm("ret");
while (1);
*/
}
void pm_axl_on()
{
HAL_ON(AXL_EN);
}
void pm_axl_off()
{
HAL_OFF(AXL_EN);
}
void pm_init()
{
cli();
HAL_INIT(VBUS_SENSE, INPUT, OFF); // USB connected indicator
HAL_INIT(VLED_EN_N, OUTPUT, OFF_N); // VLED DCDC converter enable
HAL_INIT(CHG_ACTIVE_N, INPUT, ON); // Battery charging status input
HAL_INIT(BAT_SENSE, INPUT, OFF); // No pull-up on Batt sense ADC input
HAL_INIT(BAT_SENSE_EN_N, INPUT, OFF); // Disable using High-Z
HAL_INIT(AXL_EN, OUTPUT, OFF); // Turn off AXL
HAL_INIT(AXL_I2C, INPUT, OFF); // No Pull-ups on I2C
// Hardware bug after sleep. Need to manually turn off->on I2C transceiver.
TWCR &= ~((1 << TWSTO) | (1 << TWEN));
sei();
}
void pm_disable_periphery()
{
cli();
// Turn off HW
TCCR1B = 0;
TIMSK = 0;
WDTCR = 0;
TWCR = 0;
SPCR = 0;
ADCSRA = 0;
DDRB = 0;
DDRC = 0;
DDRD = 0;
PORTB = 0;
PORTC = 0;
PORTD = 0;
}
void pm_suspend()
{
pm_disable_periphery();
// Activate wake from button
HAL_INIT(BUTTON_N, INPUT, ON); // Pull-up for user button
MCUCR = (1 << SM1) | (1 << SE);
sei();
sleep_cpu();
cli();
}
void pm_led_on_auto()
{
if (pm_ac_connected())
pm_led_off();
else
pm_led_on();
}
void pm_led_on()
{
HAL_ON_N(VLED_EN_N);
}
void pm_led_off()
{
HAL_OFF_N(VLED_EN_N);
}
int pm_ac_connected()
{
return HAL_ASSERTED(VBUS_SENSE);
}
int pm_charging()
{
return HAL_ASSERTED_N(CHG_ACTIVE_N);
}