VM3616A Programming Examples

advertisement
VM3616A Programming Examples
Outputting Static Voltages:
Immediate/Triggered
The most basic function of the VM3616A is that of a static digital to analog converter (DAC). Each of the 16 channels can be
programmed independently. All of the outputs are referenced to a common ground. If an isolated DAC is required, please refer to the
VM3618. Program Example 1 describes the sequence of SCPI commands to be sent to the device to configure the first four channels
at four different voltage levels. The output range of each channel can be configured independently or as a group to +/- 10 or +/-20.
Setting the range will affect the output resolution
PROGRAM EXAMPLE 1
sour:volt:rang 10v, (@1:4) /* all channels set to 10v range
sour:volt:lev 1.5, (@1) /*set channel 1 output to 1.5 volt
sour:volt:lev 2.5, (@2) /*set channel 2 output to 2.5 volt
sour:volt:lev 3.5, (@3) /*set channel 3 output to 3.5 volt
sour:volt:lev 4.5, (@4) /*set channel 4 output to 4.5 volt
These commands will cause the DAC's to update immediately. If it is desired to update the DAC's based on a trigger input, such as
the backplane TTLT0, then the commands in program example 2 must be sent. In this example the outputs will not be updated until a
rising edge trigger on TTLT0 occurs.
PROGRAM EXAMPLE 2
trig:sour ttlt0 /*configure trigger source as TTLT0
trig:slop pos /* trigger slope is positive
The plug&play driver includes application and configuration functions that perform similar tasks. The application function to setup
and write to the DAC can be called from the .dll per program example 3.
PROGRAM EXAMPLE 3
#include "vtvm3616A.h"
static ViSession instrHndl;
char instrDesc[50]; //A valid example for this variable would be VXI0::4::INSTR, where 4 is the logical address of the device.
static ViInt16 channelList1[1] = {1};
*/ initialize the VM3616A
vtvm3616_init (instrDesc, vtvm3616_INIT_ID_QUERY, vtvm3616_INIT_RESET, &instrHndl);
/* setup channel 1 to output 1.5V upon receipt of a rising edge trigger on TTLT0
vtvm3616_setupAndWriteToDAC (instrHndl, vtvm3616_TRIG_SRC_TTLTRG0, vtvm3616_SLOPE_POSITIVE, 1.5,
channelList, 1);
Outputting Voltages from
Scan Tables
Each DAC channel supports scan lists of up to 512 entries long. The scan list is predefined and loaded into RAM prior to use. All
DACs update synchronously and can be advanced through the list upon receipt of a front panel input or TTL trigger. The scan list can
be programmed to loop back to the beginning, or halt once the end of the list has been reached. The scan lists cannot use the internal
oscillator for pacing the output. Utilize the ARB mode if internal pacing is desired.
To setup the DACs to operate in the scan mode, refer to program example 4. In this case, channels 5 and 6 have the scan mode set to
ON and channels 7 and 8 have the scan mode set to LOOP. The trigger source is will be defined as backplane TTLT0.
PROGRAM EXAMPLE 4
scan off */ensure that no invalid mode transitions will occur
scan on, (@5:6) */set the scan mode to ON for channels 5 and 6. These channels will not loop back once the list is completed.
scan loop, (@7:8) */set the scan mode to LOOP for channels 7 and 8. These channels will loop back to start of list.
trig:sour ttlt0 */TTLT0 will be used to advance through the scan list.
scan:tabl 5,0,5,0,5,0 /* alternating off/on pattern. After the 5th trigger, this channel outputs 0V indefinitely.
scan:tabl 6,5,5,0,0,5 /* alternating off/on pattern. After the 5th trigger, this channel outputs 5V indefinitely.
scan:tabl 7,0,1,2,3,4 /* step function. After the 5th trigger, this channel repeats the pattern.
scan:tabl 8,0,2,0,4 /* step function. After the 4th trigger, this channel repeats the pattern.
Outputting Standard Waveforms
Using Arb Mode
One of the more powerful features of the VM3616A is the arbitrary waveform mode. This mode makes use of an internal timing
clock to pace the output of the data as fast as 10us intervals at 100ns resolution. Standard waveforms at lower frequencies can be
generated using the arb mode by loading the waveform data into memory, which is separate from that used for the scan lists, and
pacing the output using the internal oscillator. In arb mode, the channels share up to 1MB of memory.
There is only one oscillator per module, therefore all channel outputs are updated simultaneously. However, each channel can be
programmed with different waveform data allowing for independent waveforms. Programming example 5 illustrates how two
channels can be programmed to output continuous sine waves at different frequencies, in this case the desire is to have channel 1
output a sine wave at 193 Hz and channel 2 at 130Hz (Figure E-1). There are many different ways that the sine wave data can be
generated including software packages that generate 16-bit binary waveform data files which can be used by the VM3616A. Also,
some application development environments (ADE's) have built in analysis tools that create waveform data that can be ported directly
into the device.
FIGURE E-1.
PROGRAM EXAMPLE 5
sour:volt:rang 10v, (@1:2) /* Set the voltage range across the two channels
trig:sour none /* Set trigger source to NONE. Output will begin as soon as an INIT command is sent.
scan arb, (@1:3) /* Set channels to ARB mode
trace:def 0, 1536 /* Define the size of a segment
sour:volt:form 0 /* Define whether waveform data will be loaded as signed or unsigned binary
sour:rosc:sour tim /* Set the internal timer to be the pacer for the output data.
trig:tim 1e-5 /* Set the internal timing interval. This ultimately determines the frequency of the output.
/* Define trace data within the segment for each channel (1536 data points/channel)
trace:lev 0,1, <1536 points of sine wave data, 3 cycles> // Segment 0, Ch1
trace:lev 0,2, <1536 points of sine wave data, 2 cycles> //Segment 0, Ch2
source:seq:list (@ 0) /* Define the sequence to contain segment 0
sour:seq:start auto,(@0) /* sequence will loop and output will be continuous
init /* Begin outputting data
The frequency of the sine wave output is determined by the timing clock interval (10us) and the number of data points per cycle. For
channel 1, this works out to 1/(512*0.00001) = 195.3 Hz. Channel 2 = 1/(768*0.00001) = 130.2 Hz. Different frequencies on each
channel can be achieved by varying the internal timing interval, or the number of waveform cycles within a segment. For example a
sine wave can be defined by 128 data points, 16 cycles, effectively quadrupling the frequency of the output on channel 1.
Loading Arb Data Using
Register-Based Commands
The previous example uses word serial (or SCPI) commands to download the waveform data to the VM3616A. This is a very time
intensive process when large blocks of data are downloaded to the device via this method. While the VM3616A is a message-based
device, the registers can be accessed to speed up the data upload process. Figure E-2 shows the valid register map for the ARB mode.
0x26 Waveform Data
0x24 RAM Request
0x22 Channel Number
0x20 Segment Number
FIGURE E-2: A16 register map, ARB mode
The flow for loading data begins with the segment number and finishes with the 16-bit data. Refer to the flow chart (Figure E-3)
below. In the previous example, this sequence of register-based calls would have been performed twice, one for each active channel.
Load Segment Number
0x20
Load Channel Number
0x22
Request Ram
<write a '0' to 0x24>
Load 16-bit data value
0x26
TRUE
More data for this
channel?
FALSE
TRUE
More channels or
segments?
FALSE
DONE
FIGURE E-3: Loading arb data via registers
The plug&play driver for the VM3616A includes a function that embeds the register-based calls when loading arb data. This function
can be called from any ADE that can utilize dynamically linked libraries (.dll). The data is loaded as an array and the following
function call is used.
vtvm3616_arbLoadData (ViSession instrHndl, int segmentNumber, int channel, ViInt16 voltageDataBuffer[], ViInt32 buffSize);
Creating Arbitrary Waveform
Patterns on Multiple Channels
It is important to become familiar with the concept of traces, segments and sequences to understand the arb mode operation of the
VM3616A. A trace is the smallest building block of the arbitrary waveform (e.g. 3 cycle sine wave). A segment defines the output of
all channels set to arb mode for a specified length in time. The length in time is determined by the number of data points assigned to
the segment multiplied by the internal timer (pacing clock) interval. The sequence defines the order in which the segments will be
called to create the output pattern.
For example, if three channels are set to the arb mode, three different blocks of trace data can be loaded into memory and assigned to a
particular segment. Figure E-4 illustrates the concept of traces and segments.
FIGURE E-4
To create an arbitrary waveform from the segments described in the above example, a sequence must be created to define the order of
segment calls which ultimately defines the arbitrary pattern. Programming example 6 shows how to build arbitrary patterns across
multiple channels.
PROGRAM EXAMPLE 6
trig:sour none /* Set trigger source to NONE. Output will begin as soon as an INIT command is sent.
scan arb, (@1:3) /*Set all three channels to ARB mode
trace:def 1, 1000 /*Define the size of segment 1
trace:def 2, 500 /*Define the size of segment 2
sour:volt:form 0 /*Define whether waveform data will be loaded as signed or unsigned binary
sour:rosc:sour tim /* Set the internal timer to be the pacer for the output data.
trig:tim 1e-5 /*Set the internal timing interval. This ultimately determines the frequency of the output.
/*Define trace data within each segment. Avoid undefined segment data as it will result in a random output.
trace:lev 1,1, <1000 points of sine wave data, 3 cycles> Segment 1, Ch1
trace:lev 1,2, <1000 points of sine wave data, 2 cycles> Segment 1, Ch2
trace:lev 1,3, <1000 points of triangle wave data, 2 cycles> Segment 1, Ch3
trace:lev 1,1, <500 points of square wave data, 2 cycles> Segment 2, Ch1
trace:lev 1,2, <500 points of sine wave data, 1 cycle> Segment 2, Ch2
trace:lev 1,3, <500 points of gated sine data, 1 cycle> Segment 2, Ch3
source:seq:list (@ 1, 2, 2) /* Define the sequence
/*Define how each segment will begin outputting data within the sequence (i.e. auto or triggered)
sour:seq:start auto,(@0:2) */new segment begins as soon as previous segment is complete. Waveform loops until an abort is
issued.
init /*Begin outputting data
VXIplug&play
Programming example 7 achieves the identical waveform using the VXIplug&play driver supplied with the product
PROGRAM EXAMPLE 7
#include "vtvm3616A.h"
static ViSession instrHndl;
char instrDesc[50]; //A valid example for this variable would be VXI0::4::INSTR, where 4 is the logical address of the device.
static ViInt16 channelList[3] = {1,2,3};
static ViInt16 seqList[3] = {1,2,2};
double ThreeCycleSine[1000], TwoCycleSine[1000], Triangle[1000], OneCycleSine[500], TwoCycleSquare[500], GatedSine[500];
vtvm3616_init (instrDesc, vtvm3616_INIT_ID_QUERY, vtvm3616_INIT_RESET, &instrHndl);
vtvm3616_configTriggerParams (instrHndl, vtvm3616_TRIG_SRC_NONE, vtvm3616_SLOPE_POSITIVE);
vtvm3616_setupScanMode (instrHndl, vtvm3616_SCAN_MODE_ARB, channelList,3);
vtvm3616_arbDefineSegment (instrHndl, 1, 1000)
vtvm3616_arbDefineSegment (instrHndl, 1, 500)
vtvm3616_setupDataFormat (instrHndl, vtvm3616_FORMAT_UNSIGNED)
vtvm3616_setupClock (instrHndl, vtvm3616_ROSC_TIMER, vtvm3616_POSITIVE)
vtvm3616_setupTimer (instrHndl, 0.00001)
vtvm3616_arbLoadData (instrHndl, 1, 1, ThreeCycleSine, 1000);
vtvm3616_arbLoadData (instrHndl, 1, 2, TwoCycleSine, 1000);
vtvm3616_arbLoadData (instrHndl, 1, 3, Triangle, 1000);
vtvm3616_arbLoadData (instrHndl, 2, 1, TwoCycleSquare, 500);
vtvm3616_arbLoadData (instrHndl, 2, 2, OneCycleSine, 500);
vtvm3616_arbLoadData (instrHndl, 2, 3, GatedSine, 500);
vtvm3616_arbDefineSequence (instrHndl, seqList, 3);
vtvm3616_arbSetSeqParms (instrHndl, 0, vtvm3616_SEQ_AUTO_START, vtvm3616_SEQ_ASYNC_ADVANCE, 1,
vtvm3616_SEQ_MARKER_OFF);
vtvm3616_arbSetSeqParms (instrHndl, 1, vtvm3616_SEQ_AUTO_START, vtvm3616_SEQ_ASYNC_ADVANCE, 1,
vtvm3616_SEQ_MARKER_OFF);
vtvm3616_arbSetSeqParms (instrHndl, 2, vtvm3616_SEQ_AUTO_START, vtvm3616_SEQ_ASYNC_ADVANCE, 1,
vtvm3616_SEQ_MARKER_OFF);
vtvm3616_commandArb (instrHndl, vtvm3616_INITIATE);
As soon as the init command is issued, the channels will begin to output the data. Because each segment is defined in the 'auto' mode,
the DACs will produce a continuous output. The resultant waveform generated by the previous code is illustrated in Figure E-5.
FIGURE E-5
Single Shot Mode and Triggering
All previous examples exhibited continuous waveforms that were triggered as soon as the 'init' command was issued to the device. If
the outputs of the DAC are to be in quiescent state until a single shot waveform is desired, then some slight modifications to the code
must be made.
As an example, the front panel external input can be used to trigger the arbitrary waveform pattern defined in the previous example.
trig:sour ext /* Set trigger source to EXT. External trigger will cause DAC to begin outputting data
However, as currently defined, the DACs will begin outputting the data as soon as the 'init' command is issued. To correct this, it is
recommended to set up an initial or quiescent segment, detailed in programming example 8, at a DC level that has its sequence start
parameter set to triggered. This will cause the output of the DAC to hold at the quiescent level until the trigger is received.
PROGRAM EXAMPLE 8
trac:def 0, 2 /*define the size of segment 0 at two elements
trac:lev 0,1,0,0 /*quiescent voltage level for all three channels set to 0VDC
trac:lev 0,2,0,0
trac:lev 0,3,0,0
sour:seq:list (@0,1,2,2)
sour:seq:star trig, (@0) /*Segment 0 (sequence index 0) will execute after init is issued and then holds until trigger is issued
sour:seq:star auto, (@1:3) /* the rest of the pattern will be output after trigger is received. Single shot output.
Streaming Data:
Using the FIFO Mode
The VM3616A series has an on-board FIFO (first-in first-out) that is useful for outputting waveform patterns that require more
memory than is contained on the card. A typical application is the playback of recorded data such as audio signals. Data files that
exceed the 1MB memory limitation of the VM3616A can still be converted to an analog waveform by using the FIFO mode. The
internal timer that is used in ARB mode is the same timer that is used in the FIFO mode. The FIFO is emptied at a rate that is
equivalent to the settings of the timer. Multiple channels can be set to the FIFO mode and in this case, the data is loaded into the FIFO
interleaved.
The supplied soft front panel illustrates use of the FIFO mode. Three 16-bit binary data files are also included for example purposes.
It is recommended that the user familiarize him/herself with the soft front panel. In addition, detailed examples are listed below.
Single Channel FIFO Mode
The VM3616A converts 16-bit binary data into analog voltages. A common audio application plays back data at a rate of 43-44kb/s.
Refer to programming example #9 which shows how to playback a 16-bit audio file out of channel 1. The name of the file is
music.b16 and is stored in the root (c:\) drive.
PROGRAM EXAMPLE 9
#include "vtvm3616A.h"
static ViSession instrHndl;
char instrDesc[50]; //A valid example for this variable would be VXI0::4::INSTR, where 4 is the logical address of the device.
char FileName[] = {"C:\ music.b16"};
int FileHandle, dataBuffer, SampleCount = 50000;
static ViInt16 channelList[1] = {1}, fifoStatus;
vtvm3616_init (instrDesc, vtvm3616_INIT_ID_QUERY, vtvm3616_INIT_RESET, &instrHndl);
vtvm3616_setupScanMode (instrHndl, vtvm3616_SCAN_MODE_OFF, channelList,1); /* must first be off to transition to FIFO
vtvm3616_configTriggerParams (instrHndl, vtvm3616_TRIG_SRC_NONE, vtvm3616_SLOPE_POSITIVE);
vtvm3616_setupScanMode (instrHndl, vtvm3616_SCAN_MODE_FIFO, channelList,1);
vtvm3616_setupClock (instrHndl, vtvm3616_ROSC_TIMER, vtvm3616_POSITIVE);
vtvm3616_setupTimer (instrHndl, 0.0000227); /*44.0Khz output
vtvm3616_setupDataFormat (instrHndl, vtvm3616_FORMAT_UNSIGNED)
/* Store 50000 samples to a data buffer. These samples will be 'pre-loaded' into the FIFO
FileHandle =OpenFile (FileName, VAL_READ_ONLY, VAL_OPEN_AS_IS, VAL_BINARY);
read(FileHandle,(unsigned char *)dataBuffer, SampleCount);
/* pre-load the FIFO
vtvm3616_loadFIFO_Data (ViSession instrHndl, dataBuffer[], SampleCount);
vtvm3616_commandFifo (instrHndl, vtvm3616_INITIATE); /*FIFO starts to empty
/* Read next 50000 samples to data buffer. Then load to FIFO. This is a repetitive process that ensures that the FIFO doesn't
/*underrun (run out of data). A loop should be set up such that the FIFO status is also checked and overrun conditions are also
/*avoided.
read(FileHandle,(unsigned char *)dataBuffer, SampleCount);
vtvm3616_loadFIFO_Data (ViSession instrHndl, dataBuffer[], SampleCount);
vtvm3616_GetFifoStatus (instrHndl, *fifoStatus);
In most high speed applications where the timer is set at fast update rates, the risk of underrun is higher than an overrun. Data tends to
be emptied out of the FIFO at a faster pace than the host controller can read the file into the buffer and pass the data to the FIFO over
the VXIbus interface. In slow speed applications, it is possible that the FIFO can be filled up at a faster rate than it is emptied. In
these cases, the risk of a FIFO overflow is greater. To avoid an overflow condition, simply check the FIFO status. As long as the
status indicates that the FIFO is not full, another sample of data can be uploaded.
Multiple Channel FIFO mode:
A Register-Based example
Each sample of converted data is a 16-bit integer. When multiple channels are stored in FIFO, the data must be interleaved and with
every tick of the internal timer, each channel set to FIFO mode is updated with new data. Therefore, if 'n' channels are set to FIFO
mode, and the internal timer is set to 't' seconds, then the rate (in bytes) at which the data flows out of the FIFO is calculated using the
following equation:
(n*2)/t
For example, if three channels are set to the FIFO mode, the data in FIFO memory is stored per Fig. E-6. If the timer is set to the
minimum interval of 10us, then data is being extracted from the FIFO at a rate of 600kb/s. Slower host controllers may not be able to
refill the FIFO at a rate equivalent to which it is being emptied. Therefore, for very large files, an underrun condition is probable
(FIFO is empty and waiting for data) and the timer interval may need to be extended if possible.
0x(6n-2) Channel 3 (Sample n)
0x(6n-4) Channel 2 (Sample n)
0x(6n-6) Channel 1 (Sample n)
0x4
Channel 3 (Sample 1)
0x2
Channel 2 (Sample 1)
0x0
Channel 1 (Sample 1)
FIGURE E-6 Interleaved data in FIFO
Program Example 10 (written in LabWindows®/CVI) illustrates how to output multiple channels of FIFO data using register-based
access. In this example, channel 1 is outputting a constant square wave pulse, while channel 2 is outputting either a sine wave
(sine.b16) or triangle wave (tri.b16) depending on a selection that the user makes from a GUI (figure E-7). Both 16-bit binary files are
included with the plug and play driver. The plug and play driver function, vtvm3616_loadFIFO_Data can be used with multiple
channels as well, however, the programmer must be sure that the buffer contains interleaved data.
Register 0x20 in A16 space is the FIFO data register. Writing interleaved data to this register loads the FIFO. As soon as the FIFO
initiate command is sent, data from the FIFO is offloaded to the DACs and the conversions begin to take place at the rate at which the
timer is set. As in the single channel example, it is the program's responsibility to ensure that the FIFO does not run out of data, or
conversely, overflows. For the purpose of clarity, this example does not check the FIFO status prior to loading data to the FIFO.
FIGURE E-7
PROGRAM EXAMPLE 10
#include "vtvm3616A.h"
#define SamplesPerChannel 1000
#define ValidChannels 2
#define TotalNumOfBytesPerChannel 1000
#define TotalNumOfChannels 2
char FileName3[] = {"C:\\VXIPNP\\Win95\\Vtvm3616a\\Sine.b16"}; //file supplied with the driver program
char FileName4[] = {"C:\\VXIPNP\\Win95\\Vtvm3616a\\Tri.b16"};
ViSession instrHndl;
ViInt16
Channel_List [2] = {1, 2};
ViUInt16 fifoStatus,
Filebuffer[2000],
checkingarrayforMove[2000],
InitialFiFoData[TotalNumOfChannels*TotalNumOfBytesPerChannel],
DataForValidChannels[TotalNumOfChannels][TotalNumOfBytesPerChannel],
FiFoFinalData[TotalNumOfChannels*TotalNumOfBytesPerChannel],
UpdatedFiFoData[TotalNumOfChannels*TotalNumOfBytesPerChannel];
void
FIFOdataForCH1()
{
/* The following for loop is used to assign pulse data for channel 1in FIFO mode.*/
/* DataForValidChannels[][] is the two dimensional array containing all 16-bit channel data*/
for(DataByteCounter = 0; DataByteCounter < TotalNumOfBytesPerChannel; DataByteCounter +=2)
{
DataForValidChannels[1][DataByteCounter] = 32767;
/* 0V
DataForValidChannels[1][DataByteCounter+1] = 40959; /*5V
}
}
void
InitialFIFOdataForCH2() /* Loads sine.b16 data into DataForValidChannels Array
handle =OpenFile (FileName3, VAL_READ_ONLY, VAL_OPEN_AS_IS, VAL_BINARY);
status = read(handle,(unsigned char *)Filebuffer,FileBytescount);
i=0;
for(DataByteCounter = 0; DataByteCounter < TotalNumOfBytesPerChannel; DataByteCounter ++)
{
DataForValidChannels[2][DataByteCounter] = Filebuffer[i];
i+=1;
}
}
void
UpdatedFIFOdataForCH2() /* Loads tri.b16 data into DataForValidChannels Array
{
/* This function opens tri.b16 and reads into DataFromValidChannelArray
handle =OpenFile (FileName4, VAL_READ_ONLY, VAL_OPEN_AS_IS, VAL_BINARY);
status = read(handle,(unsigned char *)Filebuffer,FileBytescount);
i=0;
for(DataByteCounter = 0; DataByteCounter < TotalNumOfBytesPerChannel; DataByteCounter ++)
{
DataForValidChannels[2][DataByteCounter] = Filebuffer[i];
i+=1;
}
{
void InitialFIFOdataForAllValidChs() /*This function interleaves the pulse (ch1) and sine (ch2) data into InitialFiFoData array*/
{
FIFOdataForCH1(); //Function call to load data for CH#1.
InitialFIFOdataForCH2(); //Function call to load data(sine wave) for CH#2.
FiFoDataCounter = 0;
for(DataByteCounter = 0; DataByteCounter < TotalNumOfBytesPerChannel; DataByteCounter++)
{
for (ChannelCounter = 1; ChannelCounter < 3; ChannelCounter++)
{
InitialFiFoData[FiFoDataCounter] = DataForValidChannels[ChannelCounter][DataByteCounter];
FiFoDataCounter +=1;
}
}
}
void UpdatedFIFOdataForAllValidChs() /*This function interleaves pulse (ch1) and triangle (ch2) into UpdatedFiFoData array*/
{
UpdatedFIFOdataForCH4(); //Function call to load data(triangle Wave) for CH#2.
FiFoDataCounter = 0;
for(DataByteCounter = 0; DataByteCounter < TotalNumOfBytesPerChannel; DataByteCounter++)
{
for (ChannelCounter = 1; ChannelCounter < 3; ChannelCounter++)
{
UpdatedFiFoData[FiFoDataCounter] = DataForValidChannels[ChannelCounter][DataByteCounter];
FiFoDataCounter +=1;
}
}
TotalBytesToTransmit = FiFoDataCounter;
FiFoDataCounter = 0;
}
/*The above steps show how to read in data from a file and then interleave multiple channel data into arrays. In this example, a
toggle switch will determine which of two data arrays is uploaded to the FIFO. The next steps set up the VM3616A */
/*Setup channels 1 and 2 for FIFO mode*/
vtvm3616_init (instrDesc, vtvm3616_INIT_ID_QUERY, vtvm3616_INIT_RESET, &instrHndl);
vtvm3616_setupScanMode (instrHndl, vtvm3616_SCAN_MODE_OFF, Channel_List,2);
vtvm3616_configTriggerParams (instrHndl, vtvm3616_TRIG_SRC_NONE, vtvm3616_SLOPE_POSITIVE);
vtvm3616_setupScanMode (instrHndl, vtvm3616_SCAN_MODE_FIFO, Channel_List,2);
/*setup internal timer (60us) and data format as unsigned.
vtvm3616_setupDataFormat (instrHndl, vtvm3616_FORMAT_UNSIGNED);
vtvm3616_setupTimer (instrHndl, 0.00006);
vtvm3616_commandFifo (instrHndle, vtvm3616_INITIATE); /*Random data until FIFO is loaded with known data*/
/*map the A16 address space to a pointer, offset 0x20 is the FIFO data register
viMapAddress (VM3616A, VI_A16_SPACE, 0x20, 0x20, VI_FALSE, VI_NULL, &A16Ptr );
/* The next functions are called from actions on the GUI. A timer tick will cause data to be uploaded. The toggle switch
determines which timer is active and ultimately which data is uploaded to the FIFO.*/
int CVICALLBACK Timer1 (int panel, int control, int event, void *callbackData, int eventData1, int eventData2)
/* Timer1 tick will cause 1000 more sine wave samples to be loaded to the FIFO.
{
switch (event)
{
case EVENT_TIMER_TICK:
/*disable the timer until all 1000 samples have been loaded
status = SetCtrlAttribute (panelHandle, PANEL_TIMER1, ATTR_ENABLED, 0);
for(i = 0; i < 2; i++)
{
for(DataByteCounter = 0; DataByteCounter < TotalBytesToTransmit; DataByteCounter++)
{
viPoke16 (instrHndle, A16Ptr, InitialFiFoData[DataByteCounter]);// for sinewave data to fifo
}
}
/*enable the timer so the next tick will bring more data
status = SetCtrlAttribute (panelHandle, PANEL_TIMER1, ATTR_ENABLED, 1);
break;
}
return 0;
}
int CVICALLBACK Timer2 (int panel, int control, int event, void *callbackData, int eventData1, int eventData2)
/* Timer2 tick will cause 1000 more triangle samples to be loaded to the FIFO.
{
switch (event)
{
case EVENT_TIMER_TICK:
/*disable the timer until all 1000 samples have been loaded
status = SetCtrlAttribute (panelHandle, PANEL_TIMER2, ATTR_ENABLED, 0);
for(i = 0; i < 2; i++)
{
for(DataByteCounter = 0; DataByteCounter < TotalBytesToTransmit; DataByteCounter++)
{
viPoke16 (instrHndle, A16Ptr, InitialFiFoData[DataByteCounter]);// for triangle data to fifo
}
}
/*enable the timer so the next tick will bring more data
status = SetCtrlAttribute (panelHandle, PANEL_TIMER2, ATTR_ENABLED, 1);
break;
}
return 0;
}
/*This call is associated with the front panel toggle. Toggling the switch results in one of the timers being disabled, and the other one
will be enabled. This determines which data file (sine or triangle wave), gets loaded into the FIFO for Channel 2 output.
int CVICALLBACK SineTriControlSwitch (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event)
{
case EVENT_COMMIT:
status = GetCtrlVal (panelHandle, PANEL_SINETRICONTROLSWITCH, &ControlValue);
if (ControlValue == 0)
{
SetCtrlVal(panelHandle,PANEL_WAVETEXTBOXCH_4,FileName3);
status = SetCtrlAttribute (panelHandle, PANEL_TIMER1, ATTR_ENABLED, 1); //Enable timer1
status = SetCtrlAttribute (panelHandle, PANEL_TIMER2, ATTR_ENABLED, 0); //Disable timer2
}
else
{
SetCtrlVal(panelHandle,PANEL_WAVETEXTBOXCH_4,FileName4);
status = SetCtrlAttribute (panelHandle, PANEL_TIMER2, ATTR_ENABLED, 1); //Enable timer2
status = SetCtrlAttribute (panelHandle, PANEL_TIMER1, ATTR_ENABLED, 0); //Disable timer1
break;
}
return 0;
}
A more detailed variation and listing of example #10 (fifo3616.zip) can be found on the VXI Technology ftp site by connecting
through www.vxitech.com
Download