81 lines
1.6 KiB
C
81 lines
1.6 KiB
C
#define __AVR_ATmega2560__
|
|
#define F_CPU 16000000UL
|
|
|
|
#include <avr/io.h>
|
|
#include <util/delay.h>
|
|
#include <stdbool.h>
|
|
#include <avr/interrupt.h>
|
|
|
|
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);
|
|
}
|
|
}
|