101 lines
2.5 KiB
C++
101 lines
2.5 KiB
C++
#include <Arduino.h>
|
|
|
|
#define LED0 PORTD5 // D5
|
|
#define LED1 PORTD6 // D6
|
|
#define LED2 PORTB0 // D8
|
|
#define LED3 PORTB1 // D9
|
|
#define BUILTIN_LED PORTB5 // D13
|
|
|
|
#define BUTTON_SLOW PINB2 // D10
|
|
#define BUTTON_FAST PINB3 // D11
|
|
|
|
#define COMPARE_MIN 1000
|
|
#define COMPARE_MAX 50000
|
|
|
|
volatile unsigned char counter = 0;
|
|
volatile unsigned int compareValue = COMPARE_MAX;
|
|
|
|
void setupIO() {
|
|
// LEDs output
|
|
DDRD |= (1 << LED0) | (1 << LED1);
|
|
DDRB |= (1 << LED2) | (1 << LED3) | (1 << BUILTIN_LED);
|
|
|
|
// Buttons input with pull-up
|
|
DDRB &= ~((1 << BUTTON_SLOW) | (1 << BUTTON_FAST));
|
|
PORTB |= (1 << BUTTON_SLOW) | (1 << BUTTON_FAST);
|
|
|
|
// Pin change interrupt for D10/D11
|
|
PCICR |= (1 << PCIE0);
|
|
PCMSK0 |= (1 << PCINT2) | (1 << PCINT3);
|
|
}
|
|
|
|
// Setup Timer1 with COMPA (counter) and COMPB (1Hz LED)
|
|
void setupTimer1() {
|
|
TCCR1A = 0;
|
|
TCCR1B = (1 << WGM12) | (1 << CS11) | (1 << CS10); // CTC, prescaler 64
|
|
|
|
OCR1A = compareValue; // 4-bit counter update speed
|
|
OCR1B = 249999; // 1 Hz = (16e6 / 64) / 250000
|
|
TIMSK1 = (1 << OCIE1A) | (1 << OCIE1B);
|
|
}
|
|
|
|
// Show counter value on 4 LEDs
|
|
void updateLEDs(unsigned char val) {
|
|
if (val & 0x01) PORTD |= (1 << LED0); else PORTD &= ~(1 << LED0);
|
|
if (val & 0x02) PORTD |= (1 << LED1); else PORTD &= ~(1 << LED1);
|
|
if (val & 0x04) PORTB |= (1 << LED2); else PORTB &= ~(1 << LED2);
|
|
if (val & 0x08) PORTB |= (1 << LED3); else PORTB &= ~(1 << LED3);
|
|
}
|
|
|
|
// Counter interrupt (frequency adjustable)
|
|
ISR(TIMER1_COMPA_vect) {
|
|
counter = (counter + 1) & 0x0F;
|
|
updateLEDs(counter);
|
|
}
|
|
|
|
ISR(TIMER1_COMPB_vect) {
|
|
PINB |= (1 << BUILTIN_LED); // Toggle built-in LED
|
|
}
|
|
|
|
// Button interrupt: handle speed control
|
|
ISR(PCINT0_vect) {
|
|
static unsigned char lastState = 0xFF;
|
|
unsigned char current = PINB;
|
|
|
|
// Falling edge: slow down
|
|
if (!(current & (1 << BUTTON_SLOW)) && (lastState & (1 << BUTTON_SLOW))) {
|
|
if (compareValue < COMPARE_MAX) {
|
|
compareValue <<= 1;
|
|
if (compareValue > COMPARE_MAX) compareValue = COMPARE_MAX;
|
|
}
|
|
}
|
|
|
|
// Falling edge: speed up
|
|
if (!(current & (1 << BUTTON_FAST)) && (lastState & (1 << BUTTON_FAST))) {
|
|
if (compareValue > COMPARE_MIN) {
|
|
compareValue >>= 1;
|
|
if (compareValue < COMPARE_MIN) compareValue = COMPARE_MIN;
|
|
}
|
|
}
|
|
|
|
lastState = current;
|
|
}
|
|
|
|
void setup() {
|
|
cli();
|
|
setupIO();
|
|
setupTimer1();
|
|
sei();
|
|
}
|
|
|
|
void loop() {
|
|
static unsigned int lastValue = 0;
|
|
cli();
|
|
if (compareValue != lastValue) {
|
|
TIMSK1 &= ~(1 << OCIE1A);
|
|
OCR1A = compareValue;
|
|
TIMSK1 |= (1 << OCIE1A);
|
|
lastValue = compareValue;
|
|
}
|
|
sei();
|
|
} |