ATMega328P sleep mode

so much kinder to wrap it in [ code ] ... [ / code ] :slight_smile:

#include <avr/sleep.h> //Needed for sleep_mode
#include <avr/power.h> //Needed for powering down perihperals such as the ADC/TWI and Timers

#define TRUE 1
#define FALSE 0

int show_the_time = FALSE;

volatile long seconds = 0;

//The very important 32.686kHz interrupt handler
SIGNAL(TIMER2_OVF_vect){
  seconds++;
}

//The interrupt occurs when you push the button
ISR(INT1_vect){
  if(show_the_time == FALSE)show_the_time = TRUE;
}

//The interrupt occurs when you push the button
ISR(INT0_vect){
  if(show_the_time == FALSE)show_the_time = TRUE;
}

void setup() {                
  //To reduce power, setup all pins as inputs with no pullups
  for(int x = 1 ; x < 18 ; x++){
    pinMode(x, INPUT);
    digitalWrite(x, LOW);
  }
 
  //Power down various bits of hardware to lower power usage  
  set_sleep_mode(SLEEP_MODE_PWR_SAVE);
  sleep_enable();

  //Shut off ADC, TWI, SPI, Timer0, Timer1

  ADCSRA &= ~(1<<ADEN); //Disable ADC
  ACSR = (1<<ACD); //Disable the analog comparator
  DIDR0 = 0x3F; //Disable digital input buffers on all ADC0-ADC5 pins
  DIDR1 = (1<<AIN1D)|(1<<AIN0D); //Disable digital input buffer on AIN1/0
  
  power_twi_disable();
  power_spi_disable();
  power_usart0_disable();
  power_timer0_disable();
  power_timer1_disable();
  //power_timer2_disable(); //Needed for asynchronous 32kHz operation

  //Setup TIMER2
  TCCR2A = 0x00;
  TCCR2B = (1<<CS22)|(1<<CS21)|(1<<CS20); //Set CLK/1024 or overflow interrupt every 8s
  ASSR = (1<<AS2); //Enable asynchronous operation, 32kHz xtal needed
  TIMSK2 = (1<<TOIE2); //Enable the timer 2 interrupt

  //Setup external INT1 (pin3) interrupt
  EICRA = (1<<ISC11)|(1<<ISC01)|(1<<ISC10)|(1<<ISC00); //Interrupt on rising edge
  EIMSK = (1<<INT0)|(1<<INT1); //Enable INT interrupts
  //need pull downs if active high, active low can enable internal pulllups
  //digitalWrite(3, HIGH); 
  //digitalWrite(2, HIGH); 

  sei(); //Enable global interrupts
}

void loop() {
  sleep_mode(); //Stop everything and go to sleep. Wake up if the Timer2 buffer overflows or if you hit the button
  
  // 10000 ~= 5 hours
  if(seconds > 3){
    reset_5s();
  }
  
  if(show_the_time == TRUE) {
    reset_5s();
  }
}

void reset_5s(){
  
  pinMode(A0, OUTPUT); 
  digitalWrite(A0, LOW); // needs to be LOW
  fake_msdelay(1000);
  digitalWrite(A0, HIGH); // needs to be HIGH
  pinMode(A0, INPUT); 
  
  seconds = 0;
  show_the_time = FALSE;
}

//This is a not-so-accurate delay routine
//Calling fake_msdelay(100) will delay for about 100ms
//Assumes 8MHz clock
void fake_msdelay(int x){
  for( ; x > 0 ; x--)
    fake_usdelay(1000);
}

//This is a not-so-accurate delay routine
//Calling fake_usdelay(100) will delay for about 100us
//Assumes 8MHz clock
void fake_usdelay(int x){
  for( ; x > 0 ; x--) {
    __asm__("nop\n\t"); 
    __asm__("nop\n\t"); 
    __asm__("nop\n\t"); 
    __asm__("nop\n\t"); 
    __asm__("nop\n\t"); 
    __asm__("nop\n\t"); 
    __asm__("nop\n\t"); 
  }
}