blob: 4e20c6acf5245a47d867fc690635285bfb91951f [file] [log] [blame]
Austin Schuh812d0d12021-11-04 20:16:48 -07001// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
Brian Silverman8fce7482020-01-05 13:18:21 -08004
Austin Schuh1e69f942020-11-14 15:06:14 -08005#include <algorithm>
Brian Silverman8fce7482020-01-05 13:18:21 -08006#include <atomic>
7#include <chrono>
8#include <cstdio>
9#include <thread>
10
Austin Schuh812d0d12021-11-04 20:16:48 -070011#include <fmt/format.h>
Brian Silverman8fce7482020-01-05 13:18:21 -080012#include <wpi/timestamp.h>
13
14#include "MockHooksInternal.h"
15#include "NotifierInternal.h"
Austin Schuh1e69f942020-11-14 15:06:14 -080016#include "hal/simulation/NotifierData.h"
Brian Silverman8fce7482020-01-05 13:18:21 -080017
18static std::atomic<bool> programStarted{false};
19
20static std::atomic<uint64_t> programStartTime{0};
21static std::atomic<uint64_t> programPauseTime{0};
Austin Schuh1e69f942020-11-14 15:06:14 -080022static std::atomic<uint64_t> programStepTime{0};
Brian Silverman8fce7482020-01-05 13:18:21 -080023
Austin Schuh812d0d12021-11-04 20:16:48 -070024namespace hal::init {
25void InitializeMockHooks() {
26 wpi::SetNowImpl(GetFPGATime);
27}
28} // namespace hal::init
Brian Silverman8fce7482020-01-05 13:18:21 -080029
30namespace hal {
31void RestartTiming() {
Austin Schuh1e69f942020-11-14 15:06:14 -080032 programStartTime = wpi::NowDefault();
33 programStepTime = 0;
Austin Schuh812d0d12021-11-04 20:16:48 -070034 if (programPauseTime != 0) {
35 programPauseTime = programStartTime.load();
36 }
Brian Silverman8fce7482020-01-05 13:18:21 -080037}
38
39void PauseTiming() {
Austin Schuh812d0d12021-11-04 20:16:48 -070040 if (programPauseTime == 0) {
41 programPauseTime = wpi::NowDefault();
42 }
Brian Silverman8fce7482020-01-05 13:18:21 -080043}
44
45void ResumeTiming() {
46 if (programPauseTime != 0) {
Austin Schuh1e69f942020-11-14 15:06:14 -080047 programStartTime += wpi::NowDefault() - programPauseTime;
Brian Silverman8fce7482020-01-05 13:18:21 -080048 programPauseTime = 0;
49 }
50}
51
Austin Schuh812d0d12021-11-04 20:16:48 -070052bool IsTimingPaused() {
53 return programPauseTime != 0;
54}
Brian Silverman8fce7482020-01-05 13:18:21 -080055
Austin Schuh812d0d12021-11-04 20:16:48 -070056void StepTiming(uint64_t delta) {
57 programStepTime += delta;
58}
Brian Silverman8fce7482020-01-05 13:18:21 -080059
Austin Schuh1e69f942020-11-14 15:06:14 -080060uint64_t GetFPGATime() {
Brian Silverman8fce7482020-01-05 13:18:21 -080061 uint64_t curTime = programPauseTime;
Austin Schuh812d0d12021-11-04 20:16:48 -070062 if (curTime == 0) {
63 curTime = wpi::NowDefault();
64 }
Austin Schuh1e69f942020-11-14 15:06:14 -080065 return curTime + programStepTime - programStartTime;
Brian Silverman8fce7482020-01-05 13:18:21 -080066}
67
Austin Schuh812d0d12021-11-04 20:16:48 -070068double GetFPGATimestamp() {
69 return GetFPGATime() * 1.0e-6;
70}
Brian Silverman8fce7482020-01-05 13:18:21 -080071
Austin Schuh812d0d12021-11-04 20:16:48 -070072void SetProgramStarted() {
73 programStarted = true;
74}
75bool GetProgramStarted() {
76 return programStarted;
77}
Brian Silverman8fce7482020-01-05 13:18:21 -080078} // namespace hal
79
80using namespace hal;
81
82extern "C" {
83void HALSIM_WaitForProgramStart(void) {
84 int count = 0;
85 while (!programStarted) {
86 count++;
Austin Schuh812d0d12021-11-04 20:16:48 -070087 fmt::print("Waiting for program start signal: {}\n", count);
Brian Silverman8fce7482020-01-05 13:18:21 -080088 std::this_thread::sleep_for(std::chrono::milliseconds(500));
89 }
90}
91
Austin Schuh812d0d12021-11-04 20:16:48 -070092void HALSIM_SetProgramStarted(void) {
93 SetProgramStarted();
94}
Brian Silverman8fce7482020-01-05 13:18:21 -080095
Austin Schuh812d0d12021-11-04 20:16:48 -070096HAL_Bool HALSIM_GetProgramStarted(void) {
97 return GetProgramStarted();
98}
Brian Silverman8fce7482020-01-05 13:18:21 -080099
Austin Schuh812d0d12021-11-04 20:16:48 -0700100void HALSIM_RestartTiming(void) {
101 RestartTiming();
102}
Brian Silverman8fce7482020-01-05 13:18:21 -0800103
104void HALSIM_PauseTiming(void) {
105 PauseTiming();
106 PauseNotifiers();
107}
108
109void HALSIM_ResumeTiming(void) {
110 ResumeTiming();
111 ResumeNotifiers();
112}
113
Austin Schuh812d0d12021-11-04 20:16:48 -0700114HAL_Bool HALSIM_IsTimingPaused(void) {
115 return IsTimingPaused();
116}
Brian Silverman8fce7482020-01-05 13:18:21 -0800117
118void HALSIM_StepTiming(uint64_t delta) {
Austin Schuh1e69f942020-11-14 15:06:14 -0800119 WaitNotifiers();
120
121 while (delta > 0) {
122 int32_t status = 0;
123 uint64_t curTime = HAL_GetFPGATime(&status);
124 uint64_t nextTimeout = HALSIM_GetNextNotifierTimeout();
125 uint64_t step = std::min(delta, nextTimeout - curTime);
126
127 StepTiming(step);
128 delta -= step;
129
130 WakeupWaitNotifiers();
131 }
132}
133
134void HALSIM_StepTimingAsync(uint64_t delta) {
Brian Silverman8fce7482020-01-05 13:18:21 -0800135 StepTiming(delta);
136 WakeupNotifiers();
137}
138} // extern "C"