nuclear@1: /************************************************************************************ nuclear@1: nuclear@1: Filename : Util_LatencyTest.cpp nuclear@1: Content : Wraps the lower level LatencyTester interface and adds functionality. nuclear@1: Created : February 14, 2013 nuclear@1: Authors : Lee Cooper nuclear@1: nuclear@1: Copyright : Copyright 2013 Oculus VR, Inc. All Rights reserved. nuclear@1: nuclear@1: Use of this software is subject to the terms of the Oculus license nuclear@1: agreement provided at the time of installation or download, or which nuclear@1: otherwise accompanies this software in either electronic or hard copy form. nuclear@1: nuclear@1: *************************************************************************************/ nuclear@1: nuclear@1: #include "Util_LatencyTest.h" nuclear@1: nuclear@1: #include "../Kernel/OVR_Log.h" nuclear@1: #include "../Kernel/OVR_Timer.h" nuclear@1: nuclear@1: namespace OVR { namespace Util { nuclear@1: nuclear@1: static const UInt32 TIME_TO_WAIT_FOR_SETTLE_PRE_CALIBRATION = 16*10; nuclear@1: static const UInt32 TIME_TO_WAIT_FOR_SETTLE_POST_CALIBRATION = 16*10; nuclear@1: static const UInt32 TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT = 16*5; nuclear@1: static const UInt32 TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS = 16*5; nuclear@1: static const UInt32 DEFAULT_NUMBER_OF_SAMPLES = 10; // For both color 1->2 and color 2->1 transitions. nuclear@1: static const UInt32 INITIAL_SAMPLES_TO_IGNORE = 4; nuclear@1: static const UInt32 TIMEOUT_WAITING_FOR_TEST_STARTED = 1000; nuclear@1: static const UInt32 TIMEOUT_WAITING_FOR_COLOR_DETECTED = 4000; nuclear@1: static const Color CALIBRATE_BLACK(0, 0, 0); nuclear@1: static const Color CALIBRATE_WHITE(255, 255, 255); nuclear@1: static const Color COLOR1(0, 0, 0); nuclear@1: static const Color COLOR2(255, 255, 255); nuclear@1: static const Color SENSOR_DETECT_THRESHOLD(128, 255, 255); nuclear@1: static const float BIG_FLOAT = 1000000.0f; nuclear@1: static const float SMALL_FLOAT = -1000000.0f; nuclear@1: nuclear@1: //------------------------------------------------------------------------------------- nuclear@1: // ***** LatencyTest nuclear@1: nuclear@1: LatencyTest::LatencyTest(LatencyTestDevice* device) nuclear@1: : Handler(getThis()) nuclear@1: { nuclear@1: if (device != NULL) nuclear@1: { nuclear@1: SetDevice(device); nuclear@1: } nuclear@1: nuclear@1: reset(); nuclear@1: nuclear@1: srand(Timer::GetTicksMs()); nuclear@1: } nuclear@1: nuclear@1: LatencyTest::~LatencyTest() nuclear@1: { nuclear@1: clearMeasurementResults(); nuclear@1: } nuclear@1: nuclear@1: bool LatencyTest::SetDevice(LatencyTestDevice* device) nuclear@1: { nuclear@1: nuclear@1: if (device != Device) nuclear@1: { nuclear@1: if (device != NULL) nuclear@1: { nuclear@1: if (device->GetMessageHandler() != NULL) nuclear@1: { nuclear@1: OVR_DEBUG_LOG( nuclear@1: ("LatencyTest::AttachToDevice failed - device %p already has handler", device)); nuclear@1: return false; nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: if (Device != NULL) nuclear@1: { nuclear@1: Device->SetMessageHandler(0); nuclear@1: } nuclear@1: Device = device; nuclear@1: nuclear@1: if (Device != NULL) nuclear@1: { nuclear@1: Device->SetMessageHandler(&Handler); nuclear@1: nuclear@1: // Set trigger threshold. nuclear@1: LatencyTestConfiguration configuration(SENSOR_DETECT_THRESHOLD, false); // No samples streaming. nuclear@1: Device->SetConfiguration(configuration, true); nuclear@1: nuclear@1: // Set display to intial (3 dashes). nuclear@1: LatencyTestDisplay ltd(2, 0x40400040); nuclear@1: Device->SetDisplay(ltd); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: UInt32 LatencyTest::getRandomComponent(UInt32 range) nuclear@1: { nuclear@1: UInt32 val = rand() % range; nuclear@1: return val; nuclear@1: } nuclear@1: nuclear@1: void LatencyTest::BeginTest() nuclear@1: { nuclear@1: if (State == State_WaitingForButton) nuclear@1: { nuclear@1: // Set color to black and wait a while. nuclear@1: RenderColor = CALIBRATE_BLACK; nuclear@1: nuclear@1: State = State_WaitingForSettlePreCalibrationColorBlack; nuclear@1: OVR_DEBUG_LOG(("State_WaitingForButton -> State_WaitingForSettlePreCalibrationColorBlack.")); nuclear@1: nuclear@1: setTimer(TIME_TO_WAIT_FOR_SETTLE_PRE_CALIBRATION); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: void LatencyTest::handleMessage(const Message& msg, LatencyTestMessageType latencyTestMessage) nuclear@1: { nuclear@1: // For debugging. nuclear@1: /* if (msg.Type == Message_LatencyTestSamples) nuclear@1: { nuclear@1: MessageLatencyTestSamples* pSamples = (MessageLatencyTestSamples*) &msg; nuclear@1: nuclear@1: if (pSamples->Samples.GetSize() > 0) nuclear@1: { nuclear@1: // Just show the first one for now. nuclear@1: Color c = pSamples->Samples[0]; nuclear@1: OVR_DEBUG_LOG(("%d %d %d", c.R, c.G, c.B)); nuclear@1: } nuclear@1: return; nuclear@1: } nuclear@1: */ nuclear@1: nuclear@1: if (latencyTestMessage == LatencyTest_Timer) nuclear@1: { nuclear@1: if (!Device) nuclear@1: { nuclear@1: reset(); nuclear@1: return; nuclear@1: } nuclear@1: nuclear@1: if (State == State_WaitingForSettlePreCalibrationColorBlack) nuclear@1: { nuclear@1: // Send calibrate message to device and wait a while. nuclear@1: Device->SetCalibrate(CALIBRATE_BLACK); nuclear@1: nuclear@1: State = State_WaitingForSettlePostCalibrationColorBlack; nuclear@1: OVR_DEBUG_LOG(("State_WaitingForSettlePreCalibrationColorBlack -> State_WaitingForSettlePostCalibrationColorBlack.")); nuclear@1: nuclear@1: setTimer(TIME_TO_WAIT_FOR_SETTLE_POST_CALIBRATION); nuclear@1: } nuclear@1: else if (State == State_WaitingForSettlePostCalibrationColorBlack) nuclear@1: { nuclear@1: // Change color to white and wait a while. nuclear@1: RenderColor = CALIBRATE_WHITE; nuclear@1: nuclear@1: State = State_WaitingForSettlePreCalibrationColorWhite; nuclear@1: OVR_DEBUG_LOG(("State_WaitingForSettlePostCalibrationColorBlack -> State_WaitingForSettlePreCalibrationColorWhite.")); nuclear@1: nuclear@1: setTimer(TIME_TO_WAIT_FOR_SETTLE_PRE_CALIBRATION); nuclear@1: } nuclear@1: else if (State == State_WaitingForSettlePreCalibrationColorWhite) nuclear@1: { nuclear@1: // Send calibrate message to device and wait a while. nuclear@1: Device->SetCalibrate(CALIBRATE_WHITE); nuclear@1: nuclear@1: State = State_WaitingForSettlePostCalibrationColorWhite; nuclear@1: OVR_DEBUG_LOG(("State_WaitingForSettlePreCalibrationColorWhite -> State_WaitingForSettlePostCalibrationColorWhite.")); nuclear@1: nuclear@1: setTimer(TIME_TO_WAIT_FOR_SETTLE_POST_CALIBRATION); nuclear@1: } nuclear@1: else if (State == State_WaitingForSettlePostCalibrationColorWhite) nuclear@1: { nuclear@1: // Calibration is done. Switch to color 1 and wait for it to settle. nuclear@1: RenderColor = COLOR1; nuclear@1: nuclear@1: State = State_WaitingForSettlePostMeasurement; nuclear@1: OVR_DEBUG_LOG(("State_WaitingForSettlePostCalibrationColorWhite -> State_WaitingForSettlePostMeasurement.")); nuclear@1: nuclear@1: UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS); nuclear@1: setTimer(waitTime); nuclear@1: } nuclear@1: else if (State == State_WaitingForSettlePostMeasurement) nuclear@1: { nuclear@1: // Prepare for next measurement. nuclear@1: nuclear@1: // Create a new result object. nuclear@1: MeasurementResult* pResult = new MeasurementResult(); nuclear@1: Results.PushBack(pResult); nuclear@1: nuclear@1: State = State_WaitingToTakeMeasurement; nuclear@1: OVR_DEBUG_LOG(("State_WaitingForSettlePostMeasurement -> State_WaitingToTakeMeasurement.")); nuclear@1: } nuclear@1: else if (State == State_WaitingForTestStarted) nuclear@1: { nuclear@1: // We timed out waiting for 'TestStarted'. Abandon this measurement and setup for the next. nuclear@1: getActiveResult()->TimedOutWaitingForTestStarted = true; nuclear@1: nuclear@1: State = State_WaitingForSettlePostMeasurement; nuclear@1: OVR_DEBUG_LOG(("** Timed out waiting for 'TestStarted'.")); nuclear@1: OVR_DEBUG_LOG(("State_WaitingForTestStarted -> State_WaitingForSettlePostMeasurement.")); nuclear@1: nuclear@1: UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS); nuclear@1: setTimer(waitTime); nuclear@1: } nuclear@1: else if (State == State_WaitingForColorDetected) nuclear@1: { nuclear@1: // We timed out waiting for 'ColorDetected'. Abandon this measurement and setup for the next. nuclear@1: getActiveResult()->TimedOutWaitingForColorDetected = true; nuclear@1: nuclear@1: State = State_WaitingForSettlePostMeasurement; nuclear@1: OVR_DEBUG_LOG(("** Timed out waiting for 'ColorDetected'.")); nuclear@1: OVR_DEBUG_LOG(("State_WaitingForColorDetected -> State_WaitingForSettlePostMeasurement.")); nuclear@1: nuclear@1: UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS); nuclear@1: setTimer(waitTime); nuclear@1: } nuclear@1: } nuclear@1: else if (latencyTestMessage == LatencyTest_ProcessInputs) nuclear@1: { nuclear@1: if (State == State_WaitingToTakeMeasurement) nuclear@1: { nuclear@1: if (!Device) nuclear@1: { nuclear@1: reset(); nuclear@1: return; nuclear@1: } nuclear@1: nuclear@1: // Send 'StartTest' feature report with opposite target color. nuclear@1: if (RenderColor == COLOR1) nuclear@1: { nuclear@1: RenderColor = COLOR2; nuclear@1: } nuclear@1: else nuclear@1: { nuclear@1: RenderColor = COLOR1; nuclear@1: } nuclear@1: nuclear@1: getActiveResult()->TargetColor = RenderColor; nuclear@1: nuclear@1: // Record time so we can determine usb roundtrip time. nuclear@1: getActiveResult()->StartTestTicksMicroS = Timer::GetTicks(); nuclear@1: nuclear@1: Device->SetStartTest(RenderColor); nuclear@1: nuclear@1: State = State_WaitingForTestStarted; nuclear@1: OVR_DEBUG_LOG(("State_WaitingToTakeMeasurement -> State_WaitingForTestStarted.")); nuclear@1: nuclear@1: setTimer(TIMEOUT_WAITING_FOR_TEST_STARTED); nuclear@1: nuclear@1: LatencyTestDisplay ltd(2, 0x40090040); nuclear@1: Device->SetDisplay(ltd); nuclear@1: } nuclear@1: } nuclear@1: else if (msg.Type == Message_LatencyTestButton) nuclear@1: { nuclear@1: BeginTest(); nuclear@1: } nuclear@1: else if (msg.Type == Message_LatencyTestStarted) nuclear@1: { nuclear@1: if (State == State_WaitingForTestStarted) nuclear@1: { nuclear@1: clearTimer(); nuclear@1: nuclear@1: // Record time so we can determine usb roundtrip time. nuclear@1: getActiveResult()->TestStartedTicksMicroS = Timer::GetTicks(); nuclear@1: nuclear@1: State = State_WaitingForColorDetected; nuclear@1: OVR_DEBUG_LOG(("State_WaitingForTestStarted -> State_WaitingForColorDetected.")); nuclear@1: nuclear@1: setTimer(TIMEOUT_WAITING_FOR_COLOR_DETECTED); nuclear@1: } nuclear@1: } nuclear@1: else if (msg.Type == Message_LatencyTestColorDetected) nuclear@1: { nuclear@1: if (State == State_WaitingForColorDetected) nuclear@1: { nuclear@1: // Record time to detect color. nuclear@1: MessageLatencyTestColorDetected* pDetected = (MessageLatencyTestColorDetected*) &msg; nuclear@1: UInt16 elapsedTime = pDetected->Elapsed; nuclear@1: OVR_DEBUG_LOG(("Time to 'ColorDetected' = %d", elapsedTime)); nuclear@1: nuclear@1: getActiveResult()->DeviceMeasuredElapsedMilliS = elapsedTime; nuclear@1: nuclear@1: if (areResultsComplete()) nuclear@1: { nuclear@1: // We're done. nuclear@1: processResults(); nuclear@1: reset(); nuclear@1: } nuclear@1: else nuclear@1: { nuclear@1: // Run another measurement. nuclear@1: State = State_WaitingForSettlePostMeasurement; nuclear@1: OVR_DEBUG_LOG(("State_WaitingForColorDetected -> State_WaitingForSettlePostMeasurement.")); nuclear@1: nuclear@1: UInt32 waitTime = TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT + getRandomComponent(TIME_TO_WAIT_FOR_SETTLE_POST_MEASUREMENT_RANDOMNESS); nuclear@1: setTimer(waitTime); nuclear@1: nuclear@1: LatencyTestDisplay ltd(2, 0x40400040); nuclear@1: Device->SetDisplay(ltd); nuclear@1: } nuclear@1: } nuclear@1: } nuclear@1: else if (msg.Type == Message_DeviceRemoved) nuclear@1: { nuclear@1: reset(); nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: LatencyTest::MeasurementResult* LatencyTest::getActiveResult() nuclear@1: { nuclear@1: OVR_ASSERT(!Results.IsEmpty()); nuclear@1: return Results.GetLast(); nuclear@1: } nuclear@1: nuclear@1: void LatencyTest::setTimer(UInt32 timeMilliS) nuclear@1: { nuclear@1: ActiveTimerMilliS = timeMilliS; nuclear@1: } nuclear@1: nuclear@1: void LatencyTest::clearTimer() nuclear@1: { nuclear@1: ActiveTimerMilliS = 0; nuclear@1: } nuclear@1: nuclear@1: void LatencyTest::reset() nuclear@1: { nuclear@1: clearMeasurementResults(); nuclear@1: State = State_WaitingForButton; nuclear@1: nuclear@1: HaveOldTime = false; nuclear@1: ActiveTimerMilliS = 0; nuclear@1: } nuclear@1: nuclear@1: void LatencyTest::clearMeasurementResults() nuclear@1: { nuclear@1: while(!Results.IsEmpty()) nuclear@1: { nuclear@1: MeasurementResult* pElem = Results.GetFirst(); nuclear@1: pElem->RemoveNode(); nuclear@1: delete pElem; nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: LatencyTest::LatencyTestHandler::~LatencyTestHandler() nuclear@1: { nuclear@1: RemoveHandlerFromDevices(); nuclear@1: } nuclear@1: nuclear@1: void LatencyTest::LatencyTestHandler::OnMessage(const Message& msg) nuclear@1: { nuclear@1: pLatencyTestUtil->handleMessage(msg); nuclear@1: } nuclear@1: nuclear@1: void LatencyTest::ProcessInputs() nuclear@1: { nuclear@1: updateForTimeouts(); nuclear@1: handleMessage(Message(), LatencyTest_ProcessInputs); nuclear@1: } nuclear@1: nuclear@1: bool LatencyTest::DisplayScreenColor(Color& colorToDisplay) nuclear@1: { nuclear@1: updateForTimeouts(); nuclear@1: nuclear@1: if (State == State_WaitingForButton) nuclear@1: { nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: colorToDisplay = RenderColor; nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: const char* LatencyTest::GetResultsString() nuclear@1: { nuclear@1: if (!ResultsString.IsEmpty() && ReturnedResultString != ResultsString.ToCStr()) nuclear@1: { nuclear@1: ReturnedResultString = ResultsString; nuclear@1: return ReturnedResultString.ToCStr(); nuclear@1: } nuclear@1: nuclear@1: return NULL; nuclear@1: } nuclear@1: nuclear@1: bool LatencyTest::areResultsComplete() nuclear@1: { nuclear@1: UInt32 initialMeasurements = 0; nuclear@1: nuclear@1: UInt32 measurements1to2 = 0; nuclear@1: UInt32 measurements2to1 = 0; nuclear@1: nuclear@1: MeasurementResult* pCurr = Results.GetFirst(); nuclear@1: while(true) nuclear@1: { nuclear@1: // Process. nuclear@1: if (!pCurr->TimedOutWaitingForTestStarted && nuclear@1: !pCurr->TimedOutWaitingForColorDetected) nuclear@1: { nuclear@1: initialMeasurements++; nuclear@1: nuclear@1: if (initialMeasurements > INITIAL_SAMPLES_TO_IGNORE) nuclear@1: { nuclear@1: if (pCurr->TargetColor == COLOR2) nuclear@1: { nuclear@1: measurements1to2++; nuclear@1: } nuclear@1: else nuclear@1: { nuclear@1: measurements2to1++; nuclear@1: } nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: if (Results.IsLast(pCurr)) nuclear@1: { nuclear@1: break; nuclear@1: } nuclear@1: pCurr = Results.GetNext(pCurr); nuclear@1: } nuclear@1: nuclear@1: if (measurements1to2 >= DEFAULT_NUMBER_OF_SAMPLES && nuclear@1: measurements2to1 >= DEFAULT_NUMBER_OF_SAMPLES) nuclear@1: { nuclear@1: return true; nuclear@1: } nuclear@1: nuclear@1: return false; nuclear@1: } nuclear@1: nuclear@1: void LatencyTest::processResults() nuclear@1: { nuclear@1: nuclear@1: UInt32 minTime1To2 = UINT_MAX; nuclear@1: UInt32 maxTime1To2 = 0; nuclear@1: float averageTime1To2 = 0.0f; nuclear@1: UInt32 minTime2To1 = UINT_MAX; nuclear@1: UInt32 maxTime2To1 = 0; nuclear@1: float averageTime2To1 = 0.0f; nuclear@1: nuclear@1: float minUSBTripMilliS = BIG_FLOAT; nuclear@1: float maxUSBTripMilliS = SMALL_FLOAT; nuclear@1: float averageUSBTripMilliS = 0.0f; nuclear@1: UInt32 countUSBTripTime = 0; nuclear@1: nuclear@1: UInt32 measurementsCount = 0; nuclear@1: UInt32 measurements1to2 = 0; nuclear@1: UInt32 measurements2to1 = 0; nuclear@1: nuclear@1: MeasurementResult* pCurr = Results.GetFirst(); nuclear@1: UInt32 count = 0; nuclear@1: while(true) nuclear@1: { nuclear@1: count++; nuclear@1: nuclear@1: if (!pCurr->TimedOutWaitingForTestStarted && nuclear@1: !pCurr->TimedOutWaitingForColorDetected) nuclear@1: { nuclear@1: measurementsCount++; nuclear@1: nuclear@1: if (measurementsCount > INITIAL_SAMPLES_TO_IGNORE) nuclear@1: { nuclear@1: if (pCurr->TargetColor == COLOR2) nuclear@1: { nuclear@1: measurements1to2++; nuclear@1: nuclear@1: if (measurements1to2 <= DEFAULT_NUMBER_OF_SAMPLES) nuclear@1: { nuclear@1: UInt32 elapsed = pCurr->DeviceMeasuredElapsedMilliS; nuclear@1: nuclear@1: minTime1To2 = Alg::Min(elapsed, minTime1To2); nuclear@1: maxTime1To2 = Alg::Max(elapsed, maxTime1To2); nuclear@1: nuclear@1: averageTime1To2 += (float) elapsed; nuclear@1: } nuclear@1: } nuclear@1: else nuclear@1: { nuclear@1: measurements2to1++; nuclear@1: nuclear@1: if (measurements2to1 <= DEFAULT_NUMBER_OF_SAMPLES) nuclear@1: { nuclear@1: UInt32 elapsed = pCurr->DeviceMeasuredElapsedMilliS; nuclear@1: nuclear@1: minTime2To1 = Alg::Min(elapsed, minTime2To1); nuclear@1: maxTime2To1 = Alg::Max(elapsed, maxTime2To1); nuclear@1: nuclear@1: averageTime2To1 += (float) elapsed; nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: float usbRountripElapsedMilliS = 0.001f * (float) (pCurr->TestStartedTicksMicroS - pCurr->StartTestTicksMicroS); nuclear@1: minUSBTripMilliS = Alg::Min(usbRountripElapsedMilliS, minUSBTripMilliS); nuclear@1: maxUSBTripMilliS = Alg::Max(usbRountripElapsedMilliS, maxUSBTripMilliS); nuclear@1: averageUSBTripMilliS += usbRountripElapsedMilliS; nuclear@1: countUSBTripTime++; nuclear@1: } nuclear@1: } nuclear@1: nuclear@1: if (measurements1to2 >= DEFAULT_NUMBER_OF_SAMPLES && nuclear@1: measurements2to1 >= DEFAULT_NUMBER_OF_SAMPLES) nuclear@1: { nuclear@1: break; nuclear@1: } nuclear@1: nuclear@1: if (Results.IsLast(pCurr)) nuclear@1: { nuclear@1: break; nuclear@1: } nuclear@1: pCurr = Results.GetNext(pCurr); nuclear@1: } nuclear@1: nuclear@1: averageTime1To2 /= (float) DEFAULT_NUMBER_OF_SAMPLES; nuclear@1: averageTime2To1 /= (float) DEFAULT_NUMBER_OF_SAMPLES; nuclear@1: nuclear@1: averageUSBTripMilliS /= countUSBTripTime; nuclear@1: nuclear@1: float finalResult = 0.5f * (averageTime1To2 + averageTime2To1); nuclear@1: finalResult += averageUSBTripMilliS; nuclear@1: nuclear@1: ResultsString.Clear(); nuclear@1: ResultsString.AppendFormat("RESULT=%.1f (add half Tracker period) [b->w %d|%.1f|%d] [w->b %d|%.1f|%d] [usb rndtrp %.1f|%.1f|%.1f] [cnt %d] [tmouts %d]", nuclear@1: finalResult, nuclear@1: minTime1To2, averageTime1To2, maxTime1To2, nuclear@1: minTime2To1, averageTime2To1, maxTime2To1, nuclear@1: minUSBTripMilliS, averageUSBTripMilliS, maxUSBTripMilliS, nuclear@1: DEFAULT_NUMBER_OF_SAMPLES*2, count - measurementsCount); nuclear@1: nuclear@1: // Display result on latency tester display. nuclear@1: LatencyTestDisplay ltd(1, (int)finalResult); nuclear@1: Device->SetDisplay(ltd); nuclear@1: } nuclear@1: nuclear@1: void LatencyTest::updateForTimeouts() nuclear@1: { nuclear@1: if (!HaveOldTime) nuclear@1: { nuclear@1: HaveOldTime = true; nuclear@1: OldTime = Timer::GetTicksMs(); nuclear@1: return; nuclear@1: } nuclear@1: nuclear@1: UInt32 newTime = Timer::GetTicksMs(); nuclear@1: UInt32 elapsedMilliS = newTime - OldTime; nuclear@1: if (newTime < OldTime) nuclear@1: { nuclear@1: elapsedMilliS = OldTime - newTime; nuclear@1: elapsedMilliS = UINT_MAX - elapsedMilliS; nuclear@1: } nuclear@1: OldTime = newTime; nuclear@1: nuclear@1: elapsedMilliS = Alg::Min(elapsedMilliS, (UInt32) 100); // Clamp at 100mS in case we're not being called very often. nuclear@1: nuclear@1: nuclear@1: if (ActiveTimerMilliS == 0) nuclear@1: { nuclear@1: return; nuclear@1: } nuclear@1: nuclear@1: if (elapsedMilliS >= ActiveTimerMilliS) nuclear@1: { nuclear@1: ActiveTimerMilliS = 0; nuclear@1: handleMessage(Message(), LatencyTest_Timer); nuclear@1: return; nuclear@1: } nuclear@1: nuclear@1: ActiveTimerMilliS -= elapsedMilliS; nuclear@1: } nuclear@1: nuclear@1: }} // namespace OVR::Util