//-----------------------------------------------------------------------
//      Desc:   ECAN527 CANbus interface board diagnostic program
//      Mode:   Single host version
//      Rev:    1.0
//      Date:   10.10.1996
//      By:     Real Time Devices Scandinavia Oy (c) 1996
//              CASCODE Ltd. S.-Petesburg.  
//-----------------------------------------------------------------------

#include <\bc\include\fstream.h>        // << , >> , cout , cin
#include <\bc\include\conio.h>          // int getch(void) , int kbhit(void) , inportb(int)
					// outportb(int,char)
#include <\bc\include\iomanip.h>        // setw(int) , setfill(int)
#include <\bc\include\string.h>         // strlen(char*) , strcpy(char*,char*)
#include <\bc\include\stdlib.h>         // exit(int)
#include <\bc\include\dos.h>            // getvect(int) , setvect(int,void interrupt(*isr)())
					// disable() , enable()

#define SizeMess                8       // Dimension of message

//      82527 Address Map
//-----------------------------------
#define ControlReg              0x0
#define StatusReg               0x1
#define CPUInterfaceReg         0x2
#define GlobalMaskStandart0     0x6
#define GlobalMaskStandart1     0x7
#define GlobalMaskExtended0     0x8
#define GlobalMaskExtended1     0x9
#define GlobalMaskExtended2     0xA
#define GlobalMaskExtended3     0xB
#define Message15Mask0          0xC
#define Message15Mask1          0xD
#define Message15Mask2          0xE
#define Message15Mask3          0xF
#define CLKOUTReg               0x1F
#define BusConfigReg            0x2F
#define BitTimingReg0           0x3F
#define BitTimingReg1           0x4F
#define InterruptReg            0x5F
#define P1CONF                  0x9F
#define P2CONF                  0xAF
#define P1IN                    0xBF
#define P2IN                    0xCF
#define P1OUT                   0xDF
#define P2OUT                   0xEF
#define MESSAGE1                0x10
#define MESSAGE2                0x20
#define MESSAGE3                0x30
#define MESSAGE4                0x40
#define MESSAGE5                0x50
#define MESSAGE6                0x60
#define MESSAGE7                0x70
#define MESSAGE8                0x80
#define MESSAGE9                0x90
#define MESSAGE10               0xA0
#define MESSAGE11               0xB0
#define MESSAGE12               0xC0
#define MESSAGE13               0xD0
#define MESSAGE14               0xE0
#define MESSAGE15               0xF0

// Message Object Structure
//-----------------------------------
#define CONTROL0                0
#define CONTROL1                1
#define ARBITRATION0            2
#define ARBITRATION1            3
#define ARBITRATION2            4
#define ARBITRATION3            5
#define MESSCONF                6
#define OffsetData              7

 unsigned long BaseAddress1=0xA8000;    //Default Base Address, transmitter
 unsigned long BaseAddress2=0xA0000;    //Default Base Address, receiver
 int NumberInterrupt=3;                 //Number of interrupt for receiver
 int NumberVector;                      //Number of interrupt vector
 unsigned char far* NormAddress1;       //Base address in form SEGM:ADDR
 unsigned char far* NormAddress2;       //Base address in form SEGM:ADDR

//Message Arbitration array
 unsigned char ArbitObj[6][4] ={ 0x0,0x0,0x40,0x0,
				0x0,0x0,0x40,0x10,
				0x0,0x0,0x40,0x20,
				0x0,0x0,0x40,0x30,
				0x0,0x0,0x40,0x40,
				0x0,0x0,0x40,0x50 };

// Diagnostic of Status register of 82527 
 char*Diagn[8]={"   No  Error ",
		"   Stuff  Error",
		"   Form  Error",
		" Acknowledgment  Error",
		"   Bit  1  Error",
		"   Bit  0  Error",
		"   CRC  Error",
		"   Unused"         };

 void interrupt (*old_int)(...);        //For previous vector of interrupt 
 int FlagMask;                          //Flag need mask for 0x21 or 0xA1 port of 8259
 int FlagInt[3];                        //Flag of interrupt for message 4,5,6 

//------------------------------------------------------------------------------------------
//Function :    void BegInput (unsigned long& BaseAdd1,unsigned long& BaseAdd2,int& NmbInt )
//Purpose  :    Input base address, number of board, number of interrupt
//Returns  :    nothing
//------------------------------------------------------------------------------------------
void BegInput (unsigned long& BaseAdd1,unsigned long& BaseAdd2,int& NmbInt )

