add the dma interface code
This is mostly copied from what Austin wrote.
Change-Id: I06a5f2323ec2d39ca6f1a3eaac6f4d129de84a3c
diff --git a/aos/externals/forwpilib/dma.h b/aos/externals/forwpilib/dma.h
new file mode 100644
index 0000000..0baf473
--- /dev/null
+++ b/aos/externals/forwpilib/dma.h
@@ -0,0 +1,101 @@
+#ifndef _DMA_H_
+#define _DMA_H_
+
+#include <stdint.h>
+
+#include <array>
+#include <memory>
+
+#include "ChipObject.h"
+#include "DigitalSource.h"
+#include "Encoder.h"
+
+class DMA;
+
+class DMASample {
+ public:
+ DMASample() {}
+
+ // Returns the FPGA timestamp of the sample.
+ double GetTimestamp() const;
+
+ // All Get methods either return the requested value, or set the Error.
+
+ // Returns the value of the digital input in the sample.
+ bool Get(DigitalSource *input) const;
+ // Returns the raw value of the encoder in the sample.
+ int32_t GetRaw(Encoder *input) const;
+ // Returns the {1, 2, or 4} X scaled value of the encoder in the sample.
+ int32_t Get(Encoder *input) const;
+
+ private:
+ friend DMA;
+
+ // Returns the offset of the sample type in the buffer, or -1 if it isn't in
+ // the sample.
+ ssize_t offset(int index) const;
+
+ // TODO(austin): This should be re-used from WPILib... Once I merge this back
+ // into WPILib.
+
+ DMA *dma_;
+ uint32_t read_buffer_[64];
+};
+
+class DMA : public ErrorBase {
+ public:
+ DMA();
+ virtual ~DMA();
+
+ // Sets whether or not DMA is paused.
+ void SetPause(bool pause);
+
+ // Sets the number of triggers that need to occur before a sample is saved.
+ void SetRate(uint32_t cycles);
+
+ // Adds the input signal to the state to snapshot on the trigger event.
+ // Call Add() and SetExternalTrigger() before Start().
+ void Add(Encoder *encoder);
+ void Add(DigitalSource *input);
+
+ // Configures DMA to trigger on an external trigger. There can only be 4
+ // external triggers.
+ // Call Add() and SetExternalTrigger() before Start().
+ void SetExternalTrigger(DigitalSource *input, bool rising, bool falling);
+
+ // Starts reading samples into the buffer. Clears all previous samples before
+ // starting.
+ // Call Start() before Read().
+ void Start(size_t queue_depth);
+
+ enum ReadStatus {
+ STATUS_OK = 0,
+ STATUS_TIMEOUT = 1,
+ STATUS_ERROR = 2,
+ };
+
+ // Reads a sample from the DMA buffer, waiting up to timeout_ms for it.
+ // Returns a status code indicating whether the read worked, timed out, or
+ // failed.
+ // Call Add() and SetExternalTrigger() then Start() before Read().
+ // The sample is only usable while this DMA object is left started.
+ ReadStatus Read(DMASample *sample, uint32_t timeout_ms, size_t *remaining);
+
+ private:
+ ::std::unique_ptr<nFPGA::tDMAManager> manager_; // set by Start()
+ typedef nFPGA::nRoboRIO_FPGANamespace::tDMA tDMA;
+ friend DMASample;
+
+ // The offsets into the sample structure for each DMA type, or -1 if it isn't
+ // in the set of values.
+ ssize_t channel_offsets_[18];
+
+ // The size of the data to read to get a sample.
+ size_t capture_size_ = 0;
+ tDMA::tConfig tconfig_;
+ tDMA *tdma_config_;
+
+ ::std::array<bool, 4> trigger_channels_ = {{false, false, false, false}};
+};
+
+#endif // _DMA_H_