blob: 2450841ca7f18e5421c97b706c2f55fcf07e0524 [file] [log] [blame]
Brian Silverman4da58072015-01-26 20:18:52 -05001#ifndef FRC971_ENCODER_AND_POTENTIOMETER_H_
2#define FRC971_ENCODER_AND_POTENTIOMETER_H_
3
4#include <atomic>
5#include <thread>
6
7#include "aos/common/macros.h"
8#include "aos/common/mutex.h"
9
10#include "Encoder.h"
11#include "DigitalSource.h"
12#include "AnalogInput.h"
13#include "dma.h"
14
15#include "frc971/wpilib/dma_edge_counting.h"
16
17namespace frc971 {
18namespace wpilib {
19
20// Latches values from an encoder and potentiometer on positive edges from
21// another input using an interrupt.
22class InterruptEncoderAndPotentiometer {
23 public:
24 // priority is the priority the thread will run at.
25 InterruptEncoderAndPotentiometer(int priority) : priority_(priority) {}
26
27 // Starts the thread running so it can receive interrupts.
28 void Start();
29
30 // Tells the thread to stop running and then waits for it to finish.
31 void Stop() {
32 run_ = false;
33 thread_.join();
34 }
35
36 // Loops until Stop() is called, reading interrupts.
37 // Designed to be called by ::std::thread internally.
38 void operator()();
39
40 // Returns the mutex which must be held while calling index_posedge_count(),
41 // last_encoder_value(), and last_potentiometer_voltage().
42 // Holding this mutex will increase the handling latency.
43 ::aos::Mutex *mutex() { return &mutex_; }
44
45 void set_encoder(::std::unique_ptr<Encoder> encoder) {
46 encoder_ = ::std::move(encoder);
47 }
48 Encoder *encoder() const { return encoder_.get(); }
49
50 void set_index(::std::unique_ptr<DigitalSource> index) {
51 index_ = ::std::move(index);
52 }
53 DigitalSource *index() const { return index_.get(); }
54
55 void set_potentiometer(::std::unique_ptr<AnalogInput> potentiometer) {
56 potentiometer_ = ::std::move(potentiometer);
57 }
58 AnalogInput *potentiometer() const { return potentiometer_.get(); }
59
60 // Returns the number of poseges that have happened on the index input.
61 // mutex() must be held while calling this.
62 uint32_t index_posedge_count() const { return index_posedge_count_; }
63 // Returns the value of the encoder at the last index posedge.
64 // mutex() must be held while calling this.
65 int32_t last_encoder_value() const { return last_encoder_value_; }
66 // Returns the voltage of the potentiometer at the last index posedge.
67 // mutex() must be held while calling this.
68 float last_potentiometer_voltage() const {
69 return last_potentiometer_voltage_;
70 }
71
72 private:
73 ::std::unique_ptr<Encoder> encoder_;
74 ::std::unique_ptr<DigitalSource> index_;
75 ::std::unique_ptr<AnalogInput> potentiometer_;
76
77 int32_t last_encoder_value_{0};
78 float last_potentiometer_voltage_{0.0f};
79 uint32_t index_posedge_count_{0};
80
81 ::aos::Mutex mutex_;
82
83 const int priority_;
84
85 ::std::atomic<bool> run_{true};
86 ::std::thread thread_;
87
88 DISALLOW_COPY_AND_ASSIGN(InterruptEncoderAndPotentiometer);
89};
90
91// Latches values from an encoder and potentiometer on positive edges from
92// another input using DMA.
93class DMAEncoderAndPotentiometer : public DMASampleHandlerInterface {
94 public:
95 DMAEncoderAndPotentiometer() {}
96
97 void set_encoder(::std::unique_ptr<Encoder> encoder) {
98 encoder_ = ::std::move(encoder);
99 }
100 Encoder *encoder() const { return encoder_.get(); }
101
102 void set_index(::std::unique_ptr<DigitalSource> index) {
103 index_ = ::std::move(index);
104 }
105 DigitalSource *index() const { return index_.get(); }
106
107 void set_potentiometer(::std::unique_ptr<AnalogInput> potentiometer) {
108 potentiometer_ = ::std::move(potentiometer);
109 }
110 AnalogInput *potentiometer() const { return potentiometer_.get(); }
111
112 // Returns the most recent polled value of the encoder.
113 uint32_t polled_encoder_value() const { return polled_encoder_value_; }
114 // Returns the most recent polled voltage of the potentiometer.
115 float polled_potentiometer_voltage() const {
116 return polled_potentiometer_voltage_;
117 }
118
119 // Returns the number of poseges that have happened on the index input.
120 uint32_t index_posedge_count() const { return index_posedge_count_; }
121 // Returns the value of the encoder at the last index posedge.
122 int32_t last_encoder_value() const { return last_encoder_value_; }
123 // Returns the voltage of the potentiometer at the last index posedge.
124 float last_potentiometer_voltage() const {
125 return last_potentiometer_voltage_;
126 }
127
128 virtual void UpdateFromSample(const DMASample &sample) override;
129
130 virtual void PollFromSample(const DMASample &sample) override {
131 polled_encoder_value_ = sample.GetRaw(encoder_.get());
132 polled_potentiometer_voltage_ = sample.GetVoltage(potentiometer_.get());
133 }
134
135 virtual void UpdatePolledValue() override {
136 polled_encoder_value_ = encoder_->GetRaw();
137 polled_potentiometer_voltage_ = potentiometer_->GetVoltage();
138 }
139
140 virtual void AddToDMA(DMA *dma) override {
141 dma->Add(encoder_.get());
142 dma->Add(index_.get());
143 dma->Add(potentiometer_.get());
Austin Schuhc6cc4102015-02-15 23:19:53 -0800144 dma->SetExternalTrigger(index_.get(), true, true);
Brian Silverman4da58072015-01-26 20:18:52 -0500145 }
146
147 private:
148 ::std::unique_ptr<Encoder> encoder_;
149 ::std::unique_ptr<DigitalSource> index_;
150 ::std::unique_ptr<AnalogInput> potentiometer_;
151
152 int32_t polled_encoder_value_ = 0;
153 float polled_potentiometer_voltage_ = 0.0f;
154
155 int32_t last_encoder_value_ = 0;
156 float last_potentiometer_voltage_ = 0.0f;
157
158 uint32_t index_posedge_count_ = 0;
159
160 // Whether or not it was triggered in the last sample.
161 bool index_last_value_ = false;
162
163 DISALLOW_COPY_AND_ASSIGN(DMAEncoderAndPotentiometer);
164};
165
166} // namespace wpilib
167} // namespace frc971
168
169#endif // FRC971_ENCODER_AND_POTENTIOMETER_H_