Scope
FPGAPhotonCounter.cpp
1 #include "StdAfx.h"
2 #include "FPGAPhotonCounter.h"
3 #include "parameters/IO.h"
4 #include "helpers/DaqChunk.h"
5 
6 namespace scope {
7 
9  : FPGAIO6587(NiFpga_PhotonCounterV2_IndicatorBool_Onboard_Clock_Ready, NiFpga_PhotonCounterV2_ControlU16_Onboard_Clock_Write_Data
10  , NiFpga_PhotonCounterV2_ControlBool_Onboard_Clock_Write , NiFpga_PhotonCounterV2_IndicatorBool_Xpoint_Switch_Ready
11  , NiFpga_PhotonCounterV2_ControlU8_ClockSource, NiFpga_PhotonCounterV2_ControlBool_Xpoint_Switch_Write, NiFpga_PhotonCounterV2_ControlBool_Commit
12  , NiFpga_PhotonCounterV2_ControlBool_Acq_Reset) {
13  status = NiFpga_Initialize();
14  char* const Bitfile = "devices\\fpga\\" NiFpga_PhotonCounterV2_Bitfile;
15 
16  // Load but do not run yet
17  status = NiFpga_Open(Bitfile, NiFpga_PhotonCounterV2_Signature, "RIO0", NiFpga_OpenAttribute_NoRun, &session);
18  DBOUT(L"FPGAPhotonCounter: FPGA Session opened");
19 
20  // Reset the non-running FPGA to clear any bad stuff (e.g. after a program crash with open FPGA before)
21  status = NiFpga_Reset(session);
22 
23  // YOU HAVE TO WAIT THAT LONG!!!
24  // Otherwise you will occasionally (!!!) into strange problems (communication with fpga error -61046)
25  // This took me very very long to figure out...
26  std::this_thread::sleep_for(std::chrono::milliseconds(500));
27  // Run after reset
28  status = NiFpga_Run(session, 0);
29 
31 
32  // Set the fifo constants
33  fifos[0] = NiFpga_PhotonCounterV2_TargetToHostFifoU16_ToHostCh1FIFO;
34  fifos[1] = NiFpga_PhotonCounterV2_TargetToHostFifoU16_ToHostCh2FIFO;
35 }
36 
38  status = NiFpga_Close(session, 0);
39  status = NiFpga_Finalize();
40  DBOUT(L"FPGAPhotonCounter::~FPGAPhotonCounter session closed");
41 }
42 
44  if ( !initialized ) {
45  parameters = dynamic_cast<parameters::InputsFPGAPhotonCounter*>(_parameters);
46 
47  assert( (parameters->samplingrate() > 100E6) && (parameters->samplingrate() < 1.6E9));
49 
51  // YOU HAVE TO WAIT THAT LONG!!!
52  // Otherwise you will occasionally (!!!) into strange problems (communication with fpga error -61046)
53  // This took me very very long to figure out...
54  std::this_thread::sleep_for(std::chrono::milliseconds(500));
56 
58 
60 
61  FPGAInterface::Initialize(_parameters);
62  }
63 }
64 
65 double FPGAPhotonCounter::SetPixeltime(const uint32_t& _area, const double& _pixeltime) {
66  // sampling rate is twice the IO modules frequency (because of dual data rate transfer)
67  uint16_t samplesperpixel = round2ui16(_pixeltime * 1E-6 * samplingrate);
68  status = NiFpga_WriteU16(session, NiFpga_PhotonCounterV2_ControlU16_Samplesperpixel, samplesperpixel);
69  status = NiFpga_WriteU16(session, NiFpga_PhotonCounterV2_ControlU16_SamplesperpixelAcq, samplesperpixel);
70  return static_cast<double>(samplesperpixel)*1E6/samplingrate;
71 }
72 
73 double FPGAPhotonCounter::SetLinetime(const uint32_t& _area, const double& _linetime) {
74  // sampling rate is twice the IO modules frequency (because of dual data rate transfer)
75  uint16_t samplesperline = round2ui32(_linetime * 1E-6 * samplingrate);
76  status = NiFpga_WriteU16(session, NiFpga_PhotonCounterV2_ControlU32_Samplesperline, samplesperline);
77  return static_cast<double>(samplesperline*1E6/samplingrate);
78 }
79 
80 void FPGAPhotonCounter::SetTriggering(const bool& _waitfortrigger) {
81  status = NiFpga_WriteBool(session, NiFpga_PhotonCounterV2_ControlBool_Waitfortrigger, _waitfortrigger);
82 }
83 
85  status = NiFpga_WriteBool(session, NiFpga_PhotonCounterV2_ControlBool_Acquirecontinuously, _cont);
86 }
87 
88 void FPGAPhotonCounter::SetRequestedPixels(const uint32_t& _area, const uint32_t& _reqpixels) {
89  status = NiFpga_WriteU32(session, NiFpga_PhotonCounterV2_ControlU32_Requestedpixels, _reqpixels);
90 }
91 
93  if ( !initialized )
94  throw ScopeException("Initialize FPGAPhotonCounter before StartAcquisition!");
95  ClearFIFOs();
96  status = NiFpga_WriteBool(session, NiFpga_PhotonCounterV2_ControlBool_Acquire, true);
97 }
98 
99 int32_t FPGAPhotonCounter::ReadPixels(DaqChunk& _chunk, const double& _timeout, bool& _timedout) {
100  size_t remaining = 0;
101 
102  assert(_chunk.NChannels() <= 2 ); // only two channels supported in FPGA vi
103 
104  NiFpga_Status stat = NiFpga_Status_Success;
105 
106  for ( uint32_t c = 0 ; c < _chunk.NChannels() ; c++ ) {
107  stat = NiFpga_ReadFifoU16(session
108  , fifos[c]
109  , &_chunk.data[c * _chunk.PerChannel()] // offset start in vector for second channel pixels
110  , _chunk.PerChannel()
111  , static_cast<uint32_t>(_timeout * 1000) // FPGA C API takes timeout in milliseconds, to be consistent with DAQmx we have _timeout in seconds
112  , &remaining);
113 
114  _timedout = (stat == NiFpga_Status_FifoTimeout);
115  if ( _timedout )
116  return -1; // avoid throwing exception on time out (since FpgaStatus status could throw on all errors)
117  status = stat;
118  }
119 
120  if ( status.Success() )
121  return _chunk.PerChannel();
122 
123  return -1;
124 }
125 
127  status = NiFpga_WriteBool(session, NiFpga_PhotonCounterV2_ControlBool_Acquire, false);
128 }
129 
131  NiFpga_Bool b;
132  status = NiFpga_ReadBool(session, NiFpga_PhotonCounterV2_IndicatorBool_ToHostFIFOOverflowCh1, &b);
133  parameters->diagnosis.ToHostOverflowCh1 = (b!=0);
134  status = NiFpga_ReadBool(session, NiFpga_PhotonCounterV2_IndicatorBool_ToHostFIFOOverflowCh2, &b);
135  parameters->diagnosis.ToHostOverflowCh2 = (b!=0);
136  status = NiFpga_ReadBool(session, NiFpga_PhotonCounterV2_IndicatorBool_InterloopFIFOoverflow, &b);
137  parameters->diagnosis.InterloopOverflow = (b!=0);
138  status = NiFpga_ReadBool(session, NiFpga_PhotonCounterV2_IndicatorBool_InterloopFIFOtimeout, &b);
139  parameters->diagnosis.InterloopTimeout = (b!=0);
140  status = NiFpga_ReadBool(session, NiFpga_PhotonCounterV2_IndicatorBool_Acquiring, &b);
141  parameters->diagnosis.Acquiring = (b!=0);
142 }
143 
145  status = NiFpga_WriteBool(session, NiFpga_PhotonCounterV2_ControlBool_ClearInterloopFIFOs, 1);
146  std::this_thread::sleep_for(std::chrono::milliseconds(50));
147  status = NiFpga_WriteBool(session, NiFpga_PhotonCounterV2_ControlBool_ClearInterloopFIFOs, 0);
148  // Stop FIFOs (clears them)
149  for ( auto f : fifos )
150  status = NiFpga_StopFifo(session, f);
151  std::this_thread::sleep_for(std::chrono::milliseconds(50));
152  // Restart FIFOs
153  for ( auto f : fifos )
154  status = NiFpga_StartFifo(session, f);
155  std::this_thread::sleep_for(std::chrono::milliseconds(50));
156 }
157 
158 void FPGAPhotonCounter::SetCountMode(const bool& _mode) {
159  status = NiFpga_WriteBool(session, NiFpga_PhotonCounterV2_ControlBool_Countingmode, _mode);
160 }
161 
162 }
void SetCountMode(const bool &_mode)
Set the counting mode on the FPGA.
ScopeNumber< bool > countmode
Type of photon counting.
Definition: IO.h:257
ScopeNumber< double > samplingrate
Sampling rate of the IO modules clock (which is double the clock rate of the FPGA acquisition loop) i...
Definition: IO.h:184
void WriteOnboardClockFrequency(NiFpga_Session _session, const double &_clock_freq)
Writes the program for the Si570 clock chip to the device.
Definition: FPGAIO6587.cpp:67
Simple exception class for Scope.
Definition: ScopeException.h:9
void SetTriggering(const bool &_waitfortrigger) override
Sets if the FPGA should wait for a trigger before starting acquisition.
~FPGAPhotonCounter()
Close FPGA session.
Handels the NI FlexRIO adapter module IO-6587.
Definition: FPGAIO6587.h:11
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: FPGAIO6587.cpp:27
Diagnosis diagnosis
Keeps the LEDs/ScopeNumber for FPGA diagnosis together.
Definition: IO.h:285
Parameters for pixel acquisition with FPGAPhotonCounter.
Definition: IO.h:246
std::vector< uint16_t > data
The data vector.
Definition: DaqChunk.h:26
void InitializeAcquisition(NiFpga_Session _session)
Commits the clock frequency and clock source writings and resets the IO module acquisition circuit...
Definition: FPGAIO6587.cpp:116
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) ...
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 Initialize(parameters::InputsFPGA *_parameters) override
Set initial parameters.
double SetPixeltime(const uint32_t &_area, const double &_pixeltime) override
Sets the time per pixel/dwell time (in seconds)
FPGAPhotonCounter()
Load the FPGA bitfile, reset, set the IO module's onboard clock, initialize the acquisition.
FPGAStatusSafe status
current FPGA status.
Definition: FPGAInterface.h:23
#define DBOUT(s)
A debug output to the debug console.
Definition: helpers.h:153
void ClearFIFOs()
Clears the interloop and ToHost FIFOs.
void SetContinuousAcquisition(const bool &_cont) override
Sets if the FPGA should acquire data continuously or acquire the number of pixels per channel set wit...
bool Success() const
parameters::InputsFPGAPhotonCounter * parameters
the parameter set
std::array< NiFpga_PhotonCounterV2_TargetToHostFifoU16, 2 > fifos
both fifos for both channels
void SetClockSource(NiFpga_Session _session, const uint8_t &_clock_source=3)
Possible clock sources (see SetClockSource.vi from NI examples) .
Definition: FPGAIO6587.cpp:93
double samplingrate
programmed sampling rate (usually 1-1.4GHz), this is double the IO modules clock rate ...
void StopAcquisition() override
Stops the acquisition on the FPGA.
int32_t ReadPixels(DaqChunk &_chunk, const double &_timeout, bool &_timedout) override
Read only pixels from the FPGA FIFO.
virtual void Initialize(parameters::InputsFPGA *_parameters)
Set initial parameters.
Definition: FPGAInterface.h:38
Parameters for pixel acquisition with NI-FPGA.
Definition: IO.h:117
ScopeNumber< bool > Acquiring
and the Acquiring indicator
Definition: IO.h:269
void StartAcquisition() override
Starts the acquisition on the FPGA.
NiFpga_Session session
NI FPGA session handle.
Definition: FPGAInterface.h:26
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 CheckFPGADiagnosis()
Checks the status of the FIFOs on the FPGA.