blob: 0869b0de8572de7d6ea16d586a02f42b437e7148 [file] [log] [blame]
Brian Silvermanb5b46ca2016-03-13 01:14:17 -05001#ifndef FRC971_WPILIB_DMA_H_
2#define FRC971_WPILIB_DMA_H_
Brian Silverman2aa83d72015-01-24 18:03:11 -05003
Brian Silvermand49fd782015-01-30 16:43:17 -05004// Interface to the roboRIO FPGA's DMA features.
Brian Silvermanb5b46ca2016-03-13 01:14:17 -05005// TODO(Brian): Make this less wpilib-like and more frc971-like.
Brian Silvermand49fd782015-01-30 16:43:17 -05006
Brian Silverman2aa83d72015-01-24 18:03:11 -05007#include <stdint.h>
8
9#include <array>
10#include <memory>
11
Austin Schuh94f51e92017-10-30 19:25:32 -070012#if defined(WPILIB2017) || defined(WPILIB2018)
Brian Silvermane48dbc12017-02-04 20:06:29 -080013#include "HAL/ChipObject.h"
14#else
Brian Silverman2aa83d72015-01-24 18:03:11 -050015#include "ChipObject.h"
Brian Silvermane48dbc12017-02-04 20:06:29 -080016#endif
Brian Silvermand49fd782015-01-30 16:43:17 -050017#include "ErrorBase.h"
Brian Silverman2aa83d72015-01-24 18:03:11 -050018
19class DMA;
Austin Schuh94f51e92017-10-30 19:25:32 -070020#if defined(WPILIB2017) || defined(WPILIB2018)
Brian Silvermane48dbc12017-02-04 20:06:29 -080021namespace frc {
Brian Silvermand49fd782015-01-30 16:43:17 -050022class DigitalSource;
23class AnalogInput;
24class Encoder;
Brian Silvermane48dbc12017-02-04 20:06:29 -080025} // namespace frc
26#else
27class DigitalSource;
28class AnalogInput;
29class Encoder;
30namespace frc {
31using ::DigitalSource;
32using ::AnalogInput;
33using ::Encoder;
34} // namespace frc
35#endif
Brian Silverman2aa83d72015-01-24 18:03:11 -050036
Brian Silvermand49fd782015-01-30 16:43:17 -050037// A POD class which stores the data from a DMA sample and provides safe ways to
38// access it.
Brian Silverman2aa83d72015-01-24 18:03:11 -050039class DMASample {
40 public:
Brian Silvermand49fd782015-01-30 16:43:17 -050041 DMASample() = default;
Brian Silverman2aa83d72015-01-24 18:03:11 -050042
Austin Schuh8f314a92015-11-22 21:35:40 -080043 // Returns the FPGA timestamp of the sample in seconds.
Brian Silverman2aa83d72015-01-24 18:03:11 -050044 double GetTimestamp() const;
Austin Schuh8f314a92015-11-22 21:35:40 -080045 // Returns the FPGA timestamp of the sample in microseconds.
Austin Schuh94f51e92017-10-30 19:25:32 -070046 uint64_t GetTime() const;
Brian Silverman2aa83d72015-01-24 18:03:11 -050047
48 // All Get methods either return the requested value, or set the Error.
49
50 // Returns the value of the digital input in the sample.
51 bool Get(DigitalSource *input) const;
52 // Returns the raw value of the encoder in the sample.
53 int32_t GetRaw(Encoder *input) const;
54 // Returns the {1, 2, or 4} X scaled value of the encoder in the sample.
55 int32_t Get(Encoder *input) const;
Brian Silvermand49fd782015-01-30 16:43:17 -050056 // Returns the raw 12-bit value from the ADC.
Austin Schuh58d8cdf2015-02-15 21:04:42 -080057 uint16_t GetValue(AnalogInput *input) const;
Brian Silvermand49fd782015-01-30 16:43:17 -050058 // Returns the scaled value of an analog input.
59 float GetVoltage(AnalogInput *input) const;
Brian Silverman2aa83d72015-01-24 18:03:11 -050060
61 private:
62 friend DMA;
63
Austin Schuh94f51e92017-10-30 19:25:32 -070064 void CalculateTimestamp();
65
Brian Silverman2aa83d72015-01-24 18:03:11 -050066 // Returns the offset of the sample type in the buffer, or -1 if it isn't in
67 // the sample.
68 ssize_t offset(int index) const;
69
70 // TODO(austin): This should be re-used from WPILib... Once I merge this back
71 // into WPILib.
72
73 DMA *dma_;
Austin Schuh94f51e92017-10-30 19:25:32 -070074 uint64_t fpga_timestamp_;
Brian Silverman2aa83d72015-01-24 18:03:11 -050075 uint32_t read_buffer_[64];
76};
77
Brian Silvermand49fd782015-01-30 16:43:17 -050078// TODO(austin): ErrorBase...
Brian Silverman2aa83d72015-01-24 18:03:11 -050079class DMA : public ErrorBase {
80 public:
81 DMA();
82 virtual ~DMA();
83
84 // Sets whether or not DMA is paused.
Austin Schuh91c75562015-12-20 22:23:10 -080085 // If not specified, the default is false.
Brian Silverman2aa83d72015-01-24 18:03:11 -050086 void SetPause(bool pause);
87
88 // Sets the number of triggers that need to occur before a sample is saved.
Austin Schuh91c75562015-12-20 22:23:10 -080089 // If not specified, the default is 1.
Brian Silverman2aa83d72015-01-24 18:03:11 -050090 void SetRate(uint32_t cycles);
91
92 // Adds the input signal to the state to snapshot on the trigger event.
Brian Silvermand49fd782015-01-30 16:43:17 -050093 // It is safe to add the same input multiple times, but there is currently
94 // no way to remove one once it has been added.
Brian Silverman2aa83d72015-01-24 18:03:11 -050095 // Call Add() and SetExternalTrigger() before Start().
96 void Add(Encoder *encoder);
97 void Add(DigitalSource *input);
Brian Silvermand49fd782015-01-30 16:43:17 -050098 void Add(AnalogInput *input);
Brian Silverman2aa83d72015-01-24 18:03:11 -050099
100 // Configures DMA to trigger on an external trigger. There can only be 4
101 // external triggers.
102 // Call Add() and SetExternalTrigger() before Start().
103 void SetExternalTrigger(DigitalSource *input, bool rising, bool falling);
104
105 // Starts reading samples into the buffer. Clears all previous samples before
106 // starting.
107 // Call Start() before Read().
108 void Start(size_t queue_depth);
109
110 enum ReadStatus {
111 STATUS_OK = 0,
112 STATUS_TIMEOUT = 1,
113 STATUS_ERROR = 2,
114 };
115
116 // Reads a sample from the DMA buffer, waiting up to timeout_ms for it.
117 // Returns a status code indicating whether the read worked, timed out, or
118 // failed.
Brian Silvermand49fd782015-01-30 16:43:17 -0500119 // Returns in *remaining_out the number of DMA samples still queued after this
120 // Read().
Brian Silverman2aa83d72015-01-24 18:03:11 -0500121 // Call Add() and SetExternalTrigger() then Start() before Read().
122 // The sample is only usable while this DMA object is left started.
Brian Silvermand49fd782015-01-30 16:43:17 -0500123 ReadStatus Read(DMASample *sample, uint32_t timeout_ms,
124 size_t *remaining_out);
125
126 // Translates a ReadStatus code to a string name.
127 static const char *NameOfReadStatus(ReadStatus s);
Brian Silverman2aa83d72015-01-24 18:03:11 -0500128
129 private:
130 ::std::unique_ptr<nFPGA::tDMAManager> manager_; // set by Start()
131 typedef nFPGA::nRoboRIO_FPGANamespace::tDMA tDMA;
132 friend DMASample;
133
134 // The offsets into the sample structure for each DMA type, or -1 if it isn't
135 // in the set of values.
Austin Schuh91c75562015-12-20 22:23:10 -0800136#ifdef WPILIB2015
Brian Silverman2aa83d72015-01-24 18:03:11 -0500137 ssize_t channel_offsets_[18];
Austin Schuh91c75562015-12-20 22:23:10 -0800138#else
139 ssize_t channel_offsets_[20];
140#endif
Brian Silverman2aa83d72015-01-24 18:03:11 -0500141
142 // The size of the data to read to get a sample.
143 size_t capture_size_ = 0;
144 tDMA::tConfig tconfig_;
145 tDMA *tdma_config_;
146
Austin Schuh91c75562015-12-20 22:23:10 -0800147#ifndef WPILIB2015
148 ::std::array<bool, 8> trigger_channels_ = {
149 {false, false, false, false, false, false, false, false}};
150#else
Brian Silverman2aa83d72015-01-24 18:03:11 -0500151 ::std::array<bool, 4> trigger_channels_ = {{false, false, false, false}};
Austin Schuh91c75562015-12-20 22:23:10 -0800152#endif
Brian Silverman2aa83d72015-01-24 18:03:11 -0500153};
154
Brian Silvermanb5b46ca2016-03-13 01:14:17 -0500155#endif // FRC971_WPILIB_DMA_H_