blob: 2c4d4e01e0ca56d2a16a24dd5206f02501197948 [file] [log] [blame]
Brian Silverman2aa83d72015-01-24 18:03:11 -05001#ifndef _DMA_H_
2#define _DMA_H_
3
Brian Silvermand49fd782015-01-30 16:43:17 -05004// Interface to the roboRIO FPGA's DMA features.
5
Brian Silverman2aa83d72015-01-24 18:03:11 -05006#include <stdint.h>
7
8#include <array>
9#include <memory>
10
11#include "ChipObject.h"
Brian Silvermand49fd782015-01-30 16:43:17 -050012#include "ErrorBase.h"
Brian Silverman2aa83d72015-01-24 18:03:11 -050013
14class DMA;
Brian Silvermand49fd782015-01-30 16:43:17 -050015class DigitalSource;
16class AnalogInput;
17class Encoder;
Brian Silverman2aa83d72015-01-24 18:03:11 -050018
Brian Silvermand49fd782015-01-30 16:43:17 -050019// A POD class which stores the data from a DMA sample and provides safe ways to
20// access it.
Brian Silverman2aa83d72015-01-24 18:03:11 -050021class DMASample {
22 public:
Brian Silvermand49fd782015-01-30 16:43:17 -050023 DMASample() = default;
Brian Silverman2aa83d72015-01-24 18:03:11 -050024
Austin Schuh8f314a92015-11-22 21:35:40 -080025 // Returns the FPGA timestamp of the sample in seconds.
Brian Silverman2aa83d72015-01-24 18:03:11 -050026 double GetTimestamp() const;
Austin Schuh8f314a92015-11-22 21:35:40 -080027 // Returns the FPGA timestamp of the sample in microseconds.
28 uint32_t GetTime() const;
Brian Silverman2aa83d72015-01-24 18:03:11 -050029
30 // All Get methods either return the requested value, or set the Error.
31
32 // Returns the value of the digital input in the sample.
33 bool Get(DigitalSource *input) const;
34 // Returns the raw value of the encoder in the sample.
35 int32_t GetRaw(Encoder *input) const;
36 // Returns the {1, 2, or 4} X scaled value of the encoder in the sample.
37 int32_t Get(Encoder *input) const;
Brian Silvermand49fd782015-01-30 16:43:17 -050038 // Returns the raw 12-bit value from the ADC.
Austin Schuh58d8cdf2015-02-15 21:04:42 -080039 uint16_t GetValue(AnalogInput *input) const;
Brian Silvermand49fd782015-01-30 16:43:17 -050040 // Returns the scaled value of an analog input.
41 float GetVoltage(AnalogInput *input) const;
Brian Silverman2aa83d72015-01-24 18:03:11 -050042
43 private:
44 friend DMA;
45
46 // Returns the offset of the sample type in the buffer, or -1 if it isn't in
47 // the sample.
48 ssize_t offset(int index) const;
49
50 // TODO(austin): This should be re-used from WPILib... Once I merge this back
51 // into WPILib.
52
53 DMA *dma_;
54 uint32_t read_buffer_[64];
55};
56
Brian Silvermand49fd782015-01-30 16:43:17 -050057// TODO(austin): ErrorBase...
Brian Silverman2aa83d72015-01-24 18:03:11 -050058class DMA : public ErrorBase {
59 public:
60 DMA();
61 virtual ~DMA();
62
63 // Sets whether or not DMA is paused.
Austin Schuh91c75562015-12-20 22:23:10 -080064 // If not specified, the default is false.
Brian Silverman2aa83d72015-01-24 18:03:11 -050065 void SetPause(bool pause);
66
67 // Sets the number of triggers that need to occur before a sample is saved.
Austin Schuh91c75562015-12-20 22:23:10 -080068 // If not specified, the default is 1.
Brian Silverman2aa83d72015-01-24 18:03:11 -050069 void SetRate(uint32_t cycles);
70
71 // Adds the input signal to the state to snapshot on the trigger event.
Brian Silvermand49fd782015-01-30 16:43:17 -050072 // It is safe to add the same input multiple times, but there is currently
73 // no way to remove one once it has been added.
Brian Silverman2aa83d72015-01-24 18:03:11 -050074 // Call Add() and SetExternalTrigger() before Start().
75 void Add(Encoder *encoder);
76 void Add(DigitalSource *input);
Brian Silvermand49fd782015-01-30 16:43:17 -050077 void Add(AnalogInput *input);
Brian Silverman2aa83d72015-01-24 18:03:11 -050078
79 // Configures DMA to trigger on an external trigger. There can only be 4
80 // external triggers.
81 // Call Add() and SetExternalTrigger() before Start().
82 void SetExternalTrigger(DigitalSource *input, bool rising, bool falling);
83
84 // Starts reading samples into the buffer. Clears all previous samples before
85 // starting.
86 // Call Start() before Read().
87 void Start(size_t queue_depth);
88
89 enum ReadStatus {
90 STATUS_OK = 0,
91 STATUS_TIMEOUT = 1,
92 STATUS_ERROR = 2,
93 };
94
95 // Reads a sample from the DMA buffer, waiting up to timeout_ms for it.
96 // Returns a status code indicating whether the read worked, timed out, or
97 // failed.
Brian Silvermand49fd782015-01-30 16:43:17 -050098 // Returns in *remaining_out the number of DMA samples still queued after this
99 // Read().
Brian Silverman2aa83d72015-01-24 18:03:11 -0500100 // Call Add() and SetExternalTrigger() then Start() before Read().
101 // The sample is only usable while this DMA object is left started.
Brian Silvermand49fd782015-01-30 16:43:17 -0500102 ReadStatus Read(DMASample *sample, uint32_t timeout_ms,
103 size_t *remaining_out);
104
105 // Translates a ReadStatus code to a string name.
106 static const char *NameOfReadStatus(ReadStatus s);
Brian Silverman2aa83d72015-01-24 18:03:11 -0500107
108 private:
109 ::std::unique_ptr<nFPGA::tDMAManager> manager_; // set by Start()
110 typedef nFPGA::nRoboRIO_FPGANamespace::tDMA tDMA;
111 friend DMASample;
112
113 // The offsets into the sample structure for each DMA type, or -1 if it isn't
114 // in the set of values.
Austin Schuh91c75562015-12-20 22:23:10 -0800115#ifdef WPILIB2015
Brian Silverman2aa83d72015-01-24 18:03:11 -0500116 ssize_t channel_offsets_[18];
Austin Schuh91c75562015-12-20 22:23:10 -0800117#else
118 ssize_t channel_offsets_[20];
119#endif
Brian Silverman2aa83d72015-01-24 18:03:11 -0500120
121 // The size of the data to read to get a sample.
122 size_t capture_size_ = 0;
123 tDMA::tConfig tconfig_;
124 tDMA *tdma_config_;
125
Austin Schuh91c75562015-12-20 22:23:10 -0800126#ifndef WPILIB2015
127 ::std::array<bool, 8> trigger_channels_ = {
128 {false, false, false, false, false, false, false, false}};
129#else
Brian Silverman2aa83d72015-01-24 18:03:11 -0500130 ::std::array<bool, 4> trigger_channels_ = {{false, false, false, false}};
Austin Schuh91c75562015-12-20 22:23:10 -0800131#endif
Brian Silverman2aa83d72015-01-24 18:03:11 -0500132};
133
134#endif // _DMA_H_