index previous next 

file name: clock_sw.hpp, clock_sw.cpp
classification: pure simulation
contents: class CSoftwareClock
derived from: class CClock
friends: function MakeSystemSnapshot()
use: provides a class for simulating the UTCSU in pure simulation
 

global items used by the functions:

 
local items used by the functions:

const INT32 DutyEnabled: enable bit in the DUTYL registers

enum EAmortizationTypes: the current stage in the amortization phase. Register STARTAMORT is used for storing the stage and contains one of these values:

const INT8 IntDutyB1: interrupt bit of duty timer B on SSU1
const INT8 IntGPS1: interrupt bit of GPS1PPS of GPU 1
const INT8 IntGPS2: interrupt bit of GPS1PPS of GPU 2
const INT8 IntGPS3: interrupt bit of GPS1PPS of GPU 3
const INT8 IntHwSnapshot: interrupt bit of the hardware snapshot
const INT8 PolHWSnap: polarity bit of the hardware snapshot in UTCCONF1

struct SInternalRegisters: Contains those internal registers of the UTCSU that are needed for storing temporary results.

const double TwoPow16:
const double TwoPow21:
const double TwoPow29:
const double TwoPow30:
const double TwoPow32: Some powers of two that are needed for internal computations.
 

local (static) functions of the implementation file:

double DutyToSeconds (INT32 dutyh, INT32 dutyl): Converts the contents of the duty timer registers to seconds.

EClockInterrupt GetInterruptType (INT8 interruptBit): Returns the interrupt type (INTA, INTN, INTT) of the bit. The interruptBit is in the range of 0..63. If the interrupt bit is not used by the UTCSU, an assert fails.

double GetTime (const CNtpTime& cycles, double frequency): Returns the global time that corresponds to cycles clock cycles of a clock with the frequency frequency.

void PrintHex (const char *str, INT32 reg): Prints the value of str as a string with a minimum width of 14 characters (left justified), followed by the hexadecimal value of reg and a newline. The function is used by DumpRegisters() to print the contents of the UTCSU registers.
Note: the function is only available if macro NDEBUG is not defined.
 

template implementation (clock_sw.cpp):

CClockTemplate::NewClock (double frequency, SINT32 nodeID, int area): Returns a new object of the software clock. If frequency is not positive, an assert fails.
 

member types and variables:

enum EDutyTimer: The bits of the implemented duty timers (APPDUTY, and the duty timers A and B
of all SSUs) in the interrupt and status registers.

int area_: The area of the application. It is necessary for obtaining the interrupt vector.
default value: parameter area of the ctor

double assocSimTime_: The simulation time of the last clock update.
default and reset value: the current simulation time

double fOsc_: The real oscillator frequency (as opposed to the ideal frequency stored in CClock). fOsc can be manipulated through parameter ClockDrift.
default value: the ideal frequency which is returned by GetFrequency()

EGpsUnit gpu_: The GPU that has last called CaptureTime().
default and reset value: EGpsUnitCount

SInternalRegisters *internals_: The structure contains all internal clock registers that are needed for keeping track of the state of the UTCSU.
reset values: all members are set to 0, overflow is set to False

CInterruptList *listOfInterrupts_: Stores the list of all interrupts that were created (ie., enabled in UTCINTEN).

SINT32 nodeID_: The nodeID of the application (it is used as process ID of the interrupt processes).
default value: parameter nodeID of the ctor
 

member functions:

CSoftwareClock (double frequency, SINT32 nodeID, int area): Creates internals and the inherited members utscuRead and utcsuWrite, sets nodeID and area to their default values and calls Init(). If frequency is not positive, an assert fails.
The function sets registers UTCINTEN, UTCCONF, UTCSTAT and UTCINTSTAT to zero and register IDENTIFICATION to 0x49435410 ("ICT"+0x10). Please note that the clock is not reset, so apart from the above-mentioned registers, all registers are in an unknown state.
Note: in hardware-based simulation, the UTCSUs on all nodes are reset by the LANCE before SimUTC is started. So if a CSA is deleted and then created anew, the clock is not reset and the CSA has to set all registers that it needs. In consequence, in pure simulation the clock is not reset at all, thus forcing the users of the clock to manually set all members that they need and enforcing an initialization code that will also work in hardware-based simulation.

virtual ~CSoftwareClock (): Deletes the dynamic members that were created in the constructor and calls Dispose(). If the UTCINTEN registers are not zero (that is, not all interrupts that were enabled during the life of the CSA were disabled upon its destruction), an assert fails.

void CaptureTime(EGpsUnit gpu): The clock is updated, then the values of the internal macro- and timestamp are copied into the MSGPS and TSGPS registers of the specified GPU. Internal member gpu_ is set to gpu. Bit 31 in MSGPS is set to 0 to indicate that the GPS receiver is healthy (this is always the case in this version of SimUTC). If gpu is greater or equal to EGpsUnitCount, an assert fails.

void ClearSignal (INT8 signalBit): Sets bit signalBit in the appropriate UTCSTAT register to 0. The other bits are not modified. If signalBit is greater than 63, an assert fails.

CClockInterrupt *CreateInterrupt (INT8 interruptBit): The function first searches for an existing interrupt in the list of interrupts. If an interrupt process is found, it is returned. Otherwise, interruptBit is checked. If it is a GPS1PPS interrupt, a GPS interrupt process is created. If it is an interrupt of duty timer B on SSU1, an interrupt process of type CDutyB1Interrupt is created. Otherwise, a normal clock interrupt process is created. In any case, GetClockIntvec() is used to obtain the interrupt base vector, to which the type of the interrupt bit (enum INTA, INTN, INTT in interupt.hpp) is ored. Then, the interrupt is put into the interrupt list, its status register (read register UTCINTSTAT1 for bits 0..31, UTCINTSTAT2 for bits 32..63) is stored using CClockInterrupt::SetStatusRegister(), and according to the status of interruptBit in write register UTCINTEN1(2) the process is enabled or disabled. In any case, CClockInterrupt::SetPendingBit() is used to set the number of the status bit corresponding to the interrupt. The function returns the pointer to the new interrupt. If interruptBit is greater than 63, an assert fails.

void DescheduleInterrupt (INT8 interruptBit): The function searches for the interrupt in the list of interrupts, and if it is found, CClockInterrupt::CancelInterrupt() is called to remove the interrupt process from the scheduler queue.

virtual void DisableInterrupt (INT8 interruptBit): Searches for the interrupt process in the list of interrupts. If the process is found, its Disable() function is called.

virtual void Dispose(): Deletes the interrupt list, thus cancelling all interrupts stored in the list. The function must not be called twice in a row!

virtual void DumpRegisters(): Prints the contents of all registers of the UTCSU to cout. In the header, the function prints the current simulation time (split into an integer and a fractional part to avoid rounding errors because of limited output precision), the difference between the simulation time and the current associated time of the clock, and the current clock time (also split into an integral and a fractional part).
Note: the function is only available if macro NDEBUG is not defined.

virtual void EnableInterrupt (INT8 interruptBit): Searches for the interrupt process in the list of interrupts, and if it was found, its Enable() function is called.

INT32 GetAccuracy(): The function returns the current accuracy, taken from the INTPBUS. That means that bits [-8,-23] of internal register ALPHAP are stored in the lower two bytes of the return value, and bits [-8,-23] of internal register ALPHAN are stored in the upper two bytes. If the ALPHAP(N) register is negative, 0 is used instead.

virtual INT32 GetALPHANGETL(): Updates the clock, reads the internal negative accuracy into ALPHANGET(L) and the nanofractional part into the upper two bytes of NALPHAPGET and returns the value of ALPHANGET.

virtual INT32 GetALPHAPGETL(): Updates the clock, reads the internal positive accuracy into ALPHAPGET(L) and the nanofractional part into the lower two bytes of NALPHAPGET and returns the value of ALPHAPGET.

INT32 GetAmortCycles (const CNtpTime& cycles): The function returns the number of amortization cycles in the next cycles clock cycles. It returns the minimum of cycles and the value of internal register AMORTTIMER.

virtual INT32 GetAMORTTIMEGETL(): Updates the clock, then stores the current value of the internal register AMORTTIMER in AMORTTIMEGET(L) and returns that value.

void GetClockCycles (double delta, CNtpTime& cycles): If delta is not positive, cycles (both ms and ts) is set to 0. Otherwise, the real frequency of the clock (which is stored in member fOsc) is used to compute the number of cycles that occur in delta seconds (real seconds, as measured with an ideal clock). The result is stored in cycles.
Note: do not get confused: cycles is of type CNtpTime, but is no time. It should be seen as a 64 bit register (the us member is not used).

double GetCurrentClockValue(): The function returns the current clock value converted in seconds.

void GetEnvelope (EBool positive, INT32& alpha, INT16& nalpha): If positive is True, the function copies the internal register ALPHAP into alpha and internal register NALPHAP into nalpha. If positive is False, internal registers ALPHAN and NALPHAN are copied instead.

CGpsInterrupt *GetGpsInterrupt (EGpsUnit gpu): Returns the GPS interrupt process of the given GPU. If the process does not exist, it is created. If gpu is greater or equal to EGpsUnitCount, an assert fails.

EGpsUnit GetGpsUnit(): Returns member gpu, which contains the GPS unit that has last called CaptureTime().

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.

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

EBool GetPolarity (INT8 bitnumber): Checks the appropriate UTCCONF register (the write registers are used). If bit bitnumber is set to 1, True is returned. If it is 0, the function returns False. If bitnumber is greater than 63, an assert fails.

double GetRate (INT32 step): The function returns the real clock rate (clock seconds per second) if step and STEPLOW (the uppermost byte of write register MSSET) is used. The real clock frequency fOsc is used to compute the rate.

double GetRealDelay (double delta): The function returns the global time (in seconds) that will pass until the clock time delta (in seconds) has passed. If delta is less or equal to 0, the function returns 0. If delta is positive, the clock is updated. Then, the clock state is checked to find out which part of the total time delta the clock is in amortization phase, and which part the clock spends in pure phase. The clock rates of amortization and pure phase are computed (using function GetRate()) and the real delay (ie. the delay measured on a clock with ideal rate) is computed from them and returned.

EBool GetSignal (INT8 signalBit): The appropriate UTCSTAT register is checked, and if bit signalBit is set to 1, True is returned. If it is 0, the function returns False. If signalBit is greater than 63, an assert fails.

virtual INT32 GetSTATEPGETL(): Updates the clock, calls GetAccuracy() and sets STATEPGET(L) to its return value. It returns the new value of the STATEPGET(L) registers.

virtual INT32 GetTSGETL(): The function first updates the clock, ie., it computes the current clock state. Then it latches the NTP registers, the STATEPGET(L) registers of the accuracy and the ALPHAPGET(L), ALPHANGET(L) and NALPHAPGET registers of the full accuracy envelopes (all values are taken from the corresponding internal registers). It returns the value of the latched TSGET register.

virtual INT32 GetUTCCONF1(): This is a read-back register of the UTCCONF1 register. The UTCCONF1 of the write structure is simply copied into it, and its value is returned.

virtual INT32 GetUTCCONF2(): This is a read-back register of the UTCCONF2 register. The UTCCONF2 register of the write structure is copied into it, and its value is returned.

virtual INT32 GetUTCSTAT1(): Updates the clock. If the clock is in amortization phase, bit SCAMA is set to 1, else it is set to 0. The bit is set here because the value of the status bit is only important when UTCSTAT1 is read.
Note: the only other status bit that is currently set is SAPPDUTY.

void HwSnapshot(): The function updates the clock and afterwards stores the internal macrostamp and timestamp into the read registers MSSNU and TSSNU. The current accuracies are stored in ACCPSNU. If interrupt IHWSNAP is enabled, an interrupt is generated at once (ie., the interrupt process is scheduled for the current time).

virtual void Init(): creates the interrupt list, sets assocSimTime, gpu and fOsc to their reset values. The function must not be called twice in a row!

void ModifiedDutyTimer (EDutyTimer dutyBit, const CNtpTime& duty): If the duty timer (duty.ms = DutyHigh, duty.ts = DutyLow) is enabled, the function creates an interrupt process, sets its schedule time to the clock time specified by the duty timer, and schedules the process. If the duty timer is disabled, the function searches the list of interrupts for an existing process, and if one is found, its schedule time is set to a negative value (to prevent rescheduling) and the process is descheduled (calling CClockInterrupt::CancelInterrupt()). Its corresponding status bit is cleared in UTCSTAT. If the duty timer is enabled and dutyBit is greater than 63, an assert fails.

virtual int ReportError (EReportType type, char *file, int line, char *expression): Calls the global error report function with the additional information module=Clock and the nodeID and area.

void RescheduleInterrupts (): The function goes through the interrupt list and checks the status of all interrupts. If an interrupt is active or scheduled, it is rescheduled calling ScheduleInterrupt().
Note: rescheduling of interrupts is necessary after the clock state has been changed. Interrupt processes that were idle anyway will be ignored. Active interrupt processes must be rescheduled as well, because they may have been already scheduled for the next interrupt.

void ScheduleInterrupt (INT8 interruptBit): The function simply searches for the interrupt in the list of interrupts, and if it is found, it calls ScheduleInterrupt() with the pointer.

void ScheduleInterrupt (CClockInterrupt *clockint): The function first calls CClockInterrupt::GetScheduleTime() to find out the global time at which the interrupt should be scheduled. If the value returned by the function is negative, the interrupt does not need scheduling and the function has no effect. If the schedule time is not negative, GetCurrentClockValue() is used to obtain the current clock time in seconds, and the interrupt is scheduled according to the time difference. Since the time difference is given in local time, GetRealDelay() is used to compute the global delay and the interrupt is scheduled for that delay. If clockint is NULL, an assert fails.

virtual void SetALPHAPNSET(INT32 val): Updates the clock, then copies the new accuracy from the write register ALPHASET into the internal accuracy ALPHAP(N). The nanofractional part NALPHAP(N) is set to 0x1FFF (it is only 13 bit wide).

virtual void SetAPPDUTYH(INT32 val): First updates the clock. Then, function ModifiedDutyTimer() is called with the bitnumber corresponding to the duty timer in the interrupt registers and with the new value of the duty timer.

virtual void SetAPPDUTYL(INT32 val): First updates the clock. Then, function ModifiedDutyTimer() is called with the bitnumber corresponding to the duty timer and with the new value of the duty timer.

virtual void SetDUTYAH (ESSUnit ssu, INT32 val): First updates the clock. Then, function ModifiedDutyTimer() is called with the bitnumber corresponding to the duty timer of the given SSU in the interrupt registers and the new value of the duty timer.

virtual void SetDUTYAL (ESSUnit ssu, INT32 val): First updates the clock. Then, function ModifiedDutyTimer() is called with the bitnumber corresponding to the duty timer of the given SSU in the interrupt registers and the new value of the duty timer.

virtual void SetDUTYBH (ESSUnit ssu, INT32 val): First updates the clock. Then, function ModifiedDutyTimer() is called with the bitnumber corresponding to the duty timer of the given SSU in the interrupt registers and the new value of the duty timer.

virtual void SetDUTYBL (ESSUnit ssu, INT32 val): First updates the clock. Then, function ModifiedDutyTimer() is called with the bitnumber corresponding to the duty timer of the given SSU in the interrupt registers and the new value of the duty timer.

void SetEnvelope (EBool positive, INT32 alpha, INT16 nalpha): If positive is True, alpha is stored into internal register ALPHAP and nalpha is written into internal register NALPHAP. If positive is False, internal registers ALPHAN and NALPHAN are modified instead. Only 13 bits of nalpha are used, since NALPHA corresponds to bits [-39,-51].

void SetLowerLimit (EBool positive): If positive is True, internal registers ALPHAP and NALPHAP are set to their lower limit (which is 1:0...0). If positive is False, ALPHAN and NALPHAN are set to that limit instead.
Note: normally, this function should raise an interrupt INTNLALPHAP(N), because the function is only called if the limit was overstepped. But since the current version of SimUTC does not need the interrupts, and because the interrupt should be raised at the exact time the limit is reached, not some time later when UpdateEnvelopes() happens to notice the overrun, this interrupt is not implemented.

virtual void SetMSSET(INT32 val): The function checks the most significant byte (which contains the STEPLOW value). If it has changed, the clock is updated (using the old steplow value). Then, the new value is taken over into the MSSET register, and if STEPLOW has changed, interrupts are rescheduled.

virtual void SetNTPSET(INT32 val): First updates the clock. Then, the NTP time values of MSSET, TSSET and USSET are taken over into the internal registers, and the internal nanostamp is set to 0. Interrupts are rescheduled.
Note: if the new NTP time is less than the old, an interrupt should be raised. This is not implemented.

void SetOverflow (int overflow): If overflow is not 0, the internal boolean variable overflow is set to True and the uppermost byte of the internal macrostamp is set to 0. If overflow is 0, internal variable overflow is set to False.

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.

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

