Scope
OutputsDAQmxLineClock.cpp
1 #include "stdafx.h"
2 #include "OutputsDAQmxLineClock.h"
3 #include "parameters/IO.h"
4 #include "parameters/Scope.h"
5 #include "helpers/ScopeException.h"
6 
7 namespace scope {
8 
9 OutputsDAQmxLineClock::OutputsDAQmxLineClock(const uint32_t& _area, const parameters::OutputsDAQmxLineClock& _outputparams, const parameters::Scope& _params)
10  : Outputs(_area)
11  , XTotalPixels(_params.areas[area]->Currentframe().XTotalPixels())
12  , YTotalLines(_params.areas[area]->Currentframe().YTotalLines()) {
13 
14  std::wstring commontrig = _params.commontrigger();
15 
17  xpout_task.CreateAOVoltageChannel(_outputparams.xpout(), L"XPOutput", -_outputparams.range(), _outputparams.range());
18 
19  double pixelrate = 1/(_params.areas[area]->daq.pixeltime()*1E-6);
20  std::wstring xpclockstring = DAQmx::ClockString(_outputparams.pixel_timing(), _outputparams.pixel_externalclocksource());
21 
22  xpout_task.ConfigureSampleTiming(xpclockstring, pixelrate, XTotalPixels, DAQmx_Val_ContSamps, DAQmx_Val_Rising);
23 
24  if ( DaqTimingHelper::Mode::ReferenceClock ==_outputparams.pixel_timing() )
26 
28 
29  // Force to regenerate samples if we are in nframes mode
30  if ( _params.requested_mode() == DaqModeHelper::nframes )
32 
33  // all tasks (except first area's xpout_task) wait for that first xpout_task's start trigger
34  if ( area != 0 ) {
35  xpout_task.ConfigureDigStartTrigger(commontrig, DAQmx_Val_Rising);
36  }
37  // If T-Series is triggered, first xpout_task task waits for external trigger (and all other tasks waiting for that first xpout_task)
38  else if ( _params.timeseries.triggered() )
39  xpout_task.ConfigureDigStartTrigger(_params.timeseries.triggerchannel(), DAQmx_Val_Rising);
40 
42  yzout_task.CreateAOVoltageChannel(_outputparams.yzout(), L"YZPOutput", -_outputparams.range(), _outputparams.range());
43 
44  std::wstring yzclockstring = DAQmx::ClockString(_outputparams.line_timing(), _outputparams.line_externalclocksource());
45 
46  yzout_task.ConfigureSampleTiming(yzclockstring, _params.areas[area]->linerate(), YTotalLines, DAQmx_Val_ContSamps, DAQmx_Val_Rising);
47 
48  if ( DaqTimingHelper::Mode::ReferenceClock ==_outputparams.line_timing() )
50 
52 
53  // The onboard buffer of e.g. the NI-6259 is 4096 samples, with ~512 samples in a column it would take several frames for updated values to be actually generated
54  // To force updating the onboard buffer we set this data transfer condition (actually why THIS works and not DAQmx_Val_OnBrdMemNotFull I do not fully get...)
55  yzout_task.SetDataTransferCondition(_outputparams.yzout(), DAQmx_Val_OnBrdMemEmpty);
56 
57  // Force to regenerate samples if we are in nframes mode
58  if ( _params.requested_mode() == DaqModeHelper::nframes )
60 
61  // all tasks (except first area's xpout_task) wait for that first xpout_task's start trigger
62  yzout_task.ConfigureDigStartTrigger(commontrig, DAQmx_Val_Rising);
63 }
64 
65 OutputsDAQmxLineClock::~OutputsDAQmxLineClock(void) {
66  Stop();
67  xpout_task.Clear();
68  yzout_task.Clear();
69 }
70 
72  // Start yzout first, since it waits on xpout's ao/StartTrigger as master trigger
73  yzout_task.Start();
74  xpout_task.Start();
75 }
76 
78  xpout_task.Stop();
79  yzout_task.Stop();
80 }
81 
82 int32_t OutputsDAQmxLineClock::Write(const std::vector<int16_t>& _xyzp, const uint32_t& _blocks) {
83  int32_t written = 0;
84 
85  int32_t yblocksize = YTotalLines/_blocks;
86  int32_t lastyblocksize = yblocksize + (YTotalLines - yblocksize*_blocks); // adjust size of last block if size per channel is not a multiple of blocksize
87 
88  try {
89  if ( writeabort == true ) {
90  DBOUT(L"OutputsDAQmxLineClock::Write writeabort");
91  writeabort = false;
92  return 0;
93  }
94  // First write xp as one block, this is very fast since xp (one line) output is also very fast
95  written += xpout_task.WriteAnalogI16(_xyzp.data(), XTotalPixels, false, 2, DAQmx_Val_GroupByScanNumber);
96 
97  // Then write yz in blocks, since yz is very slow and we want to check in between for a writeabort and do not want to set high timeout times for WriteAnalogI16
98  // Since one column is often smaller than the device buffer, use a different transfer condition (see constructor)
99  for ( uint32_t b = 0 ; b < _blocks ; b++ ) {
100  if ( writeabort == true ) {
101  DBOUT(L"OutputsDAQmxLineClock::Write writeabort");
102  break;
103  }
104  yzout_task.SetWriteOffset(b*yblocksize); // set write offset in the device buffer
105  // data layout is by sample, offset for yz data is 2*XTotalPixels
106  written += yzout_task.WriteAnalogI16((_xyzp.data() + 2*XTotalPixels + 2*b*yblocksize) // set offset in the data vector
107  , ((b==_blocks-1)?lastyblocksize:yblocksize), false, 2, DAQmx_Val_GroupByScanNumber); // data layout is by sample
108  }
109 
110  } catch (...) { ScopeExceptionHandler(__FUNCTION__); }
111 
112  writeabort = false;
113  DBOUT(L"OutputsDAQmxLineClock::Write written " << written << L" samples");
114  return written;
115 }
116 
119  try {
120  task.CreateTask();
121  task.CreateAOVoltageChannel(_params.xpout()
122  , L"XPOut"
123  , -_params.range()
124  , _params.range());
125  task.WriteAnalogI16(std::make_shared<std::vector<int16_t>>(2,0)->data(), 1, true);
126  task.WaitUntilDone(200);
127  task.Clear();
128  task.CreateTask();
129  task.CreateAOVoltageChannel(_params.yzout()
130  , L"YZOut"
131  , -_params.range()
132  , _params.range());
133  task.WriteAnalogI16(std::make_shared<std::vector<int16_t>>(2,0)->data(), 1, true);
134  task.WaitUntilDone(200);
135  task.Clear();
136  } catch (...) { ScopeExceptionHandler(__FUNCTION__); }
137 }
138 
139 
140 }
ScopeString commontrigger
The trigger channel which is the internal common master trigger for all devices.
Definition: Scope.h:262
ScopeString pixel_referenceclocksource
source terminal of the reference clock for pixel sampling clock
Definition: IO.h:625
void SetRegeneration(const bool &_regenerate)
Sets the mode of sample regeneration.
Definition: DAQmxTask.cpp:177
The master parameters class.
Definition: Scope.h:204
void ConfigureReferenceClock(const std::wstring &_src, const float64 &_rate)
Configures the reference clock for the task.
Definition: DAQmxTask.cpp:128
int32_t WaitUntilDone(const float64 &_waittime)
Waits until the task is done.
Definition: DAQmxTask.cpp:163
DAQmx::CDAQmxAnalogOutTask yzout_task
Task for y-scanner/fast z clocked by the line clock from the FPGA.
std::array< std::unique_ptr< Area >, SCOPE_NAREAS > areas
holds AreaParameters for all areas.
Definition: Scope.h:231
ScopeValue< DaqTiming > line_timing
where to get the line sampling clock from? Onboard, from external reference clock, or from external source
Definition: IO.h:617
std::wstring ClockString(const scope::DaqTimingHelper::Mode &_timing, const std::wstring &_externalclocksource)
Generates a string for the sample clock from daq_timing.
Definition: DAQmxTask.cpp:46
std::atomic< bool > writeabort
Signal for aborting a write operation (since write is performed in several blocks, abort can happen in between)
Definition: Outputs.h:13
ScopeString triggerchannel
channel name for trigger input
Definition: Runstates.h:78
uInt32 ConfigureBuffer(const uInt32 &_sampsperchannel)
Configure the daqmx output buffer on the PC.
Definition: DAQmxTask.cpp:201
DAQmx::CDAQmxAnalogOutTask xpout_task
Task for x-scanner/Pockels clocked by the pixel clock from the FPGA.
Timeseries timeseries
the TimeseriesParameters
Definition: Scope.h:240
int32 WriteAnalogI16(const int16 *_data, int32 _sampsperchan, bool _autostart=false, int32 _timeout=2, bool32 _layout=DAQmx_Val_GroupByChannel)
Writes several samples to the buffer of an analog output task.
Definition: DAQmxTask.cpp:258
void Start() override
Start task.
void SetWriteOffset(int32 posreltofirst)
Sets the write offset relative to the first buffer position.
Definition: DAQmxTask.cpp:172
void SetDataTransferCondition(const std::wstring &_channel, const int32_t &_cond)
Configures the condition for data transfer to the device.
Definition: DAQmxTask.cpp:229
This is the include file for standard system include files, or project specific include files that ar...
ScopeValue< DaqMode > requested_mode
requested acquisition mode (see DaqModeHelper)
Definition: Scope.h:279
void Start(void)
Starts the task.
Definition: DAQmxTask.cpp:145
ScopeValue< DaqTiming > pixel_timing
where to get the pixel sampling clock from? Onboard, from external reference clock, or from external source
Definition: IO.h:614
int32_t YTotalLines
Length of a column in samples.
ScopeNumber< bool > triggered
the current/first repeat is triggered on triggerchannel
Definition: Runstates.h:81
ScopeNumber< double > pixel_referenceclockrate
rate in Hertz of the reference clock for pixel clock.
Definition: IO.h:632
#define DBOUT(s)
A debug output to the debug console.
Definition: helpers.h:153
int32_t XTotalPixels
Length of a line in samples.
void ScopeExceptionHandler(const std::string &_origin, const bool &_log, const bool &_showmessagebox, const bool &_trace, const bool &_rethrow)
Handles all exceptions and does nice logging.
ScopeString line_referenceclocksource
source terminal of the reference clock for line sampling clock
Definition: IO.h:628
void CreateAOVoltageChannel(const std::wstring &_devices, const std::wstring &_channelname=L"", float64 _minval=-10.0, float64 _maxval=10.0, int32 _units=DAQmx_Val_Volts, const std::wstring &_customscalename=L"")
Creates an analog output channel Allowed values for terminal configuration (from NiDAQmx.h): Values for DAQmx_PhysicalChan_AI_TermCfgs and DAQmx_PhysicalChan_AO_TermCfgs Value set TerminalConfigurationBits .
Definition: DAQmxTask.cpp:182
Wraps a DAQmx Analog Output task.
Definition: DAQmxTask.h:137
void Clear(void)
Clear the task.
Definition: DAQmxTask.cpp:153
ZeroOutputsDAQmxLineClock(const parameters::OutputsDAQmxLineClock &_params)
Create a simple tasks for writing a scalar zero to all channels.
void CreateTask(const std::wstring &_name=L"")
Definition: DAQmxTask.cpp:91
void ConfigureSampleTiming(const std::wstring &_src, const float64 &_rate, const int32 &_samplesperchan, const int32 &_samplingtype=DAQmx_Val_ContSamps, const int32 &_actedge=DAQmx_Val_Rising)
Configures a sample timing for the task.
Definition: DAQmxTask.cpp:109
const uint32_t area
which area this one is for
Definition: Outputs.h:10
int32_t Write(const std::vector< int16_t > &_xyzp, const uint32_t &_blocks) override
Writes values for one frame of X-Y-fastZ and pockels data to the device buffer.
ScopeNumber< double > line_referenceclockrate
rate in Hertz of the reference clock for line clock.
Definition: IO.h:636
ScopeNumber< double > range
Output range of the DAC to use for all outputs.
Definition: IO.h:526
ScopeString yzout
Analog output channel for y-scanner and fast z device (clocked by line clock)
Definition: IO.h:611
ScopeString pixel_externalclocksource
source terminal of an external clock for x and p pixel clock
Definition: IO.h:639
OutputsDAQmxLineClock(const uint32_t &_area, const parameters::OutputsDAQmxLineClock &_outputparams, const parameters::Scope &_params)
Creates the tasks and clock tasks.
void Stop() override
Stops task.
ScopeString line_externalclocksource
source terminal of an external clock for y and z line clock
Definition: IO.h:642
Parameters for x/y-scanner/fast z/Pockels signal generation with NI-DAQmx where xp are driven by a pi...
Definition: IO.h:596
ScopeString xpout
Analog output channel for x-scanner and Pockels cell (clocked by pixel clock)
Definition: IO.h:608
void ConfigureDigStartTrigger(const std::wstring &_src, const int32 &_trigedge=DAQmx_Val_Rising)
Configures the start trigger.
Definition: DAQmxTask.cpp:134
void Stop(void)
Stops the task.
Definition: DAQmxTask.cpp:149
Wraps hardware connection for signal output to scanners, fast z control, and pockels cell...
Definition: Outputs.h:6