{
	clrscr();

	// Header text
	//------------
	cout<<"\n"<<"             CAN network set up on one computer  "<<'\n';
	cout<<" ECAN527 Diagnostic program Ver 1.0 (c) RTD Scandinavia Oy , 1996 ";
	cout<<"\n\n\n";

	// Input Base Address for transmitter
	//-----------------------------------
	BaseAdd1=0xA8000;        //Default value
	cout<<"Full Base Address for Transmitter Board in HEX : ";
	cin>>hex>>BaseAdd1;
	if(!cin)// if input mistake
	  {cin.clear(0); cin.seekg(0,ios::end);}
	cout<<"Address: "; cout<<hex<<BaseAdd1<<"\n\n";

	// Input Base Address for receiver
	//--------------------------------
	BaseAdd2=0xA0000;        //Default value
	cout<<"Full Base Address for Receiver Board in HEX : ";
	cin>>hex>>BaseAdd2;
	if(!cin)                // if input mistake
	  {cin.clear(0); cin.seekg(0,ios::end);}
	cout<<"Address: "; cout<<hex<<BaseAdd2<<"\n\n";

	// Input number of interrupt for receiver
	// --------------------------------------
	NmbInt=2;               //Default value
	cout<<"Receiver board interrupt in DECIMAL ( 2..7 10..15 ): ";
	cin>>dec>>NmbInt;
	if(!cin)// if input mistake
	  {cin.clear(0); cin.seekg(0,ios::end);}
	if( !((NmbInt>=2&NmbInt<=7)|(NmbInt>=10&NmbInt<=15)) )
		NmbInt=2;       //Default value
	cout<<"Interrupt: "; cout<<dec<<NmbInt<<"\n\n"<<hex;
}

//------------------------------------------------------------------------------------------
//Function :    void ResetMask(void)  
//Purpose  :    Reset mask for 0x21 or 0xA1 port of 8259   
//Returns  :    nothing
//------------------------------------------------------------------------------------------
void ResetMask(void)
{
 unsigned hlp1;
 unsigned hlp2;

	if(NumberInterrupt>=8)
		// Port 0xA1
	       {
		hlp1=1<<(NumberInterrupt-8);
		if( (inportb(0xA1))&hlp1)
		       {
			FlagMask=hlp1;
			hlp1=~hlp1;
			hlp2=(inportb(0xA1))&hlp1;
			outportb(0xA1,hlp2);
		       }
		else
			FlagMask=0;
	       }
	else
		// Port 0x21
	       {
		hlp1=1<<NumberInterrupt;
		if( (inportb(0x21))&hlp1)
		       {
			FlagMask=hlp1;
			hlp1=~hlp1;
			hlp2=(inportb(0x21))&hlp1;
			outportb(0x21,hlp2);
		       }
		else
			FlagMask=0;
	       }
       }


//------------------------------------------------------------------------------------------
//Function :    void SetMask(void)  
//Purpose  :    Sets mask for 0x21 or 0xA1 port of 8259   
//Returns  :    nothing
//------------------------------------------------------------------------------------------
void SetMask(void)
{
	int hlp;
	if(FlagMask)
	       {
		if(NumberInterrupt>=8)
		       {
			hlp=(inportb(0xA1))|FlagMask;
			outportb(0xA1,hlp);
		       }
		else
		       {
			hlp=(inportb(0x21))|FlagMask;
			outportb(0x21,hlp);
		       }
	       }
}

//------------------------------------------------------------------------------------------
//Function :    int GetNVector(int NmbInt)  
//Purpose  :    Converts physical IRQ to correct interrupt vector number
//Returns  :    XT and AT interrupot vector numbers
//------------------------------------------------------------------------------------------
int GetNVector(int NmbInt)
{
	switch(NmbInt)
	       {
		// First 8259, XT
		case 0: return 0x8;
		case 1: return 0x9;
		case 2: return 0xA;
		case 3: return 0xB;
		case 4: return 0xC;
		case 5: return 0xD;
		case 6: return 0xE;
		case 7: return 0xF;

		// Second 8259 ,AT
		case 8:  return 0x70;
		case 9:  return 0x71;
		case 10: return 0x72;
		case 11: return 0x73;
		case 12: return 0x74;
		case 13: return 0x75;
		case 14: return 0x76;
		case 15: return 0x77;
		default: return 0;
	       }
}


