Skip to content

Instantly share code, notes, and snippets.

@matthijskooijman
Created May 7, 2014 19:43
Show Gist options
  • Save matthijskooijman/ec46363bc6c7ed2598b6 to your computer and use it in GitHub Desktop.
Save matthijskooijman/ec46363bc6c7ed2598b6 to your computer and use it in GitHub Desktop.
#include <avr/sleep.h>
#include <avr/interrupt.h>
#include <util/delay.h>
void setup(){
Serial.begin(115200);
pinMode(LED_RED, OUTPUT);
pinMode(LED_GREEN, OUTPUT);
pinMode(LED_BLUE, OUTPUT);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(4, INPUT_PULLUP);
pinMode(5, INPUT_PULLUP);
pinMode(6, INPUT_PULLUP);
pinMode(7, INPUT_PULLUP);
pinMode(8, INPUT_PULLUP);
pinMode(A0, INPUT_PULLUP);
pinMode(A1, INPUT_PULLUP);
pinMode(A2, INPUT_PULLUP);
pinMode(A3, INPUT_PULLUP);
pinMode(A4, INPUT_PULLUP);
pinMode(A5, INPUT_PULLUP);
pinMode(A6, INPUT_PULLUP);
pinMode(A7, INPUT_PULLUP);
pinMode(MISO, INPUT_PULLUP);
pinMode(MOSI, INPUT_PULLUP);
pinMode(SCK, INPUT_PULLUP);
pinMode(BACKPACK_BUS, INPUT_PULLUP);
pinMode(13, INPUT_PULLUP);
pinMode(14, INPUT_PULLUP);
pinMode(SDA, INPUT_PULLUP);
pinMode(SCL, INPUT_PULLUP);
pinMode(VCC_ENABLE, OUTPUT);
Serial.write("DONE");
}
ISR(TIMER2_COMPA_vect) {
// Do nothing, only used to trigger a wakeup
}
void loop() {
// Stop timer2
TCCR2B = 0;
// Enable asynchronous mode for timer2 (uses external 32kHz
// crystal. This might corrupt the settings registers, so re-set
// TCCR2B.
ASSR |= (1 << AS2);
TCCR2B = 0;
// Outputs disconnected, Fast PWM mode (COMPA didn't seem to
// work properly in normal mode)
TCCR2A = (1 << WGM21) | (1 << WGM20);
// Reset timer
TCNT2 = 0;
// Interrupt at 5 seconds
OCR2A = 160;
// Clear any pending interrupt
TIFR2 = (1 << OCF2A);
TIMSK2 = (1 << OCIE2A);
// Put tranceiver to sleep
TRXPR |= (1 << SLPTR);
PRR2 |= (1 << PRTRX24);
// Disable Analag comparator
ACSR = (1 << ACD);
// Disable ADC
ADCSRA &= ~(1 << ADEN);
// TODO: When re-enabling the ADC, wait for the AVDDOK bit
// Disable the TX side of UART0. If the 16u2 it connects to is
// powered off, it offers a path to ground, so keeping the pin
// enabled and high (TTL idle) wastes around 1mA of current.
UCSR0B &= ~(1 << TXEN0);
UCSR0B &= ~(1 << RXEN0);
set_sleep_mode(SLEEP_MODE_PWR_SAVE);
cli();
// Start timer, prescaler 1024, meaning a single timer increment
// is 1/32s
TCCR2B = (1 << CS22) | (1 << CS21) | (1 << CS20);
// When the timer is in asynchronous mode, it takes up to one
// 32kHz clock cycle for register writes to take effect. Wait
// until that's done before sleeping.
while (ASSR & (1 << TCR2BUB)) /* nothing */;
sleep_enable();
#ifdef sleep_bod_disable
// On 256rfr2, BOD is automatically disabled in deep sleep, but
// some other MCUs need explicit disabling. This should happen shortly
// before actually sleeping. It's always automatically re-enabled.
sleep_bod_disable();
#endif
sei();
// AVR guarantees that the instruction after sei is executed, so
// there is no race condition here
sleep_cpu();
sleep_disable();
// Disable interrupt again
TIMSK2 = 0;
digitalWrite(LED_GREEN, LOW);
delay(1000);
digitalWrite(LED_GREEN, HIGH);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment