blob: d14f704f625c6c2d6f2af43bab253e3e05d39203 [file] [log] [blame]
Sabina Davisadc58542019-02-01 22:23:00 -08001#ifndef FRC971_WPILIB_SENSOR_READER_H_
2#define FRC971_WPILIB_SENSOR_READER_H_
3
4#include <atomic>
5#include <chrono>
6
Austin Schuhdf6cbb12019-02-02 13:46:52 -08007#include "aos/events/event-loop.h"
8#include "aos/robot_state/robot_state.q.h"
Sabina Davisadc58542019-02-01 22:23:00 -08009#include "aos/stl_mutex/stl_mutex.h"
10#include "aos/time/time.h"
Austin Schuh54667ac2019-02-02 16:44:49 -080011#include "frc971/control_loops/control_loops.q.h"
Sabina Davisadc58542019-02-01 22:23:00 -080012#include "frc971/wpilib/ahal/DigitalGlitchFilter.h"
13#include "frc971/wpilib/ahal/DigitalInput.h"
Austin Schuh3b010bc2019-02-24 17:25:37 -080014#include "frc971/wpilib/ahal/DriverStation.h"
Sabina Davis1ffa4172019-02-01 22:38:33 -080015#include "frc971/wpilib/dma.h"
16#include "frc971/wpilib/dma_edge_counting.h"
Austin Schuh54667ac2019-02-02 16:44:49 -080017#include "frc971/wpilib/encoder_and_potentiometer.h"
Sabina Davisadc58542019-02-01 22:23:00 -080018
19using ::aos::monotonic_clock;
20namespace chrono = ::std::chrono;
21
22namespace frc971 {
23namespace wpilib {
24
25class SensorReader {
26 public:
Austin Schuhdf6cbb12019-02-02 13:46:52 -080027 SensorReader(::aos::EventLoop *event_loop);
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080028 virtual ~SensorReader() {}
Sabina Davisadc58542019-02-01 22:23:00 -080029
Austin Schuh45a549f2019-02-02 15:43:56 -080030 // Updates the fast and medium encoder filter frequencies.
31 void UpdateFastEncoderFilterHz(int hz);
32 void UpdateMediumEncoderFilterHz(int hz);
33
Sabina Davisb6317b72019-02-01 22:53:23 -080034 // Sets the left drivetrain encoder.
35 void set_drivetrain_left_encoder(::std::unique_ptr<frc::Encoder> encoder);
36
37 // Sets the right drivetrain encoder.
38 void set_drivetrain_right_encoder(::std::unique_ptr<frc::Encoder> encoder);
39
Sabina Davis6292bec2019-02-06 22:53:14 -080040 // Adds a sensor to DMA.
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080041 void AddToDMA(DMASampleHandlerInterface *handler) {
Sabina Davis6292bec2019-02-06 22:53:14 -080042 if (!dma_synchronizer_) {
43 dma_synchronizer_.reset(
44 new ::frc971::wpilib::DMASynchronizer(std::make_unique<DMA>()));
45 }
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080046 dma_synchronizer_->Add(handler);
47 }
48
Austin Schuh3b010bc2019-02-24 17:25:37 -080049 // Sets PWM trigger mode. If true, synchronize the control loops with the PWM
50 // pulses. The sensors are sampled 50 uS after the falling edge of the PWM
51 // pulse.
52 void set_pwm_trigger(bool trigger) { pwm_trigger_ = trigger; }
Sabina Davisadc58542019-02-01 22:23:00 -080053
Sabina Davisa42cc352019-02-01 22:55:50 -080054 // Stops the pwm trigger on the next iteration.
55 void Quit() { run_ = false; }
56
Sabina Davis399dbd82019-02-01 23:06:08 -080057 virtual void RunIteration() = 0;
Sabina Davis6292bec2019-02-06 22:53:14 -080058 // Runs the DMA iteration after the synchronizer. This only gets run if a
59 // sensor has been added to DMA.
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080060 virtual void RunDmaIteration() {}
Sabina Davis399dbd82019-02-01 23:06:08 -080061
62 void operator()();
63
Sabina Davisadc58542019-02-01 22:23:00 -080064 protected:
Austin Schuh54667ac2019-02-02 16:44:49 -080065 // Copies a DMAEncoder to a IndexPosition with the correct unit and direction
66 // changes.
67 void CopyPosition(const ::frc971::wpilib::DMAEncoder &encoder,
68 ::frc971::IndexPosition *position,
69 double encoder_counts_per_revolution, double encoder_ratio,
70 bool reverse) {
71 const double multiplier = reverse ? -1.0 : 1.0;
72 position->encoder =
73 multiplier * encoder_translate(encoder.polled_encoder_value(),
74 encoder_counts_per_revolution,
75 encoder_ratio);
76 position->latched_encoder =
77 multiplier * encoder_translate(encoder.last_encoder_value(),
78 encoder_counts_per_revolution,
79 encoder_ratio);
80 position->index_pulses = encoder.index_posedge_count();
81 }
82
83 // Copies a AbsoluteEncoderAndPotentiometer to a PotAndAbsolutePosition with
84 // the correct unit and direction changes.
85 void CopyPosition(
86 const ::frc971::wpilib::AbsoluteEncoderAndPotentiometer &encoder,
87 ::frc971::PotAndAbsolutePosition *position,
88 double encoder_counts_per_revolution, double encoder_ratio,
89 ::std::function<double(double)> potentiometer_translate, bool reverse,
90 double pot_offset) {
91 const double multiplier = reverse ? -1.0 : 1.0;
92 position->pot = multiplier * potentiometer_translate(
93 encoder.ReadPotentiometerVoltage()) +
94 pot_offset;
95 position->encoder =
96 multiplier * encoder_translate(encoder.ReadRelativeEncoder(),
97 encoder_counts_per_revolution,
98 encoder_ratio);
99
100 position->absolute_encoder =
101 (reverse ? (1.0 - encoder.ReadAbsoluteEncoder())
102 : encoder.ReadAbsoluteEncoder()) *
103 encoder_ratio * (2.0 * M_PI);
104 }
105
106 // Copies a DMAEdgeCounter to a HallEffectAndPosition with the correct unit
107 // and direction changes.
108 void CopyPosition(const ::frc971::wpilib::DMAEdgeCounter &counter,
109 ::frc971::HallEffectAndPosition *position,
110 double encoder_counts_per_revolution, double encoder_ratio,
111 bool reverse) {
112 const double multiplier = reverse ? -1.0 : 1.0;
113 position->encoder =
114 multiplier * encoder_translate(counter.polled_encoder(),
115 encoder_counts_per_revolution,
116 encoder_ratio);
117 position->current = !counter.polled_value();
118 position->posedge_count = counter.negative_count();
119 position->negedge_count = counter.positive_count();
120 position->posedge_value =
121 multiplier * encoder_translate(counter.last_negative_encoder_value(),
122 encoder_counts_per_revolution,
123 encoder_ratio);
124 position->negedge_value =
125 multiplier * encoder_translate(counter.last_positive_encoder_value(),
126 encoder_counts_per_revolution,
127 encoder_ratio);
128 }
129
Sabina Davis8d8ac0a2019-02-06 23:51:07 -0800130 // Copies a Absolute Encoder with the correct unit
131 // and direction changes.
132 void CopyPosition(
133 const ::frc971::wpilib::AbsoluteEncoder &encoder,
134 ::frc971::AbsolutePosition *position,
135 double encoder_counts_per_revolution, double encoder_ratio,
136 bool reverse) {
137 const double multiplier = reverse ? -1.0 : 1.0;
138 position->encoder =
139 multiplier * encoder_translate(encoder.ReadRelativeEncoder(),
140 encoder_counts_per_revolution,
141 encoder_ratio);
142
143 position->absolute_encoder =
144 (reverse ? (1.0 - encoder.ReadAbsoluteEncoder())
145 : encoder.ReadAbsoluteEncoder()) *
146 encoder_ratio * (2.0 * M_PI);
147 }
148
Sabina Davis2243cab2019-02-05 21:45:08 -0800149 void CopyPosition(
150 const ::frc971::wpilib::DMAEncoderAndPotentiometer &encoder,
151 ::frc971::PotAndIndexPosition *position,
152 ::std::function<double(int32_t)> encoder_translate,
153 ::std::function<double(double)> potentiometer_translate, bool reverse,
154 double pot_offset) {
155 const double multiplier = reverse ? -1.0 : 1.0;
156 position->encoder =
157 multiplier * encoder_translate(encoder.polled_encoder_value());
158 position->pot = multiplier * potentiometer_translate(
159 encoder.polled_potentiometer_voltage()) +
160 pot_offset;
161 position->latched_encoder =
162 multiplier * encoder_translate(encoder.last_encoder_value());
163 position->latched_pot =
164 multiplier *
165 potentiometer_translate(encoder.last_potentiometer_voltage()) +
166 pot_offset;
167 position->index_pulses = encoder.index_posedge_count();
168 }
169
Austin Schuh54667ac2019-02-02 16:44:49 -0800170 double encoder_translate(int32_t value, double counts_per_revolution,
171 double ratio) {
172 return static_cast<double>(value) / counts_per_revolution * ratio *
173 (2.0 * M_PI);
174 }
175
Austin Schuhdf6cbb12019-02-02 13:46:52 -0800176 ::aos::EventLoop *event_loop_;
177 ::aos::Sender<::aos::RobotState> robot_state_sender_;
178
Austin Schuh45a549f2019-02-02 15:43:56 -0800179 frc::DigitalGlitchFilter fast_encoder_filter_, medium_encoder_filter_;
180
181 ::std::unique_ptr<frc::Encoder> drivetrain_left_encoder_,
182 drivetrain_right_encoder_;
183
184 private:
Austin Schuh2c2cc2e2019-02-02 20:19:45 -0800185 // Gets called right before the DMA synchronizer is up and running.
186 virtual void Start() {}
187
Austin Schuh3b010bc2019-02-24 17:25:37 -0800188 // Returns the monotonic time of the start of the first PWM cycle.
189 // Returns min_time if no start time could be calculated.
190 monotonic_clock::time_point GetPWMStartTime();
Sabina Davisadc58542019-02-01 22:23:00 -0800191
Austin Schuh3b010bc2019-02-24 17:25:37 -0800192 bool pwm_trigger_;
Sabina Davisadc58542019-02-01 22:23:00 -0800193
Sabina Davis1ffa4172019-02-01 22:38:33 -0800194 ::std::unique_ptr<::frc971::wpilib::DMASynchronizer> dma_synchronizer_;
195
Sabina Davisadc58542019-02-01 22:23:00 -0800196 ::std::atomic<bool> run_{true};
Austin Schuh3b010bc2019-02-24 17:25:37 -0800197 ::frc::DriverStation *ds_;
Sabina Davisadc58542019-02-01 22:23:00 -0800198};
199
200} // namespace wpilib
201} // namespace frc971
202
203#endif // FRC971_WPILIB_SENSOR_READER_H_