The communications function is partly an interrupt driven function. It's
using interrupt number 4 and registerset number 3 of the 80535 processor.
If
it receives an interrupt it tries to find-out who was interrupting. It can
either be the send (TI bit) or receive (RI bit). The whole communication part
exist out of 4 parts.
The first part is the so called
Communication_Interface which deals with the interrupt's. The second part part
is the so called "Receive_Char" function which is grabbing the
characters coming from MCAD. The thrid part so called "TransMit_Char"
deals with sending characters to MCAD. It includes also an standard function so
called "Putchar". This function has slitly changed and is therefore
included as seperad source file which you can find in the same directory as the
progam "MCAM".
The last bit is the so called "Calc_CheckSum"
function which does a simple calculation to add a checksum byte to the message
or check the checksum if it has received an message.
It is only possible to get into this function by receiving an interrupt.
The function then first looks to see if it is an RI interrupt which means that
we have received an character from MCAD. If it has recieved an charachter it
then set the "TransMitStatus flag to zero. This is done because the
communication protocol is a synchroniced protocol. Meaning if MCAD sends then we
are not alowed to send or visa versa. Then we check to findout if we already
have received the control-byte from MCAD. If so that then means that the rest of
the characters are coming in. So you see that we only allow the system to
interrupt twice. After that we go to the function Recieve_Char to receive the
rest. I could have done it all under interrupt control but ones we get the
control-byte from MCAD we then will receive more. And the system is normally not
busy with doing anything else. If all the characters needs to be interrupt
driven then we need to created an pointer to keep track of where we are in
receiving characters. In Receive_Char you will see that we use the value count
for receiving characters which comes from MCAD.
If the interrupt was a TI
interrupt then I first see if we have to send something by checking the flag
TransMitStatus. If these both are true then we have to send and therefore go
into TransMit_Char(variable) to send what we have to send.
/*===========================================================================*/ /* FunctionName : Communication_Interface. */ /* FunctionInput : SBUF via Interrupt. */ /* FunctionOutput: NONE. */ /* CommonVarUse : TransMitStatus, SBUF */ /* StructureUse : ReceiveInfo. */ /* Description : This function is an interrupt drive function. It checks */ /* : weather it needs sending or receiving. */ /* LastUpdated : ../../96 [.... Test] */ /*===========================================================================*/ #pragma NOAREGS void Communication_Interface(void) interrupt 4 using 3 { unsigned char xdata Edit; if (RI) /* See if received something */ { TransMitStatus=0; /* No transmition allowed */ if (ReceivedInfo.ControlByte[0]) /* Received control byte ? */ { ES=0; /* Disable Interrupt on Serial */ TimeOutSet = 500; /* TimeOut using 500 mSec. */ Receive_Char(); /* Get the rest of it. */ ES=1; /* Interrupts allowed */ } else { Edit=SBUF; /* Get character from SBUF */ if (Edit & 0xc0 ) /* Yes, got you. */ { ReceivedInfo.ControlByte[0]=Edit; } } ES=1; /* Enable transmitting. */ RI=0; /* Get ready for next Byte */ } if (TransMitStatus) /* Something to send ? */ { ES = 1; /* If so enable transmitting */ TransMit_Char(NumbOfChars); /* OK, we need transmitting */ } return; } #pragma AREGS
/*==============================*/ /* FunctionName : Receive Character. */ /* FunctionInput : None. */ /* FunctionOutput: None. */ /* CommonVarUse : */ /* StructureUse : ReceivedInfo. */ /* Description : The first to byte's are read separed, the Argument are */ /* : read through a loop. The loop information comes from SYS */ /* : (mum) and is hidden into the controlbyte. */ /* : Getkey is a standard Lib. function but is changed due to */ /* : us timeouts. */ /* LastUpdated : ../../96 [.... Test] */ /*===========================================================================*/ void Receive_Char(void) { int xdata Counter, xdata Counter1; unsigned char xdata ChkSum; char *Pointer; ReceivedInfo.MechName[0] = _getkey(); /* Second Byte is Mech. Name */ ReceivedInfo.MechAction[0] = _getkey(); /* Third Byte is Action on Mech.*/ Counter=ReceivedInfo.ControlByte[0] & 0x3f; /* Get counter for bytes to Rec.*/ NumbOfChars=Counter; for (Counter1=0; Counter1 < (Counter-2); Counter1++) /* Sys has said so... */ { ReceivedInfo.Argument[Counter1] = _getkey(); /* Get arguments for Mech or */ } ReceivedInfo.CheckSum[0] = _getkey(); /* Last byte is Checksum */ MessageRec = 1; /* Set for interpetation */ Pointer=&ReceivedInfo.MechName[0]; /* Create pointer for CheckSum */ ChkSum = Calc_CheckSum(&ReceivedInfo.MechName[0]); /* Calculate Checksum */ if (ChkSum != ReceivedInfo.CheckSum[0]) /* Check if equal */ { SendInfo.ACK[0]= Nack; /* Sys wants NACK if not */ TransMitStatus = 1; /* Make Sure SYS receives NACK */ MessageRec = 0; /* Prefent for interpetation */ Clear_ReceivedInfo(); /* Clear Received Messages */ NumbOfChars=0; /* Nothing Received Well */ } ReceivedInfo.ControlByte[0] = Reset; /* All Received wait for next */ return; }
This function makes sure that all characters in the Transmit Buffer will be send to MCAD. On entry we first get the number of characters to send. This number is also used for calculating the Checksum which is the second step in this function. After the calculation has been done we then trigger MCAD with the first Character, either a NACK or an ACK.The Third step is to send the arguments if any. The last step is to send the Checksum byte over. On exit we clear the buffer and resetting some flags.
/*========================================================================================================================*/ /* FunctionName : TransMitting Characters */ /* FunctionInput : */ /* FunctionOutput: */ /* CommonVarUse : */ /* StructureUse : */ /* Description : */ /* : */ /* : */ /* : */ /* : */ /* LastUpdated : ../../96 [.... Test] */ /*===========================================================================*/ void TransMit_Char(int CharsToSend) { int xdata Counter; NumbOfChars=NumbOfChars+1; SendInfo.CheckSum[0] = Calc_CheckSum(&SendInfo.ACK[0]); putchar (SendInfo.ACK[0]); /* Send ACK or NACK as first */ NumbOfChars=NumbOfChars-1; for (Counter=0; Counter < CharsToSend; Counter++) { putchar (SendInfo.Argument[Counter]); /* Send Character SBUF out */ } putchar (SendInfo.CheckSum[0]); /* They want CheckSums as well, why ? */ TransMitStatus = 0; /* All send so stop Sending */ Clear_SendInfo(); /* Clear Structure for Re-use */ NumbOfChars=0; /* Nothing left to send */ ES=1; return; }
The function to Calculate a Checksum is added because of some secure way to communicated. This is only a 8 bit checksum and it adds just all values in the Send buffer or in the Receive Buffer. The only variable past on to this function is a pointer which points to the message of which we have to calculate the Checksum. If the Checksum passes the 8-bit max. value then we just ignore the most-significant value.
/*===========================================================================*/ /* FunctionName : Calculate Checksum */ /* FunctionInput : */ /* FunctionOutput: */ /* CommonVarUse : */ /* StructureUse : */ /* Description : */ /* : */ /* : */ /* : */ /* : */ /* LastUpdated : ../../96 [.... Test] */ /*===========================================================================*/ unsigned char Calc_CheckSum (char *Pointer) { unsigned char xdata ChkSum; int xdata Counter; ChkSum=0; for (Counter=0; Counter < NumbOfChars; Counter++) { ChkSum = ChkSum + *Pointer++; } return ChkSum; }