/* demo 11: INT_CHAN_0 & INT_CHAN_1 interrupt demo */ /* step 1 : apply a init_HIGH & active_LOW signal to PC3 of port-2 */ /* (note: PC7 of port-2 is don't care */ /* step 2 : apply a init_HIGH & active_LOW signal to PC3 of port-5 */ /* (note: PC7 of port-5 is don't care */ /* step 3 : run demo11.exe */ /* --------------------------------------------------------------- */ #include "PIO.H" #define A1_8259 0x20 #define A2_8259 0xA0 #define EOI 0x20 WORD init_high(); WORD wBase,wIrq; WORD pio_d48_c0(char cConfig, char cLow, char cHigh); WORD pio_d48_c1(char cConfig, char cLow, char cHigh); WORD pio_d48_c2(char cConfig, char cLow, char cHigh); static void interrupt irq_service(); int irqmask,now_int_state,invert,new_int_state,int_c; int INT0_H,INT0_L,INT1_H,INT1_L; int main() { int i,j; WORD wBoards,wRetVal; WORD wSubVendor,wSubDevice,wSubAux,wSlotBus,wSlotDevice,t1,t2,t3,t4,t5; char c; DWORD dwVal; /* step 1: find address-mapping of PIO/PISO cards */ clrscr(); wRetVal=PIO_DriverInit(&wBoards,0x80,0x01,0x30); /* for PIO-D48 */ printf("\nThrer are %d PIO_D48 Cards in this PC",wBoards); if (wBoards==0) exit(0); printf("\n----------------- The Configuration Space -------------------------"); for(i=0; i "); ShowPioPiso(wSubVendor,wSubDevice,wSubAux); } /* select card_0 */ PIO_GetConfigAddressSpace(0,&wBase,&wIrq,&t1,&t2,&t3,&t4,&t5); /* step 2: enable all D/I/O port */ outportb(wBase,1); /* enable D/I/O */ init_high(); /* interrupt initialize, INIT_CHAN_0/1 is HIGH now */ printf("\n*** show the count of Low_pulse **\n"); for (;;) { printf("\nINT0=[%x,%x] , INT1=[%x,%x]",INT0_L,INT0_H,INT1_L,INT1_H); if (kbhit()!=0) {getch(); break;} } outportb(wBase+5,0); /* disable all interrupt */ PIO_DriverClose(); } /* -------------------------------------------------------------------- */ /* Use INT_CHAN_0 & INT_CHAN_1 as external interrupt signal */ WORD init_high() { DWORD dwVal; disable(); outportb(wBase+5,0); /* disable all interrupt */ if (wIrq<8) { irqmask=inportb(A1_8259+1); outportb(A1_8259+1,irqmask & (0xff ^ (1 << wIrq))); setvect(wIrq+8, irq_service); } else { irqmask=inportb(A1_8259+1); outportb(A1_8259+1,irqmask & 0xfb); /* IRQ2 */ outportb(A1_8259+1,irqmask & (0xff ^ (1 << wIrq))); irqmask=inportb(A2_8259+1); outportb(A2_8259+1,irqmask & (0xff ^ (1 << (wIrq-8)))); setvect(wIrq-8+0x70, irq_service); } /* select PC3 of port_2 & PC3 of port_5 as interrupt signal */ outportb(wBase+0xf0,0x28); /* CTRL_D5/4/3/2=1010 --> */ /* INT_CHAN_0=PC3 of port_2 */ /* INT_CHAN_1=PC3 of port_5 */ /* Note: now both PC3 are HIGH */ /* --> INV0, INV1 must select the inverted PC3 */ /* --> INT_CHAN_0=!PC3 of port_2=init_LOW, active_HIGH */ /* --> INT_CHAN_1=!PC3 of port_5=init_LOW, active_HIGH */ invert=0; outportb(wBase+0x2a,invert);/* select the inverted PC3 */ /* INT_CHAN_0=!PC3 of port_2 */ /* INT_CHAN_1=!PC3 of port_5 */ now_int_state=3; /* now both PC3 are high */ outportb(wBase+5,3); /* enable INT_CHAN_0 & INT_CHAN_1 */ for (;;) /* wait both PC3 are HIGH */ { if ((inportb(wBase+7)&3)!=0) break; printf("\nWait PC3 of port-2 & PC3 of port-5 are HIGH"); } INT0_H=INT0_L=INT1_H=INT1_L=0; enable(); } /* --------------------------------------------------------------------- */ /* NOTE : 1. The hold-time of INT_CHAN_0 & INT_CHAN_1 must long enough. */ /* 2. The ISR must read the interrupt status again to identify */ /* the active interrupt sources. */ /* 3. The INT_CHAN_0 & INT_CHAN_1 can be active at the same time. */ /* --------------------------------------------------------------------- */ void interrupt irq_service() { /* now ISR can not know which interrupt is active */ new_int_state=inportb(wBase+7)&0x03; /* read all interrupt signal states */ int_c=new_int_state ^ now_int_state; /* compare new_state to old_state */ /* INT_CHAN_0 & INT_CHAN_1 can be active at the same time */ if ((int_c&0x01) !=0 ) /* INT_CHAN_0 is active */ { if ((new_int_state&1)==0) /* now INT_CHAN_0 is changed to LOW now */ { INT0_L++; } else /* now INT_CHAN_0 is changed to HIGH now */ { INT0_H++; } invert=invert^1; /* to generate a HIGH_pulse */ } if ((int_c&0x02) !=0 ) /* INT_CHAN_1 is active */ { if ((new_int_state&2)==0) /* now INT_CHAN_1 is changed to LOW now */ { INT1_L++; } else /* now INT_CHAN_1 is changed to HIGH now */ { INT1_H++; } invert=invert^2; /* to generate a HIGH_pulse */ } now_int_state=new_int_state; /* update interrupt status */ outportb(wBase+0x2a,invert); /* generate a HIGH_pulse */ if (wIrq>=8) outportb(A2_8259,0x20); outportb(A1_8259,0x20); } /* -------------------------------------------------------------------- */ WORD pio_d48_c0(char cConfig, char cLow, char cHigh) /* COUNTER_0 */ { outportb(wBase+0xec,cConfig); outportb(wBase+0xe0,cLow); outportb(wBase+0xe0,cHigh); return(NoError); } WORD pio_d48_c1(char cConfig, char cLow, char cHigh) /* COUNTER_1 */ { outportb(wBase+0xec,cConfig); outportb(wBase+0xe4,cLow); outportb(wBase+0xe4,cHigh); return(NoError); } WORD pio_d48_c2(char cConfig, char cLow, char cHigh) /* COUNTER_2 */ { outportb(wBase+0xec,cConfig); outportb(wBase+0xe8,cLow); outportb(wBase+0xe8,cHigh); return(NoError); }