| DEFINE_INT_HANDLER | Language Extension

intr.h

Defines an interrupt handler function.

DEFINE_INT_HANDLER is a language extension macro which is used for defining interrupt handlers. The syntax is similar to function definition:

    DEFINE_INT_HANDLER (HandlerName)
    {
      // The body of the handler...
    }

Note, however, that DEFINE_INT_HANDLER does not define a standard function: it constructs an object named HandlerName of INT_HANDLER type, which is initialized to point to the handler body (implemented internally as a function, but unaccessable directly to the rest of the program). So, you can not call the interrupt handler using a standard call construction like

    HandlerName ();

Such behaviour is implemented due to safety reasons: interrupt handlers are not supposed to be executed directly. If you need to call the interrupt handler anyway, you can use ExecuteHandler function. Here is an example of the program which installs the new (user-defined) interrupt handler for auto interrupt 5 (the programable timer interrupt), in which the old (default) handler is called as well (called "Interrupt Handler"):

    // Interrupt handler incrementing a counter

    #define USE_TI89              // Compile for TI-89
    #define USE_TI92PLUS          // Compile for TI-92 Plus
    #define USE_V200              // Compile for V200

    #define OPTIMIZE_ROM_CALLS    // Use ROM Call Optimization
    #define MIN_AMS 100           // Compile for AMS 1.00 or higher
    #define SAVE_SCREEN           // Save/Restore LCD Contents

    #include <tigcclib.h>         // Include All Header Files

    INT_HANDLER OldInt5 = NULL;
    volatile int Counter = 0;

    DEFINE_INT_HANDLER(MyInt5)
    {
      Counter++;
      ExecuteHandler (OldInt5);
    }

    void _main(void)
    {
      OldInt5 = GetIntVec (AUTO_INT_5);
      SetIntVec (AUTO_INT_5, MyInt5);
      while (!kbhit()) printf_xy (50, 50, "Counter = %d  ", Counter);
      SetIntVec (AUTO_INT_5, OldInt5);
      GKeyFlush ();
    }

The only legal usage of INT_HANDLER objects is to be passed as arguments to the functions SetIntVec or ExecuteHandler.
Be aware that the variable Counter in above example is declared as `volatile`. In fact, any global variable which may be changed by the interrupt handler should be declared as `volatile`, especially if it is accessed from the other parts of the program (i.e. out of the interrupt handler). This is necessary to prevent various optimizations which may be fooled by the fact that the variable may be changed in a way which is completely unpredictable from the aspect of the normal program flow. For example, various optimizations may force keeping the variable content in a register, so if the variable is changed asynchronously, the compiler will not know anything about it. `volatile` will prevent keeping the variable in a register, so it will be reloaded from the memory on each access. The example given above will still work if you omit the `volatile` keyword, but more complicated programs will probably not work correctly without it.