void SetSignal (INT8 signalBit): The function first searches for an interrupt that is associated with this bit. If an interrupt was found in the list of interrupts, and if that interrupt is either scheduled or active, the function has no effect. If no interrupt process was found, or if the process is idle, the signal is set in the appropriate UTCSTAT register. If signalBit is greater than 63, an assert fails.

virtual void SetSTARTAMORT(INT32 val): Updates the clock. Afterwards, several write registers are taken over into the internal registers: AMORTTIMESET into the internal AMORTTIMER, STEPPURE into STEPPUREACT, LAMBDAP(N)PURE into LAMBDAP(N)PUREACT. If the AMORTTIMER is greater than 0, write register STARTAMORT is set to the enum BeginAmortization to signify the start of the amortization phase. If AMORTTIMER is 0, STARTAMORT is set to NoAmortization.

virtual void SetSTEPAMORT(INT32 val): Updates the clock, then takes over the new STEPAMORT value. If the clock is currently in amortization phase (you should not change the STEPAMORT value during amortization), an error is reported (because most likely that was not intended) and interrupts are rescheduled.

virtual void SetSWRESET(INT32 val): Sets all UTCSU registers, whether internal or of the read/write structures, to 0. Only write register BOUNDP is set to 0xFFFFFFFF (all bits are 1) and read register IDENTIFICATION is set to 0x49435410 ("ICT"+0x10). The internal overflow variable is set to False, and assocSimTime is set to the current simulation time. All interrupt processes are disabled, and all except the GPS interrupts are descheduled as well.

virtual void SetSWSNAP(INT32 val): calls function SwSnapshot() to capture all dynamic registers.

void SetUpperLimit (EBool positive): If positive is True, internal registers ALPHAP and NALPHAP are set to their upper limit (which is 0:1...1). If positive is False, ALPHAN and NALPHAN are set to that limit instead.
Note: since the nanofractional part of the accuracy is only 13 bits wide, NALPHAP(N) is set to 0x1FFF.
Note: normally, this function should raise an interrupt INTPLALPHAP(N), because the function is only called if the limit was overstepped. But since the current version of SimUTC does not need the interrupts, and because the interrupt should be raised at the exact time the limit is reached, not some time later when UpdateEnvelopes() happens to notice the overrun, this interrupt is not implemented.

virtual void SetUTCINTCLEAR1(INT32 val): Every bit that is 1 in val is set to 0 in read register UTCINTSTAT1.

virtual void SetUTCINTCLEAR2(INT32 val): Every bit that is 1 in val is set to 0 in read register UTCINTSTAT2.

virtual void SetUTCINTEN1(INT32 val): First updates the clock. Then each bit of val is checked, and if it is set to 1, the interrupt process corresponding to that bit is enabled and scheduled, whereas if it is 0, the interrupt is disabled and descheduled.

virtual void SetUTCINTEN2(INT32 val): First updates the clock. Again, each bit of val is checked. The first three bits are GPS1PPS interrupts, and if one of these bits is set to 1, the corresponding GPS interrupt is enabled. If the bit is 0, the interrupt is disabled but not descheduled, so the interrupt process still gets active every second, but it does not invoke the ISR (the process needs to stay scheduled, because upon activation it has to schedule itself for the next second). The other bits and their interrupts are treated as described for SetUTCINTEN1().

void SwSnapshot(): The function simply calls GetTSGETL() to capture all dynamic registers.

void Update(): The function computes the current clock state and updates the clock registers. First, the function compares assocSimTime to the current global time. If assocSimTime is greater or equal to the global time, no update is necessary and the function returns at once. Otherwise, the function computes the number of (full) clock cycles that must have occurred since the last update. If it is zero, the function returns at once (only full cycles can be updated).
Otherwise, if the clock is in amortization phase (AMORTTIMER is not 0), the number of amortization cycles since the last update is computed, and the clock state and accuracy envelopes are updated (using the amortization step values) calling UpdateNtp() and UpdateEnvelopes(). If all amortization cycles were used up, write register STARTAMORT is set to enum constant NoAmortization, else it is set to MiddleOfAmortization. The cycles used for amortization are subtracted from the total number of cycles. If any cycles remain, the clock state and accuracy envelopes are modified again using the step values for pure phase. UpdateEvelopes() and UpdateNtp() are used to update the registers. In any case, the updated time (which is computed through local function GetTime()) is added to assocSimTime, and the clock registers are all up to date when the function returns.

