Implemented sleep modes
This commit is contained in:
parent
12d45b8760
commit
8332eb6b0f
13
Source/TODO
Normal file
13
Source/TODO
Normal file
@ -0,0 +1,13 @@
|
||||
- After turning off, turning on doesn't really respond well to the option button
|
||||
- Store value in EEPROM (after a timeout)
|
||||
- Long press shows menu with reset option (menu prevents accidental resets)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Pin-out reminder:
|
||||
|
||||
SW2 = - = pin 2, PB3
|
||||
SW3 = menu = pin 3, PB4
|
||||
SW1 = + = pin 6, PB1
|
@ -37,7 +37,6 @@ void buttons_init()
|
||||
|
||||
// Enable timer interrupt
|
||||
TIMSK = _BV(OCIE0A);
|
||||
|
||||
sei();
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,7 @@ int main()
|
||||
// Delay is required on power-on for the SSD1306 to initialize,
|
||||
_delay_ms(40);
|
||||
ssd1306_init();
|
||||
ssd1306_clear();
|
||||
|
||||
buttons_init();
|
||||
|
||||
@ -28,6 +29,7 @@ int main()
|
||||
if (powerState == On)
|
||||
{
|
||||
handleCurrentScreen();
|
||||
sleepUntilButton(_BV(BUTTON_UP) | _BV(BUTTON_DOWN) | _BV(BUTTON_OPTION));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,19 @@
|
||||
#include "power.h"
|
||||
#include <stdint.h>
|
||||
#include <avr/io.h>
|
||||
#include <avr/interrupt.h>
|
||||
#include <avr/sleep.h>
|
||||
#include <util/delay.h>
|
||||
#include <ssd1306xled.h>
|
||||
|
||||
|
||||
// I'm not really keen on referencing the buttons directly from here,
|
||||
// feels like a coding red flag. It'll do for now until I come up with
|
||||
// a better design. Or forget about it most likely.
|
||||
#include "buttons.h"
|
||||
|
||||
|
||||
|
||||
|
||||
#define VccOffTreshold 3000
|
||||
#define VccOnTreshold 3100
|
||||
@ -12,6 +21,7 @@
|
||||
#define SSD1306CommandOff 0xAE
|
||||
#define SSD1306CommandOn 0xAF
|
||||
|
||||
#define SleepInterval8s (_BV(WDP3) | _BV(WDP0))
|
||||
|
||||
|
||||
PowerState powerState = BatteryLow;
|
||||
@ -41,9 +51,7 @@ void checkPower()
|
||||
if (vcc < VccOffTreshold)
|
||||
{
|
||||
setPowerState(BatteryLow);
|
||||
|
||||
// TODO go into a sleep cycle until the battery is recharged
|
||||
_delay_ms(10);
|
||||
sleepUntilTimer(SleepInterval8s);
|
||||
}
|
||||
|
||||
break;
|
||||
@ -52,16 +60,12 @@ void checkPower()
|
||||
if (vcc > VccOnTreshold)
|
||||
setPowerState(On);
|
||||
else
|
||||
{
|
||||
// TODO continue sleep cycle
|
||||
_delay_ms(10);
|
||||
}
|
||||
sleepUntilTimer(SleepInterval8s);
|
||||
|
||||
break;
|
||||
|
||||
case ManualOff:
|
||||
// TODO go into sleep mode
|
||||
_delay_ms(10);
|
||||
sleepUntilButton(_BV(BUTTON_OPTION));
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -75,6 +79,7 @@ void setPowerState(PowerState newState)
|
||||
{
|
||||
case On:
|
||||
ssd1306_send_command(SSD1306CommandOn);
|
||||
//buttons_init(); TODO this doesn't help, fix it!
|
||||
break;
|
||||
|
||||
case BatteryLow:
|
||||
@ -144,4 +149,75 @@ uint16_t readVCC() {
|
||||
ADCSRA &= ~(_BV(ADEN));
|
||||
|
||||
return result == 0 ? 0 : 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
|
||||
}
|
||||
|
||||
|
||||
inline void sleepStart()
|
||||
{
|
||||
// Turn ADC off
|
||||
ADCSRA &= ~_BV(ADEN);
|
||||
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
|
||||
|
||||
// Set sleep bit and halt the CPU
|
||||
sleep_enable();
|
||||
sei();
|
||||
sleep_cpu();
|
||||
|
||||
// ...goooood morning!
|
||||
cli();
|
||||
}
|
||||
|
||||
|
||||
inline void sleepEnd()
|
||||
{
|
||||
sleep_disable();
|
||||
ADCSRA |= _BV(ADEN);
|
||||
|
||||
sei();
|
||||
}
|
||||
|
||||
|
||||
void sleepUntilButton(uint8_t pinMask)
|
||||
{
|
||||
// Enable pin change interrupts
|
||||
GIMSK |= _BV(PCIE);
|
||||
|
||||
// Set up pin change mask
|
||||
PCMSK = pinMask;
|
||||
|
||||
sleepStart();
|
||||
PCMSK = 0;
|
||||
sleepEnd();
|
||||
}
|
||||
|
||||
|
||||
void sleepUntilTimer(uint8_t prescaler)
|
||||
{
|
||||
// Disable watchdog reset flag
|
||||
MCUSR &= ~_BV(WDRF);
|
||||
|
||||
// Enable watchdog
|
||||
WDTCR |= _BV(WDCE) | _BV(WDE);
|
||||
|
||||
// Set timeout value and enable interrupt mode
|
||||
WDTCR = prescaler | _BV(WDIE);
|
||||
|
||||
sleepStart();
|
||||
|
||||
// Disable watchdog (need to write a logic one first, see datasheet)
|
||||
WDTCR |= _BV(WDCE) | _BV(WDE);
|
||||
WDTCR = 0;
|
||||
|
||||
sleepEnd();
|
||||
}
|
||||
|
||||
|
||||
// Interrupt for pin changes
|
||||
ISR(PCINT0_vect)
|
||||
{
|
||||
}
|
||||
|
||||
// Interrupt for watchdog timer
|
||||
ISR(WDT_vect)
|
||||
{
|
||||
}
|
@ -13,6 +13,21 @@ extern uint16_t vcc;
|
||||
extern void checkPower();
|
||||
extern void setPowerState(PowerState newState);
|
||||
|
||||
extern void sleepUntilButton(uint8_t pinMask);
|
||||
|
||||
// 0 = 16 ms
|
||||
// 1 = 32 ms
|
||||
// 2 = 64 ms
|
||||
// 3 = 128 ms
|
||||
// 4 = 250 ms
|
||||
// 5 = 500 ms
|
||||
// 6 = 1 sec
|
||||
// 7 = 2 sec
|
||||
// 8 = 4 sec
|
||||
// 9 = 8 sec
|
||||
extern void sleepUntilTimer(uint8_t interval);
|
||||
|
||||
|
||||
extern uint8_t getScreenInvalidated();
|
||||
extern void setScreenInvalidated();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user