//------------------------------------------------------------------------------------------
//Function :    void Start527(unsigned char far* Addr527)   
//Purpose  :    Enables interrupts, this makes the CAN-controller active
//Returns  :    nothing
//------------------------------------------------------------------------------------------
void Start527(unsigned char far* Addr527)
{
	*(Addr527+ControlReg)=0x2;      // IE set
}

//------------------------------------------------------------------------------------------
//Function :    void Init527 ( unsigned char far* Addr527 ) 
//Purpose  :    Initializes all the registers for communication, refer
//              to AN82527 datasheet for register definitions
//Returns  :    nothing
//------------------------------------------------------------------------------------------

void Init527 ( unsigned char far* Addr527 )
{
	*(Addr527+ControlReg)=0x41;     // Set Init.bit; CCE bit
	*(Addr527+CLKOUTReg)=0x30;
	*(Addr527+StatusReg)=0x0;
	*(Addr527+P1CONF)=0x0;          // Port 1 for input
	*(Addr527+P2CONF)=0x3;          // Port 2 for output for leds
	*(Addr527+P2OUT)=0x1;           // Turn on green led
	*(Addr527+CPUInterfaceReg)=0x1; // Clockout enable
	*(Addr527+BusConfigReg)=0x0;    // Programate RX TX
	*(Addr527+BitTimingReg0)=0x40;  // SJW,BRP
	*(Addr527+BitTimingReg1)=0x23;  // TSEG1,TSEG2,Spl
	*(Addr527+Message15Mask0)=0xFF;
	*(Addr527+Message15Mask1)=0xFF;
	*(Addr527+Message15Mask2)=0xFF;
	*(Addr527+Message15Mask3)=0xFF;
	*(Addr527+GlobalMaskStandart0)=0xFF;
	*(Addr527+GlobalMaskStandart1)=0xFF;
	*(Addr527+GlobalMaskExtended0)=0xFF;
	*(Addr527+GlobalMaskExtended1)=0xFF;
	*(Addr527+GlobalMaskExtended2)=0xFF;
	*(Addr527+GlobalMaskExtended3)=0xFF;

	// Turn off all message objects
	// MsgVal,TXIE,RXIE,IntPnd invalid

	*(Addr527+MESSAGE1+CONTROL0)=0x55;
	*(Addr527+MESSAGE2+CONTROL0)=0x55;
	*(Addr527+MESSAGE3+CONTROL0)=0x55;
	*(Addr527+MESSAGE4+CONTROL0)=0x55;
	*(Addr527+MESSAGE5+CONTROL0)=0x55;
	*(Addr527+MESSAGE6+CONTROL0)=0x55;
	*(Addr527+MESSAGE7+CONTROL0)=0x55;
	*(Addr527+MESSAGE8+CONTROL0)=0x55;
	*(Addr527+MESSAGE9+CONTROL0)=0x55;
	*(Addr527+MESSAGE10+CONTROL0)=0x55;
	*(Addr527+MESSAGE11+CONTROL0)=0x55;
	*(Addr527+MESSAGE12+CONTROL0)=0x55;
	*(Addr527+MESSAGE13+CONTROL0)=0x55;
	*(Addr527+MESSAGE14+CONTROL0)=0x55;
	*(Addr527+MESSAGE15+CONTROL0)=0x55;

	// RmtPnd,TxRqst,MsgLst/CPUUpd,NewDat invalid

	*(Addr527+MESSAGE1+CONTROL1)=0x55;
	*(Addr527+MESSAGE2+CONTROL1)=0x55;
	*(Addr527+MESSAGE3+CONTROL1)=0x55;
	*(Addr527+MESSAGE4+CONTROL1)=0x55;
	*(Addr527+MESSAGE5+CONTROL1)=0x55;
	*(Addr527+MESSAGE6+CONTROL1)=0x55;
	*(Addr527+MESSAGE7+CONTROL1)=0x55;
	*(Addr527+MESSAGE8+CONTROL1)=0x55;
	*(Addr527+MESSAGE9+CONTROL1)=0x55;
	*(Addr527+MESSAGE10+CONTROL1)=0x55;
	*(Addr527+MESSAGE11+CONTROL1)=0x55;
	*(Addr527+MESSAGE12+CONTROL1)=0x55;
	*(Addr527+MESSAGE13+CONTROL1)=0x55;
	*(Addr527+MESSAGE14+CONTROL1)=0x55;
	*(Addr527+MESSAGE15+CONTROL1)=0x55;
}

