indexpreviousnext

file name: lance.hpp, lance.cpp
classification: simulation
contents: class CLance
derived from: CApplControlledObject, CCrashingModule and CNeedInterrupt
use: provides an interface to the clock interface (CI) of the network driver (ci.hpp)
 

global items used:


local items used:

const addr broadcastAddress: the address used to specify a broadcast message.

const int AddedBufferLength: the size of additional buffer that the Lance needs for sending own information. Whenever GetBuffer() is called, the Lance allocates AddedBufferLength bytes more, but returns a pointer to the first byte after this additional portion. Thus, for the caller, the function behaves as expected, but internally there is an additional buffer allocated at the front.
Note: currently, the size is set to four bytes, because the Lance adds the message ID.
 

local (static) functions of the implementation file:

bufx *BufToBufx (char *buf): If buf is NULL, then the function returns NULL. Otherwise, it assumes that buf is part of a bufx buffer allocated by GetBuffer() and that AddedBufferLength bytes before buf belong to bufx as well. The function returns a pointer to the address bufx-AddedBufferLength, which is cast to type bufx*.

char *BufxToBuf (bufx *buf): If buf is NULL, then the function returns NULL. Otherwise, it casts buf to type char* and returns a pointer to the address of byte AddedBufferLength.

void ExtractMessage (bufx *buf, INT16 size, SINT32 nodeID, int if_num, STimeData *time, char **message, INT16 *msgsize): extracts the original message from the message buffer announced by the Lance. The data that was automatically inserted into the buffer (the clock value and area of the sender) is stored in time. The rest of the message is put into message (an array of characters is allocated for it) and the size of that array is stored in msgsize. If one of the pointers is NULL, an assert fails.
The function asserts that all added items have sizes between zero and four byte. In addition, the accuracy may only have a size of zero, two or four bytes. And if the size of the macrostamp is greater than zero, the timestamp must have a size of four bytes.
If an item has a size less than four bytes, it is assumed that the following part of the original four byte value was transmitted:

The function reassembles the data into the four-byte values of STimeData. The bits that were not transmitted are set to zero. Thus, if the length of an item was zero, the value is set to zero.

void CI_GetBuffer (INT16 size, bufx **buf, int if_num, int area):
void CI_GetEnvelope (int mode, tenvx **tenv, int if_num, int area):
void CI_RetBuffer (bufx *buf):
void CI_RetEnvelope (tenvx *tenv):
void CI_Send (int mode, tenvx *tenv, bufx **buf, INT16 size, int if_num, int area):
Same as the CI functions. The functions are just wrappers to hide the use of the CI dispatcher.
 

member variables:

int area_: the area of the application.
default: parameter area of the ctor

CClockInterface *clock_: a pointer to the associated clock.
default: NULL

CClockSync *clockSync_: a pointer to the associated clock synchronization module. If it is set to NULL, incoming messages are ignored.
default: NULL

SRandomData distDataRecv_: distribution data used for choosing the delay of outgoing messages.
default and reset value: dist=Uniform, all other members are 0

SRandomData distDataSend_: distribution data used for choosing the delay of outgoing messages.
default and reset value: dist=Uniform, all other members are 0

CDelayList listOfDelayedMessages_: the list of all currently delayed messages.
default and reset value: empty list

SDelayMcb msg_: the delayed message that is handled (sent or delivered) next.
default and reset value: NULL

INT32 msgID_: the number of the next message that is sent.
default and reset value: 0

double pRecvDuplicate_: the probability that an incoming message is duplicated.
default and reset value: 0

double pSendDuplicate_: the probability that an outgoing message is duplicated.
default and reset value: 0

double pRecvScramble_: the probability that an incoming message is scrambled.
default and reset value: 0

double pSendScramble_: the probability that an outgoing message is scrambled.
default and reset value: 0

CRandom random_: the random class used to obtain the delay of a message.

