file name: clocksyn.hpp, clocksyn.cpp
classification: simulation
contents: class CClockSync
derived from: class CApplControlledObject,
class CNeedInterrupt
friends: class ACClockSyncAlgorithm
use: the main class of clock synchronization application
global items used by CClockSync:
local items used by CClockSync:
const int
CI_Mode: message transmission mode for the LANCE driver.
enum EMessageMode:
Timestamp, DelayMeasurement, DelayMeasurementReply, RateSynchronization,
GpsTime
specifies the contents of a message.
enum ERoundStage:
BeforeSend, BeforeCV, BeforeResync
specifies all possible round stages.
member variables:
int area_:
the DMA area of the clock. The user identifies a clock synchronization
application through the pair <nodeID, area>.
default: area parameter of the ctor
CClockInterface
*clock_: a pointer to the clock object of the node and area. Again,
it must be set to a value other than NULL before the module can send synchronization
messages.
default: NULL
double
computationDelayCompensation_: the time (in seconds) from the execution
of the CV to the clock update at the end of the round, cf. Figure 1. This
parameter denotes the worst case execution time of the CV. In pure simulation,
the execution time of the CV is zero.
default and reset value: DefaultComputationDelayCompensation
ACClockSyncAlgorithm
*csa_: a pointer to the object that implements the clock synchronization
algorithm.
default and reset value: a newly created object of the algorithm type
FreeRun.
EAlgorithmType
csaType_: the type of the currently used clock synchronization algorithm.
default and reset value: FreeRun
double
delayCompensation_: the time (in seconds) from the full message exchange
(FME) at the beginning of the round to the execution of the convergence
function (CV), cf. Figure 1. Again, a duty timer
of the UTCSU is used to wait for that time.
default and reset value: DefaultDelayCompensation
INT32 delayCycles_:
the period of delay measurement messages (in number of calls to FME). Example:
if every n-th message should include delay measurement, set delayCycles
to n; n=0 prevents delay measurement.
default and reset value: 0
INT32 delayCounter_:
If delay measurement is active, it counts the calls to function BroadcastTime(),
and if its value is greater or equal to the value of delayCycles,
the message sent in the FME will contain a request for delay measurement
and the delay counter is reset to 0.
Note: if delayCycles is changed, delayCounter
is always set to be one less than delayCycles. Thus, whenever
you activate delay measurement, the next message that is sent will already
contain the request.
default and reset value: 0
EBool initCalled_:
is set to True by Init(), to False by Dispose().
default and reset value: True
CLance
*lance_: a pointer to the lance object of the node and area. It must
be set to a value different from NULL before the module can send synchronization
messages.
default: NULL
CNodeIdList
listOfConnectedNetworks_: all connected networks of the application.
There must be at least one entry (which is set by the user) before the
module can take part in the synchronization process.
default and reset value: Empty
INT32 rateCycles_:
INT32
rateCounter_: These two are handled exactly like delayCycles
and delayCounter, but are used for controlling rate synchronization.
Whenever the value of rateCounter exceeds that of rateCycles,
rate information of the local clock is included into the message.
default and reset value: 0
EBool reportDelays_:
is True if transmission delays for incoming messages should be reported
to the evaluation.
default and reset value: False
EBool resynchronizing_:
If this variable is set to True, messages are not marked as timestamped
(that is, they do not have flag Timestamp in their mode). Also,
only delay measurement messages and/or rate synchronization messages are
sent. Messages that would only contain the local timestamp are *not* sent.
The csa may set the variable to True if it deems the clock value
to be wrong.
default: False
double
roundPeriod_: the round period (in seconds) of a synchronization round,
cf. Figure 1. A duty timer of the UTCSU is used
to wait for that time.
default and reset value: DefaultRoundPeriod
INT8 roundStage_:
Is needed to store the current stage in a synchronization round. A value
of BeforeSend means that the next call to the isr() should
broadcast a synchronization message, BeforeCV causes the isr()
to execute the CV, and BeforeResync prompts the isr()
to resynchronize the clock (see Figure 1).
default and reset value: BeforeSend
EBool suspended_:
If the variable is True, Announce() ignores incoming messages.
The member may well become obsolete: if suspension is done right, the Lance
object should be suspended first and ignore all messages anyway. If the
value is False, the variable has no effect.
default and reset value: False
double
timeOfResync_: contains the time of the next resynchronization (m*roundPeriod
+ delayCompensation + computationDelayCompensation, with
m
some multiple of the round period). The member is needed to compute the
time from the reception of a message until the time the clock is resynchronized.
This delay is needed by the clock synchronization algorithm. If it is negative,
the time of the next resynchronization is not known.
default and reset value: NoAccount
message formats: the format of the message buffer of the messages that are exchanged between the applications. The mode may contain several flags:
Timestamp, DelayMeasurement (Node P [FME] -> Node Q [Announce]):
Node P: INT32 mode, SINT32 nodeID (P)
RateSynchronization (Node P [FME] -> Node Q [Announce]):
Node P: INT32 mode, SINT32 nodeID (P), double thetaPlus (P), double
thetaMinus (P), double u (P)
DelayMeasurementReply (Node Q [ReplyToMessage] -> Node P [Announce]):
Node Q: INT32 mode, SINT32 nodeID (Q), INT32 receiveTimestamp (Q),
double thetaMinus (Q), double thetaPlus (Q), INT32 area (P), ti_acx time
(P)
member functions:
CClockSync
(CControllingObject *ctrl, int area): Stores the area, calls
SetISR()
to set the interrupt vector (duty timer B4) for the ISR (the call is made
atomic by calling DisableInterrupts() before
and EnableInterrupts() after the statement),
sets csa to NULL and initCalled to False, then calls
Init().
virtual
~CClockSync (): Disables the interrupts from the duty timer B4 and
disables the timers themselves (sets the enable bit to zero). The clock
object must not have been deleted at this time! Calls RemoveISR()
(again, the call is made atomic), then deletes the dynamic members that
were created by the object through a call to Dispose(). The lance
and clock objects are not deleted.
void Announce
(renvx *renv, STimeData time, char *buf, INT16 msgsize, int if_num, INT32
msgID): Should be called by the Lance if a message has been received.
The msgID is the identifier of the message and only needed for
the event report. If suspended is False, the function takes over
the data, extracts the information (timestamp, delay measurement and rate
information) and gives it to csa for further processing. If the
message contained a request for delay measurement, the function sends a
reply. The function sends event ReceivedMessage
to the evaluation, and if member reportDelays is True, then it
calls GetTransmitTimestamp() to get the send
timestamp for the message, subtracts the receive timestamp in renv->utcsu,
and sends event TransmissionDelay with this delay.
Note: currently, the drift of the clock is not considered when
computing the transmission delay.
void ApplyConvergenceFunction():
Prompts csa to use the collected data to compute a new clock value.
This is the end of stage BeforeCV in the synchronization round
(see Figure 1).
void BroadcastTime
(): Broadcasts a timestamped message. If resynchronizing
is True, messages that only consist of the clock value are not send, and
in messages with additional information the timestamp is marked invalid
(i.e., the Timestamp flag is not set). The function is called
at the end of stage BeforeSend in the synchronization round (see
Figure
1). The message is sent to all networks stored in listOfConnectedNetworks,
and for each single send, event SendMessage is
reported to the evaluation. If the macro ADDITIONAL_PNODE_DATA
is defined (compiler option -D) and the CSA is a P-Node, then
the data is sent for another ADDITIONAL_PNODE_DATA times.
EBool
ChangeAlgorithm (EAlgorithmType newType): Changes the synchronization
algorithm (members csa and csaType). The algorithm can
be changed on the fly (at any time, the csa pointer is valid).
If the algorithm type has not been installed (the algorithm manager does
not have a create function), the function returns False and has no effect.
Otherwise, the function returns True. Changing the algorithm discards all
data that has been collected by the old algorithm, but keeps general configuration
information like the number of nodes or the associated network (see csa::operator=()
for details). The function can be called if csa is NULL. In that
case, it just creates a new object and sets csa to it.
void ComputeDelay
(renvx *renv, STimeData& time, SReplyData& data, STimeData&
myTime, int if_num): Computes the transmission delay. The function
is called by Announce() if a reply to a transmission delay request
has been received. The function uses all data to compute the complete delay
from the sending of request to the receipt of the reply (in the time of
the local clock) and the remote delay from the receipt of the request to
the sending of the reply (in the time of the remote clock), and passes
these values, together with the clock rate information that has been sent
from the remote CSA, to csa for further processing.
virtual
void Dispose(): If initCalled is True, all dynamic members
are deleted and initCalled is set to False. Since csa
is dynamic, it is deleted and all data it has collected is lost. If initCalled
is False, the function has no effect.
virtual
EBool ExecuteCommand (const SCommand& command): Supported commands:
virtual
EBool GetParameter (SParameter& param) const: Returns True if the
parameter could be read. All supported parameters of this class assume
that param is of type SSingleParameter.
Supported parameters:
virtual
void Init(): If initCalled is False, the function creates
all dynamic members and sets all class members to their reset values. Member
initCalled
is then set to True. If initCalled is True, the function has no
effect.
void
InterruptAtMult(): Disables duty timer B4, calls clock->InterruptAtMult()
for duty timer B4 with roundPeriod, sets timeOfResync
to the time of the next resynchronization, which occurs at the end of stage
BeforeResync
(see Figure 1). Then B4 is enabled again.
virtual
void isr (): The function is called for INTT interrupts. If no interrupt
from duty timer B4 is pending, the function returns and has no effect.
Otherwise, it clears this interrupt and sends event TimerEvent.
The call to the ISR always denotes the end of the current stage as stored
in roundStage and the beginning of the next stage. First, if the
next stage has a non-zero duration, the function programs the duty timer
to trigger an interrupt at its end. Then it calls either BroadcastTime()
(end of stage BeforeSend) or ApplyConvergenceFunction()
and csa::PreloadNewClockValue() (end of stage BeforeCV).
At the end of every stage, roundStage is set to the next stage.
If this stage is not BeforeSend and if its duration is zero, then
the ISR behaves as if it had been called again at once and handles the
new stage.
Note: After the ISR has handled stage BeforeResync,
it always calls InterruptAtMult() to set the duty timer to the
end of stage BeforeSend and returns. InterruptAtMult()
modifies member timeOfResync to contain the time of the end of
the next stage BeforeResync.
Note: Stage BeforeResync does not call any functions
(amortization is started automatically) and will be removed in future versions.
void ReplyToMessage
(renvx *renv, STimeData& time, int if_num): Replies to a request
for transmission delay measurement. If either clock or lance
are NULL, an assert fails. Otherwise, the function assembles the reply
message, reports event SendMessage to the evaluation
and sends the message.
virtual
int ReportError (EReportType type, char *file, int line, char *expression):
Calls the global ReportError() function with the
additional information module=ClockSync, nodeID=GetNodeID(),
area=area_.
void Resume
(): Enables interrupts from duty timer B4 and calls InterruptAtMult()
to trigger a duty timer interrupt. If clock is NULL, an assert
fails.
void Resynchronize():
Prompts csa to set the clock to the new value. This denotes the
end of stage BeforeResync in the synchronization round.
void SetClock
(CClockInterface *clock): Sets the internal clock pointer to clock
and calls csa::ClockChanged(). You must set the internal pointer
to a valid clock object before the object can participate in clock synchronization.
void SetLance
(CLance *lance): Sets the lance pointer to lance. You must
set the internal pointer to a valid Lance object before the object can
send messages.
virtual
EBool SetParameter (const SParameter& param): Returns True if the
parameter could be set. All supported parameters of this class assume that
param
is of type SSingleParameter. Supported parameters:
void StoreTime
(renvx *renv, STimeData& time, int if_num): Passes the clock timestamp
of the remote clock and the time difference from the reception of the message
until the local clock is resynchronized to csa.
void Suspend
(): Disables interrupts from duty timer B4 and sets suspended
to True. Incoming messages are ignored, roundStage is set to BeforeSend,
timeOfResync
is set to NoAccount, and csa::Suspend()
is called.