// Listing 1: Interrupt nach Auflösung der Präprozessor-Defines

extern "C" void __vector_13 ( void ) __attribute__((signal, used, externally_visible));
void __vector_13 ( void ) {
  // code for handling the interrupt
}



// Listing 2: Millisekundentimerklasse mit Interrupt-Handler

class timer {
  public :
    volatile static uint32_t counter ;
    static void init ();
    static void serviceRoutine () __asm__ (" __vector_13 ") __attribute__ ((
__signal__ , __used__ , __externally_visible__ ));
};

volatile uint32_t timer :: counter = 0;

void timer :: init () {
  // initialization of the timer according to the used timer
peripheral
}

void timer :: serviceRoutine () {
  ++ counter ;
}



// Listing 3: Beispiel für die Erweiterung der Timer-Klasse zum Template

template < uint16_t rate >
class timer {
...
static void serviceRoutine () __asm__ (" __vector_13 ") __attribute__ ((
__signal__ , __used__ , __externally_visible__ ));
...
};

template class timer <1000 >;
template class timer <1 >;



// Listing 4: InterruptHandler.h

template <typename Derived >
class InterruptHandler {
  static constexpr bool check ( uint8_t vectNum ) {
    return Derived :: check ( vectNum );
  }

  static void interruptServiceRoutine () {
    Derived :: interruptServiceRoutine ();
  }
};



// Listing 5: Beispielhafte Implementierung für check und interruptServiceRoutine

static constexpr bool check ( uint8_t vectNum ) {
  return ( vectNum == TCB0_INT_vect_num ? true : false );
  // TCB0_INT_vect_num == 13
}

static void interruptServiceRoutine () __attribute__ (( signal ));
void interruptServiceRoutine () {
  TCB0 . INTFLAGS = TCB_CAPT_bm ;
  ++ timer_millis ;
}



// Listing 6: config.h

typedef AVRseries_millis <F_CPU , TCB0_ADDR > millisB ;
typedef InterruptDispatcher < millisB > MyDispatcher ;



// Listing 7: InterruptDispatcher.cpp

// vorhergehende ISRs

ISR ( TCB0_INT_vect ) __attribute__ (( naked ));
ISR ( TCB0_INT_vect ) {
  goto * MyDispatcher :: dispatch ( TCB0_INT_vect_num );
}

ISR ( TCD0_OVF_vect ) __attribute__ (( naked ));
ISR ( TCD0_OVF_vect ) {
  goto * MyDispatcher :: dispatch ( TCD0_OVF_vect_num );
}

// nachfolgende ISRs



// Listing 8: InterruptDispatcher.h

typedef void (* fptr )();

extern "C" void __vector_default (); // already defined

template < typename ... Rest >
struct InterruptDispatcher {
  static constexpr fptr dispatch ( uint8_t vectNum ) {
    return __vector_default ;
  }
};

template <typename First , typename ... Rest >
struct InterruptDispatcher <First , Rest ... > {
  static constexpr fptr dispatch ( uint8_t vectNum ) {
    if( First :: check ( vectNum )) {
      return First :: interruptServiceRoutine ;
    } else {
      return InterruptDispatcher < Rest ... >:: dispatch ( vectNum );
    }
  }
};



// Listing 9: config.h für InterruptDispatcher mit zwei Klassen

typedef AVRseries_millis <F_CPU , TCB0_ADDR > millisB ;
typedef AVRseries_millis <F_CPU , TCA0_ADDR > millisA ;
typedef InterruptDispatcher < millisB , millisA > MyDispatcher ;



// Listing 10: main.cpp mit eigenem Startup-Code

extern "C" void __dtors_end ();
extern "C" void _exit ();

void reset ( void ) __attribute__ (( naked ));
void reset ( void ) {
  asm (" clr r1");
  SREG =0;
  SP= RAMEND ;

  goto *& __dtors_end ;
}

int main (){
  while (1) ;
}

void jmp_main ( void ) __attribute__ (( naked , section (". init9 ")));
void jmp_main ( void ) {
  main ();
  goto *& _exit ;
}



// Listing 11: InterruptDispatcher.cpp mit eigenem Startup-Code (Auszug)

extern void reset ( void ) __attribute__ (( naked ));

void vector0 ( void ) __attribute__ (( naked ));
__attribute__ (( section (". vectors ")))
void vector0 ( void ) {
  goto *& reset ;
}

void vector1 ( void ) __attribute__ (( naked ));
__attribute__ (( section (". vectors ")))
void vector1 ( void ) {
  goto * MyDispatcher :: dispatch (1) ;
}

// usw fuer alle weiteren Vektoren

ISR ( BADISR_vect ) {
  while (1) ;
}



// Listing 12: Auszug aus der LSS-Datei der herkömmlichen Variante 1

00000034 <__ctors_end >:
...
40: 02 d0 rcall .+4 ; 0 x46 <main >
42: 08 c0 rjmp .+16 ; 0 x54 <_exit >

...

00000054 <_exit >:
54: f8 94 cli

00000056 <__stop_program >:
56: ff cf rjmp .-2 ; 0 x56 <__stop_program >