//-------------------------------------------------
//Variable definition for [Char far* GetAddress ()]   
//-------------------------------------------------

union UAddrLng
       {
	unsigned char far* Addr;
	unsigned long Numb;
       };
//------------------------------------------------------------------------------------------
//Function :    char far* GetAddress ( unsigned long Ad)   
//Purpose  :    converts address to page and segment
//Returns  :    char type far pointer to address
//------------------------------------------------------------------------------------------
char far* GetAddress ( unsigned long Ad)
       {
	UAddrLng UAL;
	UAL.Numb=Ad;
	Ad&=0xF;
	UAL.Numb&=0xFFFF0l;
	UAL.Numb=(UAL.Numb<<12)|Ad;
	return UAL.Addr;
       }

//------------------------------------------------------------------------
//Class definitions and descriptions for screen handling and communication
//------------------------------------------------------------------------
 class MessageClass
      {
       private:
	int PozX;       // Begining pozition for X
	int PozY;       // Begining pozition for Y
	int MessN;      // Number of message
	int FlagTransmit;//Flag Transmit/Receive
	int NumByte;    // Number input bytes
	int CurrPoz;    // Current pozition for input
	int CurrX;      // Current pozition for input
	unsigned char far* Message;//Message array: Data0...Data7

       public:
	unsigned char far* Control0;
	unsigned char far* Control1;
	unsigned char far* Arbitration0;
	unsigned char far* Arbitration1;
	unsigned char far* Arbitration2;
	unsigned char far* Arbitration3;
	unsigned char far* MessConf;

	MessageClass(int PozX0,int PozY0,int MessN0,int FlagTransmit0,
		int NumByte0,int CurrPoz0,int CurrX0);

	~MessageClass(void){}

	void PrintFrame(void);
	void PrintMessage (void);
	void InsertMessage (int num);
	int ReadByte(void);
	void SetXY(void);
      };

 MessageClass::MessageClass(int PozX0,int PozY0,
		int MessN0=1,int FlagTransmit0=1,
		int NumByte0=SizeMess,int CurrPoz0=0,int CurrX0=0):
	PozX(PozX0),
	PozY(PozY0),
	MessN(MessN0),
	FlagTransmit(FlagTransmit0),
	NumByte(NumByte0),
	CurrPoz(CurrPoz0),
	CurrX(CurrX0)
       {
	if(FlagTransmit)
		Control0=NormAddress1+MessN*0x10;
	else
		Control0=NormAddress2+MessN*0x10;
	Control1=Control0+CONTROL1;
	Arbitration0=Control0+ARBITRATION0;
	Arbitration1=Control0+ARBITRATION1;
	Arbitration2=Control0+ARBITRATION2;
	Arbitration3=Control0+ARBITRATION3;
	MessConf=Control0+MESSCONF;
	Message=Control0+OffsetData;
	for(int i=0;i<NumByte;i++)
		Message[i]=0;
	if(FlagTransmit)
		// Transmit message
	       {
		*MessConf=0x8C; // Transmit,8 bytes,extended arb.
		*Control0=0x95; // MsgVal set
	       }
	else
		// Receive message
	       {
		*MessConf=0x84; // Receive,8 bytes,extended arb.
		*Control0=0x99; // MsgVal,RXIE set
	       }
	i=MessN-1;      // Index for ArbitObj[][]
	*Arbitration0=ArbitObj[i][0];
	*Arbitration1=ArbitObj[i][1];
	*Arbitration2=ArbitObj[i][2];
	*Arbitration3=ArbitObj[i][3];
       }

 void MessageClass::PrintFrame(void)
       {
	gotoxy(PozX+1,PozY-2);
	cout<<"Message"<<" "<<MessN<<"   ";
	if(FlagTransmit)
		cout<<"Transmit";
	else
		cout<<"Receive";
	gotoxy(PozX-2,PozY);
	cout<<'³';
	gotoxy(PozX-2,PozY-1);
	cout<<'Ú';
	gotoxy(PozX-2,PozY+1);
	cout<<'À';
	for(int i=0;i<NumByte*2+NumByte+1;i++)
	       {
		gotoxy(PozX-1+i,PozY-1);
		cout<<'Ä';
	       }
	gotoxy(PozX+NumByte*2+NumByte,PozY-1);
	cout<<'¿';
	gotoxy(PozX+NumByte*2+NumByte,PozY  );
	cout<<'³';
	gotoxy(PozX+NumByte*2+NumByte,PozY+1);
	cout<<'Ù';
	for(i=0;i<NumByte*2+NumByte+1;i++)
	       {
		gotoxy(PozX-1+i,PozY+1);
		cout<<'Ä';
	       }
       }

 void MessageClass::PrintMessage (void)
