//----------------------------------------------------------------
//  Desc:	ECAN527 CANbus interface board diagnostic program
//  Mode:	Dual host version, two boards on different hosts
//  Rev:	1.0
//  Date:	10.10.1996
//  Compiler:	Borland C, Version 4.5
//  By:		Real Time Devices Scandinavia Oy (c) 1996
//          	A/O CASCOD S.Petesburg
//----------------------------------------------------------------

#include <fstream.h>    	// << , >> , cout , cin
#include <conio.h>      	// int getch(void) , int kbhit(void) , inportb(int)
				// outportb(int,char)
#include <iomanip.h>    	// setw(int) , setfill(int)
#include <string.h>     	// strlen(char*) , strcpy(char*,char*)
#include <stdlib.h>     	// exit(int)
#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 BaseAddress;     	//Base Address
 int NumberBoard;               	//Board identifier
 int NumberInterrupt;           	//Number of interrupt
 int NumberVector;              	//Number of vector
 unsigned char far* NormAddress;	//Base address in form SEGM:ADDR

//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 82527 from Status Register
 char*Diagn[8]={"       No  Error ",
                "       Stuff  Error",
                "       Form  Error",
                "       Acknowledgment  Error",
                "       Bit  1  Error",
		"       Bit  0  Error",
                "       CRC  Error",
                "       Unused"         };
 int FlagMask;  			//Flag need mask for 0x21 or 0xA1 port of 8259
 int FlagInt[3];                	//Flag of interrupt for message 4,5,6
 void interrupt (*old_int)(...);	//For previous vector of interrupt

//------------------------------------------------------------------------
//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 to 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 vector number
//Returns:    XT and AT 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:     converd 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;
}

//----------------------------------------------------------------------------
//Function:    void BegInput (unsigned long& BaseAdd,int& NmbBrd,int& NmbInt )
//Purpose:     Input base address, number of board, number of interrupt
//Returns:     nothing
//----------------------------------------------------------------------------
void BegInput (unsigned long& BaseAdd,int& NmbBrd,int& NmbInt )
{
	clrscr();
	// Header text
	cout<<"\n"<<"             CAN network set up on two computers  "<<'\n';
	cout<<" ECAN527 Diagnostic program Ver 1.0 (c) RTD Scandinavia Oy , 1996 ";
	cout<<"\n\n\n";

	// Input Base Address
	//-------------------
	BaseAdd=0xA8000;        //Default value
	cout<<"Full Base Address for board in HEX : ";
	cin>>hex>>BaseAdd;
	if(!cin)		// if input mistake
	  {cin.clear(0); cin.seekg(0,ios::end);}
	cout<<"Address: "; cout<<hex<<BaseAdd<<"\n\n";

	// Input board identifier
	//-----------------------
	NmbBrd=1;               //Default value
	cout<<"Board identifier ( 1 or 2 ): ";
	cin>>hex>>NmbBrd;
	if(!cin)		// if input mistake
	  {cin.clear(0); cin.seekg(0,ios::end);}
	if( !(NmbBrd==1|NmbBrd==2) )
		NmbBrd=1;       //Default value
	cout<<"Identifier: "; cout<<dec<<NmbBrd<<"\n\n"<<hex;

	// Input number of interrupt
	// --------------------------
	NmbInt=2;               //Default value
	cout<<"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;
}

//-------------------------------------------------------
//Class definitions 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)
       {
	Control0=NormAddress+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[][]
	if(NumberBoard==2)
		// Board 2
	       {
		if(i<=2) i+=3;
		else     i-=3;
	       }
	*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=*(NormAddress+InterruptReg);
	if(inm>=6 & inm<=8)
		// Receive only 4...6 message
	       {
		inm-=2;
		*(NormAddress+inm*0x10+1)=0x55;
		*(NormAddress+inm*0x10)  =0xFD;
		FlagInt[inm-4]=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 (BaseAddress,NumberBoard,NumberInterrupt);
	NormAddress=GetAddress(BaseAddress);
	NumberVector=GetNVector(NumberInterrupt);

	// Init. 82527
	Init527(NormAddress);

	//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 in head
	//-------------------
	//Board identifier
	FrameClass  Frm1("Board #",8,4,NumberBoard,1);
	//Base Address of board
	FrameClass  Frm2("Base Address: ",20,4,BaseAddress,5);
	//Communication speed
	FrameClass  Frm3("Speed 1 Mbit/s",43,4);
	//Number of interrupt
	FrameClass  Frm4("INT #",61,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,4,0);
	//Receive message 5
	MessageClass Mess5(45,13,5,0);
	//Receive message 6
	MessageClass Mess6(45,17,6,0);

	//Start 82527
	//------------
	// Clear flag array
	for(int i=0;i<3;i++)
		FlagInt[i]=0;
	disable();
	ResetMask();
	old_int=getvect(NumberVector);
	setvect(NumberVector,my_int);
	enable();
	Start527(NormAddress);

	// 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
	gotoxy(9,19);
	cout<<"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
		CurrMistake=*(NormAddress+StatusReg);
		CurrMistake&=0x7;
		if(CurrMistake!=PrevMistake)
		       {
			PrevMistake=CurrMistake;
			Frm5.PrintAnyText(Diagn[CurrMistake]);
			PMess->SetXY();
			if(CurrMistake)
				*(NormAddress+P2OUT)=0x2; // Turn on red led
			else
				*(NormAddress+P2OUT)=0x1; // Turn on green led
		       }
	       }
       }


//---------------- END OF PROGRAM ----------------------------