EBool suspended_: is set to True if the Lance is currently suspended (in this case, incoming messages are ignored). If Send() is called, the variable is set to False.
default and reset value: True
 

member functions:

CLance (CControllingObject *ctrl, int area): Calls Init() to set all members to their default values, installs the ISR for duty timer B5 using SetISR(). Interrupts are turned off using DisableInterrupts() before the call to SetISR() and turned on using EnableInterrupts() afterwards.

~CLance (): If member clock is not NULL, the duty timer B5 interrupt and timer itself are disabled via the functions DisableInterrupt() and DisableDutyTimer() of CClockInterface. The ISR is removed from the vector table through a call to RemoveISR(), which is again placed within a call to DisableInterrupts() and EnableInterrupts(). Then, Dispose() is called to delete the dynamic members.

void Announce (renvx *renv, bufx *buf, INT16 size, int if_num): The function calls ModifyCrashStatus(), then checks if the module is crashed or suspended. If it is, ReportMessageEvent() is called with DiscardRecvMessage and renv and buf are returned using RetReceiveEnvelope() and RetReceiveBuffer(). If the module is not crashed, DelayMessage() is called to delay the message. If the message should be duplicated, then renv and buf are copied into freshly allocated structures and DelayMessage() is called a second time for the duplicated message. In this case, ReportMessageEvent() is called with DuplicateRecvMessage to report the duplication.
Note: the function assumes that renv and buf are local and were allocated using the member functions GetReceiveBuffer() and GetReceiveEnvelope().

void AnnounceNow (renvx *renv, bufx *buf, INT16 size, int if_num): The function is called by the isr() and delivers the message to the ClockSync module.
The function first checks if a ClockSync module is attached (that is, member clockSync is not NULL). If there is none, ReportMessageEvent() is called with DiscardRecvMessage and renv and buf are returned using RetReceiveEnvelope() and RetReceiveBuffer(). Then the function returns.
Otherwise, ExtractMessage() is called to get the original message, ModifyCrashStatus() is invoked, and afterwards the function checks if the module is crashed or suspended. If it is, ReportMessageEvent() is called with DiscardRecvMessage, the buffers are returned as described above and the function returns.
Otherwise, ScrambleMessage() is called with the sender address, the sender time and the original data buffer, and at last CClockSync::Announce() is called to deliver the message. Afterwards, the buffers are returned.
Note: the function assumes that renv and buf are local and were allocated using the member functions GetReceiveBuffer() and GetReceiveEnvelope().

int Crash (): Calls the Crash() function of the base class CCrashingModule to crash the module, but in addition calls DeleteDelayedMessages() to discard all delayed messages.

DelayMessage (int mode, tenvx *tenv, char *message, INT16 msgsize, int if_num, int area): Delays outgoing messages according to distDataSend. The function gets the current time from the clock, then delays the message according to the computed delay and calls Insert() to put the message into the listOfDelayedMessages.
If member clock is NULL, an assert fails.

DelayMessage (renvx *renv, bufx *buf, INT16 size, int if_num): Delays incoming messages. Has the same behaviour as the function described above, but uses the data structures for incoming messages.
If member clock is NULL, an assert fails.

void DeleteDelayedMessages (): If member msg is NULL, the function returns at once. Otherwise, it disables the duty timer B5, then deletes all messages contained in msg or stored in the listOfDelayedMessages. At last, msg is set to NULL.

Dispose (): Calls DeleteDelayedMessages() to discard all currently delayed messages, then deletes members random and listOfDelayedMessages.

virtual EBool ExecuteCommand (const SCommand& command): All commands are first passed to the ExecuteCommand() function of the base class CApplControlledObject. If it returns True, than this function returns True as well. Otherwise, it returns the value of CCrashingModule::ExecuteCommand().