// Array Message[] print to screen
       {
	gotoxy(PozX,PozY);
	for(int i=0; i<NumByte;i++)
	       {
		cout<<hex<<setw(2)<<setfill('0');
		cout<<(unsigned) Message[i]<<' ';
	       }
	gotoxy(PozX,PozY);
       }

 void MessageClass::InsertMessage (int num)
// Insert half of byte to message
       {
	int i=CurrPoz/2;
	if(CurrPoz&1)
		// Odd half of byte ( low part of byte )
	       {
		Message[i]=(Message[i]&0xF0)|num;
		if ( CurrPoz==(NumByte*2-1) )
			// 1 step back
			gotoxy(PozX+CurrX,PozY);
		else
			// 2 steps forward
		       {
			CurrPoz++; CurrX+=2; cout<<' ';
		       }
	       }
	else
		// Even half of byte ( high part of byte )
	       {
		Message[i]=(Message[i]&0x0F)|(num*0x10);
		CurrPoz++; CurrX++;
	       }
	PrintMessage();
	gotoxy(PozX+CurrX,PozY);
       }

 int MessageClass::ReadByte(void)
// Input byte from keyboard
// Return code: 0 - not change
//              1 - input new number
//              2 - TAB
//              3 - SHIFT/TAB
       {
	unsigned char ch;
	int  num;
	if (!kbhit())
		return 0 ;
	ch=getch();
	// Input of number
	if ( ch>='0'&& ch<='9')
	       {
		cout<<ch;
		num=ch-'0';
		InsertMessage(num);
		return 1 ;
	       }
	if ( ch>='a'&& ch<='f')
	       {
		cout<<ch;
		num=ch-'a'+10;
		InsertMessage(num);
		return 1 ;
	       }
	if ( ch>='A'&& ch<='F')
	       {
		cout<<ch;
		num=ch-'A'+10;
		InsertMessage(num);
		return 1 ;
	       }
	// Input TAB
	if ( ch==9 )
	       {
		return 2 ;
	       }
	// Input other control key
	if(ch) return 0 ;
	ch=getch();
	switch(ch)
	       {
		case 0xF:       // SHIFT/TAB
			return 3 ;
		case 0x44:      // F10
			disable();
			SetMask();
			setvect(NumberVector,old_int);
			enable();
			clrscr();
			exit(0) ;
		case 0x47:      // Home key
			CurrX=0; CurrPoz=0;
			break;
		case 0x4D:      // Right Shift key
			if( CurrPoz!=(NumByte*2-1) )
			       {
				if( CurrPoz&1 )
					CurrX++;
				CurrPoz++; CurrX++;
			       }
			break;
		case 0x4B:      // Left Shift key
			if(CurrPoz!=0)
			       {
				if( !(CurrPoz&1) )
					CurrX--;
				CurrPoz--; CurrX--;
			       }
			break;
	       }
	gotoxy(PozX+CurrX,PozY);
	return 0 ;
       }

 void MessageClass::SetXY(void)
       {
	gotoxy(PozX+CurrX,PozY);
       }

 class FrameClass
      {
       private:
	char*Text;      // Text in frame
	int TPozX;      // X for Text
	int TPozY;      // Y for Text
	int NPozX;      // X for Number
	int NPozY;      // Y for Number
	int Length;     // Length of string
	unsigned long Nmbr;//Number for print
	int SizeNumber; // Size of field for number
	int FlagHex;    // Flag of hex/decimal
       public:
	FrameClass(char*rText,int rTPozX,int rTPozY,
		unsigned long rNmbr=0,int rSizeNumber=0,int rFlagHex=1):
	TPozX(rTPozX),TPozY(rTPozY),Nmbr(rNmbr),
	SizeNumber(rSizeNumber),FlagHex(rFlagHex)
       {
	// Input string
	Length=strlen(rText);
	Text=new char[Length+1];
	strcpy(Text,rText);
	// Calculate NPozX, NPozY
	NPozX=TPozX+Length;
	NPozY=TPozY;
       }
	~FrameClass()
       {
	delete Text;
       }
	void PrintText(void);
	void PrintAnyText(char*txt);
     };

 void FrameClass::PrintText(void)
       {
	// Print Text
	gotoxy(TPozX,TPozY);
	cout<<Text;
	// Print number
	if(SizeNumber)
	       {
		gotoxy(NPozX,NPozY);
		if(FlagHex)
			cout<<hex;
		else
			cout<<dec;
		cout<<setw(SizeNumber)<<setfill('0')<<Nmbr;
	       }
	// Print frame
	gotoxy(TPozX-2,TPozY);
	cout<<'³';
	gotoxy(TPozX-2,TPozY-1);
	cout<<'Ú';
	gotoxy(TPozX-2,TPozY+1);
	cout<<'À';
	for(int i=0;i<Length+SizeNumber+2;i++)
	       {
		gotoxy(TPozX-1+i,TPozY-1);
		cout<<'Ä';
	       }
	gotoxy(TPozX+Length+SizeNumber+1,TPozY-1);
	cout<<'¿';
	gotoxy(TPozX+Length+SizeNumber+1,TPozY  );
	cout<<'³';
	gotoxy(TPozX+Length+SizeNumber+1,TPozY+1);
	cout<<'Ù';
	for(i=0;i<Length+SizeNumber+2;i++)
	       {
		gotoxy(TPozX-1+i,TPozY+1);
		cout<<'Ä';
	       }
       }

 void FrameClass::PrintAnyText(char*txt)
       {
	gotoxy(TPozX,TPozY);
	cout<<Text;
	gotoxy(TPozX,TPozY);
	cout<<txt;
	gotoxy(TPozX,TPozY);
       }

