blob: 2e0cd0ac362788b417a1d1e631151137a1672197 [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"
Austin Schuhdf6cbb12019-02-02 13:46:52 -08007#include "aos/logging/queue_logging.h"
Sabina Davisadc58542019-02-01 22:23:00 -08008#include "aos/util/compiler_memory_barrier.h"
Sabina Davis399dbd82019-02-01 23:06:08 -08009#include "aos/util/phased_loop.h"
Sabina Davisadc58542019-02-01 22:23:00 -080010#include "frc971/wpilib/ahal/DigitalInput.h"
Austin Schuh3b010bc2019-02-24 17:25:37 -080011#include "frc971/wpilib/ahal/DriverStation.h"
Sabina Davisadc58542019-02-01 22:23:00 -080012#include "frc971/wpilib/ahal/Utility.h"
Austin Schuh45a549f2019-02-02 15:43:56 -080013#include "frc971/wpilib/wpilib_interface.h"
Austin Schuh3b010bc2019-02-24 17:25:37 -080014#include "hal/PWM.h"
Sabina Davisadc58542019-02-01 22:23:00 -080015
16namespace frc971 {
17namespace wpilib {
18
Austin Schuhdf6cbb12019-02-02 13:46:52 -080019SensorReader::SensorReader(::aos::EventLoop *event_loop)
20 : event_loop_(event_loop),
21 robot_state_sender_(
22 event_loop_->MakeSender<::aos::RobotState>(".aos.robot_state")) {
Austin Schuh45a549f2019-02-02 15:43:56 -080023 // Set some defaults. We don't tend to exceed these, so old robots should
24 // just work with them.
25 UpdateFastEncoderFilterHz(500000);
26 UpdateMediumEncoderFilterHz(100000);
Austin Schuh3b010bc2019-02-24 17:25:37 -080027 ds_ = &::frc::DriverStation::GetInstance();
Austin Schuh45a549f2019-02-02 15:43:56 -080028}
29
30void SensorReader::UpdateFastEncoderFilterHz(int hz) {
31 fast_encoder_filter_.SetPeriodHz(::std::max(hz, 100000));
32}
33
34void SensorReader::UpdateMediumEncoderFilterHz(int hz) {
35 medium_encoder_filter_.SetPeriodHz(::std::max(hz, 50000));
36}
Sabina Davisadc58542019-02-01 22:23:00 -080037
Sabina Davisb6317b72019-02-01 22:53:23 -080038void SensorReader::set_drivetrain_left_encoder(
39 ::std::unique_ptr<frc::Encoder> encoder) {
40 fast_encoder_filter_.Add(encoder.get());
41 drivetrain_left_encoder_ = ::std::move(encoder);
Austin Schuh45a549f2019-02-02 15:43:56 -080042 drivetrain_left_encoder_->SetMaxPeriod(0.005);
Sabina Davisb6317b72019-02-01 22:53:23 -080043}
44
45void SensorReader::set_drivetrain_right_encoder(
46 ::std::unique_ptr<frc::Encoder> encoder) {
47 fast_encoder_filter_.Add(encoder.get());
48 drivetrain_right_encoder_ = ::std::move(encoder);
Austin Schuh45a549f2019-02-02 15:43:56 -080049 drivetrain_right_encoder_->SetMaxPeriod(0.005);
Sabina Davisb6317b72019-02-01 22:53:23 -080050}
51
Austin Schuh3b010bc2019-02-24 17:25:37 -080052monotonic_clock::time_point SensorReader::GetPWMStartTime() {
53 int32_t status = 0;
54 const hal::fpga_clock::time_point new_fpga_time = hal::fpga_clock::time_point(
55 hal::fpga_clock::duration(HAL_GetPWMCycleStartTime(&status)));
Sabina Davisadc58542019-02-01 22:23:00 -080056
Austin Schuh3b010bc2019-02-24 17:25:37 -080057 aos_compiler_memory_barrier();
58 const hal::fpga_clock::time_point fpga_time_before = hal::fpga_clock::now();
59 aos_compiler_memory_barrier();
60 const monotonic_clock::time_point monotonic_now = monotonic_clock::now();
61 aos_compiler_memory_barrier();
62 const hal::fpga_clock::time_point fpga_time_after = hal::fpga_clock::now();
63 aos_compiler_memory_barrier();
Sabina Davisadc58542019-02-01 22:23:00 -080064
Austin Schuh3b010bc2019-02-24 17:25:37 -080065 const chrono::nanoseconds fpga_sample_length =
66 fpga_time_after - fpga_time_before;
67 const chrono::nanoseconds fpga_offset =
68 hal::fpga_clock::time_point((fpga_time_after.time_since_epoch() +
69 fpga_time_before.time_since_epoch()) /
70 2) -
71 new_fpga_time;
Sabina Davisadc58542019-02-01 22:23:00 -080072
Austin Schuh3b010bc2019-02-24 17:25:37 -080073 // Make sure that there wasn't a context switch while we were sampling the
74 // clocks. If there was, we are better off rejecting the sample than using
75 // it.
76 if (ds_->IsSysActive() && fpga_sample_length <= chrono::microseconds(20) &&
77 fpga_sample_length >= chrono::microseconds(0)) {
78 // Compute when the edge was.
79 return monotonic_now - fpga_offset;
80 } else {
81 return monotonic_clock::min_time;
Sabina Davisadc58542019-02-01 22:23:00 -080082 }
Sabina Davisadc58542019-02-01 22:23:00 -080083}
84
Sabina Davis399dbd82019-02-01 23:06:08 -080085void SensorReader::operator()() {
86 ::aos::SetCurrentThreadName("SensorReader");
87
Austin Schuh45a549f2019-02-02 15:43:56 -080088 int32_t my_pid = getpid();
Sabina Davis399dbd82019-02-01 23:06:08 -080089
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080090 Start();
Sabina Davis6292bec2019-02-06 22:53:14 -080091 if (dma_synchronizer_) {
92 dma_synchronizer_->Start();
93 }
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080094
Austin Schuh3b010bc2019-02-24 17:25:37 -080095 const chrono::microseconds period =
96 pwm_trigger_ ? chrono::microseconds(5050) : chrono::microseconds(5000);
Austin Schuh45a549f2019-02-02 15:43:56 -080097 if (pwm_trigger_) {
Austin Schuh45a549f2019-02-02 15:43:56 -080098 LOG(INFO, "Using PWM trigger and a 5.05 ms period\n");
99 } else {
100 LOG(INFO, "Defaulting to open loop pwm synchronization\n");
Austin Schuh45a549f2019-02-02 15:43:56 -0800101 }
102 ::aos::time::PhasedLoop phased_loop(
Austin Schuhd32b3622019-06-23 18:49:06 -0700103 period, ::aos::monotonic_clock::now(),
Austin Schuh45a549f2019-02-02 15:43:56 -0800104 pwm_trigger_ ? ::std::chrono::milliseconds(3) : chrono::milliseconds(4));
Sabina Davis399dbd82019-02-01 23:06:08 -0800105
Sabina Davis399dbd82019-02-01 23:06:08 -0800106 ::aos::SetCurrentThreadRealtimePriority(40);
Austin Schuh3b010bc2019-02-24 17:25:37 -0800107 monotonic_clock::time_point last_monotonic_now = monotonic_clock::now();
Sabina Davis399dbd82019-02-01 23:06:08 -0800108 while (run_) {
109 {
110 const int iterations = phased_loop.SleepUntilNext();
111 if (iterations != 1) {
112 LOG(WARNING, "SensorReader skipped %d iterations\n", iterations - 1);
113 }
114 }
Austin Schuh3b010bc2019-02-24 17:25:37 -0800115 const monotonic_clock::time_point monotonic_now = monotonic_clock::now();
Austin Schuh45a549f2019-02-02 15:43:56 -0800116
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800117 {
118 auto new_state = robot_state_sender_.MakeMessage();
119 ::frc971::wpilib::PopulateRobotState(new_state.get(), my_pid);
120 LOG_STRUCT(DEBUG, "robot_state", *new_state);
121 new_state.Send();
122 }
Sabina Davis399dbd82019-02-01 23:06:08 -0800123 RunIteration();
Sabina Davis6292bec2019-02-06 22:53:14 -0800124 if (dma_synchronizer_) {
125 dma_synchronizer_->RunIteration();
126 RunDmaIteration();
127 }
Sabina Davis399dbd82019-02-01 23:06:08 -0800128
Austin Schuh45a549f2019-02-02 15:43:56 -0800129 if (pwm_trigger_) {
Austin Schuh3b010bc2019-02-24 17:25:37 -0800130 LOG(DEBUG, "PWM wakeup delta: %lld\n",
131 (monotonic_now - last_monotonic_now).count());
132 last_monotonic_now = monotonic_now;
Austin Schuh45a549f2019-02-02 15:43:56 -0800133
Austin Schuh3b010bc2019-02-24 17:25:37 -0800134 monotonic_clock::time_point last_tick_timepoint = GetPWMStartTime();
Austin Schuh45a549f2019-02-02 15:43:56 -0800135 if (last_tick_timepoint == monotonic_clock::min_time) {
136 continue;
137 }
Austin Schuh45a549f2019-02-02 15:43:56 -0800138
Austin Schuh3b010bc2019-02-24 17:25:37 -0800139 last_tick_timepoint +=
140 (monotonic_now - last_tick_timepoint) / period * period;
141 // If it's over 1/2 of a period back in time, that's wrong. Move it
142 // forwards to now.
143 if (last_tick_timepoint - monotonic_now < -period / 2) {
144 last_tick_timepoint += period;
145 }
146
147 // We should be sampling our sensors to kick off the control cycle 50 uS
148 // after the falling edge. This gives us a little bit of buffer for
149 // errors in waking up. The PWM cycle starts at the falling edge of the
150 // PWM pulse.
151 chrono::nanoseconds new_offset = phased_loop.OffsetFromIntervalAndTime(
152 period, last_tick_timepoint + chrono::microseconds(50));
Austin Schuh45a549f2019-02-02 15:43:56 -0800153
154 phased_loop.set_interval_and_offset(period, new_offset);
Sabina Davis399dbd82019-02-01 23:06:08 -0800155 }
Sabina Davis399dbd82019-02-01 23:06:08 -0800156 }
Sabina Davis399dbd82019-02-01 23:06:08 -0800157}
158
Sabina Davisadc58542019-02-01 22:23:00 -0800159} // namespace wpilib
160} // namespace frc971