Files
allwpilib/hal/src/main/native/sim/MockHooks.cpp

156 lines
3.5 KiB
C++
Raw Normal View History

// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "wpi/hal/simulation/MockHooks.h"
#include <algorithm>
#include <atomic>
#include <chrono>
#include <thread>
#include "MockHooksInternal.hpp"
#include "NotifierInternal.hpp"
2025-11-07 19:56:21 -05:00
#include "wpi/hal/simulation/NotifierData.h"
2025-11-07 19:57:55 -05:00
#include "wpi/util/print.hpp"
2026-01-04 10:22:33 -08:00
#include "wpi/util/timestamp.hpp"
static std::atomic<bool> programStarted{false};
static std::atomic<int64_t> programState{0};
static std::atomic<uint64_t> programStartTime{0};
static std::atomic<uint64_t> programPauseTime{0};
static std::atomic<uint64_t> programStepTime{0};
2025-11-07 20:00:05 -05:00
namespace wpi::hal::init {
void InitializeMockHooks() {
wpi::util::SetNowImpl(GetMonotonicTime);
}
2025-11-07 20:00:05 -05:00
} // namespace wpi::hal::init
2025-11-07 20:00:05 -05:00
namespace wpi::hal {
void RestartTiming() {
2025-11-07 20:00:05 -05:00
programStartTime = wpi::util::NowDefault();
programStepTime = 0;
if (programPauseTime != 0) {
programPauseTime = programStartTime.load();
}
}
void PauseTiming() {
if (programPauseTime == 0) {
2025-11-07 20:00:05 -05:00
programPauseTime = wpi::util::NowDefault();
}
}
void ResumeTiming() {
if (programPauseTime != 0) {
2025-11-07 20:00:05 -05:00
programStartTime += wpi::util::NowDefault() - programPauseTime;
programPauseTime = 0;
}
}
bool IsTimingPaused() {
return programPauseTime != 0;
}
void StepTiming(uint64_t delta) {
programStepTime += delta;
}
uint64_t GetMonotonicTime() {
uint64_t curTime = programPauseTime;
if (curTime == 0) {
2025-11-07 20:00:05 -05:00
curTime = wpi::util::NowDefault();
}
return curTime + programStepTime - programStartTime;
}
void SetProgramStarted(bool started) {
programStarted = started;
}
bool GetProgramStarted() {
return programStarted;
}
2025-11-07 20:00:05 -05:00
} // namespace wpi::hal
2025-11-07 20:00:05 -05:00
using namespace wpi::hal;
extern "C" {
void HALSIM_WaitForProgramStart(HAL_Bool waitForFirstNotifier) {
int count = 0;
while (!programStarted) {
count++;
if (count % 10 == 0) {
wpi::util::print("Waiting for program start signal: {}\n", count);
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
// Frameworks observe program start before arming their first notifier alarm.
// Wait for that alarm so a following StepTiming() can see and service it.
while (waitForFirstNotifier &&
HALSIM_GetNextNotifierTimeout() == UINT64_MAX) {
count++;
if (count % 10 == 0) {
wpi::util::print("Waiting for first notifier alarm: {}\n", count);
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
void HALSIM_SetProgramStarted(HAL_Bool started) {
SetProgramStarted(started);
}
HAL_Bool HALSIM_GetProgramStarted(void) {
return GetProgramStarted();
}
void HALSIM_SetProgramState(HAL_ControlWord controlWord) {
programState = controlWord.value;
}
void HALSIM_GetProgramState(HAL_ControlWord* controlWord) {
controlWord->value = programState;
}
void HALSIM_RestartTiming(void) {
RestartTiming();
}
void HALSIM_PauseTiming(void) {
PauseTiming();
PauseNotifiers();
}
void HALSIM_ResumeTiming(void) {
ResumeTiming();
ResumeNotifiers();
}
HAL_Bool HALSIM_IsTimingPaused(void) {
return IsTimingPaused();
}
void HALSIM_StepTiming(uint64_t delta) {
WaitNotifiers();
while (delta > 0) {
uint64_t curTime = HAL_GetMonotonicTime();
uint64_t nextTimeout = HALSIM_GetNextNotifierTimeout();
uint64_t step = (std::min)(delta, nextTimeout - curTime);
StepTiming(step);
delta -= step;
WakeupWaitNotifiers();
}
}
void HALSIM_StepTimingAsync(uint64_t delta) {
StepTiming(delta);
WakeupNotifiers();
}
} // extern "C"