#define __AVR_ATmega2560__ #define F_CPU 16000000UL #include #include #include #include uint16_t freq_high = 1200; uint16_t freq_low = 800; volatile uint8_t speed = 25; volatile uint8_t tick_count = 0; volatile uint16_t beep_time = 0; volatile int debounce_int2 = 10; volatile int debounce_int3 = 10; volatile int tick_timer_start = 0xffff; void start_timer() { TCCR1B |= _BV(CS10) | _BV(CS12); // clk/1024 TIMSK1 |= _BV(TOIE1); TCCR4B |= _BV(CS41); // clk/8 TIMSK4 |= _BV(OCIE4A); TCNT1 = tick_timer_start; // Enable interrupts sei(); } ISR(INT2_vect) { if (debounce_int2) return; debounce_int2 = 100; if (speed < 100) speed++; } ISR(INT3_vect) { if (debounce_int3) return; debounce_int3 = 100; if (speed > 1) speed--; } ISR(TIMER1_OVF_vect) { tick_count++; if (tick_count > 3) tick_count = 0; beep_time = 50; TCNT1 = tick_timer_start; } ISR(TIMER4_COMPA_vect) { if (beep_time > 0) { PORTK ^= 0b10000000; beep_time--; } TCNT4 = 0; } void main() { DDRK = 0b10000000; DDRD = 0b00000000; PORTD |= 0b00001100; // EIMSK controls which ports can trigger interrupts EIMSK |= _BV(INT2) | _BV(INT3); // Trigger on falling edge on INT2 and INT3 EICRA |= _BV(ISC21) | _BV(ISC31); start_timer(); while (true) { OCR4A = (F_CPU / 8) / (tick_count == 0 ? freq_high : freq_low); tick_timer_start = 0xffff - (F_CPU / 1024 / 1000) * (100 + speed * 10); if (debounce_int2 > 0) debounce_int2--; if (debounce_int3 > 0) debounce_int3--; _delay_ms(1); } }