Handling an External Interrupt



/* Program INTR_1.C
**
** Routine first flashes an LED on P2.6 10 times.
**
** Then flashes LED each time a pushbutton on P1.1 (PINT0) is depressed.
**
** Illustrates the use of handling an external interrupt.
**
** Bit 1 of PMC1 is configured for external interrupt PINT0 by setting
** the bit to a one.
**
** The interrupt vector 24 is set to the address of the interrupt service
** routine.
**
** The external interrupt is configured for interrupt on a falling edge
** by setting bit ES0 of the External Interrupt Mode Register (INTM) to
** to a zero.  Thus, pokeb(SEG, INTM, 0x00).
**
** The PINT0 interrupt is configured for vectored service  without bank
** switching by setting bits MS/INT and ENCS of the EXIC0  register to
** zero.  The interrupt is enabled or disabled by setting the
** IMK bit of EXIC0 to either a 0 or 1, respectively.
**
** Thus, to enable the interrupt; pokeb(SEG, EXICO, 0x07). To disable;
** pokeb(SEG, EXICO, 0x47).
**
** As this was my first experience with interrupts using the Flashlite
** V25, I was cautious.  The interrupt service routine, simply sets a
** variable to true.  When main recognizes this, it disables further
** interrupts, sets the variable to false and performs the task of
** flashing the LED and then again enables the interrupt.
**
** One troublesome item was that prior to exiting the isr, the assembly
** instruction FINT (must be executed).  This requires use of the TASM
** assembler.  To avoid the tedium of performing this chore each time
** the program is compiled, the fint() routine was compiled to a separate
** .obj file.  Thus, the project consists of this file and fint.obj.
**
** The implementation of "fint()" is illustrated at the bottom of this
** page.
**
** copyright, Peter H. Anderson, Baltimore, MD, Oct, '00
*/

#include <stdio.h>
#include <dos.h>

#define SEG 0xf000

#define P1_OFFSET 0xff08
#define PM1_OFFSET 0xff09
#define PMC1_OFFSET 0xff0a

#define P2_OFFSET 0xff10
#define PM2_OFFSET 0xff11
#define PMC2_OFFSET 0xff12

#define INTM 0xff40
#define EXICO 0xff4c

#define FALSE 0
#define TRUE !0

typedef unsigned char byte;

void interrupt far isr_intp0(void);
void flash(int num);
extern void fint(void);

int intp0_flag;
byte far *p2, far *pm2, far *pmc2;

void main(void)
{

   int ad_val;

   p2 = (byte far *) MK_FP(SEG, P2_OFFSET);
   pm2 = (byte far *) MK_FP(SEG, PM2_OFFSET);
   pmc2 = (byte far *)MK_FP(SEG, PMC2_OFFSET);

   *pmc2 = 0x00;  /* not special purpose */
   *pm2 =  0x0f;     /* bit 6 is an output */
   *p2 = 0x00;       /* turn LED off */

   flash(10);

   pokeb(SEG, PMC1_OFFSET, 0x02);    /* intp0 on bit 1*/
   pokeb(SEG, PM1_OFFSET, 0xff);
   pokeb(SEG, INTM, 0x00);          /* falling edge */

   setvect(24, isr_intp0);          /* set new vector */

   intp0_flag = FALSE;

   while(1)
   {
      printf(".");
      pokeb(SEG, EXICO, 0x07);   /* enable interrupts */
      if (intp0_flag)               /* an interrupt occurred */
      {
          pokeb(SEG, EXICO, 0x47);  /* disable */
          flash(10);
          intp0_flag = FALSE;
      }
  }
}

void interrupt far isr_intp0(void)
{
    intp0_flag = TRUE;
    fint();
}


void flash(int num)
{
    int n;
    for (n=0; n<num; n++)
    {
       *p2 = 0x40;
       delay(250);
       *p2 = 0x00;
       delay(250);
    }
}


/* Program fint.c
**
** Implements the FINT instruction.
**
** copyright, Peter H. Anderson, Baltimore, MD, Oct, '00
*/

#include <stdio.h>

void fint(void);

void fint(void)
{
   asm  db 0x0f
   asm  db 0x92
}