#include ; declarations for better readability .equ LED_PORT, _SFR_IO_ADDR(PORTA) .equ LED_DIR, _SFR_IO_ADDR(DDRA) .equ LED_PIN, PA3 .equ BTN_PORT, _SFR_IO_ADDR(PORTA) .equ BTN_DIR, _SFR_IO_ADDR(DDRA) .equ BTN_PIN, PA7 .equ BTN_INTERRUPT, (1 << PCIE0) .equ BTN_INTERRUPT_PIN, (1 << PCINT7) ; naming registers we use .equ tmp, 17 .equ tmp1, 18 .equ pressed, 19 .section .text ; jump to main program rjmp main ; declaring the pin change interrupt routine .global PCINT0_vect PCINT0_vect: cp pressed, 0 brne skip ; if the button is already pressed, toggle LED in tmp, LED_PORT eor tmp, tmp1 out LED_PORT, tmp skip: ; toggle internal button state eor pressed, tmp1 reti ; declaring the main routine .global main main: ; initialize LED pin (i.e. output high) sbi LED_PORT, LED_PIN sbi LED_DIR, LED_PIN ; initialize button pin (i.e. input, pullup enabled) sbi BTN_PORT, BTN_PIN cbi BTN_DIR, BTN_PIN ; configure clock division to operate at 20MHz ldi tmp, (1 << CLKPCE) ldi tmp1, (0 << CLKPS3) | (0 << CLKPS2) | (0 << CLKPS1) | (0 << CLKPS0) out _SFR_IO_ADDR(CLKPR), tmp out _SFR_IO_ADDR(CLKPR), tmp1 ; enable interrupts for the port of the button in tmp, _SFR_IO_ADDR(GIMSK) sbr tmp, BTN_INTERRUPT out _SFR_IO_ADDR(GIMSK), tmp ; enable interrupts for the pin of the button in tmp, _SFR_IO_ADDR(PCMSK0) sbr tmp, BTN_INTERRUPT_PIN out _SFR_IO_ADDR(PCMSK0), tmp ; globally enable interrupts sei ; turn LED off cbi LED_PORT, LED_PIN ; select "standby" sleep mode in tmp, _SFR_IO_ADDR(MCUCR) sbr tmp, (1 << SM1) | (1 << SM0) out _SFR_IO_ADDR(MCUCR), tmp ; initialize register with bit mask for pin A3 sbr tmp1, (1 << LED_PIN) loop: ; set sleep enable bit in tmp, _SFR_IO_ADDR(MCUCR) sbr tmp, (1 << SE) out _SFR_IO_ADDR(MCUCR), tmp ; go to sleep sleep ; clear sleep enable bit in tmp, _SFR_IO_ADDR(MCUCR) cbr tmp, (1 << SE) out _SFR_IO_ADDR(MCUCR), tmp ; jump back rjmp loop