/* demo1 : D/O demo for PIO-D48 */ /* step 1 : connect a ADP-37/PCI to CN2 of PIO-D48 */ /* step 2 : connect CN1 of PIO-D48 to ADP-37/PCI in step 1 */ /* (by one DB-37 to DB-37 cable) */ /* step 3 : run DEMO3.EXE */ /* ----------------------------------------------------------- */ #include "PIO.H" #define A1_8259 0x20 #define A2_8259 0xA0 #define EOI 0x20 WORD init_high_1(); WORD init_low_2(); WORD init_high_3(); WORD init_high_4(); 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_1(); static void interrupt irq_service_2(); static void interrupt irq_service_3(); static void interrupt irq_service_4(); static int COUNT,now_int_state,irqmask; WORD wBase,wIrq; WORD wBase2,wIrq2; int main() { int i,j,k,jj,dd; WORD wBoards,wRetVal,j1,j2,j3; WORD wSubVendor,wSubDevice,wSubAux,wSlotBus,wSlotDevice,t1,t2,t3,t4,t5; char c; /* 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 */ /* step 3: program 8255-1-PA-PB-PC as output port */ outportb(wBase+0xcc,0x80); /* 8255-1-PA,PB,PC are all output port */ outportb(wBase+0xc0,0); /* 8255-1-PA initial=0 */ outportb(wBase+0xc4,0); /* 8255-1-PB initial=0 */ outportb(wBase+0xc8,0); /* 8255-1-PB initial=0 */ /* step 4: program 8255-2-PA-PB-PC as input port */ outportb(wBase+0xdc,0x9B); /* 8255-2-PA,PB,PC are all input port */ /* step 5: read/write test pattern */ printf("\n----------- Test1: D/I/O CN1-CN2 ------------"); i=1; for (;;) { /* send test pattern to CN1 of PIO_D48 */ outportb(wBase+0xc0,i); outportb(wBase+0xc4,i); outportb(wBase+0xc8,i); printf("\nCN1=output, CN2=input, Output=%x",i); delay(1000); /* delay for D/O settle time */ /* read test pattern to CN2 of PIO_D48 */ j1=inportb(wBase+0xd0); j2=inportb(wBase+0xd4); j3=inportb(wBase+0xd8); printf(" , DI=[%2x,%2x,%2x]",j1,j2,j3); delay(1000); if (kbhit()!=0) { c=getch(); if ((c=='q') || (c=='Q')) break; } i=i<<1; /* next bit */ if (i>0x80) { i=1; c=getch(); if ((c=='Q') || (c=='q')) break; printf("\n----------- Test1: D/I/O CN1-CN2 ------------"); } } printf("\n=========== Test2: D/I/O CN1-CN2 ============"); /* step 6: program 8255-1-PA-PB-PC as input port */ outportb(wBase+0xcc,0x9B); /* 8255-1-PA,PB,PC are all output port */ /* step 7: program 8255-2-PA-PB-PC as outport port */ outportb(wBase+0xdc,0x80); /* 8255-2-PA,PB,PC are all input port */ outportb(wBase+0xd0,0); /* 8255-1-PA initial=0 */ outportb(wBase+0xd4,0); /* 8255-1-PB initial=0 */ outportb(wBase+0xd8,0); /* 8255-1-PB initial=0 */ /* step 8: read/write test pattern */ i=1; for (;;) { /* send test pattern to CN2 of PIO_D48 */ outportb(wBase+0xd0,i); outportb(wBase+0xd4,i); printf("\nCN1=input, CN2=output, Output=%x",i); outportb(wBase+0xd8,i); delay(1000); /* delay for D/O settle time */ /* read test pattern to CN1 of PIO_D48 */ j1=inportb(wBase+0xc0); j2=inportb(wBase+0xc4); j3=inportb(wBase+0xc8); printf(" , DI=[%2x,%2x,%2x]",j1,j2,j3); delay(1000); if (kbhit()!=0) { c=getch(); if ((c=='q') || (c=='Q')) break; } i=i<<1; /* next bit */ if (i>0x80) { i=1; c=getch(); if ((c=='Q') || (c=='q')) break; printf("\n=========== Test2: D/I/O CN1-CN2 ============"); } } outportb(wBase+0xf0,0x15); /* CTRL_D0=1-->timer clock=32768 Hz */ init_high_1(); /* interrupt initialize, INIT_CHAN_3 is HIGH now */ COUNT=0; for (;;) { printf("\nTEST3: Low Pulse Count=%d (one low pulse every second) INT_STATUS=[%x %x]",COUNT, inportb(wBase+7)&8, now_int_state); if (kbhit()!=0) {getch(); break;} } outportb(wBase+0xf0,0x14); /* CTRL_D0=0-->timer clock=2M Hz */ init_high_1(); /* interrupt initialize, INIT_CHAN_3 is HIGH now */ COUNT=0; for (;;) { printf("\nTEST4: Low Pulse Count=%d (one low pulse every second) INT_STATUS=[%x %x]",COUNT, inportb(wBase+7)&8, now_int_state); if (kbhit()!=0) {getch(); break;} } init_low_2(); /* INIT_CHAN_2 */ outportb(wBase+0xcc,0x80); /* 8255-1-PA,PB,PC are all output port */ outportb(wBase+0xc0,0); outportb(wBase+0xc4,0); outportb(wBase+0xc8,0); COUNT=0; for (;;) { outportb(wBase+0xc8,1); /* PC0=1 */ printf("\nTEST5: High Pulse Count=%d",COUNT); outportb(wBase+0xc8,0); /* PC0=0 */ if (kbhit()!=0) {getch(); break;} } init_high_3(); /* INIT_CHAN_0 */ outportb(wBase+0xcc,0x80); /* 8255-1-PA,PB,PC are all output port */ outportb(wBase+0xc0,0); outportb(wBase+0xc4,0); outportb(wBase+0xc8,8); COUNT=0; for (;;) { outportb(wBase+0xc8,0); /* PC3=0 */ printf("\nTEST6: Low Pulse Count=%d",COUNT); outportb(wBase+0xc8,8); /* PC3=1 */ if (kbhit()!=0) {getch(); break;} } init_high_4(); /* INIT_CHAN_1 */ outportb(wBase+0xdc,0x80); /* 8255-1-PA,PB,PC are all output port */ outportb(wBase+0xd0,0); outportb(wBase+0xd4,0); outportb(wBase+0xd8,8); COUNT=0; for (;;) { outportb(wBase+0xd8,0); /* PC3=0 */ printf("\nTEST7: Low Pulse Count=%d",COUNT); outportb(wBase+0xd8,8); /* PC3=1 */ if (kbhit()!=0) {getch(); break;} } outportb(wBase+5,0); /* disable all interrupt */ PIO_DriverClose(); } /* -------------------------------------------------------------------- */ /* Use INT_CHAN_3 as external interrupt signal */ WORD init_high_1() { 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_1); } 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_1); } /* program OUT1 to 2 Hz */ pio_d48_c1(0x76,0,0x40); /* COUNTER1,MODE-3,32768/0x4000=2 Hz */ /* program OUT2 to 1 Hz */ /* note: the 8254 need extra 2-clock for initialization */ pio_d48_c2(0xb6,2,0); /* COUNTER2,MODE-3,2/2=1Hz */ /* Note: now the COUT2 is HIGH */ /* --> INV3 must select the inverted COUT2 */ /* --> INT_CHAN_3=!COUT2=init_LOW, active_HIGH */ outportb(wBase+0x2a,0); /* select the inverted COUT2 */ /* INT_CHAN_3=!COUT2 */ now_int_state=1; /* now COUT2 is high */ outportb(wBase+5,8); /* enable INT_CHAN_3 interrupt */ enable(); } /* -------------------------------------------------------------------- */ void interrupt irq_service_1() { if (now_int_state==1) /* now COUT2 is changed to LOW */ { /* --> INT_CHAN_3=!COUT2=HIGH now */ COUNT++; /* find a LOW_pulse (COUT2) */ if((inportb(wBase+7)&8)==0) /* the COUT2 is still fixed in LOW */ { /* --> need to generate a high_pulse */ outportb(wBase+0x2a,8); /* INV3 select the non-inverted input */ /* INT_CHAN_3=COUT2=LOW --> */ /* INT_CHAN_3 generate a high_pulse */ now_int_state=0; /* now COUT2=LOW */ } else now_int_state=1; /* now COUT2=HIGH */ /* (no need to generate high_pulse ) */ } else /* now COUT2 is changed to HIGH */ { /* --> INT_CHAN_3=COUT2=HIGH now */ /* find a HIGH_pulse (COUT2) */ if((inportb(wBase+7)&8)==8) /* the COUT2 is still fixed in HIGH */ { /* --> need to generate a high_pulse */ outportb(wBase+0x2a,0); /* INV3 select the inverted input */ /* INT_CHAN_3=!COUT2=LOW --> */ /* INT_CHAN_3 generate a high_pulse */ now_int_state=1; /* now COUT2=HIGH */ } else now_int_state=0; /* now COUT2=LOW */ /* (no need to generate 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); } /* -------------------------------------------------------------------- */ /* Use INT_CHAN_2 as external interrupt signal */ WORD init_low_2() { DWORD dwVal; disable(); if (wIrq<8) { irqmask=inportb(A1_8259+1); outportb(A1_8259+1,irqmask & (0xff ^ (1 << wIrq))); setvect(wIrq+8, irq_service_2); } 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_2); } outportb(wBase+5,0); /* disable all interrupt */ /* select PC0 of port_2 as init_HIGH & active_LOW sinal */ outportb(wBase+0xf0,0); /* CTRL_D1=0 -> init_HIGH, active_LOW */ /* NOTE : The 8254 need the extra starting two event_clock to initialize */ /* So the counter value before the starting two clock is error */ pio_d48_c0(0x30,1,0); /* COUNTER0,mode-0 down count 1+2=5 */ /* Note: now the COUT0 is LOW */ /* --> INV2 must select the non-inverted COUT0 */ /* --> INT_CHAN_2=COUT0=init_LOW, active_HIGH */ outportb(wBase+0x2a,4); /* select the non-inverted COUT0 */ /* INT_CHAN_2=COUT0=LOW now */ now_int_state=0; /* now COUT0 is LOW */ outportb(wBase+5,4); /* enable INT_CHAN_2 interrupt */ enable(); } /* -------------------------------------------------------------------- */ void interrupt irq_service_2() { if (now_int_state==0) /* now COUT0 is changed to HIGH */ { /* --> INT_CHAN_2=COUT0=HIGH now */ COUNT++; /* find a HIGH_pulse (COUT0) */ pio_d48_c0(0x30,1,0); /* COUNTER0,mode-0 down count 1+2=3 */ /* now INT_CHAN_2=COUT0=LOW now --> */ /* INT_CHAN_2 generate a HIGH_pulse */ now_int_state=0; /* now COUT0=LOW */ } if (wIrq>=8) outportb(A2_8259,0x20); outportb(A1_8259,0x20); } /* -------------------------------------------------------------------- */ /* Use INT_CHAN_0 as external interrupt signal */ WORD init_high_3() { 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_3); } 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_3); } /* select PC3 & PC7 of port_2 as interrupt signal */ outportb(wBase+0xf0,0x10); /* CTRL_D3=0,CTRL_D2=0 --> */ /* INT_CHAN_0=PC3&!PC7 -> */ /* PC7 can enable/disable PC3 */ /* PC3 can enable/disable PC7 */ /* Note: In this demo, assume the PC3 is init_HIGH & active_LOW */ /* the PC7 is used to enable/disable PC3 --> */ /* PC7=VCC --> PC3-interrupt is disable */ /* PC7=GND --> PC3-interrupt is enable */ /* ------------------------------------------------------------ */ /* now the PC3 of port-2 is HIGH */ /* --> INV0 must select the inverted PC3 */ /* --> INT_CHAN_0=!PC3=init_LOW, active_HIGH */ outportb(wBase+0x2a,0); /* select the inverted PC3 */ /* INT_CHAN_0=!PC3 */ now_int_state=1; /* now PC3 is high */ outportb(wBase+5,1); /* enable INT_CHAN_0 interrupt */ enable(); } /* -------------------------------------------------------------------- */ void interrupt irq_service_3() { if (now_int_state==1) /* now PC3 is changed to LOW */ { /* --> INT_CHAN_3=!PC3=HIGH now */ COUNT++; /* find a LOW_pulse (PC3) */ if((inportb(wBase+7)&1)==0) /* the PC3 is still fixed in LOW */ { /* --> need to generate a high_pulse */ outportb(wBase+0x2a,1); /* INV0 select the non-inverted input */ /* INT_CHAN_0=PC3=LOW --> */ /* INT_CHAN_0 generate a high_pulse */ now_int_state=0; /* now PC3=LOW */ } else now_int_state=1; /* now PC3=HIGH */ /* (no need to generate high_pulse ) */ } else /* now PC3 is changed to HIGH */ { /* --> INT_CHAN_0=PC3=HIGH now */ /* find a HIGH_pulse (PC3) */ if((inportb(wBase+7)&1)==1) /* the PC3 is still fixed in HIGH */ { /* --> need to generate a high_pulse */ outportb(wBase+0x2a,0); /* INV0 select the inverted input */ /* INT_CHAN_0=!PC3=LOW --> */ /* INT_CHAN_0 generate a high_pulse */ now_int_state=1; /* now PC3=HIGH */ } else now_int_state=0; /* now PC3=LOW */ /* (no need to generate high_pulse ) */ } if (wIrq>=8) outportb(A2_8259,0x20); outportb(A1_8259,0x20); } /* -------------------------------------------------------------------- */ /* Use INT_CHAN_1 as external interrupt signal */ WORD init_high_4() { 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_4); } 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_4); } /* select PC3 & !PC7 of port_5 as interrupt signal */ outportb(wBase+0xf0,0x04); /* CTRL_D5=0,CTRL_D4=0 --> */ /* INT_CHAN_1=PC3&!PC7 -> */ /* PC7 can enable/disable PC3 */ /* Note: In this demo, assume the PC3 is init_HIGH & active_LOW */ /* the PC7 is used to enable/disable PC3 --> */ /* PC7=VCC --> PC3-interrupt is disable */ /* PC7=GND --> PC3-interrupt is enable */ /* ------------------------------------------------------------ */ /* now the PC3 of port-5 is HIGH */ /* --> INV1 must select the inverted PC3 */ /* --> INT_CHAN_1=!PC3=init_LOW, active_HIGH */ outportb(wBase+0x2a,0); /* select the inverted PC3 */ /* INT_CHAN_1=!PC3 */ now_int_state=1; /* now PC3 is high */ outportb(wBase+5,2); /* enable INT_CHAN_1 interrupt */ enable(); } /* -------------------------------------------------------------------- */ void interrupt irq_service_4() { if (now_int_state==1) /* now PC3 is changed to LOW */ { /* --> INT_CHAN_1=!PC3=HIGH now */ COUNT++; /* find a LOW_pulse (PC3) */ if((inportb(wBase+7)&2)==0) /* the PC3 is still fixed in LOW */ { /* --> need to generate a high_pulse */ outportb(wBase+0x2a,2); /* INV1 select the non-inverted input */ /* INT_CHAN_1=PC3=LOW --> */ /* INT_CHAN_1 generate a high_pulse */ now_int_state=0; /* now PC3=LOW */ } else now_int_state=1; /* now PC3=HIGH */ /* (no need to generate high_pulse ) */ } else /* now PC3 is changed to HIGH */ { /* --> INT_CHAN_1=PC3=HIGH now */ /* find a HIGH_pulse (PC3) */ if((inportb(wBase+7)&2)==2) /* the PC3 is still fixed in LOW */ { /* --> need to generate a high_pulse */ outportb(wBase+0x2a,0); /* INV1 select the inverted input */ /* INT_CHAN_1=!PC3=LOW --> */ /* INT_CHAN_1 generate a high_pulse */ now_int_state=1; /* now PC3=HIGH */ } else now_int_state=0; /* now PC3=HIGH */ /* (no need to generate high_pulse ) */ } if (wIrq>=8) outportb(A2_8259,0x20); outportb(A1_8259,0x20); }