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
|
// Enable timer interrupt
|
||||||
TIMSK = _BV(OCIE0A);
|
TIMSK = _BV(OCIE0A);
|
||||||
|
|
||||||
sei();
|
sei();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ int main()
|
|||||||
// Delay is required on power-on for the SSD1306 to initialize,
|
// Delay is required on power-on for the SSD1306 to initialize,
|
||||||
_delay_ms(40);
|
_delay_ms(40);
|
||||||
ssd1306_init();
|
ssd1306_init();
|
||||||
|
ssd1306_clear();
|
||||||
|
|
||||||
buttons_init();
|
buttons_init();
|
||||||
|
|
||||||
@ -28,6 +29,7 @@ int main()
|
|||||||
if (powerState == On)
|
if (powerState == On)
|
||||||
{
|
{
|
||||||
handleCurrentScreen();
|
handleCurrentScreen();
|
||||||
|
sleepUntilButton(_BV(BUTTON_UP) | _BV(BUTTON_DOWN) | _BV(BUTTON_OPTION));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
#include "power.h"
|
#include "power.h"
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <avr/io.h>
|
#include <avr/io.h>
|
||||||
|
#include <avr/interrupt.h>
|
||||||
|
#include <avr/sleep.h>
|
||||||
#include <util/delay.h>
|
#include <util/delay.h>
|
||||||
#include <ssd1306xled.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 VccOffTreshold 3000
|
||||||
#define VccOnTreshold 3100
|
#define VccOnTreshold 3100
|
||||||
@ -12,6 +21,7 @@
|
|||||||
#define SSD1306CommandOff 0xAE
|
#define SSD1306CommandOff 0xAE
|
||||||
#define SSD1306CommandOn 0xAF
|
#define SSD1306CommandOn 0xAF
|
||||||
|
|
||||||
|
#define SleepInterval8s (_BV(WDP3) | _BV(WDP0))
|
||||||
|
|
||||||
|
|
||||||
PowerState powerState = BatteryLow;
|
PowerState powerState = BatteryLow;
|
||||||
@ -41,9 +51,7 @@ void checkPower()
|
|||||||
if (vcc < VccOffTreshold)
|
if (vcc < VccOffTreshold)
|
||||||
{
|
{
|
||||||
setPowerState(BatteryLow);
|
setPowerState(BatteryLow);
|
||||||
|
sleepUntilTimer(SleepInterval8s);
|
||||||
// TODO go into a sleep cycle until the battery is recharged
|
|
||||||
_delay_ms(10);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -52,16 +60,12 @@ void checkPower()
|
|||||||
if (vcc > VccOnTreshold)
|
if (vcc > VccOnTreshold)
|
||||||
setPowerState(On);
|
setPowerState(On);
|
||||||
else
|
else
|
||||||
{
|
sleepUntilTimer(SleepInterval8s);
|
||||||
// TODO continue sleep cycle
|
|
||||||
_delay_ms(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ManualOff:
|
case ManualOff:
|
||||||
// TODO go into sleep mode
|
sleepUntilButton(_BV(BUTTON_OPTION));
|
||||||
_delay_ms(10);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -75,6 +79,7 @@ void setPowerState(PowerState newState)
|
|||||||
{
|
{
|
||||||
case On:
|
case On:
|
||||||
ssd1306_send_command(SSD1306CommandOn);
|
ssd1306_send_command(SSD1306CommandOn);
|
||||||
|
//buttons_init(); TODO this doesn't help, fix it!
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BatteryLow:
|
case BatteryLow:
|
||||||
@ -144,4 +149,75 @@ uint16_t readVCC() {
|
|||||||
ADCSRA &= ~(_BV(ADEN));
|
ADCSRA &= ~(_BV(ADEN));
|
||||||
|
|
||||||
return result == 0 ? 0 : 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
|
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 checkPower();
|
||||||
extern void setPowerState(PowerState newState);
|
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 uint8_t getScreenInvalidated();
|
||||||
extern void setScreenInvalidated();
|
extern void setScreenInvalidated();
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user