microcontroller-project/main.c

81 lines
1.6 KiB
C
Raw Permalink Normal View History

2024-01-07 22:33:09 +00:00
#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);
}
}