/* ----------------------------------------------------------- */

/* demo 7 : test RS-232 port (single VXC-112A + PC-COM1)       */

/* step 1 : RS-232 port of vxc112A connect to COM1 of PC       */

/* step 2 : run DEMO7.EXE				                       */

/* NOTE   : PC_COM1=send=polling,   receive=polling	           */

/*	    Vxc112A=send=interrupt, receive=interrupt	           */

/* ----------------------------------------------------------- */



#include "..\PIO.H"

#include "..\VxCard.h"

#define COM1	  0x3f8

#define COM2	  0x2f8

#define COM3	  0x3e8

#define COM4	  0x2e8



#define A1_8259   0x20

#define A2_8259   0xA0

#define EOI	      0x20



#define A1_8259   0x20

#define A2_8259   0xA0

#define EOI	      0x20

#define LLL	      64



WORD init_low();

WORD restore_int();

void interrupt (*oldfunc) ();

static void interrupt irq_service();

int  rs232_val,rs232_status,irqmask,now_int_state;

char buf[1000];

WORD front,rear;



WORD wBase,wIrq,wBase0,wBase1,wA0,wA1;

WORD wT=32000;



int main()

{

    int   t,tt,i,j,ii,jj,k,i2,j2;

    char  c;

    char  cCmd[50];

    int   iRet,iComPort;

    DWORD dd;

    WORD  wSubVendor,wSubDevice,wSubAux,wSlotBus,wSlotDevice;

	WORD  wBoards,wRetVal,t1,t2,t3,t4,t5,t0,tt0,tt1;



	clrscr();

	/* step 1: find address-mapping of PIO/PISO cards		  */

	wRetVal=PIO_DriverInit(&wBoards,0x1D61,0x00,0x00);  /* for VXC-112A */

	printf("\nThrer are %d VXC-112A Cards in this PC; Ret=%d",wBoards, wRetVal);

    if (wBoards==0) return 1;



    printf("\n--------------- The Configuration Space ---------------");

    for(i=0; i<wBoards; i++)

    {

        PIO_GetConfigAddressSpace(i,&wBase,&wIrq,&wSubVendor,&wSubDevice,

                &wSubAux,&wSlotBus,&wSlotDevice);

		printf("\nCard_%d: wBase=%x,wIrq=%x,subID=[%x,%x],SlotID=[%x,%x]",i,wBase,wIrq,wSubVendor,wSubDevice,wSlotBus,wSlotDevice);

		printf(" --> ");

		ShowPioPiso(wSubVendor,wSubDevice,wSubAux);

    }



    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  */

    Vxc_SetConfig(wBase, VXC_112A_CONFIG);   /* for VXC-112A */

    Vxc_SetLed(wBase, VXC_112A_LED_ON); 	 /* led on	   */

    Vxc_SetSpeedMode(wBase,1,VXC_LOW_SPEED); /* low speed	   */



    printf("\ninit 1");

    init_low();

	printf("\ninit 2\n");



	/* step 3: select port  */

	printf("Please select 1:Port1, or other keys:Port2\n");

    wA1=wBase + ( '1' == getch()? VXC_PORT1 : VXC_PORT2 );



    iRet=Vxc_OpenCom(wA1,115200L, "8N1");   /* RS-232 of VXC-112A=115200	   */

    if (iRet==0) printf("\n\n(1) Open card_0 OK");

	else         printf("\niRET=%d",iRet);



    iRet=Vxc_OpenCom(COM1, 115200L, "8N1");   /* RS_232 of PC-COM1=115200	   */

    if (iRet==0) printf("\n\n(1) Open PC COM OK");

	else         printf("\niRET=%d",iRet);



	outportb(wA1 + VXC_IER, 1);



    i=0x55; j=0xaa; rs232_status=0;

    for (;;)

    {

        t0=0; t1=0; tt0=0; tt1=0; i2=0; j2=0;



        for (t1=0; t1<LLL; t1++) Vxc_SendRs232(j+t1);



		for (;;)

        {

            if (t0<LLL)

            {

                if ( 0 == Vxc_SendChar(COM1, i+t0, 2) ) /* pc-send=polling */

					t0++;

            }



            if ( 0 == Vxc_ReceiveChar(COM1, &k, 2) )    /* pc-receive=polling */

            {

	            k-=(j+j2)&0xff;

				if (k!=0) {

                    printf("[Err0,%2x,%2x]",k,j); 

                    return 1; 

                }

	            tt0++; j2++;

	        }



			if (rs232_status==1)		/* vxc-112A-receive=interrupt */

	        {

                k=rs232_val;

	            k-=(i+i2)&0xff;

			    rs232_status=0;

			    if (k!=0) {

                    printf("[Err1,%2x,%2x]",k,i); 

                    return 1; 

                }

			    tt1++; i2++;

	        }

            if ((tt0>=LLL) && (tt1>=LLL)) 

                break;

		}



        i++; i=i&0xff;

        j++; j=j&0xff;

        if (kbhit()!=0) {getch(); break;}

        printf("\n[i=%2x, j=%2x] [front=%d, rear=%d",i,j,front,rear);

    }



    restore_int();

    PIO_DriverClose();

	return 0;

}



