blob: 5bcb84af4d4aa28b49f772ac49e6901ecfaff61c [file] [log] [blame]
Sabina Davisadc58542019-02-01 22:23:00 -08001#include "frc971/wpilib/sensor_reader.h"
2
Sabina Davis399dbd82019-02-01 23:06:08 -08003#include <inttypes.h>
4#include <unistd.h>
5
Sabina Davisadc58542019-02-01 22:23:00 -08006#include "aos/init.h"
7#include "aos/util/compiler_memory_barrier.h"
Sabina Davis399dbd82019-02-01 23:06:08 -08008#include "aos/util/phased_loop.h"
Sabina Davisadc58542019-02-01 22:23:00 -08009#include "frc971/wpilib/ahal/DigitalInput.h"
Austin Schuh3b010bc2019-02-24 17:25:37 -080010#include "frc971/wpilib/ahal/DriverStation.h"
Sabina Davisadc58542019-02-01 22:23:00 -080011#include "frc971/wpilib/ahal/Utility.h"
Austin Schuh45a549f2019-02-02 15:43:56 -080012#include "frc971/wpilib/wpilib_interface.h"
Austin Schuh3b010bc2019-02-24 17:25:37 -080013#include "hal/PWM.h"
Sabina Davisadc58542019-02-01 22:23:00 -080014
15namespace frc971 {
16namespace wpilib {
17
Austin Schuh217a9782019-12-21 23:02:50 -080018SensorReader::SensorReader(::aos::ShmEventLoop *event_loop)
Austin Schuhdf6cbb12019-02-02 13:46:52 -080019 : event_loop_(event_loop),
Austin Schuh217a9782019-12-21 23:02:50 -080020 robot_state_sender_(event_loop_->MakeSender<::aos::RobotState>("/aos")),
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070021 my_pid_(getpid()) {
Austin Schuh45a549f2019-02-02 15:43:56 -080022 // Set some defaults. We don't tend to exceed these, so old robots should
23 // just work with them.
24 UpdateFastEncoderFilterHz(500000);
25 UpdateMediumEncoderFilterHz(100000);
Austin Schuh3b010bc2019-02-24 17:25:37 -080026 ds_ = &::frc::DriverStation::GetInstance();
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070027
28 event_loop->SetRuntimeRealtimePriority(40);
29
30 // Fill in the no pwm trigger defaults.
31 phased_loop_handler_ =
32 event_loop_->AddPhasedLoop([this](int iterations) { Loop(iterations); },
33 period_, chrono::milliseconds(4));
34
35 event_loop->set_name("SensorReader");
36 event_loop->OnRun([this]() { DoStart(); });
Austin Schuh45a549f2019-02-02 15:43:56 -080037}
38
39void SensorReader::UpdateFastEncoderFilterHz(int hz) {
40 fast_encoder_filter_.SetPeriodHz(::std::max(hz, 100000));
41}
42
43void SensorReader::UpdateMediumEncoderFilterHz(int hz) {
44 medium_encoder_filter_.SetPeriodHz(::std::max(hz, 50000));
45}
Sabina Davisadc58542019-02-01 22:23:00 -080046
Sabina Davisb6317b72019-02-01 22:53:23 -080047void SensorReader::set_drivetrain_left_encoder(
48 ::std::unique_ptr<frc::Encoder> encoder) {
49 fast_encoder_filter_.Add(encoder.get());
50 drivetrain_left_encoder_ = ::std::move(encoder);
Austin Schuh45a549f2019-02-02 15:43:56 -080051 drivetrain_left_encoder_->SetMaxPeriod(0.005);
Sabina Davisb6317b72019-02-01 22:53:23 -080052}
53
54void SensorReader::set_drivetrain_right_encoder(
55 ::std::unique_ptr<frc::Encoder> encoder) {
56 fast_encoder_filter_.Add(encoder.get());
57 drivetrain_right_encoder_ = ::std::move(encoder);
Austin Schuh45a549f2019-02-02 15:43:56 -080058 drivetrain_right_encoder_->SetMaxPeriod(0.005);
Sabina Davisb6317b72019-02-01 22:53:23 -080059}
60
Austin Schuh3b010bc2019-02-24 17:25:37 -080061monotonic_clock::time_point SensorReader::GetPWMStartTime() {
62 int32_t status = 0;
63 const hal::fpga_clock::time_point new_fpga_time = hal::fpga_clock::time_point(
64 hal::fpga_clock::duration(HAL_GetPWMCycleStartTime(&status)));
Sabina Davisadc58542019-02-01 22:23:00 -080065
Austin Schuh3b010bc2019-02-24 17:25:37 -080066 aos_compiler_memory_barrier();
67 const hal::fpga_clock::time_point fpga_time_before = hal::fpga_clock::now();
68 aos_compiler_memory_barrier();
69 const monotonic_clock::time_point monotonic_now = monotonic_clock::now();
70 aos_compiler_memory_barrier();
71 const hal::fpga_clock::time_point fpga_time_after = hal::fpga_clock::now();
72 aos_compiler_memory_barrier();
Sabina Davisadc58542019-02-01 22:23:00 -080073
Austin Schuh3b010bc2019-02-24 17:25:37 -080074 const chrono::nanoseconds fpga_sample_length =
75 fpga_time_after - fpga_time_before;
76 const chrono::nanoseconds fpga_offset =
77 hal::fpga_clock::time_point((fpga_time_after.time_since_epoch() +
78 fpga_time_before.time_since_epoch()) /
79 2) -
80 new_fpga_time;
Sabina Davisadc58542019-02-01 22:23:00 -080081
Austin Schuh3b010bc2019-02-24 17:25:37 -080082 // Make sure that there wasn't a context switch while we were sampling the
83 // clocks. If there was, we are better off rejecting the sample than using
84 // it.
85 if (ds_->IsSysActive() && fpga_sample_length <= chrono::microseconds(20) &&
86 fpga_sample_length >= chrono::microseconds(0)) {
87 // Compute when the edge was.
88 return monotonic_now - fpga_offset;
89 } else {
90 return monotonic_clock::min_time;
Sabina Davisadc58542019-02-01 22:23:00 -080091 }
Sabina Davisadc58542019-02-01 22:23:00 -080092}
93
Austin Schuhbd1fe9c2019-06-29 16:35:48 -070094void SensorReader::DoStart() {
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080095 Start();
Sabina Davis6292bec2019-02-06 22:53:14 -080096 if (dma_synchronizer_) {
97 dma_synchronizer_->Start();
98 }
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080099
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700100 period_ =
Austin Schuh3b010bc2019-02-24 17:25:37 -0800101 pwm_trigger_ ? chrono::microseconds(5050) : chrono::microseconds(5000);
Austin Schuh45a549f2019-02-02 15:43:56 -0800102 if (pwm_trigger_) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700103 AOS_LOG(INFO, "Using PWM trigger and a 5.05 ms period\n");
Austin Schuh45a549f2019-02-02 15:43:56 -0800104 } else {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700105 AOS_LOG(INFO, "Defaulting to open loop pwm synchronization\n");
Austin Schuh45a549f2019-02-02 15:43:56 -0800106 }
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700107
108 // Now that we are configured, actually fill in the defaults.
109 phased_loop_handler_->set_interval_and_offset(
110 period_,
Austin Schuh45a549f2019-02-02 15:43:56 -0800111 pwm_trigger_ ? ::std::chrono::milliseconds(3) : chrono::milliseconds(4));
Sabina Davis399dbd82019-02-01 23:06:08 -0800112
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700113 last_monotonic_now_ = monotonic_clock::now();
114}
Austin Schuh45a549f2019-02-02 15:43:56 -0800115
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700116void SensorReader::Loop(const int iterations) {
117 if (iterations != 1) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700118 AOS_LOG(WARNING, "SensorReader skipped %d iterations\n", iterations - 1);
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700119 }
120
121 const monotonic_clock::time_point monotonic_now =
122 event_loop_->monotonic_now();
123
124 {
Alex Perrycb7da4b2019-08-28 19:35:56 -0700125 auto builder = robot_state_sender_.MakeBuilder();
126 builder.Send(::frc971::wpilib::PopulateRobotState(&builder, my_pid_));
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700127 }
128 RunIteration();
129 if (dma_synchronizer_) {
130 dma_synchronizer_->RunIteration();
131 RunDmaIteration();
132 }
133
134 if (pwm_trigger_) {
Austin Schuhf257f3c2019-10-27 21:00:43 -0700135 AOS_LOG(DEBUG, "PWM wakeup delta: %lld\n",
136 (monotonic_now - last_monotonic_now_).count());
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700137 last_monotonic_now_ = monotonic_now;
138
139 monotonic_clock::time_point last_tick_timepoint = GetPWMStartTime();
140 if (last_tick_timepoint == monotonic_clock::min_time) {
141 return;
Sabina Davis6292bec2019-02-06 22:53:14 -0800142 }
Sabina Davis399dbd82019-02-01 23:06:08 -0800143
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700144 last_tick_timepoint +=
145 ((monotonic_now - last_tick_timepoint) / period_) * period_;
146 // If it's over 1/2 of a period back in time, that's wrong. Move it
147 // forwards to now.
148 if (last_tick_timepoint - monotonic_now < -period_ / 2) {
149 last_tick_timepoint += period_;
Sabina Davis399dbd82019-02-01 23:06:08 -0800150 }
Austin Schuhbd1fe9c2019-06-29 16:35:48 -0700151
152 // We should be sampling our sensors to kick off the control cycle 50 uS
153 // after the falling edge. This gives us a little bit of buffer for
154 // errors in waking up. The PWM cycle starts at the falling edge of the
155 // PWM pulse.
156 chrono::nanoseconds new_offset =
157 ::aos::time::PhasedLoop::OffsetFromIntervalAndTime(
158 period_, last_tick_timepoint + chrono::microseconds(50));
159
160 phased_loop_handler_->set_interval_and_offset(period_, new_offset);
Sabina Davis399dbd82019-02-01 23:06:08 -0800161 }
Sabina Davis399dbd82019-02-01 23:06:08 -0800162}
163
Sabina Davisadc58542019-02-01 22:23:00 -0800164} // namespace wpilib
165} // namespace frc971