blob: af803218c275ca53e784bc654df283d197a99353 [file] [log] [blame]
Brian Silverman7be68ba2020-01-08 22:08:40 -08001#ifndef FRC971_WPILIB_FPGA_TIME_CONVERSION_H_
2#define FRC971_WPILIB_FPGA_TIME_CONVERSION_H_
3
Brian Silverman7be68ba2020-01-08 22:08:40 -08004#include <chrono>
Philipp Schrader790cb542023-07-05 21:06:52 -07005#include <optional>
6
Austin Schuh99f7c6a2024-06-25 22:07:44 -07007#include "absl/log/check.h"
8#include "absl/log/log.h"
Brian Silverman7be68ba2020-01-08 22:08:40 -08009
10#include "aos/time/time.h"
Brian Silverman7be68ba2020-01-08 22:08:40 -080011#include "hal/cpp/fpga_clock.h"
12
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080013namespace frc971::wpilib {
Brian Silverman7be68ba2020-01-08 22:08:40 -080014
15// Returns the offset from the monotonic clock to the FPGA time. This is defined
16// as `fpga_time - monotonic_time`.
17// Returns nullopt if sampling the time once failed.
18std::optional<std::chrono::nanoseconds> CalculateFpgaOffset();
19
20class FpgaTimeConverter {
21 public:
22 aos::monotonic_clock::time_point FpgaToMonotonic(
23 hal::fpga_clock::time_point fpga_time) {
24 UpdateOffset();
25 return aos::monotonic_clock::epoch() +
26 (fpga_time.time_since_epoch() + offset_);
27 }
28
29 hal::fpga_clock::time_point MonotonicToFpga(
30 aos::monotonic_clock::time_point monotonic_time) {
31 UpdateOffset();
32 return hal::fpga_clock::epoch() +
33 std::chrono::duration_cast<hal::fpga_clock::duration>(
34 monotonic_time.time_since_epoch() - offset_);
35 }
36
37 private:
38 void UpdateOffset() {
39 for (int i = 0; i < 10; ++i) {
40 const auto new_offset = CalculateFpgaOffset();
41 if (new_offset) {
42 offset_ = *new_offset;
43 return;
44 } else if (offset_ != offset_.min()) {
45 return;
46 }
47 }
48 LOG(FATAL) << "Failed to calculate FPGA offset";
49 }
50
51 std::chrono::nanoseconds offset_ = std::chrono::nanoseconds::min();
52};
53
Stephan Pleinesd99b1ee2024-02-02 20:56:44 -080054} // namespace frc971::wpilib
Brian Silverman7be68ba2020-01-08 22:08:40 -080055
56#endif // FRC971_WPILIB_FPGA_TIME_CONVERSION_H_