void UpdateEnvelopes (EBool pure, const CNtpTime& cycles): The function updates the internal accuracy envelopes stored in ALPHAP(N) (bits S:[-8,-38]) and NALPHAP(N) (bits [-39,-51]). If pure is True, internal register LAMBDAP(N)PUREACT (bits S:[-37,-51]) is added to ALPHAP(N) and NALPHAP(N) for cycles cycles. If pure is False, write register LAMBDAP(N)AMORT (bits S:[-37,-51]) is used instead, and if STARTAMORT is equal to BeginAmortization, the first cycle is used to realign the accuracy envelopes by adding write register STATEP(N)SET (bits S:[-8,-38]). During the remaining cycles the envelopes are updated according to LAMBDAP(N)AMORT. If the update of an envelope (either the positive or negative one) results in an overrun or underflow of the register, the envelope is set to its upper limit (using SetUpperLimit()) or its lower limit (through function SetLowerLimit()).

void UpdateNtp (INT32 step, const CNtpTime& cycles): This function updates the NTP registers of the clock. It adds the value of step (bits [-20,-51]) and STEPLOW for cycles clock cycles to the NTPTIME (which is the complete 91 bit time value in the range [+31,-59]; it is split into the macrostamp (MS) [+31,+8], TS [+7,-24], US [-25,-56] and the NS [-57,-59]). The uppermost byte of write register MSSET is taken as the STEPLOW portion (bits [-52,-59]) of step. After the new NTPTIME was computed, SetOverflow() is called to set the internal overflow flag in case of an overflow, or to clear it if no overflow has occured.
 

simulated UTCSU registers:

The UTCSU contains many registers. This is a list of all of them, using 32 bit access (the first name in a line is the name of the 32 bit register in the UTCSU register structure). Those that are not simulated by the software clock are marked with a minus sign (-), those that display a slightly different behaviour are marked with an asteriks (*). The results of accessing these registers are described below. Accessing the other registers yields the same results as accessing the real UTCSU registers.
 
 
 

read
write
MSGET/CS 
TSGETL 
USGET 
TSGET 
NSGET 
AMORTTIMEGETL 
AMORTTIME
MSSET/STEPLOW 
TSSET 
USSET 
NTPSET 
STEPAMORT 
STEPPURE 
AMORTTIMESET 
STARTAMORT
STATEPGETL/STATENGETL 
STATEPGET/STATENGET 
ALPHAPGETL 
ALPHANGETL 
ALPHAPGET 
ALPHANGET 
NALPHAPGET/NALPHANGET
LAMBDAPPURE/LAMBDAPAMORT 
LAMBDANPURE/LAMBDANAMORT 
STATEPSET 
STATENSET 
BOUNDP/BOUNDN 
ALPHASET 
ALPHAPNSET
  SWRESET
IDENTIFICATION 
UTCSTAT1 
UTCSTAT2 
UTCCONF1 
UTCCONF2 
UTCINTSTAT1 
UTCINTSTAT2
UTCCONF1 
UTCCONF2 
UTCINTEN1 
UTCINTEN2 
UTCINTCLEAR1 
UTCINTCLEAR2
MSSIG (-) 
TSSIG (-) 
ACCSIG (-) 
MSSUM (-) 
TSSUM (-) 
ACCSUM (-) 
PUREPHASE (-)
TESTSEL (-) 
TESTGATE (-)
MSSNU 
TSSNU 
ACCPSNU/ACCNSNU
SWSNAP (*) 
DUTYH (-) 
DUTYL/E (-)
MSAPP (-) 
TSAPP (-) 
ACCPAPP/ACCNAPP (-) 
MSAPPX (-) 
TSAPPX (-) 
ACCPAPPX/ACCNAPPX (-)
APPDUTYH 
APPDUTYL 
APPSEL (-) 
APPCLEAR (-)
MSGPS 
TSGPS
 
MSRCV (-) 
TSRCV (-) 
MSXMT (-) 
TSXMT (-) 
ACCPXMT/ACCNXMT (-) 
ACCNPNPLXMT (-) 
ACCNPNPHXMT (-)
DUTYAH 
DUTYAL 
DUTYBH 
DUTYBL
 
SWSNAP: Samples the current clock state into the registers, but does not raise an interrupt.
last modified: Fri Feb 5 18:56:02 1999