text: /***********************************************************************
   * 
   * Control LEDs using functions from GPIO and Timer libraries. Do not 
   * use delay library any more.
   * ATmega328P (Arduino Uno), 16 MHz, AVR 8-bit Toolchain 3.6.2
   *
   * Copyright (c) 2018-2020 Tomas Fryza
   * Dept. of Radio Electronics, Brno University of Technology, Czechia
   * This work is licensed under the terms of the MIT license.
   * 
   **********************************************************************/
  
  /* Defines -----------------------------------------------------------*/
  #define LED_D1  PB5
  #define LED_D2  PB4
  #define LED_D3  PB3
  
  /* Includes ----------------------------------------------------------*/
  #include <avr/io.h>         // AVR device-specific IO definitions
  #include <avr/interrupt.h>  // Interrupts standard C library for AVR-GCC
  #include "gpio.h"           // GPIO library for AVR-GCC
  #include "timer.h"          // Timer library for AVR-GCC
  
  /* Function definitions ----------------------------------------------*/
  /**
   * Main function where the program execution begins. Toggle one LED
   * on the Multi-function shield using the internal 8- or 16-bit 
   * Timer/Counter.
   */
  int main(void)
  {
      /* Configuration of LED(s) */
      GPIO_config_output(&DDRB, LED_D1);
      GPIO_write_low(&PORTB, LED_D1);
  
      GPIO_config_output(&DDRB, LED_D2);
      GPIO_write_low(&PORTB, LED_D2);
  
      GPIO_config_output(&DDRB, LED_D3);
      GPIO_write_low(&PORTB, LED_D3);
  
      /* Configuration of 16-bit Timer/Counter1
       * Set prescaler and enable overflow interrupt */
  
      TIM0_overflow_16us();
      TIM0_overflow_interrupt_enable();
  
      TIM1_overflow_4ms();
      TIM1_overflow_interrupt_enable();
  
      TIM2_overflow_512us();
      TIM2_overflow_interrupt_enable();
  
      // Enables interrupts by setting the global interrupt mask
      sei();
  
      // Infinite loop
      while (1)
      {
          /* Empty loop. All subsequent operations are performed exclusively 
           * inside interrupt service routines ISRs */
      }
  
      // Will never reach this
      return 0;
  }
  
  /* Interrupt service routines ----------------------------------------*/
  /**
   * ISR starts when Timer/Counter1 overflows. Toggle D1 LED on 
   * Multi-function shield. */
  ISR(TIMER0_OVF_vect)
  {
      GPIO_toggle(&PORTB, LED_D1);
  }
  
  ISR(TIMER1_OVF_vect)
  {
      GPIO_toggle(&PORTB, LED_D2);
  }
  
  ISR(TIMER2_OVF_vect)
  {
      GPIO_toggle(&PORTB, LED_D3);
  }