blob: 24d33f8aeeef4b48900eca59ad1e6e76a3267437 [file] [log] [blame]
Sabina Davisadc58542019-02-01 22:23:00 -08001#include "frc971/wpilib/sensor_reader.h"
2
3#include "aos/init.h"
4#include "aos/util/compiler_memory_barrier.h"
5#include "frc971/wpilib/ahal/DigitalInput.h"
6#include "frc971/wpilib/ahal/Utility.h"
7
8namespace frc971 {
9namespace wpilib {
10
11SensorReader::SensorReader() {}
12
Sabina Davisb6317b72019-02-01 22:53:23 -080013void SensorReader::set_drivetrain_left_encoder(
14 ::std::unique_ptr<frc::Encoder> encoder) {
15 fast_encoder_filter_.Add(encoder.get());
16 drivetrain_left_encoder_ = ::std::move(encoder);
17}
18
19void SensorReader::set_drivetrain_right_encoder(
20 ::std::unique_ptr<frc::Encoder> encoder) {
21 fast_encoder_filter_.Add(encoder.get());
22 drivetrain_right_encoder_ = ::std::move(encoder);
23}
24
25// All of the DMA-related set_* calls must be made before this, and it
26// doesn't hurt to do all of them.
Sabina Davis1ffa4172019-02-01 22:38:33 -080027void SensorReader::set_dma(::std::unique_ptr<DMA> dma) {
28 dma_synchronizer_.reset(
29 new ::frc971::wpilib::DMASynchronizer(::std::move(dma)));
30}
31
Sabina Davisadc58542019-02-01 22:23:00 -080032void SensorReader::set_pwm_trigger(
33 ::std::unique_ptr<frc::DigitalInput> pwm_trigger) {
34 medium_encoder_filter_.Add(pwm_trigger.get());
35 pwm_trigger_ = ::std::move(pwm_trigger);
36}
37
38void SensorReader::RunPWMDetecter() {
39 ::aos::SetCurrentThreadRealtimePriority(41);
40
41 pwm_trigger_->RequestInterrupts();
42 // Rising edge only.
43 pwm_trigger_->SetUpSourceEdge(true, false);
44
45 monotonic_clock::time_point last_posedge_monotonic =
46 monotonic_clock::min_time;
47
48 while (run_) {
49 auto ret = pwm_trigger_->WaitForInterrupt(1.0, true);
50 if (ret == frc::InterruptableSensorBase::WaitResult::kRisingEdge) {
51 // Grab all the clocks.
52 const double pwm_fpga_time = pwm_trigger_->ReadRisingTimestamp();
53
54 aos_compiler_memory_barrier();
55 const double fpga_time_before = frc::GetFPGATime() * 1e-6;
56 aos_compiler_memory_barrier();
57 const monotonic_clock::time_point monotonic_now = monotonic_clock::now();
58 aos_compiler_memory_barrier();
59 const double fpga_time_after = frc::GetFPGATime() * 1e-6;
60 aos_compiler_memory_barrier();
61
62 const double fpga_offset =
63 (fpga_time_after + fpga_time_before) / 2.0 - pwm_fpga_time;
64
65 // Compute when the edge was.
66 const monotonic_clock::time_point monotonic_edge =
67 monotonic_now - chrono::duration_cast<chrono::nanoseconds>(
68 chrono::duration<double>(fpga_offset));
69
70 LOG(DEBUG, "Got PWM pulse %f spread, %f offset, %lld trigger\n",
71 fpga_time_after - fpga_time_before, fpga_offset,
72 monotonic_edge.time_since_epoch().count());
73
74 // Compute bounds on the timestep and sampling times.
75 const double fpga_sample_length = fpga_time_after - fpga_time_before;
76 const chrono::nanoseconds elapsed_time =
77 monotonic_edge - last_posedge_monotonic;
78
79 last_posedge_monotonic = monotonic_edge;
80
81 // Verify that the values are sane.
82 if (fpga_sample_length > 2e-5 || fpga_sample_length < 0) {
83 continue;
84 }
85 if (fpga_offset < 0 || fpga_offset > 0.00015) {
86 continue;
87 }
88 if (elapsed_time > chrono::microseconds(5050) + chrono::microseconds(4) ||
89 elapsed_time < chrono::microseconds(5050) - chrono::microseconds(4)) {
90 continue;
91 }
92 // Good edge!
93 {
94 ::std::unique_lock<::aos::stl_mutex> locker(tick_time_mutex_);
95 last_tick_time_monotonic_timepoint_ = last_posedge_monotonic;
96 last_period_ = elapsed_time;
97 }
98 } else {
99 LOG(INFO, "PWM triggered %d\n", ret);
100 }
101 }
102 pwm_trigger_->CancelInterrupts();
103}
104
105} // namespace wpilib
106} // namespace frc971