/* -------------------------------------------------------------- */



WORD init_low()

{

    DWORD dwVal;



    disable();

    outportb(wBase+5,0);			 /* disable all interrupt */



    if (wIrq<8)

    {

        oldfunc=getvect(wIrq+8);

        irqmask=inportb(A1_8259+1);

		outportb(A1_8259+1,irqmask & (0xff ^ (1 << wIrq)));

        setvect(wIrq+8, irq_service);

    } else {

        oldfunc=getvect(wIrq-8+0x70);

        irqmask=inportb(A1_8259+1);

		outportb(A1_8259+1,irqmask & 0xfb);			  /* IRQ2 */

		irqmask=inportb(A2_8259+1);

		outportb(A2_8259+1,irqmask & (0xff ^ (1 << (wIrq-8))));

		setvect(wIrq-8+0x70, irq_service);

	}



	outportb(wBase+0x2a,12); 	       /* non-invert COM1	  */

	now_int_state=0x0;		           /* now COM1 is low	  */

	outportb(wBase+5,12);		       /* enable DI1 interrupt	  */

	enable();



	front=rear=0;			           /* send queue empty	  */

	return 0;

}



/* -------------------------------------------------------------- */



WORD restore_int()

{

	disable();



	outportb(wBase+5,0);			 /* disable all interrupt */

	if (wIrq<8)

	{

		setvect(wIrq+8,oldfunc);

	} else {

		setvect(wIrq-8+0x70,oldfunc);

	}

	return 0;

}



/* -------------------------------------------------------------- */



void interrupt irq_service()

{

	WORD data;



	Vxc_SetLed(wBase, VXC_LED_OFF); 	/* led OFF	 */

	switch(inportb(wA1+VXC_IIR)&0x07)

	{

	case 0 : break;

	case 1 : goto end;

	case 2 : /* send data    */

		if (front!=rear)

		{

			if (rear<900) rear++; else rear=0;

			data=buf[rear]&0xff;

			outportb(wA1 + VXC_THR, data);

			if (front==rear) outportb(wA1 + VXC_IER,0x01);

		} else

			outportb(wA1 + VXC_IER,0x01);

		   break;

	case 4 : /* receive data */

		rs232_status=1;

		rs232_val=inportb(wA1);

		break;

	default: goto end;

	}



end:

	if (wIrq>=8) outportb(A2_8259,0x20);

	outportb(A1_8259,0x20);

	Vxc_SetLed(wBase, VXC_112A_LED_ON); 	/* led ON	 */

}



/* -------------------------------------------------------------- */



Vxc_SendRs232(int data)

{

	if (front<900) front++; else front=0;

	buf[front]=data;

	outportb(wA1+VXC_IER,0x03);

	return 0;

}



