blob: dc34e1ce1cfc418bc5fd94a5e60e7702cedd0818 [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
7#include "aos/stl_mutex/stl_mutex.h"
8#include "aos/time/time.h"
Austin Schuh54667ac2019-02-02 16:44:49 -08009#include "frc971/control_loops/control_loops.q.h"
Sabina Davisadc58542019-02-01 22:23:00 -080010#include "frc971/wpilib/ahal/DigitalGlitchFilter.h"
11#include "frc971/wpilib/ahal/DigitalInput.h"
Sabina Davis1ffa4172019-02-01 22:38:33 -080012#include "frc971/wpilib/dma.h"
13#include "frc971/wpilib/dma_edge_counting.h"
Austin Schuh54667ac2019-02-02 16:44:49 -080014#include "frc971/wpilib/encoder_and_potentiometer.h"
Sabina Davisadc58542019-02-01 22:23:00 -080015
16using ::aos::monotonic_clock;
17namespace chrono = ::std::chrono;
18
19namespace frc971 {
20namespace wpilib {
21
22class SensorReader {
23 public:
24 SensorReader();
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080025 virtual ~SensorReader() {}
Sabina Davisadc58542019-02-01 22:23:00 -080026
Austin Schuh45a549f2019-02-02 15:43:56 -080027 // Updates the fast and medium encoder filter frequencies.
28 void UpdateFastEncoderFilterHz(int hz);
29 void UpdateMediumEncoderFilterHz(int hz);
30
Sabina Davisb6317b72019-02-01 22:53:23 -080031 // Sets the left drivetrain encoder.
32 void set_drivetrain_left_encoder(::std::unique_ptr<frc::Encoder> encoder);
33
34 // Sets the right drivetrain encoder.
35 void set_drivetrain_right_encoder(::std::unique_ptr<frc::Encoder> encoder);
36
Sabina Davis6292bec2019-02-06 22:53:14 -080037 // Adds a sensor to DMA.
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080038 void AddToDMA(DMASampleHandlerInterface *handler) {
Sabina Davis6292bec2019-02-06 22:53:14 -080039 if (!dma_synchronizer_) {
40 dma_synchronizer_.reset(
41 new ::frc971::wpilib::DMASynchronizer(std::make_unique<DMA>()));
42 }
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080043 dma_synchronizer_->Add(handler);
44 }
45
Sabina Davisb6317b72019-02-01 22:53:23 -080046 // Sets the pwm trigger.
Sabina Davisadc58542019-02-01 22:23:00 -080047 void set_pwm_trigger(::std::unique_ptr<frc::DigitalInput> pwm_trigger);
48
Sabina Davisa42cc352019-02-01 22:55:50 -080049 // Stops the pwm trigger on the next iteration.
50 void Quit() { run_ = false; }
51
Sabina Davis399dbd82019-02-01 23:06:08 -080052 virtual void RunIteration() = 0;
Sabina Davis6292bec2019-02-06 22:53:14 -080053 // Runs the DMA iteration after the synchronizer. This only gets run if a
54 // sensor has been added to DMA.
Austin Schuh2c2cc2e2019-02-02 20:19:45 -080055 virtual void RunDmaIteration() {}
Sabina Davis399dbd82019-02-01 23:06:08 -080056
57 void operator()();
58
Sabina Davisadc58542019-02-01 22:23:00 -080059 protected:
Austin Schuh54667ac2019-02-02 16:44:49 -080060 // Copies a DMAEncoder to a IndexPosition with the correct unit and direction
61 // changes.
62 void CopyPosition(const ::frc971::wpilib::DMAEncoder &encoder,
63 ::frc971::IndexPosition *position,
64 double encoder_counts_per_revolution, double encoder_ratio,
65 bool reverse) {
66 const double multiplier = reverse ? -1.0 : 1.0;
67 position->encoder =
68 multiplier * encoder_translate(encoder.polled_encoder_value(),
69 encoder_counts_per_revolution,
70 encoder_ratio);
71 position->latched_encoder =
72 multiplier * encoder_translate(encoder.last_encoder_value(),
73 encoder_counts_per_revolution,
74 encoder_ratio);
75 position->index_pulses = encoder.index_posedge_count();
76 }
77
78 // Copies a AbsoluteEncoderAndPotentiometer to a PotAndAbsolutePosition with
79 // the correct unit and direction changes.
80 void CopyPosition(
81 const ::frc971::wpilib::AbsoluteEncoderAndPotentiometer &encoder,
82 ::frc971::PotAndAbsolutePosition *position,
83 double encoder_counts_per_revolution, double encoder_ratio,
84 ::std::function<double(double)> potentiometer_translate, bool reverse,
85 double pot_offset) {
86 const double multiplier = reverse ? -1.0 : 1.0;
87 position->pot = multiplier * potentiometer_translate(
88 encoder.ReadPotentiometerVoltage()) +
89 pot_offset;
90 position->encoder =
91 multiplier * encoder_translate(encoder.ReadRelativeEncoder(),
92 encoder_counts_per_revolution,
93 encoder_ratio);
94
95 position->absolute_encoder =
96 (reverse ? (1.0 - encoder.ReadAbsoluteEncoder())
97 : encoder.ReadAbsoluteEncoder()) *
98 encoder_ratio * (2.0 * M_PI);
99 }
100
101 // Copies a DMAEdgeCounter to a HallEffectAndPosition with the correct unit
102 // and direction changes.
103 void CopyPosition(const ::frc971::wpilib::DMAEdgeCounter &counter,
104 ::frc971::HallEffectAndPosition *position,
105 double encoder_counts_per_revolution, double encoder_ratio,
106 bool reverse) {
107 const double multiplier = reverse ? -1.0 : 1.0;
108 position->encoder =
109 multiplier * encoder_translate(counter.polled_encoder(),
110 encoder_counts_per_revolution,
111 encoder_ratio);
112 position->current = !counter.polled_value();
113 position->posedge_count = counter.negative_count();
114 position->negedge_count = counter.positive_count();
115 position->posedge_value =
116 multiplier * encoder_translate(counter.last_negative_encoder_value(),
117 encoder_counts_per_revolution,
118 encoder_ratio);
119 position->negedge_value =
120 multiplier * encoder_translate(counter.last_positive_encoder_value(),
121 encoder_counts_per_revolution,
122 encoder_ratio);
123 }
124
125 double encoder_translate(int32_t value, double counts_per_revolution,
126 double ratio) {
127 return static_cast<double>(value) / counts_per_revolution * ratio *
128 (2.0 * M_PI);
129 }
130
Austin Schuh45a549f2019-02-02 15:43:56 -0800131 frc::DigitalGlitchFilter fast_encoder_filter_, medium_encoder_filter_;
132
133 ::std::unique_ptr<frc::Encoder> drivetrain_left_encoder_,
134 drivetrain_right_encoder_;
135
136 private:
Austin Schuh2c2cc2e2019-02-02 20:19:45 -0800137 // Gets called right before the DMA synchronizer is up and running.
138 virtual void Start() {}
139
Sabina Davisb6317b72019-02-01 22:53:23 -0800140 // Uses the pwm trigger to find the pwm cycle width and offset for that
141 // iteration.
Sabina Davisadc58542019-02-01 22:23:00 -0800142 void RunPWMDetecter();
143
144 ::std::unique_ptr<frc::DigitalInput> pwm_trigger_;
145
Sabina Davisadc58542019-02-01 22:23:00 -0800146 // Mutex to manage access to the period and tick time variables.
147 ::aos::stl_mutex tick_time_mutex_;
148 monotonic_clock::time_point last_tick_time_monotonic_timepoint_ =
149 monotonic_clock::min_time;
Austin Schuh45a549f2019-02-02 15:43:56 -0800150 chrono::nanoseconds last_period_;
Sabina Davisadc58542019-02-01 22:23:00 -0800151
Sabina Davis1ffa4172019-02-01 22:38:33 -0800152 ::std::unique_ptr<::frc971::wpilib::DMASynchronizer> dma_synchronizer_;
153
Sabina Davisadc58542019-02-01 22:23:00 -0800154 ::std::atomic<bool> run_{true};
Sabina Davisadc58542019-02-01 22:23:00 -0800155};
156
157} // namespace wpilib
158} // namespace frc971
159
160#endif // FRC971_WPILIB_SENSOR_READER_H_