void GetBuffer (INT16 msgsize, char **message, INT32& msgID): Allocates a local(!) buffer which has AddedBufferLength more bytes than specified in msgsize and sets *message to the value of BufxToBuf(). Member msgID is copied into the additional buffer in front of buf, and parameter msgID is set to the value of internal member msgID. The latter is then incremented.
If message is NULL, an assert fails.
Note: since messages can be delayed for a long time, the data is kept locally until it is really sent so as not to waste the CI buffers.

void GetEnvelope (tenvx **tenv): Allocates a structure of type tenvx. Again, the structure resides in local memory and is only copied into a CI envelope upon send.
If tenv is NULL, an assert fails.

virtual EBool GetParameter (SParameter& param) const: Returns True if the parameter could be read. If not specified otherwise, all parameters assume that param is of type SSingleParameter.

All other parameters are passed to the GetParameter() function of the base class CApplControlledObject and its value is returned.

void GetReceiveBuffer (INT16 size, bufx **rbuf): Allocates a local buffer of the requested size.
If rbuf is NULL, an assert fails.

void GetReceiveEnvelope (renvx **renv): Allocates a local structure of type renvx.
If renv is NULL, an assert fails.

void Init (): All members are set to their reset values, dynamic members random and listOfDelayedMessages are created. In addition, the function calls Suspend() to suspend the module.

void Insert (SDelayMcb *mcb): Adds the message contained in mcb to the list of delayed messages. If the delivery time of the message is earlier than that currently stored in member msg, the message stored in msg is put into the listOfDelayedMessages and msg is set to mcb. Otherwise, mcb is simply inserted into the listOfDelayedMessages.
If mcb or clock is NULL, an assert fails.

int isr(): Checks if an interrupt from duty timer B5 is pending. If not, the function returns at once. Otherwise, it clears the interrupt and sends event TimerEvent. Then it gets the current time from the clock, and delivers (that is, calls SendNow() or AnnounceNow()) all messages that are due at or before the current time. Then, the duty timer is either loaded with a new time (the delivery time of the next message that is due) or disabled (if there are no more delayed messages).
If clock is NULL, an assert fails. Also, if a B5 interrupt is pending and no message is delayed (i.e., msg is NULL), an assert fails.

Note: In pure simulation, the fact that the granularity of the duty timer is less than the granularity of the double value of the delivery time can cause an endless loop, if the delivery time is compared to the exact current time. Therefore, a message is delivered if its delivery time is less than or equal to the current time plus one tick of the duty timer (2^-16 seconds). For simplicities sake, this is also done in hardware-based simulation, because the slight error in the delivery is not considered important.

virtual void ReportCrashChange(): Creates an event of type SApplCrashEvent, sets its type to CrashStatusChange, the module to Lance, and crashed to the return value of Crashed(), then sends it to the evaluation.

virtual void ReportError(): Calls the global ReportError() function with module = Lance, nodeID = GetNodeID() and area = area_.

void ReportMessageEvent (EEvent type, INT32 msgID): Creates an event of type SApplSendMsgEvent, sets its type and msgID members to the parameters, sets the receiver to NoAccount, the module to Lance, and sends the event to the evaluation.

void ReportMessageEvent (EEvent type, SINT32 nodeID, int area, INT32 msgID): Creates an event of type SApplRecvMsgEvent, sets its type, sender, senderArea and msgID members to the parameters, sets the receiver to its own node ID, the module to Lance, and sends the event to the evaluation.

int Reset (): Just calls the Reset() functions of the base classes CCrashingModule and CControlledObject.

void ReturnBuffer (char *message): Calls BufToBux() to get the real bufx pointer and then frees this pointer. The function assumes that the buffer was allocated using GetBuffer().
If message is NULL, an assert fails.

void ReturnEnvelope (tenvx *tenv): Frees the pointer. The function assumes that the envelope was allocated using GetEnvelope().
If tenv is NULL, an assert fails.

void RetReceiveBuffer (bufx *rbuf): Frees the buffer. The function assumes that the buffer was allocated using GetReceiveBuffer().
If rbuf is NULL, an assert fails.

