Scope
FPGAAnalogIntegrator.cpp
1 #include "StdAfx.h"
2 #include "FPGAAnalogIntegrator.h"
3 #include "parameters/IO.h"
4 #include "helpers/DaqChunk.h"
5 
6 namespace scope {
7 
9  : FPGAIO5771(NiFpga_AnalogIntegrator_NI5771_IndicatorBool_UserCommandIdle
10  , NiFpga_AnalogIntegrator_NI5771_IndicatorBool_PLLLocked
11  , NiFpga_AnalogIntegrator_NI5771_IndicatorBool_Configured
12  , NiFpga_AnalogIntegrator_NI5771_IndicatorBool_UserError
13  , NiFpga_AnalogIntegrator_NI5771_IndicatorU8_UserCommandStatus
14  , NiFpga_AnalogIntegrator_NI5771_ControlU8_UserCommand
15  , NiFpga_AnalogIntegrator_NI5771_ControlU16_UserData0
16  , NiFpga_AnalogIntegrator_NI5771_ControlU8_UserData1
17  , NiFpga_AnalogIntegrator_NI5771_ControlBool_UserCommandCommit) {
18  assert(SCOPE_NAREAS == 1);
19 
20  status = NiFpga_Initialize();
21 
22  char* const Bitfile = "devices\\fpga\\" NiFpga_AnalogIntegrator_NI5771_Bitfile;
23 
24  // Load but do not run yet
25  status = NiFpga_Open(Bitfile, NiFpga_AnalogIntegrator_NI5771_Signature, "RIO0", 0, &session);
26  DBOUT(L"FPGAAnalogIntegrator: FPGA Session opened");
27 
28  // Reset the non-running FPGA to clear any bad stuff (e.g. after a program crash with open FPGA before)
29  status = NiFpga_Reset(session);
30 
31  // YOU HAVE TO WAIT THAT LONG!!!
32  // Otherwise you will occasionally (!!!) into strange problems (communication with fpga error -61046)
33  // This took me very very long to figure out...
34  std::this_thread::sleep_for(std::chrono::milliseconds(500));
35  // Run after reset
36  status = NiFpga_Run(session, 0);
37 
39 
40  // Set the fifo constants
41  fifos[0] = NiFpga_AnalogIntegrator_NI5771_TargetToHostFifoU32_ToHostCh1FIFO;
42  fifos[1] = NiFpga_AnalogIntegrator_NI5771_TargetToHostFifoU32_ToHostCh2FIFO;
43 }
44 
46  status = NiFpga_Close(session, 0);
47  status = NiFpga_Finalize();
48  DBOUT(L"FPGAAnalogIntegrator::~FPGAAnalogIntegrator session closed");
49 }
50 
52  if ( !initialized ) {
53  parameters = dynamic_cast<parameters::InputsFPGAAnalogIntegrator*>(_parameters);
54 
56 
57  FPGAInterface::Initialize(_parameters);
58  }
59 }
60 
61 double FPGAAnalogIntegrator::SetPixeltime(const uint32_t& _area, const double& _pixeltime) {
62  // sampling rate of the NI 5771 is 1.5GHz
63  uint16_t samplesperpixel = round2ui16(_pixeltime * 1E-6 * 1.5E9);
64  status = NiFpga_WriteU16(session, NiFpga_AnalogIntegrator_NI5771_ControlU32_Samplesperpixel, samplesperpixel);
65 
66  DBOUT(L"FPGAAnalogIntegrator::SetPixeltime samples per pixel" << samplesperpixel);
67  // Since the AnalogIntegrator VI is working on arrays of 8 samples clockcycles has to be a multiple of 8
68  if ( samplesperpixel%8 != 0 ) {
69  samplesperpixel -= (samplesperpixel%8);
70  DBOUT(L"FPGAAnalogIntegrator::SetPixeltime Coerced samples per per pixel" << samplesperpixel);
71  }
72 
73  return static_cast<double>(samplesperpixel)*1E6/1.5E9;
74 }
75 
76 double FPGAAnalogIntegrator::SetLinetime(const uint32_t& _area, const double& _linetime) {
77  // sampling rate of the NI 5771 is 1.5GHz
78  uint16_t samplesperline = round2ui32(_linetime * 1E-6 * 1.5E9);
79  status = NiFpga_WriteU16(session, NiFpga_AnalogIntegrator_NI5771_ControlU32_Samplesperline, samplesperline);
80 
81  DBOUT(L"FPGAAnalogIntegrator::SetPixeltime samples per line" << samplesperline);
82  // Since the AnalogIntegrator VI is working on arrays of 8 samples clockcycles has to be a multiple of 8
83  if ( samplesperline%8 != 0 ) {
84  samplesperline -= (samplesperline%8);
85  DBOUT(L"FPGAAnalogIntegrator::SetPixeltime Coerced samples per per pixel" << samplesperline);
86  }
87 
88  return static_cast<double>(samplesperline)*1E6/1.5E9;
89 }
90 
91 void FPGAAnalogIntegrator::SetTriggering(const bool& _waitfortrigger) {
92  status = NiFpga_WriteBool(session, NiFpga_AnalogIntegrator_NI5771_ControlBool_Waitfortrigger, _waitfortrigger);
93 }
94 
96  status = NiFpga_WriteBool(session, NiFpga_AnalogIntegrator_NI5771_ControlBool_Acquirecontinuously, _cont);
97 }
98 
99 void FPGAAnalogIntegrator::SetRequestedPixels(const uint32_t& _area, const uint32_t& _reqpixels) {
100  status = NiFpga_WriteU32(session, NiFpga_AnalogIntegrator_NI5771_ControlU32_Requestedpixels, _reqpixels);
101 }
102 
104  ClearFIFOs();
105  SetChannelProps();
106  status = NiFpga_WriteBool(session, NiFpga_AnalogIntegrator_NI5771_ControlBool_Acquire, true);
107 }
108 
109 int32_t FPGAAnalogIntegrator::ReadPixels(DaqChunk& _chunk, const double& _timeout, bool& _timedout) {
110  size_t remaining = 0;
111 
112  // only two channels and one area supported in FPGA vi
113  assert( (_chunk.NChannels() == 2) && (_chunk.Area() == 0) );
114 
115  // we need enough space
116  assert(_chunk.data.size() >= _chunk.PerChannel() * _chunk.NChannels());
117 
118  NiFpga_Status stat = NiFpga_Status_Success;
119 
120  std::vector<uint32_t> u32data(_chunk.PerChannel());
121  std::vector<const uint8_t> bitshift(_chunk.NChannels());
122  bitshift[0] = parameters->BitshiftCh1();
123  bitshift[1] = parameters->BitshiftCh2();
124 
125  // Read each channels fifo
126  for ( uint32_t c = 0 ; c < _chunk.NChannels() ; c++ ) {
127  stat = NiFpga_ReadFifoU32(session
128  , fifos[c]
129  , u32data.data()
130  , _chunk.PerChannel()
131  , static_cast<uint32_t>(_timeout * 1000) // FPGA C API takes timeout in milliseconds, to be consistent with DAQmx we have _timeout in seconds
132  , &remaining);
133 
134  _timedout = (stat == NiFpga_Status_FifoTimeout);
135 
136  // avoid throwing exception on time out (since FpgaStatus status could throw on all errors)
137  // return immediately, makes no sense to also wait for the other channels, since anyway something went seriously wrong
138  if ( _timedout )
139  return -1;
140 
141  // this could throw on error (if we would use FPGAStatus instead of FPGAStatusSafe)
142  status = stat;
143 
144  std::transform(std::begin(u32data), std::end(u32data), std::begin(_chunk.data)+c*_chunk.PerChannel(), [&](const uint32_t& u32) {
145  return static_cast<uint16_t>(u32 >> bitshift[c]);
146  } );
147 
148  }
149 
150  if ( status.Success() )
151  return _chunk.PerChannel();
152 
153  return -1;
154 }
155 
157  status = NiFpga_WriteBool(session, NiFpga_AnalogIntegrator_NI5771_ControlBool_Acquire, false);
158 }
159 
161  // We want to right-shift bits thus *-1
162  //status = NiFpga_WriteI8(session, NiFpga_AnalogIntegrator_NI5771_ControlI8_BitshiftCh1, -1 * parameters->BitshiftCh1());
163  //status = NiFpga_WriteI8(session, NiFpga_AnalogIntegrator_NI5771_ControlI8_BitshiftCh2, -1 * parameters->BitshiftCh2());
164  // We subtract baseline from cumulated 8 samples, thus 8*
165  status = NiFpga_WriteU8(session, NiFpga_AnalogIntegrator_NI5771_ControlU8_Baselinex8Ch1, parameters->BaselineCh1());
166  status = NiFpga_WriteU8(session, NiFpga_AnalogIntegrator_NI5771_ControlU8_Baselinex8Ch2, parameters->BaselineCh2());
167 
168  DBOUT(L"FPGAAnalogIntegrator::SetChannelProps " << parameters->BitshiftCh1() << L" " << parameters->BaselineCh1());
169 }
170 
172  NiFpga_Bool b;
173  status = NiFpga_ReadBool(session, NiFpga_AnalogIntegrator_NI5771_IndicatorBool_ToHostCh1FIFOOverflow, &b);
174  parameters->diagnosis.ToHostOverflowCh1 = (b!=0);
175  status = NiFpga_ReadBool(session, NiFpga_AnalogIntegrator_NI5771_IndicatorBool_ToHostCh2FIFOOverflow, &b);
176  parameters->diagnosis.ToHostOverflowCh2 = (b!=0);
177  status = NiFpga_ReadBool(session, NiFpga_AnalogIntegrator_NI5771_IndicatorBool_InterloopFIFOOverflow, &b);
178  parameters->diagnosis.InterloopOverflow = (b!=0);
179  status = NiFpga_ReadBool(session, NiFpga_AnalogIntegrator_NI5771_IndicatorBool_InterloopFIFOTimeout, &b);
180  parameters->diagnosis.InterloopTimeout = (b!=0);
181  status = NiFpga_ReadBool(session, NiFpga_AnalogIntegrator_NI5771_IndicatorBool_Acquiring, &b);
182  parameters->diagnosis.Acquiring = (b!=0);
183  status = NiFpga_ReadBool(session, NiFpga_AnalogIntegrator_NI5771_IndicatorBool_IOModuleAIOverRange, &b);
184  parameters->diagnosis.AIOverRange = (b!=0);
185 }
186 
188  // Clear interloop fifo
189  status = NiFpga_WriteBool(session, NiFpga_AnalogIntegrator_NI5771_ControlBool_ClearInterloopFIFO, true);
190  std::this_thread::sleep_for(std::chrono::milliseconds(50));
191  status = NiFpga_WriteBool(session, NiFpga_AnalogIntegrator_NI5771_ControlBool_ClearInterloopFIFO, false);
192 
193  // Stop to host FIFOs (clears them)
194  for ( auto f : fifos )
195  status = NiFpga_StopFifo(session, f);
196  std::this_thread::sleep_for(std::chrono::milliseconds(50));
197 
198  // Restart to host FIFOs
199  for ( auto f : fifos )
200  status = NiFpga_StartFifo(session, f);
201  std::this_thread::sleep_for(std::chrono::milliseconds(50));
202 }
203 
204 }
ScopeNumber< uint8_t > BitshiftCh2
Number of bits to shift U32 right before casting to U16 (channel 2)
Definition: IO.h:425
ScopeNumber< bool > AIOverRange
indicator if input is over the ADC range
Definition: IO.h:440
std::array< NiFpga_AnalogIntegrator_NI5771_TargetToHostFifoU32, 2 > fifos
both fifos for both channels
FPGAAnalogIntegrator()
Load the FPGA bitfile, set the IO module's onboard clock and initialize the acquisition.
int32_t ReadPixels(DaqChunk &_chunk, const double &_timeout, bool &_timedout) override
Read only pixels from the FPGA FIFO.
bool CheckIOModule(NiFpga_Session _session)
Necessary calls at the moment not supported by NI FPGA API 12.0, see CheckIOModule.vi for what to do.
Definition: FPGAIO5771.cpp:92
Handels the NI FlexRIO adapter module IO-5771.
Definition: FPGAIO5771.h:11
ScopeNumber< uint8_t > BitshiftCh1
Number of bits to shift U32 right before casting to U16 (channel 1)
Definition: IO.h:422
std::vector< uint16_t > data
The data vector.
Definition: DaqChunk.h:26
ScopeNumber< uint8_t > BaselineCh2
Baseline U8 value to set zero in channel 2 (NI5771 reads ~ -1..+1V as unsigned 8 bit number...
Definition: IO.h:307
void ClearFIFOs()
Clears the interloop and ToHost FIFOs.
A DaqChunk contains data from all channels sequentially.
Definition: DaqChunk.h:9
This is the include file for standard system include files, or project specific include files that ar...
bool initialized
true if already initialized
Definition: FPGAInterface.h:29
void StartAcquisition() override
Starts the acquisition on the FPGA.
void SetRequestedPixels(const uint32_t &_area, const uint32_t &_reqpixels) override
Sets the number of pixels per channel the FPGA should acquire, set to -1 for live scanning...
void StopAcquisition() override
Stops the acquisition on the FPGA.
FPGAStatusSafe status
current FPGA status.
Definition: FPGAInterface.h:23
void SetContinuousAcquisition(const bool &_cont) override
Sets if the FPGA should acquire data continuously or acquire the number of pixels per channel set wit...
#define DBOUT(s)
A debug output to the debug console.
Definition: helpers.h:153
bool Success() const
void SetChannelProps()
Set channel properties as baseline and bitshift.
~FPGAAnalogIntegrator()
Close FPGA session.
Parameters for pixel acquisition FPGAAnalogIntegrator.
Definition: IO.h:411
void Initialize(parameters::InputsFPGA *_parameters) override
Set initial parameters.
void SetClockSource(NiFpga_Session _session, const uint8_t &_clock_source=0)
Possible clock sources (see adapter modules help and Configure Clock.vi from NI 5771 Clock Select exa...
Definition: FPGAIO5771.cpp:41
double SetPixeltime(const uint32_t &_area, const double &_pixeltime) override
Sets the time per pixel/dwell time (in seconds)
ScopeNumber< bool > Acquiring
and the Acquiring indicator
Definition: IO.h:437
void SetTriggering(const bool &_waitfortrigger) override
Sets if the FPGA should wait for a trigger before starting acquisition.
double SetLinetime(const uint32_t &_area, const double &_linetime) override
Sets the time per line (in seconds) for the generation of the line clock (if implemented) ...
virtual void Initialize(parameters::InputsFPGA *_parameters)
Set initial parameters.
Definition: FPGAInterface.h:38
ScopeNumber< uint8_t > BaselineCh1
Baseline U8 value to set zero in channel 1 (NI5771 reads ~ -1..+1V as unsigned 8 bit number...
Definition: IO.h:304
Diagnosis diagnosis
Keeps the LEDs/ScopeNumber for FPGA diagnosis together.
Definition: IO.h:453
Parameters for pixel acquisition with NI-FPGA.
Definition: IO.h:117
parameters::InputsFPGAAnalogIntegrator * parameters
the parameter set
NiFpga_Session session
NI FPGA session handle.
Definition: FPGAInterface.h:26
void CheckFPGADiagnosis()
Checks the status of the FIFOs on the FPGA.