//------------------------------------------------------------------------------------------
//Function :    void interrupt my_int(...)       
//Purpose  :    new interrupt handler
//Returns  :    nothing
//------------------------------------------------------------------------------------------
void interrupt my_int(...)
{
	unsigned char inm;
	inm=*(NormAddress2+InterruptReg);
	if(inm>=3 & inm<=5)
		// Receive only 1...3 message
	       {
		inm-=2;
		*(NormAddress2+inm*0x10+1)=0x55;
		*(NormAddress2+inm*0x10)  =0xFD;
		FlagInt[inm-1]=1;
	       }
	if(NumberVector>=0x70)
		outportb(0xA0,0x20);
	outportb(0x20,0x20);
}

//------------------------------------------------------------------------------------------
//Function :    void main(void)     
//Purpose  :    main program
//Returns  :    nothing
//------------------------------------------------------------------------------------------
void main(void)
{
	//Begining input
	BegInput(BaseAddress1,BaseAddress2,NumberInterrupt);
	NormAddress1=GetAddress(BaseAddress1);
	NormAddress2=GetAddress(BaseAddress2);
	NumberVector=GetNVector(NumberInterrupt);

	// Init. 82527
	Init527(NormAddress1);
	Init527(NormAddress2);

	//Clear all screen
	//-----------------
	clrscr();

	//Header of screen
	//----------------
	gotoxy(3,1);
	cout<<"ECAN527 Diagnostic Program Ver 1.0 (c)  ";
	cout<<"Real Time Devices Scandinavia Oy ";

	//Info field into header
	//----------------------
	//Base Address of transmitter
	FrameClass  Frm1(" Tx Address ",8,4,BaseAddress1,5);
	//Communication Speed
	FrameClass  Frm2("Speed 1 Mbit/s",29,4);
	//Base Address of receiver
	FrameClass  Frm3(" Rx Address ",47,4,BaseAddress2,5);
	//Number of interrupt for receiver
	FrameClass  Frm4("INT #",68,4,NumberInterrupt,2,0);

	//Transmit messages
	//------------------
	//Transmit message 1
	MessageClass Mess1(8,9);
	//Transmit message 2
	MessageClass Mess2(8,13,2);
	//Transmit message 3
	MessageClass Mess3(8,17,3);

	// Receive messages
	//------------------
	//Receive message 4
	MessageClass Mess4(45,9,1,0);
	//Receive message 5
	MessageClass Mess5(45,13,2,0);
	//Receive message 6
	MessageClass Mess6(45,17,3,0);

	//Start 82527
	//------------
	// Clear flag array
	for(int i=0;i<3;i++)
		FlagInt[i]=0;

	//Set interrupt vectors
	//---------------------
	disable();
	ResetMask();
	old_int=getvect(NumberVector);
	setvect(NumberVector,my_int);
	enable();

	//Start transmitter and receiver
	//------------------------------
	Start527(NormAddress1);
	Start527(NormAddress2);

	// Print screen
	//-------------
	Frm1.PrintText();
	Frm2.PrintText();
	Frm3.PrintText();
	Frm4.PrintText();
	Mess1.PrintFrame();
	Mess1.PrintMessage();
	Mess2.PrintFrame();
	Mess2.PrintMessage();
	Mess3.PrintFrame();
	Mess3.PrintMessage();
	Mess4.PrintFrame();
	Mess4.PrintMessage();
	Mess5.PrintFrame();
	Mess5.PrintMessage();
	Mess6.PrintFrame();
	Mess6.PrintMessage();

	//Info field in bottom
	//---------------------
	//Diagnostic field 1
	gotoxy(9,19);
	cout<<"Transmiter Diagnostic";
	FrameClass  Frm5("                       ",8,21);
	Frm5.PrintText();
	Frm5.PrintAnyText(Diagn[0]);
	int CurrMistake;                //Current mistake from Status Reg.
	int PrevMistake=0;              //Previous mistake from Status Reg.

	//Info about keys
	gotoxy(5,24);
	cout<<"Used keys:  Shift left/right, TAB, SHIFT/TAB, number keys, F10 exit";

	//Main Loop
	//----------
	int CurrMess=0;                 //Current transmit message: 0...2
	int FlagChangeMess=0;           //Flag of changing current message
	MessageClass*PMess=&Mess1;      //Current MessageClass
	Mess1.SetXY();

	// First transmit
	*(Mess1.Control1)=0x66;
	*(Mess2.Control1)=0x66;
	*(Mess3.Control1)=0x66;
	while(1)
	       {
		if(FlagChangeMess)
		       {
			switch(CurrMess)
			       {
				case 0: PMess=&Mess1; break;
				case 1: PMess=&Mess2; break;
				case 2: PMess=&Mess3; break;
			       }
			PMess->SetXY(); FlagChangeMess=0;
		       }
		switch(PMess->ReadByte())
		       {
			case 1: *(PMess->Control1)=0x66;        //TxRqst,NewDat
				break;                          //Data exchange
			case 2: FlagChangeMess=1;               //TAB
				if(CurrMess==2)
				       {
					CurrMess=0;
				       }
				else
				       {
					CurrMess+=1;
				       }
				break;
			case 3: FlagChangeMess=1;               //SHIFT/TAB
				if(CurrMess==0)
				       {
					CurrMess=2;
				       }
				else
				       {
					CurrMess-=1;
				       }
				break;
		       }

		//Check receive interrupt
		//-----------------------
		if(FlagInt[0])
		       {
			Mess4.PrintMessage();
			FlagInt[0]=0; PMess->SetXY();
		       }
		if(FlagInt[1])
		       {
			Mess5.PrintMessage();
			FlagInt[1]=0; PMess->SetXY();
		       }
		if(FlagInt[2])
		       {
			Mess6.PrintMessage();
			FlagInt[2]=0; PMess->SetXY();
		       }

		//Check error of 82527 transmitter
		//--------------------------------
		CurrMistake=*(NormAddress1+StatusReg);
		CurrMistake&=0x7;
		if(CurrMistake!=PrevMistake)
		       {
			PrevMistake=CurrMistake;
			Frm5.PrintAnyText(Diagn[CurrMistake]);
			PMess->SetXY();
			if(CurrMistake)
				*(NormAddress1+P2OUT)=0x2;      //Turn on red led
			else
				*(NormAddress1+P2OUT)=0x1;      //Turn on green led
		       }
	       }
}

//----------------- END OF PROGRAM ------------------------------------------------