void RetReceiveEnvelope (renvx *renv): Frees the envelope. The function assumes that the envelope was allocated using GetReceiveEnvelope().
If renv is NULL, an assert fails.

void Scramble (void *data, INT16 size): Scrambles size bytes of the buffer pointed to by data. The function draws a uniform random number in the interval (0, 0xFFFFFFFF), then XORs this value to every four byte of the data. If size is no multiple of four, the last bytes are scrambled using the first byte of the random number.

void ScrambleMessage (addr address, char *msg, INT16 size, INT32 msgID): Scrambles outgoing data. The function decides according to pSendScramble if the data should be scrambled. If it should not, the function returns at once. Otherwise, it calls ReportMessageEvent() with ScrambleSendMessage and then calls Scramble() to scramble the the address and msg buffers.

void ScrambleMessage (addr address, STimeData *time, char *msg, INT16 size, int if_num, int area, INT32 msgID): Scrambles incoming messages. The function decides according to pRecvScramble if the message should be scrambled. If it should not, the function returns at once. Otherwise, it calls ReportMessageEvent() with ScrambleRecvMessage and then calls Scramble() to scramble the address, time and msg buffers.

void Send (int mode, tenvx *tenv, char *message, INT16 size, int if_num, int area): The function sets suspended to False, then calls ModifyCrashStatus() and afterwards checks the crash status of the module. If it is crashed, ReportMessageEvent() is called with DiscardSendMessage and tenv and message are returned using ReturnEnvelope() and ReturnBuffer(). If the module is not crashed, DelayMessage() is called to delay the message. If the message should be duplicated, then tenv and message are copied into freshly allocated structures and DelayMessage() is called a second time for the duplicated message.  In this case, ReportMessageEvent() is called with DuplicateSendMessage to report the duplication. The message ID that is reported is that of the duplicated message.
Parameter tenv may be NULL.

int SendNow (int mode, tenvx *tenv, char *message, INT16 size, int if_num, int area): Is called by the isr() and delivers the message to the network. Parameter tenv may be NULL.
The function calls ModifyCrashStatus() and then checks if the module is crashed. If it is, ReportMessageEvent() is called with event DiscardSendMessage, tenv and message are returned using ReturnEnvelope() and ReturnBuffer(). Then the function returns 0.
If the module is not crashed, ScrambleMessage() is called with the message and the destination address (if tenv is NULL, the broadcast address is used). Then the CI buffers are allocated using CI_GetEnvelope() and CI_GetBuffer(), and tenv and message are copied into them (in the case of the latter, the AddedBufferLength bytes directly before the pointer are copied as well). At last, CI_Send() is called to send the message, the CI buffers are returned and the local tenv and message are returned as well. The function returns the result of CI_Send().
If message is NULL, an assert fails.

void SetClock (CClockInterface *clock): Sets the CClockInterface pointer clock_ to the object. More specifically, the function checks if member clock is NULL, and if it is not, DisableInterrupt() and DisableDutyTimer() of class CClockInterface are called to disable the interrupt and timer B5 of the old clock, before the member is set to the new clock. After the assignment, member clock is checked again, and if it is not NULL, CClockInterface::EnableInterrupt() is called for duty timer B5. In addition, if member msg is not NULL, that is, if delayed messages exist, then the duty timer is programmed to produce an interrupt at the delivery time of the message stored in msg.

void SetClockSync (CClockSync *cs): Sets the CClockSync pointer cs_ to the object.

virtual EBool SetParameter (SParameter& param) const: Returns True if the parameter could be set. If not specified otherwise, all parameters assume that param is of type SSingleParameter.

All other parameters are passed to the GetParameter() function of the base class CApplControlledObject and its value is returned.

void Suspend(): Sets suspended to True to go into suspension mode. In that mode, function Announce() will ignore messages from the network. In addition, the function discards all currently delayed messages via DeleteDelayedMessages().
The lance will stay in suspension mode until function Send() is called.


last modified: Fri Feb 5 18:56:25 1999