blob: 970497c5871795e003c2605285bf2807c3b5faea [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
12#include "ChipObject.h"
Brian Silvermand49fd782015-01-30 16:43:17 -050013#include "ErrorBase.h"
Brian Silverman2aa83d72015-01-24 18:03:11 -050014
15class DMA;
Brian Silvermand49fd782015-01-30 16:43:17 -050016class DigitalSource;
17class AnalogInput;
18class Encoder;
Brian Silverman2aa83d72015-01-24 18:03:11 -050019
Brian Silvermand49fd782015-01-30 16:43:17 -050020// A POD class which stores the data from a DMA sample and provides safe ways to
21// access it.
Brian Silverman2aa83d72015-01-24 18:03:11 -050022class DMASample {
23 public:
Brian Silvermand49fd782015-01-30 16:43:17 -050024 DMASample() = default;
Brian Silverman2aa83d72015-01-24 18:03:11 -050025
Austin Schuh8f314a92015-11-22 21:35:40 -080026 // Returns the FPGA timestamp of the sample in seconds.
Brian Silverman2aa83d72015-01-24 18:03:11 -050027 double GetTimestamp() const;
Austin Schuh8f314a92015-11-22 21:35:40 -080028 // Returns the FPGA timestamp of the sample in microseconds.
29 uint32_t GetTime() const;
Brian Silverman2aa83d72015-01-24 18:03:11 -050030
31 // All Get methods either return the requested value, or set the Error.
32
33 // Returns the value of the digital input in the sample.
34 bool Get(DigitalSource *input) const;
35 // Returns the raw value of the encoder in the sample.
36 int32_t GetRaw(Encoder *input) const;
37 // Returns the {1, 2, or 4} X scaled value of the encoder in the sample.
38 int32_t Get(Encoder *input) const;
Brian Silvermand49fd782015-01-30 16:43:17 -050039 // Returns the raw 12-bit value from the ADC.
Austin Schuh58d8cdf2015-02-15 21:04:42 -080040 uint16_t GetValue(AnalogInput *input) const;
Brian Silvermand49fd782015-01-30 16:43:17 -050041 // Returns the scaled value of an analog input.
42 float GetVoltage(AnalogInput *input) const;
Brian Silverman2aa83d72015-01-24 18:03:11 -050043
44 private:
45 friend DMA;
46
47 // Returns the offset of the sample type in the buffer, or -1 if it isn't in
48 // the sample.
49 ssize_t offset(int index) const;
50
51 // TODO(austin): This should be re-used from WPILib... Once I merge this back
52 // into WPILib.
53
54 DMA *dma_;
55 uint32_t read_buffer_[64];
56};
57
Brian Silvermand49fd782015-01-30 16:43:17 -050058// TODO(austin): ErrorBase...
Brian Silverman2aa83d72015-01-24 18:03:11 -050059class DMA : public ErrorBase {
60 public:
61 DMA();
62 virtual ~DMA();
63
64 // Sets whether or not DMA is paused.
Austin Schuh91c75562015-12-20 22:23:10 -080065 // If not specified, the default is false.
Brian Silverman2aa83d72015-01-24 18:03:11 -050066 void SetPause(bool pause);
67
68 // Sets the number of triggers that need to occur before a sample is saved.
Austin Schuh91c75562015-12-20 22:23:10 -080069 // If not specified, the default is 1.
Brian Silverman2aa83d72015-01-24 18:03:11 -050070 void SetRate(uint32_t cycles);
71
72 // Adds the input signal to the state to snapshot on the trigger event.
Brian Silvermand49fd782015-01-30 16:43:17 -050073 // It is safe to add the same input multiple times, but there is currently
74 // no way to remove one once it has been added.
Brian Silverman2aa83d72015-01-24 18:03:11 -050075 // Call Add() and SetExternalTrigger() before Start().
76 void Add(Encoder *encoder);
77 void Add(DigitalSource *input);
Brian Silvermand49fd782015-01-30 16:43:17 -050078 void Add(AnalogInput *input);
Brian Silverman2aa83d72015-01-24 18:03:11 -050079
80 // Configures DMA to trigger on an external trigger. There can only be 4
81 // external triggers.
82 // Call Add() and SetExternalTrigger() before Start().
83 void SetExternalTrigger(DigitalSource *input, bool rising, bool falling);
84
85 // Starts reading samples into the buffer. Clears all previous samples before
86 // starting.
87 // Call Start() before Read().
88 void Start(size_t queue_depth);
89
90 enum ReadStatus {
91 STATUS_OK = 0,
92 STATUS_TIMEOUT = 1,
93 STATUS_ERROR = 2,
94 };
95
96 // Reads a sample from the DMA buffer, waiting up to timeout_ms for it.
97 // Returns a status code indicating whether the read worked, timed out, or
98 // failed.
Brian Silvermand49fd782015-01-30 16:43:17 -050099 // Returns in *remaining_out the number of DMA samples still queued after this
100 // Read().
Brian Silverman2aa83d72015-01-24 18:03:11 -0500101 // Call Add() and SetExternalTrigger() then Start() before Read().
102 // The sample is only usable while this DMA object is left started.
Brian Silvermand49fd782015-01-30 16:43:17 -0500103 ReadStatus Read(DMASample *sample, uint32_t timeout_ms,
104 size_t *remaining_out);
105
106 // Translates a ReadStatus code to a string name.
107 static const char *NameOfReadStatus(ReadStatus s);
Brian Silverman2aa83d72015-01-24 18:03:11 -0500108
109 private:
110 ::std::unique_ptr<nFPGA::tDMAManager> manager_; // set by Start()
111 typedef nFPGA::nRoboRIO_FPGANamespace::tDMA tDMA;
112 friend DMASample;
113
114 // The offsets into the sample structure for each DMA type, or -1 if it isn't
115 // in the set of values.
Austin Schuh91c75562015-12-20 22:23:10 -0800116#ifdef WPILIB2015
Brian Silverman2aa83d72015-01-24 18:03:11 -0500117 ssize_t channel_offsets_[18];
Austin Schuh91c75562015-12-20 22:23:10 -0800118#else
119 ssize_t channel_offsets_[20];
120#endif
Brian Silverman2aa83d72015-01-24 18:03:11 -0500121
122 // The size of the data to read to get a sample.
123 size_t capture_size_ = 0;
124 tDMA::tConfig tconfig_;
125 tDMA *tdma_config_;
126
Austin Schuh91c75562015-12-20 22:23:10 -0800127#ifndef WPILIB2015
128 ::std::array<bool, 8> trigger_channels_ = {
129 {false, false, false, false, false, false, false, false}};
130#else
Brian Silverman2aa83d72015-01-24 18:03:11 -0500131 ::std::array<bool, 4> trigger_channels_ = {{false, false, false, false}};
Austin Schuh91c75562015-12-20 22:23:10 -0800132#endif
Brian Silverman2aa83d72015-01-24 18:03:11 -0500133};
134
Brian Silvermanb5b46ca2016-03-13 01:14:17 -0500135#endif // FRC971_WPILIB_DMA_H_