// Function prototypes
void timer1_init(void);
void timer2_init(void);
void setup() {
volatile char *dirf = (char *)0x30; // Direction register for port F
volatile char *outf = (char *)0x31; // Output register for port F
volatile char *dirk = (char *)0x107; // Direction register for port F
volatile char *outk = (char *)0x108; // Output register for port F
// Set pins PF0 and PF1 as output
*dirf = 0x01; // 0x03 sets PF0 and PF1 as output
*outf = 0x00; // Ensure both LEDs are initially off
*dirk = 0x01; // 0x03 sets PF0 and PF1 as output
*outk = 0x00; // Ensure both LEDs are initially off
// Enable global interrupts
sei(); // This is important! Without this, the ISRs won't be triggered.
// Initialize Timer1 and Timer2
timer1_init();
timer2_init();
}
void loop() {
// Main loop is empty, the timers will handle LED blinking
}
// Timer1 Initialization for LED1 (slower blinking)
void timer1_init(void) {
volatile char *Timer1_TCCR1A = (char *)0x80; // Timer1 Control Register A
volatile char *Timer1_TCCR1B = (char *)0x81; // Timer1 Control Register B
volatile char *Timer1_TCNT1 = (char *)0x84; // Timer1 Counter Register
volatile char *Timer1_OCR1A = (char *)0x88; // Timer1 Output Compare A Register
volatile char *Timer1_TIMSK = (char *)0x6F; // Timer1 Interrupt Mask Register
// Initialize Timer1
*Timer1_TCCR1A = 0x00; // Clear Timer1 control register A
*Timer1_TCCR1B = 0x00; // Clear Timer1 control register B
*Timer1_TCNT1 = 0x00; // Reset Timer1 counter
*Timer1_OCR1A = 30; // Set compare value for 1-second interval (for 16 MHz clock)
*Timer1_TIMSK = 0x02; // Enable Timer1 Output Compare Match A interrupt
// Set Timer1 prescaler (Prescaler = 256)
*Timer1_TCCR1B = 0x04;
}
void timer2_init(void) {
volatile char *Timer2_TCCR3A = (char *)0x90; // Timer2 Control Register A
volatile char *Timer2_TCCR3B = (char *)0x91; // Timer2 Control Register B
volatile char *Timer2_TCNT3 = (char *)0x94; // Timer2 Counter Register
volatile char *Timer2_OCR3A = (char *)0x98; // Timer2 Output Compare A Register
volatile char *Timer2_TIMSK = (char *)0x71; // Timer2 Interrupt Mask Register
// Initialize Timer2
*Timer2_TCCR3A = 0x00; // Clear Timer2 control register A
*Timer2_TCCR3B = 0x00; // Clear Timer2 control register B
*Timer2_TCNT3 = 0x00; // Reset Timer2 counter
*Timer2_OCR3A = 7812; // Set compare value for 0.5-second interval (for 16 MHz clock)
*Timer2_TIMSK = 0x02; // Enable Timer2 Output Compare Match A interrupt
// Set Timer2 prescaler (Prescaler = 64)
*Timer2_TCCR3B = 0x03; // Corrected: Set prescaler for Timer2 to 64
}
// Interrupt Service Routine for Timer1 Output Compare Match A (LED1)
ISR(TIMER3_COMPA_vect) {
volatile char *outf = (char *)0x31; // Output register for port F
*outf = *outf ^ 0x01; // Toggle LED1 (bit 0 of port F)
}
// Interrupt Service Routine for Timer2 Output Compare Match A (LED2)
ISR(TIMER1_COMPA_vect) {
volatile char *outk = (char *)0x108; // Output register for port F
*outk = *outk ^ 0x01; // Toggle LED2 (bit 1 of port F)
}