Quantcast
Channel: Marvin Test Solutions - Knowledge Base Articles
Viewing all 549 articles
Browse latest View live

How to print a HTML or TEXT file from within an ATEasy application - Published on 4/16/2014

$
0
0
One method of printing a HTML file from within an ATEasy application is to use the ALog control. This can be done as follows:

1. Create a form and uncheck the form Visible property.
2. Place an ALog control in the form and set it's PlainText property to False for HTML or True for text file printing.
3. Create a public procedure with one parameter that contains the location and name of the HTML file to be printed.
4. The procedure should load the form in Modeless mode, set the logPrint.LocationURL to the HTML file location, call logPrint.PrintLog and then return.

The example that accompanies this KB article is called DownloadQ200180.zip. In the example the form used to print the HTML file is called PrintHTMLForm. The public procedure used to call the form and print the file is called PrintHTML(). The same code can be used to print TEXT (log) files. The procedure code is as follows:

PrintHTML(sFile)
  {
! Declare a PrintHTMLForm form variable called frmPrintHTML

Load frmPrintHTML, False, 0  !Load the PrintHTML form
DoEvents()   !Process all pending operations
frmPrintHTML.logPrint.LocationURL=sFile  !Set the URL of the file to be printed

!Wait for the file to be loaded
while frmPrintHTML.logPrint.ReadyState <> alogReadyStateComplete
  DoEvents()
endwhile

frmPrintHTML.logPrint.PrintLog()  !Print the file
Unload frmPrintHTML
frmPrintHTML= Nothing
  }


For more information about how to select a printer for printing refer to Q000090

How to Repeat a test multiple times - Published on 4/16/2014

$
0
0
In ATEasy, there are many ways to display the results of tests.  The following example demonstrates how to measure and display the results of similar measurements in a single test loop rather than several individual tests. For example, we already have a test that calls an instrument to make a measurement.  We want to measure and display the results eight times.

To achieve this goal, we are going to create a test to make a measurement.  After we take a measuremet we call the RepeatTest() procedure to repeat the test times as required. Finally, we will create a variable to track the number of iterations in a driver public variable m_nTestIteration (initialized to -1).

The test to repeat and make the measurements will be:



DMM Measure(TestResult)
RepeatTest(8) ! add this line at the end of every test that need to be repeated



The procedure to loop would be:

Procedure RepeatTest(nNumberOfIterations) : Void
nNumberOfIterations: Val Short
{
if m_nTestIteration=-1
     m_nTestIteration=nNumberOfIterations! start count
endif

m_nTestIteration=m_nTestIteration-1

if m_nCurrentTest=0
    return    ! we are done
endif

Test EndEvents Test ! repeat this test
}


Create the module variable:

m_nTestIteration: Short = -1


The result shows that the test 1.1 ran 8 times, taking different measurements each time.



From the picture, we can see that the tests numbers were all identical: “001, no matter what iteration was it.  Another problem is that if the last iteration of the test has a PASS status, the program status will show as PASS no matter if one of the test iteration failed. We can add code to include the test iteration in the test number by revising the RepeatTest procedure:

Procedure RepeatTest(nNumberOfIterations) : Void
nNumberOfIterations: Val Short
s: String
i: Short
{
if m_nTestIteration=-1
     m_nTestIteration=nNumberOfIterations! start count
endif

m_nTestIteration=m_nTestIteration-1

! display test number - test iteration to the log
s=GetLogString(aLogStringCalcTestStatus)
i=pos(Format(test.Index+1, "000"), s)
SetLogString(Left(s, i)+Format(test.Index+1,"000") + "." + str(nNumberOfIterations-m_nTestIteration) + mid(s, i+len(Format(test.Index+1, "000"))))

! if one test failed fail the program
if TestStatus=FAIL
    program.Status=FAIL
endif

if m_nTestIteration=0
    return    ! we are done
endif

Test EndEvents Test ! repeat this test
}




The ATEasy driver which contains the RepeatTest procedure can be downloaded Downloadhere.

Real-Time Digital IO Compare Example - Published on 4/16/2014

$
0
0
In this tutorial, we will be running a PXI Digital IO GX5292 board in real-time compare mode through DIOEasy and examining some of its functionality.

Create the pattern we will use in DIOEasy as follows:

1. Open DIOEasy.

2. Create a new file with the following settings:
  • File Type: DIO (DIOEasy File Menu)
  • Board Type: GX5290 (DIOEasy File Properties - General tab)
  • Num. Of Boards: 1 (DIOEasy File Properties - General tab)
  • Num. Of Steps: 1024 (DIOEasy File Properties - General tab)
  • Operating Mode: Real Time Compare (DIOEasy File Properties - General tab)
  • Clock Delay (ns): 0.00 (DIOEasy File Properties - Setup tab)
  • Strobe Delay (ns): 0.00 (DIOEasy File Properties - Setup tab)
3. Set Channels 0 through 15 to output
  • Select Channel 0 through Channel 15
  • From the menu bar, select Fill -> Direction…
  • Click Output
4. Fill Channels 0 through 15 with a walking one pattern
  • While Channels 0 through 15 are still highlighted, select Fill -> Shift / Rotate…
  • In the dialog that pops up, change the Type from ‘Shift’ to ‘Rotate’
  • Click Overwrite!
5. Create the expected pattern for Channel 16 through 31
  • Select Channel 16 through 31.
  • From the menu bar, select Fill -> Shift / Rotate…
  • In the dialog that pops up, change the Type from ‘Shift’ to ‘Rotate’
  • Click Overwrite!
6. Add HALT command to the end of the pattern
  • Click on the last step of your pattern (step 1023)
  • Hit Alt+Enter to open the command properties window.
  • Change the command for this step from NOP to HALT
7. Insert error in Channel 0
  • Click Channel 0 to highlight the entire channel
  • From the menu bar, select Fill -> Value…
  • Select to fill the channel with all 0s and click Overwrite!
8. Save this file as “DownloadRTCError.dio

Digital IO Pattern using DIOEasy

The image above depicts the DIO file created.  When executed, it will output a walking one pattern on J1 channels 0 through 15 while reading J1 channels 16 through 31 as input.  Externally, the first sixteen channels will need to be wired to the second sixteen channels (channel 0 wired to channel 16, channel 1 wired to channel 17, and so on) to achieve a loopback.  We are expecting to see the same walking one pattern on channels 16 through 31 as we output on channels 0 through 15.    Since we want to observe some errors, we have intentionally set all steps in channel 0 to LOW.  This will generate 64 errors (1 error every 16 steps).

Run the Pattern using GTDIO Panel:

1. Launch the GTDIO Panel from DIOEasy using the shortcut (F10).

2. Initialize the driver for the board.

3. Load and run the RTCError.dio pattern
  • Change the vector from 'File' to 'Window' and click 'Execute'
  • After the pattern is loaded to the DIO, click 'Arm!', then click 'Trig!'
4. View the resultant pattern.
  • Change the vector from 'Load' to 'Show' and click 'Execute'
  • In the dialog box that pops up, select the option 'Load into New Window'

A result pattern will be loaded into DIOEasy.  Whenever discrepancies are found between the expected results and the actual results, the column containing the error will be shaded as shown below:

Digital IO Pattern Compare using DIOEasy

Masking / Unmasking:

If there is a channel or number of steps that you do not want to check for errors, the real time compare input mask can be used to enable/disable the compare engine.

1. Mask steps 0 through 15
  • Highlight steps 0 through 15.
  • From the menu bar, select Fill -> Real Time Compare Input Mask
  • Click Mask On
2. Run the Pattern using the GTDIO Panel

In the result pattern below, you can see that the error that was masked does not appear shaded because it was not analyzed.

Digital IO Pattern Compare using DIOEasy

Real Time Compare Error Logging Modes

When your DIO is operating in Real Time Compare mode, you can set stop conditions.  In DIOEasy, hit CTRL+R or use the menu bar to open the File-> Properties dialog window.  Click on the Real Time Compare tab.  By default, it is set up to not stop for any special condition.  By changing the 'Failures count:' to 10 and clicking Set, we indicate that the pattern should stop running if ten errors are encountered during execution.  You can use this properties window to set the DIO to stop execution if a certain data value is encountered or when the program counter reaches a specified value.

Digital IO Real Time Compare Settings

Proper Termination of High-Speed Digital Signals - Published on 4/16/2014

$
0
0
When interfacing to any digital logic source, it is important to provide quality signals to the device under test (DUT).  And the key to providing quality signals is to treat the interconnecting cables between the digital source and the digital receiver as a transmission line requiring proper termination.  This termination can take the form of impedance matching and Impedance bridging.

Impedance matching is the design practice of setting the input impedance (ZL) of an electrical load equal to the fixed output impedance (ZS) of the signal source to which it is connected, usually in order to maximize the power transfer and minimize reflections from the load1, while Impedance Bridging maximizes transfer of a voltage signal to the load2.  When the output impedance of a device is connected to the input impedance of another device, it is a bridging connection if the second device does not appreciably load the previous device2.

For many electrical systems, simple wires and cables are adequate connection schemes, but for high-speed digital signals, this is not the case.  The fast edge rates of these signals contain frequency components that are much faster that the data rate of the signals.  And it is edge speed, not data rate or clock frequency that is the critical parameter.  As the edge rate of the signal approaches the round-trip propagation delay of the signal through the cable, the cable begins to behave as a transmission line.  A good rule-of-thumb in determining the propagation delay of a cable is to use 1nS per foot cable length.  In figure 1, if the cable length (L) were 1 foot, then a digital signal with a 2nS edge rate would require that the cable be terminated with a load of Z ohms.

Unterminated Transmission Line
Figure 1 – Unterminated Transmission Line


There are many methods for terminating a transmission line.  While some use active components, like diodes, this article will focus on the more common method of using resistors.  For instance, a common TTL transmission environment is 100 ohms.  Impedances of 50-75 ohms are also used, but have a disadvantage that the termination resistors would place a large load on the digital driver.  This is best to avoid, especially for "weak" drive devices.  The simplest way to terminate a 100 ohm transmission line would be to place a resistor at the end or the cable (Figure 2) where RL is equal to Z Ohms.


Terminated Transmission Line
Figure 2 – Terminated Transmission Line


This termination scheme, while simple, places an added load on the driver.  In keeping with the above example, if the drive voltage were 5V, and RL is 100 ohms, then the termination load is 5Volts/100Ohms=50mA.  This is beyond what many TTL devices can accommodate.  One way to address this loading is to use a higher impedance cable.  Simply changing your transmission environment to 125 ohms would lower the termination loading to 40mA – still high, but lower than the previous example.  An advantage of this method of termination is the ability to handle multiple fanouts.  Each fanout stub would have their own termination resistors, but the fanout network would multiply the termination loading.

To address the loading drawback, parallel termination can be used.  Terminating the transmission line requires that the termination load be referenced to a power plane.  While the ground plane is typically considered the termination reference, the VCC power plane can also be used (Figure 3).  The resistors RPU (Pull-Up) and RPD (Pull-Down), while technically not in parallel, for the purposes of transmission line termination, are in parallel with each other.  The resulting termination value is calculated using Ohms Law:  RL=(RPU x RPD) / (RPU + RPD).  If Z were 125 ohms, then using RPU and RPD with values of 180 ohms and 390 ohms, respectively, would result in a Thévenin equivalent termination of 123 ohms.  The load on the driver, when outputting a 4V logic “1”, would only be around 10mA – well within the range of most TTL devices.

Parallel Termination
Figure 3 – Parallel Terminated Transmission Line


The GX5292 has 330/390 parallel termination built in and are user selectable in groups of eight channels using on-board relays.  This termination is intended to provide proper termination of UUT driven signals, but has minimal affect of signals driver by the GX5292.  The termination can be enabled programatically, or using the Group Termination controls on the DioEasy Panel's I/O Channel Settings tab.  The GX5055 and GX5960 also provide on-board termination, however, they are controlled per pin, and includes the ability to source and sink current.

DioEasy Panel
Figure 4 – DioEasy Panel - Group Termination Controls


A little overshoot is not harmful to your system.  In fact, many designs under-terminate a signal on purpose to achieve some overshoot and undershoot.  This guarantees a clean transition through the UUT input thresholds so you don't linger in the hysteresis range of the receiver.  It will also reduce termination loading further.  Under-termination produces some ringing in the signal at the receiver (figure 4), but so long as the negative "bounce" does not drop below the input-high threshold of your receiver (Vih), there is no negative affect.  As a general rule, if the ringing is not affecting your UUT's operation, then it may not be a problem and you can ignore it.  A 220/330 ohm termination network would provide 132 ohm termination; slightly under-terminating a 125 ohm transmission line and producing minor ringing on the signal.

Minor ringing
Figure 5 – Minor ringing in a digital signal


Digital signal are often part of a bi-directional bus, and it is typically a requirement that when a bi-directional line is tristated, the bus will “float” to a known level.  A 125 ohm termination resistor to ground or VCC will guarantee that a tristated bus would be pulled to ground or to VCC, respectively.  Parallel termination can allow a bus that is in an undriven state to float to a predetermined value.  For example, 180/390 ohm parallel termination will force a tristated signal to about 46% of VCC, or about 2.3V for VCC equal to 5V.

Source termination is an example of Impedance Bridging termination.  As mentioned previously, impedance bridging maximizes transfer of a voltage signal to the load.  Since most IC’s have a very high input impedance, large drive currents are not required to transmit a signal, so long as the voltage levels comply with the VIL and VIH parameters.  Source termination places a resistor in series with the driver, with the source resistance value (RS) equal to the characteristic impedance of the transmission line (Figure 5).  The resistor (RS Ohms), in series with the transmission line (Z Ohms) will appear as a voltage divider.  When RS Ohms equals Z Ohms, the instantaneous voltage on the transmission line will be 50% of the voltage provided by the driver.

Source Termination
Figure 6 – Impedance Bridging Source Termination


The 50% amplitude wave propagates down the transmission line until it sees the large mismatch at the unterminated receiver.  Source termination relies on the large mismatch to reflect 100% (ideally) of the signal back into the transmission line – in effect, instantly doubling the voltage at the receiver from 50% of the drive voltage to 100%.  Since there is very little power transferred to the receiver - remember, source termination is impedance bridging, not impedance matching, the voltage level remains nearly equal to the drive voltage.  The reflected wave propagates back down the transmission line, where the source termination resistor absorbs it.

There are a couple of caveats to using this termination scheme.  First, if you were to look at the signal on the transmission line side of the source termination resistor, you would see a very poor digital signal.  The signal would rise to 50% of the driver voltage, remain at this level for 2x the propagation delay of the cable (approximately 1nS/ft), and then complete the transition to 100% of the drive voltage, producing a stair-step transition.  However, we are not concerned with the signal integrity at the source.  The receiver sees a clean 100% signal transition, which is what is important in digital signal transmission.

The other disadvantage of source termination is that it works best for a single receiver.  Additional receivers on the bus will be unterminated stubs.  When the source terminated signal reaches a stub, the 50% amplitude signal is divided in half again, producing a 25% amplitude signal (assuming the stub matches the impedance of the transmission line).  Now the 100% reflection at the receiver produces a 50% amplitude transition (assuming a single stub), and the reflected wave when it reaches the transmission line will be split between propagating back down the transmission line, and propagating to the other stub.  With multiple receivers on a source terminated transmission line, instead of seeing clean transitions at the receiver, you get a transition with steps and added ringing caused by multiple reflections bouncing every which-way.  If the length of all of the stubs is very short, then the perturbations in the edge transitions will be minimal, and the signal quality might be adequate.  But with source termination, as the unterminated stub lengths increase, edge transition quality for all receivers decreases.

One final caution about using source termination.  Providing both source and load termination on the same signal, while resulting in a very reliable signal, will also limit the amplitude to half of what it would otherwise be.  As illustrated in figure 6, double termination creates a voltage divider at the receiver.  The current across RS and RL is equal, and assuming the values of RS and RL are equal, the voltage at the receiver is 50% of the source voltage, rather than the full source voltage.


Source Termination
Source Termination
Figure 7 – Double Terminated Signal


The voltage drop from double termination can be compensated for if the source driver has programmable outputs with a range at least double the desired logic level.  The GX528x and GX529x series digital instruments available from Geotest (excepth the GX5295) all have programmable output levels in the range of 0V to 3.6V.  The GX5295 has a programmable range of -2V to +7V and the GX5055 and GX5960 have programmable output levels in the range of –10V to +15V.

Terminating a Differential transmission line requires placing a resistor of the same value as the characteristic impedance of the cable, across the differential signals (figure 8).  The termination can be on either or both ends of the transmission line, depending on the application requirements.  Cables are generally rated for their characteristic impedance based on the type of cable.  For example, the GT95022 cable supplied with Geotest DIO instruments is a SCSI Fast cable, and as SCSI is a differential transmission standard, the cable impedance is specified as a differential Impedance of 124 ohms, ± 10 Ohms.  When used in a single-ended application, then the impedance is half the rated differential impedance.

Differential Termination
Figure 8 – Differential Termination


To facilitate easy connection of Geotest dynamic digital instruments, Geotest has optional breakout adapters, the GT95014 and GT95015, which provide 34 x 2 rows of male pins on a 0.1” spacing.  This is compatible with a 68-pin IDC type connector.  These adapters accommodate single-ended or differential signals, respectively, and provide sockets for termination resistors on the board.  Documentation for these adapters can be found here (DownloadGT95014**) and here (DownloadGT95015).

GT95014GT95015
Figure 9 - GT95014 & GT95015 Breakout Adapters


In summary, to guarantee good signal quality in a digital environment, it is important to understand when termination is required (as the edge speed of the signal transition approaches the round-trip delay time of the signal through the interface cable), the different methods of terminating a transmission line (source termination, single load termination and parallel load termination), and the advantages and disadvantages of each.

1. Wikipedia - http://en.wikipedia.org/wiki/Impedance_matching
2. Wikipedia - http://en.wikipedia.org/wiki/Impedance_bridging


Translating Waveform Generation Language Files (WGL) to Geotest DIO File Format - Published on 4/16/2014

$
0
0

Defining WGL

The Waveform Generation Language (WGL) is a data description language supported by Test Systems Strategies Inc.  A WGL file uses an ASCII representation of the digital waveform data, so can be edited using any text editor.  WGL is also an intermediate file format used by the semiconductor industry for converting digital test patterns from a logic simulator to tester hardware, and back again.

Test information is represented in a WGL file using a structured, free form language with small, specialized structural blocks contained within larger, more generalized blocks.  A full discussion of the WGL language and syntax is beyond the scope of this article, but can be found in the TDS Languages Guide, Version 2007.1, published by Test Systems Strategies, Inc.  The benefit of WGL is that any digital instrument or tester that is capable of reading or writing test patterns using the WGL language, has a link to any simulation tool that also supports WGL, either directly between the simulator and tester hardware, or indirectly through other translators or filters.

To illustrate the Geotest Digital I/O (DIO) WGL import filter, a DownloadSimple WGL file was manually generated.  Note, this is not a typical WGL file as many of the structural blocks are excluded for clarity.  But it does serve as a good primer into the WGL file structure and facilitates demonstrating the process for importing WGL files into the Geotest DIO format.

A Simple WGL File

Waveform Sample

  Signal
    Stim00   : input;
    Stim01   : input;
    Stim02   : input;
    Stim03   : input;
    Stim04   : input;
    Stim05   : input;
    Stim06   : input;
    Stim07   : input;
    Stim08   : input;
    Stim09   : input;
    Stim10   : input;
    Stim11   : input;
    Stim12   : input;
    Stim13   : input;
    Stim14   : input;
    Stim15   : input;
    Resp00   : output;
    Resp01   : output;
    Resp02   : output;
    Resp03   : output;
    Resp04   : output;
    Resp05   : output;
    Resp06   : output;
    Resp07   : output;
    Resp08   : output;
    Resp09   : output;
    Resp10   : output;
    Resp11   : output;
    Resp12   : output;
    Resp13   : output;
    Resp14   : output;
    Resp15   : output;
  End

  Timeplate Match_0 Period 100nS
    Stim00   := input[0pS:S];
    Stim01   := input[0pS:S];
    Stim02   := input[0pS:S];
    Stim03   := input[0pS:S];
    Stim04   := input[0pS:S];
    Stim05   := input[0pS:S];
    Stim06   := input[0pS:S];
    Stim07   := input[0pS:S];
    Stim08   := input[0pS:S];
    Stim09   := input[0pS:S];
    Stim10   := input[0pS:S];
    Stim11   := input[0pS:S];
    Stim12   := input[0pS:S];
    Stim13   := input[0pS:S];
    Stim14   := input[0pS:S];
    Stim15   := input[0pS:S];
    Resp00   := output[0pS:Q];
    Resp01   := output[0pS:Q];
    Resp02   := output[0pS:Q];
    Resp03   := output[0pS:Q];
    Resp04   := output[0pS:Q];
    Resp05   := output[0pS:Q];
    Resp06   := output[0pS:Q];
    Resp07   := output[0pS:Q];
    Resp08   := output[0pS:Q];
    Resp09   := output[0pS:Q];
    Resp10   := output[0pS:Q];
    Resp11   := output[0pS:Q];
    Resp12   := output[0pS:Q];
    Resp13   := output[0pS:Q];
    Resp14   := output[0pS:Q];
    Resp15   := output[0pS:Q];
  End

  Pattern Loopback (Stim00,Stim01,Stim02,Stim03,Stim04,Stim05,Stim06,Stim07,Stim08,Stim09,Stim10,
                    Stim11,Stim12,Stim13,Stim14,Stim15,Resp00,Resp01,Resp02,Resp03,Resp04,Resp05,
                    Resp06,Resp07,Resp08,Resp09,Resp10,Resp11,Resp12,Resp13,Resp14,Resp15)

    {Start Vectors}
    Loop 32
      Vector(+, Match_0) := [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0];
      Vector(+, Match_0) := [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0];
    End

    Repeat 4
      {End Vectors}
      Vector(+, Match_0) := [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0];
    End
  End
End


The keyword Waveform denotes the beginning of a waveform block called Sample.  Within the Waveform block are several sub-blocks; the first is a sub-block denoted by the keyword Signal.  This block defines the signal names and types.  The point of reference for the signal types is the UUT, meaning that all the Input signals (Stim Names) are input to the UUT, and all Output signals (Resp  signal names) are output from the UUT.  WGL defines other signal types that are not used in this example.

The Timeplate keyword defines the beginning of the block structure called Match_0, where signal timing is defined.  It also defines the period of the Match_0 timing set to be 100nS – a 10 MHz data rate.  All of the Stim signals are defined as being active at the beginning of the test cycle (0pS), and the driven data pattern will be substituted (:S) by the value in the signals associated bit position within Pattern block (discussed later).  All of the Resp signals are defined as being active at the beginning of the test cycle (0pS), and the compare data pattern will be substituted (:Q) by the value in the signals associated bit position within Pattern block.

The Pattern block called Loopback first defines the bit ordering for the subsequent data patterns.  The ordering is LSB first, so Stim00 is the LSB data position, and the drive state is be represented by the left-most bit value in the vector field.  Bit ordering continues with Resp15 being the MSB, with the compare state being represented by the right-most bit value in the vector field.

The Vector field defines the substitute I/O patterns for the :S and :Q signals defined in the Match_0 Timeplate, and stipulating the Match_0 timeplate specifies the timing parameters to use.  In WGL, each vector has the capability of using different timing parameters, although that is not the case in our simple example.  The data pattern for the Stimulus pins and Response pins is a Walking 1 pattern from the LSB word to the MSB word, providing a 16-bit loop back pattern (16 LSB Stimulus pins to 16 MSB Response pins).  The pattern is entered once, but looped 32 times, as denoted by the Loop keyword.  The final four vectors are a repeat of the last vector, which contains all 0’s for both the Stimulus and Response signals, as indicated by the Repeat keyword.

Each sub-block structure is terminated by the End keyword, and the text contained in the curly-braces {} indicated text labels that are included as labels in the resulting DIO file.

WGL can represent simple Stimulus/Record digital test patterns, as well as more complex Stimulus/Response patterns that incorporate Real-Time compare functionality.  Since several Geotest DIO products support both functions, this article will demonstrate importing the sample WGL file both ways.

Activating DIOEasy-FIT - WGL Import Toolkit

The Geotest WGL import utility is a licensed product of Geotest, Inc.  Once purchased, the File Import Translator license (FIT) can be activated by entering a unique license string for the system.  The license string is based on the Computer ID of the host system where the license will be installed, and can be found from DIOEasy by clicking on Help\About DIOEasy\Setup License, and selecting Setup License (see figure 1).

License Setup

Figure 1:  File Import Translator License Setup


The computer ID is the 10 digit code displayed at the bottom of the DIOEasy License Setup dialog - "XXXX YYYY ZZ" in figure 2.  To obtain the FIT license, open a Magic incident, request an FIT license, and provide the sales order number of your FIT purchase and the Computer ID.  You will receive a license that is unique to the system whose ID you provided.  Enter the license string in the "License String/File" text box and click on "OK".

Computer ID
Figure 2:  Computer ID Code


The Geotest WGL import utility is supported using DIOEasy, Geotest's interactive digital development tool set, and from GtDio32.dll API, a Dynamic Link Library of DIO software functions.  The full list of these DIO functions and their syntax and uses can be found in the "DioSoftwareProgRef.PDF" document.  This document is included with the GtDio.Exe driver installation package available from the Geotest web page:

http://www.geotestinc.com/Downloads.aspx?prodId=16&search=package

The DioFileImportWgl Function

One of the functions included in the GtDio32.Dll is DioFileImportWgl().  This function is an import utility for reading WGL formated digital test patterns and converting them into a Geotest DIO formatted file.  The file can be loaded to the instrument, opened for viewing and editing using DIOEasy, or opened under program control so digital pattern data can be accessed from within a test program.  The syntax for this function, and an example of it’s usage are provided below:

DioFileImportWgl (pszSourceWglFile, pszDestDioFile, nConversionMode, nBoardType, pdMaxFrequncy, pdwMaxSteps, pszError, nErrMaxLen, pnStatus)

Parameters:
NameTypeComments
pszSourceWglFilePCSTRSource file
pszDestDioFilePCSTRTarget DIO file name
nConversionModeSHORTConversion mode:
   0 DIO_FILE_WGL_TO_DIO: Standard DIO file.
   1 DIO_FILE_WGL_TO_DIO_RTC: Real Time Compare DIO file
nBoardTypeSHORTSets the target supported DIO board type:
   0x55 DIO_BOARD_TYPE_GX5055 – Gx5055 DIO board type.
   0x70 DIO_BOARD_TYPE_GX5290 - Gx5290 DIO board type.
   0x75 DIO_BOARD_TYPE_GX5290E - Gc5290 Express DIO board type.
   0x7A DIO_BOARD_TYPE_GX5295 - Gc5295 board type.
pdMaxFrequncyPDOUBLE 0 for the WGL importer to use the best vector clock frequency, otherwise overwrites the vector max frequency.
pdwMaxStepsPDWORDThe maximum number of steps to convert.
pszErrorPSTRBuffer to contain the returned error string.
nErrMaxLenSHORTSize of the buffer to contain the error string.
pnStatusPSHORTReturned status: 0 on success, negative number on failure.


Importing WGL In DIOEasy

To import a WGL file into a DIOEasy digital file, click on File from the menu bar, and select Import WGL File.  A dialog will pop up prompting you to select the source WGL file, and the destination DIO file (figure 3).  In addition to specifying the source and destinations files, you must also select the target DIO instrument from the drop-down list (see the nBoardType parameter above), and whether to use the default values for the test frequency (data rate) and file size.  When importing a WGL file, the import filter will determine the optimal timing to use based on the capabilities of the DIO instrument selected, and set the clock rate accordingly.

DIOEasy WGL Import Dialog
Figure 3:  DIOEasy WGL Import Dialog


One final selection is whether to translate the WGL patterns for stimulus/record operations with Post Process compare, or to translate the WGL patterns for Real-Time compare.  Real-Time compare has the advantage of performing a hardware comparison of the UUT response against a pre-loaded expected response.  Since the compare process is done in hardware, and at the speed the digital engine is operating at, pass/fail results are instantaneous, whereas, post-process compare requires software to read the recorded information from the DIO hardware, and compare each step against a reference file that contains the expected UUT response.  The WGL import filter supports both test methodologies, as do selected Geotest digital instruments.

Once the import process completes, a new DIO file is created and automatically loaded to DIOEasy.  The file can be viewed and edited, the same as any other DIO file, and the test file can be loaded to the DIO hardware for execution.  Figure 4 shows a portion of the translated Simple.WGL file.

Translated Simple.WGL Digital Test Patterns
Figure 4:  Translated Simple.WGL Digital Test Patterns


Timing Translation

A common concern when porting digital test from the simulation environment to hardware is how timing parameters are interpreted.  A simulator can generate process with picosecond timing resolution.  This is far beyond the capability of the actual hardware test system to implement.  The WGL import filter will try to fit the timing parameters into the capabilities of the hardware by adjusting the clock frequency to accommodate the minimum phase resolution between the signals.  This is done by dividing the WGL test cycle time by the minimum phase difference between the various signals.  For example, if you had a WGL file with a cycle time of 1uS (1 MHz data rate), but there was a setup parameter of 10nS between a clock and data channel, the importer would calculate a new data rate for the hardware that meets both criteria.  In this example, the digital hardware would run at 100 MHz, providing the 10nS phase resolution.  This translates to more digital test vectors loaded into the hardware than the native WGL file represents.  In this case, 1uS period / 10nS resolution results in 10:1 pattern depth on the digital tester.  So, if the WGL pattern file were initially 1M vectors, the pattern file loaded to the hardware would be 10M vectors.

In some cases, the simulated phase resolution exceeds the capability of the tester, so the WGL importer maintains a proportional relationship between the signals.  For example, assume the cycle time is 50nS and some of the channels in that cycle change on 5nS phases (200 MHz resolution).  The WGL importer determines that one WGL cycle will require ten DIO cycles (50nS period / 5nS resolution).  Assuming the hardware is the GX5292, the minimum  cycle timing for this instrument is 10nS (100 MHz maximum frequency), so the pattern data rate would be set to 100 MHz, but you would maintain the 10:1 pattern ratio to keep the phase relationships proportional to the original WGL pattern ( (50nS period / 5nS resolution) = (100nS period / 10nS resolution) ).

Capturing channels simultaneously with the GX2472 Digitizer - Published on 4/16/2014

$
0
0
The GX2472 is a dual differential channel, 14-bit digitizer offering a 70 MS/s ADC and 512K of memory.  Each of the GX2472's differential channels has its own amplifier, filters, ADC and capture memory allowing for simultaneous waveform capture.

The following procedure demonstrates how to achieve simultaneous digitization using psuedocode.  For more details, there are example projects at the end of the article.  For more information, refer to the Gx2472 User's Guide.

Procedure to Achieve Simultaneous Digitization

  • Setup channel parameters for each channel
  • Arm both channels for triggering
  • Wait for GX2472 to finish data capture
  • Read device memory

Breakdown of Procedure

Each channel saves its own parameters independently.  The first step is to setup each channel's parameters.  This is done by sequentially setting each channel to active, unlocking the channel to allow changes and configuring that channels parameters.  In the psuedocode below, both channel's parameters will be identical.

For ChannelNumber = 1 to 2
    SetActiveChannel(ChannelNumber)
    UnlockChannel()
    SetClockSource(...)
    SetRange(...)
    SetTriggerLevel(...)
    SetDCOffset(...)
Next


After parameters have been set, lock the channels to initiate a capture.  Each channel has it's own configurable trigger criteria.  After a channel is locked, it awaits a trigger to begin data capture.  Each channel has it's own trigger settings and can be connected to a different stimulus.  Therefore, it is possible for one channel to trigger and begin capture while the other channel does not trigger and simply remains in the armed state.  The psuedocode below demonstrates locking both channels to arm for triggering.

For ChannelNumber = 1 to 2
    SetActiveChannel(ChannelNumber)
    LockChannel() ! Locks access to the controller and allows channel to begin capture
Next


Now, the controller must wait for the channels to complete their data capture.  This is done by repeatedly checking the status of the GX2472 to see if both channels have completed.  A timeout condition should also exist in case one or both channels do not trigger and thereby never complete their data capture.  The pseudocode demonstrates such a loop:

Repeat
    GetTestStatus()
Until (TestComplete or TimeOut)


Finally, each channel must transfer its capture memory back to the controller.  Again, we must loop through each channel, reading the memory back sequentially.  The psuedocode below shows this:

For ChannelNumber = 1 to 2
    SetActiveChannel(ChannelNumber)
    UnlockChannel() ! Allows memory to be accessed by controller
    ReadADCResults(Array[ChannelNumber])
Next


Sample Projects and Examples

The sample projects below contain working code that sets both channels for capturing a 50,000 sample waveform:
  • ATEasy example can be downloaded Downloadhere.
  • Microsoft Visual C++ 2005 example can be downloaded Downloadhere.

Accessing ATEasy Internal Classes from other programming languages - Published on 4/16/2014

$
0
0
ATEasy has many documented methods for accessing externally developed code and software.  DLLs, ActiveX objects, and .NET classes can be imported.  Command line utilities, VIs, and scripts can be run from within the ATEasy environment.  Should the need arise, ATEasy code can be exported to be used by other development environments.  ATEasy projects can be compiled to DLLs which can be linked within other languages.  Parameters described in a DLL procedure that are defined as ATEasy basic data types (short, long, word, dword, etc.) are easily passed and cast as a native type in the calling language.  The article Comparing C/C++, C#, VB and ATEasy Basic Data Types can be used as a reference for setting compatible basic data types.  But, ATEasy Internal classes such as ATest, ATask, and ALog can require a bit more work.  This article details the process using C++ and C#.

IDispatch: Using the methods and properties of an ATEasy object

ATEasy objects and classes are ActiveX/COM objects. The COM IDispatch interface allows the programmer to access an object's property and method list at run-time.  ATEasy reserved objects such as Program, System, and Test can be passed out of ATEasy and used using the IDispatch interface.  The ATEasy object's members can subsequently be read and altered.

Example 1: Creating The DLL - C++

The DLL we are creating within Visual Studio will contain three exported functions:
  • ATEasyClassSet() : Set a value to the specified property of the referenced object.
  • ATEasyClassGet() : Get the value of the specified property of the referenced object.
  • ATEasyClassMethod() : Call a method of the referenced object.
The project created is a Win32 console application that will be compiled to DLL.  The project code was created in Microsoft Visual Studio 2005 and entitled IDispatchExample.  It is provided at the bottom of this article.The Microsoft knowledge base article How To Use Visual C++ to Access DocumentProperties with Automation details the automation of Excel operations using the IDispatch interface.  We will reuse the helper function Autowrap() included within that article.  The Autowrap() function ensures that your request is formatted properly and provides some user notification in case of an error while performing the get, set or call.  Each of the following three exported functions will make a call to Autowrap:

ATEasyClassSet(): Setting an object's property
//PURPOSE: Sets the specified value vtParam to the specified property, sProperty on the object pATEasyObject        

void WINAPI ATEasyClassSet(IDispatch *pATEasyObject, LPOLESTR sProperty, VARIANT vtParam)
{
   AutoWrap(DISPATCH_PROPERTYPUT, NULL, pATEasyObject, sProperty, 1, vtParam);
}


ATEasyClassGet(): Getting an object's property
//PURPOSE: Gets the value of the specified property, sProperty of the specified object pATEasyObject and returns it in the referenced variant pvtParam.

void WINAPI ATEasyClassGet(IDispatch *pATEasyObject, LPOLESTR sProperty, VARIANT *pvtParam)
{
   AutoWrap(DISPATCH_PROPERTYGET, pvtParam, pATEasyObject, sProperty, 0);
}


ATEasyClassMethod(): Calling an object's method
C supports calling functions with a variable number of arguments.  Autowrap() supports variable arguments because we will be utilizing objects which are undefined within the DLL.  The ATEasyClassMethod() function will take 4 variants as parameters and then check to see if each variant has been defined before calling Autowrap() (you can define it with more optional parameter in ATEasy if you use more than 4 arguments). It is assumed that if a variant is undefined within ATEasy, it will be passed to the DLL with the variant type VT_ERROR.

//PURPOSE: Executes the specified object pATEasyObject's method sMethod.  This method supports 0 to 4 parameters.        

void WINAPI ATEasyClassMethod(IDispatch *pATEasyObject, LPOLESTR sMethod, VARIANT vtParam1/*=VT_EMPTY*/, VARIANT vtParam2/*=VT_EMPTY*/, VARIANT vtParam3/*=VT_EMPTY*/, VARIANT vtParam4/*=VT_EMPTY*/)
{
    if (vtParam1.vt==VT_EMPTY)
         AutoWrap(DISPATCH_METHOD, NULL, pATEasyObject, sMethod, 0);
    else
        if (vtParam2.vt==VT_EMPTY)
            AutoWrap(DISPATCH_METHOD, NULL, pATEasyObject, sMethod, 1, vtParam1);
        else
             if (vtParam3.vt==VT_EMPTY)
                 AutoWrap(DISPATCH_METHOD, NULL, pATEasyObject, sMethod, 2,
                       vtParam2, vtParam1);
             else
                 if (vtParam4.vt==VT_EMPTY)
                     AutoWrap(DISPATCH_METHOD, NULL, pATEasyObject, sMethod, 3, vtParam3,
                           vtParam2, vtParam1);
                 else
                     AutoWrap(DISPATCH_METHOD, NULL, pATEasyObject, sMethod, 4, vtParam4,
                             vtParam3, vtParam2, vtParam1);
}


Testing the DLL with ATEasy - C++

Now that the DLL has been created, we can create an ATEasy application to test it.

The first step is to define the DLL in ATEasy.  The ATEasy Internal Class should be passed as a Val Object.  The property or method specifier should be a Val BString and the parameter data should Val or Var Variant, depending on whether you are sending or retrieve data.  I started by creating a new library within my program module called IDispatchExample and defining the DLL procedures as such:

Procedure ATEasyClassMethod(pATEasyObject, sMethod, vtParam1, vtParam2, vtParam3, vtParam4): Void
--------------------------------------------------------------------------------
   pATEasyObject: Val Object      !Specifies the ATEasy Object to access
   sMethod: Val BString           !Specifies the method to call
   vtParam1: [Val] Variant = VarEmpty ! Optional parameter 1
   vtParam2: [Val] Variant = VarEmpty ! Optional parameter 2
   vtParam3: [Val] Variant = VarEmpty ! Optional parameter 3
   vtParam4: [Val] Variant = VarEmpty ! Optional parameter 4

Procedure ATEasyClassGet(pATEasyObject, sProperty, pvtParam): Void
--------------------------------------------------------------------------------
   pATEasyObject: Val Object      !Specifies the ATEasy Object to access
   sProperty: Val BString         !Specifies the property to get the value of
   pvtParam: Var Variant          !The returned value

Procedure ATEasyClassSet(pATEasyObject, sProperty, vtParam): Void
--------------------------------------------------------------------------------
   pATEasyObject: Val Object      !Specifies the ATEasy Object to access
   sProperty: Val BString         !Specifies the property to set the value of
   vtParam: Val Variant           !The value to be set


For the ATEasyClassSet test, the TestResult is intentionally set outside the Min/Max bounds.  The ATEasyClassSet procedure is used to set the Min/Max bounds to 40 and 50.  We expect this test to PASS if the ATEasyClassSet procedure is working.

Test 1.1 : "Modified Test Properties"   ! ATEasyClassSet Test
-------------------------------------------------------------
Type = MinMax
Min = 5
Max = 5
{
   TestResult=42
   IDispatchExample.ATEasyClassSet(Test, "Max", 50)
   IDispatchExample.ATEasyClassSet(Test, "Min", 40)
}


For the ATEasyClassMethod test, the TestResult is set to 42 and the Min/Max bounds have been set to 40 and 50.  Within the test Test.Min and Test.Max have been used to set the Min and Max bounds to 5 and 10.  The procedure ATEasyClassMethod is used to call the Test Object's Reset method. This should return the Max/Min bounds to 40 and 50 and will cause this test to PASS.

Test 1.2 : "Reset Method Called"   ! ATEasyClassMethod Test
-------------------------------------------------------
Type = MinMax
Min = 40
Max = 50
{
   TestResult=42

   !Manually set the Test properties
   Test.Max=5
   Test.Min=10

   !Call reset method from DLL, returning Test Properties to design-time default
   IDispatchExample.ATEasyClassMethod(Test, "Reset")
}


The third test simply demonstrates the use of ATEasyClassMethod when a parameter has been provided.  In this implementation, up to four parameters can be included with a method call.  If this is working correctly, you should see the message "I am working!" appended to the end of this test.

Test 1.3 : "Log Append Called"  !ATEasyClassMethod w/ Param Test
----------------------------------------------------------------
Type = Other
{
   IDispatchExample.ATEasyClassMethod(Log, "Append", "\r\n///////////////////\r\n")
   IDispatchExample.ATEasyClassMethod(Log, "Append", "// I am working! //\r\n")
   IDispatchExample.ATEasyClassMethod(Log, "Append", "///////////////////\r\n")
   TestStatus=PASS
}


The fourth and final test retrieves the file location of the Log object natively and also uses ATEasyClassGet to retrieve the Log's FullName property externally.  The two values are compared and, if they match, the test will PASS.

Test 1.4 : "Get Log Properties" !ATEasyClassGet Test
----------------------------------------------------
Type = String
String = ""
{
   !Retrieve the application's file and path natively
   Test.String=Log.FullName

   !Retrieve the application's file and path using IDispatch
   IDispatchExample.ATEasyClassGet(Log, "FullName", varTest)
   TestResult=varTest
}


Example 2: Creating The DLL - C#

The DLL we are creating within Visual Studio will contain three exported functions:
  • ATEasyTestSetMinMax() : Set the min and max properties of the referenced object.
  • ATEasyTaskGetTestCount() : Get the value of the TestsCount property of the referenced object.
  • ATEasyLogClear() : Call the Clear() method of the referenced object.
The project created is a Console Application (.NET 3.5 framework) that will be compiled to DLL.  The project code was created in Microsoft Visual Studio 2008 and entitled ATEasyNetInterface.  Make sure that you set the output of this project to Class Library.  Change the default Class Name to Interface.  Finally, add references to "C:\Windows\System32\AteRt.dll" and "C:\Windows\System32\AteCtl.dll".  The project is provided at the bottom of this article.

ATEasyTestSetMinMax(): Sets a ATEasy test object's min and max properties
//PURPOSE: Sets the specified values iMin and iMax to the specified ATest object pExtObject        

public void ATEasyTestSetMinMax(ref Object pExtObject, int iMin, int iMax)
{
   AteRtLib.ATest ATEasyObject = (AteRtLib.ATest)pExtObject;
   ATEasyObject.Min = iMin;
   ATEasyObject.Max = iMax;
}


ATEasyTaskGetTestCount(): Getting an object's property
//PURPOSE: Gets the value of the TestsCount property from the specified ATask object pExtObject and returns it in the reference parameter iTestCount.

public void ATEasyTaskGetTestCount(ref Object pExtObject, ref int iTestCount)
{
    AteRtLib.ATask ATEasyObject = (AteRtLib.ATask)pExtObject;
    iTestCount = ATEasyObject.TestsCount;
}


ATEasyLogClear(): Clear the log of the specified ALog file
The Clear() method that is being demonstrated does not require any parameters be passed in.  When creating a method which requires one or more parameters, they will have to be passed in or hard-coded within this class.

//PURPOSE: Executes the specified ALog object pExtObject's Clear() method.

public void ATEasyLogClear(ref Object pExtObject)
{
    AteCtlLib.ALog ATEasyObject = (AteCtlLib.ALog)pExtObject;
    ATEasyObject.Clear();
}


Testing the DLL with ATEasy - C#

Now that the DLL has been created, we can create an ATEasy application to test it.

After creating the ATEasy Test Application, insert the .NET assembly that we just created (ATEasyNetInterface.dll) into the Program module.  Also, include the mscorlib assembly.  Then create these variables:

NetInterface: ATEasyNetInterface.Interface
varExtObj: Variant
obExtObj: mscorlib.NetObject
lTestCount: Long


For the first test, the Log clear() method is called, which causing the application and program header to be erased from the Test Log.

Test 1.1 : "Call Method"
--------------------------------------------------------------------------------
  Id = Call_Method
  Type = MinMax
{
  !Create instance of .NET class
  data=new ClassLibrary1.Class1()
  !Load Test object into variant
  varALog=Log
  !Load Test object variant into mscorlib.NetObject
  obALog=varALog
  !Send Test object to .Net DLL along with new properties
  data.ATEasyLogClear(obALog)
}


For the second test, the TestResult is set to 42 and the Min/Max bounds have been set to 0 and 10.  The call to ATEasyTestSetMinMax will return the Max/Min bounds to 40 and 50 and will cause this test to PASS.

Test 1.2 : "Set Properties"
--------------------------------------------------------------------------------
  Id = Set_Properties
  Type = MinMax
  Min = 0
  Max = 10
{
  !Set TestResult outside of the bound of the test so the test will fail if the Min/Max aren't changed
  TestResult=42
  !Create instance of .NET class
  data=new ClassLibrary1.Class1()
  !Load Test object into variant
  varATest=Test
  !Load Test object variant into mscorlib.NetObject
  obATest=varATest
  !Send Test object to .Net DLL along with new properties
  data.ATEasyTestSetMinMax(obATest, 40, 45)
}


The third test demonstrates the use of ATEasyTaskGetTestCount to retrieve a property of an ATEasy object.

Test 1.3 : "Get Property"
--------------------------------------------------------------------------------
  Id = Get_Property
  Type = Precise
  Value = 3
{
  !Create instance of .NET class
  data=new ClassLibrary1.Class1()
  !Load Test object into variant
  varATask=Task
  !Load Test object variant into mscorlib.NetObject
  obATask=varATask
  !Send Test object to .Net DLL along with new properties
  data.ATEasyTaskGetTestCount(obATask, lTestCount)
  TestResult=lTestCount
}

Applications

  • Integration of ATEasy and a scripting language.
  • Passing ATEasy objects out to be parsed externally.

Downloads

DownloadVS2005 C++ Project
DownloadATEasy Test Workspace for C++ DLL
DownloadVS2010 C# Project
DownloadATEasy Test Workspace for C# Assembly

Consume a web service in ATEasy - Published on 4/16/2014

$
0
0
In this article, we will be consuming the CDYNE free weather service.  We will be using the following resources:

Weather Service WIKI
Weather service Specification Sheet

Use WSDL.exe to generate the source code for the proxy class in one of the Visual Studio languages.

WSDL is a tool provided by Microsoft for the generation of Web Services proxy classes.  The help file for the tool is located here.

The weather service specification sheet provides us with a listing of functions and parameters as well as the location of the WSDL formatted files.  Type the following into your command prompt to generate the proxy class code in Visual Basic and save the output to "C:\Temp\myProxyClass.vb".

>WSDL /L:VB /O:C:\Temp\myProxyClass.vb HTTP://wsf.cdyne.com/WeatherWS/Weather.asmx?wsdl


Use Visual Studio to generate a .Net assembly from the source code.

Launch Visual Studio and create a class library project and import the code generated by WSDL.exe.  User Project | Add Reference to add System.Web.Services to your project.  Build the project and locate the compiled library.

DownloadDownload Visual Basic project

Import the .NET library into ATEasy.

Create a new ATEasy application and a new driver.  Rename the new driver to WeatherSvc.  Import the .NET library into the new driver.  For convenience, you can also move the DLL file into the ATEasy application directory.

Instantiate the proxy class with ATEasy.

Create a driver procedure GetWeather().  This procedure will allow us to retrieve the city, state and current temperature for the provided zip code.

Procedure GetWeather(zipcode, temperature, state, city): Void
--------------------------------------------------------------------------------
zipcode: Val BString
temperature: Var BString
state: Var BString
city: Var BString
WeatherReturn: WeatherProxyClass.WeatherReturn
weather: WeatherProxyClass.Weather
{
weather=new WeatherProxyClass.Weather()
WeatherReturn=weather.GetCityWeatherByZIP(zipcode)
city=WeatherReturn.City
state=WeatherReturn.State
temperature=WeatherReturn.Temperature
}


Create a command tree within your driver to link to this procedure.  Attach this procedure to the "Driver Get Weather" command.

To test this, create a series of variables and tests in the program module.

weatherCity: BString
weatherState: BString
weatherTemperature: BString


Task 1 : "Perform Weather Operations"
--------------------------------------------------------------------------------
Id = Perform_Weather_Operations

Test 1.1 : "Request information"
--------------------------------------------------------------------------------
Id = Request_information
Type = Other
{
WeatherSvc Get Weather("92614", weatherTemperature, weatherState, weatherCity)
}

Test 1.2 : "Check City"
--------------------------------------------------------------------------------
Id = Check_City
Type = String
String = "Irvine"
{
TestResult=weatherCity
}

Test 1.3 : "Check State"
--------------------------------------------------------------------------------
Id = Check_State
Type = String
String = "CA"
{
TestResult=weatherState
}

Test 1.4 : "Check Temp"
--------------------------------------------------------------------------------
Id = Check_Temp
Unit = "Fahrenheit"
Type = MinMax
Min = 30
Max = 120
{
TestResult=Val(weatherTemperature)
}


DownloadDownload ATEasy project

Semiconductor Continuity Test Using the GX5295 Digital IO w/ PMU - Published on 4/16/2014

$
0
0

Introduction

Prior to testing the functionality of a semiconductor device, it is often a requirement to verify the structural integrity of the device including connections from the tester to the device. DC Parametric Measurement Units (PMU's) which are used to perform dc characterization tests on a device by forcing a voltage and measuring a current, and by forcing a current and measuring a voltage.  This same PMU can be used to verify the integrity of connections between the UUT and tester.

This article focuses on how the the per-pin PMU capabilities of the GX5295 can be used to perform continuity and shorts / opens tests on the device under test. The test programs are written in ATEasy, although any modern programming language could be used. All screen captures are of the ATEasy application.  The tests described here can be conducted on a wide variety of devices, from semiconductor IC's to printed circuit boards, so the ATEasy application was written to allow easier migration to other devices.

Continuity Test

The first step in the test process, and the focus of this article, is to determine if the Device Under Test (DUT) is connected to the tester resources – in this case the GX5295 Digital IO (DIO).  This test is called a “Continuity” test, and it verifies continuity between the tester and DUT by detecting the ESD diode found on IC pins.  Tester-to-DUT continuity is measured by forcing a small current on to the DUT pins, and measuring for the presence or absence of a voltage.  This utilizes the Force Current, Measure Voltage (FIMV) capability of the GX5295’s PMU.  The ESD protection diode is a semiconductor device, and the voltage developed across it when a current flows is consistent with the voltage drop across a semiconductor junction.  If the ESD diode is not present, or in the case of continuity tests, if the tester is not connected to the DUT pin, current will not flow through the ESD diode and the voltage will be inconsistent with semiconductor junction voltage drops.  If the ESD diode is defective, then other voltage anomalies can be detected, such as “0” volts measured across an ESD diode in cases where the diode is shorted.

Pin Mapping

Before any test or measurement can be performed, you must define the system configuration.  An ATEasy "Command" was created that allows the test programmer to define the number of DUT's (Device Under Test) installed in the test fixture, and their pin counts.  For additional information about defining commands in ATEasy, refer to the ATEasy Help/Commands on-line documentation.  It is assumed that all of the DUT's are of the same type device.  The command specifys the number of DUT devices to test (nCount), and the number of pins per DUT (nPins), takes the form:

Dut Define Counts(nCount, nPins)

In order to force currents and measure voltages on DUT pins, it is necessary to define in software the connections between the tester resources and the DUT IO.  In this example, pin mapping is performed using another special command defined in ATEasy that will store the “Tester-Channel to DUT-Pin” correlation in a structured array.  The pin-map structure also holds the DUT pin name and pin type (Output, Input, IO, Vcc1:4 and Ground) - which is useful for providing information about the pins being tested.  When used, the “Dut Define PinMap” command specifies the DUT pin_type, the DUT pin_name, the DUT pin_number, and an array containing the DIO channel numbers channel_number.  An array is used for the DIO channel numbers to support mapping pins from multiple DUT devices to appropriate DIO channels.  The command takes the form:
Dut Define PinMap pin_type ("pin_name", pin_number, channel_number[])

The sample device used is an SN74HC273 octal latch in a 20-pin TSSOP package.  The commands for defining the number of DUT devices, the DUT pin count, and the DUT/DIO pin mapping are shown below.

Note:  The DIO channel array is defined in line with the pin mapping commands for clarity, but could be entered via oteher means, such as reading from a file or spreadsheet, or by entering the channel numbers from a dedicated GUI, to mention a few:

Dut Define Counts(1,20)

Dut.DioChannels={0}
Dut Define PinMap Input ("Clr-", 1, Dut.DioChannels)
Dut.DioChannels={1}
Dut Define PinMap Output ("Q1"  , 2, Dut.DioChannels)
Dut.DioChannels={2}
Dut Define PinMap Input ("D1"  , 3, Dut.DioChannels)
Dut.DioChannels={7}
Dut Define PinMap Input ("D2"  , 4, Dut.DioChannels)
Dut.DioChannels={4}
Dut Define PinMap Output ("Q2"  , 5, Dut.DioChannels)
Dut.DioChannels={5}
Dut Define PinMap Output ("Q3"  , 6, Dut.DioChannels)
Dut.DioChannels={6}
Dut Define PinMap Input ("D3"  , 7, Dut.DioChannels)
Dut.DioChannels={3}
Dut Define PinMap Input ("D4"  , 8, Dut.DioChannels)
Dut.DioChannels={8}
Dut Define PinMap Output ("Q4"  , 9, Dut.DioChannels)
Dut.DioChannels={-1}
Dut Define PinMap Ground ("Gnd" ,10, Dut.DioChannels)
Dut.DioChannels={17}
Dut Define PinMap Input  ("Clk+",11, Dut.DioChannels)
Dut.DioChannels={15}
Dut Define PinMap Output ("Q5"  ,12, Dut.DioChannels)
Dut.DioChannels={10}
Dut Define PinMap Input  ("D5"  ,13, Dut.DioChannels)
Dut.DioChannels={13}
Dut Define PinMap Input  ("D6"  ,14, Dut.DioChannels)
Dut.DioChannels={12}
Dut Define PinMap Output ("Q6"  ,15, Dut.DioChannels)
Dut.DioChannels={11}
Dut Define PinMap Output ("Q7"  ,16, Dut.DioChannels)
Dut.DioChannels={14}
Dut Define PinMap Input  ("D7"  ,17, Dut.DioChannels)
Dut.DioChannels={9}
Dut Define PinMap Input  ("D8"  ,18, Dut.DioChannels)
Dut.DioChannels={16}
Dut Define PinMap Output ("Q8"  ,19, Dut.DioChannels)
Dut.DioChannels={1000}
Dut Define PinMap Vcc1   ("Vcc" ,20, Dut.DioChannels)


Note:  Two special pin mapping parameters need to be mentioned.  First, the "-1" DIO channel specified for the DUT "Gnd" signal indicates that this DUT pin is not mapped to any DIO channel.  In this case, this is due to the layout of the DUT load board, which connected the DUT Gnd pin to a ground plane, rather than a DIO channel.  Second, specifying DIO channel "1000" for the DUT "+5V" Vcc pin means the Vcc pin is connected to one of the four auxilliary IO pins on the GX5295.  These "Aux" channels are mapped to DIO channels starting at 1000.  Specifying DIO channel 1000 as the DUT Vcc input means that the GX5295 AUX 0 channel will be supplying the Vcc voltage for the DUT.

Continuity Measurement

To test for continuity, another ATEasy command has been defined.  This command accepts the DUT number and the DUT pin.  The DUT pin is a type Variant and can accept the DUT name, as defined by the pin mapping command, the DUT pin number as a text parameter, or the DUT pin number as a numeric parameter.  Two other parameters are passed by reference (pointer) and return the DUT pin number and DUT pin name associated with the DUT pin Variant.  The command returns a type Double voltage measurement for the specified pin after a small negative current is first applied to the pin.  The command takes the form:
dMeasurement = Dut PMU Measure Continuity (nDutNumber, varDutPin, pnDutPin, psDutPin)

As an object oriented programming language, ATEasy allow a unique name for each test defined in it’s Task/Test structure (see ATEasy Help/Test).  The test name is accessible as a text string at run-time using the "Test" object variable and the “Name” property, as shown below:
string = Test.Name

This simplifies the overall test program to simply calling the Dut PMU Measure Continuity() command using Test.Name, and defining the Test.Name to be either the DUT pin name, or the DUT pin number.  The example below measures continuity on the DUT pin defined by the test name, and using ATEasy’s internally defined TestResult variable to store the continuity measurement.  The continuity measurements can all be invoked the same for each test:
TestResult=Dut PMU Measure Continuity (1, Test.Name, pnDutPin, psDutPin)

An example of the ATEasy Task/Test structure is shown in figure 1 below.  Notice that each test name is unique and the same as the names used in the pin mapping commands from above.  Notice also that each test provides the minimum and maximum voltages for determining the Pass/Fail status of the continuity test (Min/Max parameters are visible just above the highlighted command).  ATEasy will automatically evaluate the measurement returned to TestResult against the Min/Max parameters to determine the Pass/Fail status of each continuity measurement, and will automatically report the results of the evaluation to the Test Log (standard output) or Test Executive (ATEasy’s Test Management driver utility).

Continuity Tests
Figure 1:  Continuity Task/Test Structure and Test Command


The Test PMU Measure Command is attached to a procedure call where the continuity measurement occurs.  The procedure, TestContinuity, is located in a driver called DUT, as are the commands discussed in this article.  The procedure calls another procedure, _GetPinInfo, which searches the structure array for the name or number of the DUT Variant pin passed in by the command, and when found, extracts the DUT pin number and DIO channel number associated with that pin.  The code for _GetPinInfo is shown below:

Procedure _GetPinInfo(nDutNumber, varDutPin, nDioPin, pnDutPin, psDutPin): Void
--------------------------------------------------------------------------------
nDutNumber: Val Short          !DUT device number
varDutPin: Val Variant         !DUT Pin ("Name", "Number" or valNumber)
nDioPin: Var Short             !DIO Channel number
pnDutPin: Var Short            !Returned DUT pin number
psDutPin: Var String           !Returned DUT pin name
nHandle: Short                 !DIO handle
iPin: Long                     !Pin index counter

{
! Get the DIO session handle
   Dio Get MasterHandle(nHandle)

   If VarType(varDutPin)=vtBstr
   ! The procedure searches the structure array for the "name"
   ! or "number" of the DUT pin passed in by the command,...
      For iPin=0 to m_nDutCount[1]-1
         !  and when "name" is found...
         If LCase(m_astDomain[nDutNumber-1,iPin].Name)=LCase(varDutPin)
            ! the DUT pin number is saved, ...
            pnDutPin=iPin+1
            ! the DUT pin name is saved, ...
            psDutPin=m_astDomain[nDutNumber-1,iPin].Name
            ! the DIO channel number is used for the measurement process
            nDioPin=m_astDomain[nDutNumber-1,iPin].DIO
            ExitLoop ! exit the loop
         ! or when "number" is found...
         ElseIf Val(varDutPin)=(iPin+1)
            ! the DUT pin number is saved, ...
            pnDutPin=iPin+1
            ! the DUT pin name is saved, ...
            psDutPin=m_astDomain[nDutNumber-1,iPin].Name
            ! the DIO channel number is used for the measurement process
            nDioPin=m_astDomain[nDutNumber-1,iPin].DIO
            ExitLoop ! exit the loop
         EndIf
      Next

      ! If the DUT pin "name/number" was not found...
      If iPin=m_nDutCount[1]
         ! generate an error exception and return
         Error 1,"DUT pin name/number \""+varDutPin+"\" not found"
         Return
      EndIf
   Else
      pnDutPin=varDutPin
      ! If the DUT pin number exceeds it's limits...
      If pnDutPin<1 or pnDutPin>m_nDutCount[1]
         ! generate an error exception and return
         Error 1,"DUT pin number "+Str(pnDutPin)+" invalid"
         Return
      EndIf

      ! The DUT pin name is saved, and ...
      psDutPin=m_astDomain[nDutNumber-1,pnDutPin-1].Name
      ! the DIO channel number is used for the measurement process
      nDioPin=m_astDomain[nDutNumber-1,pnDutPin-1].DIO
   EndIf
}


The DIO channel number returned by _GetPinInfo is used for the continuity measurement.  The DIO channel is placed in the Force Current mode and the commutating voltages (voltage clamps) of +5V and -2V are applied to the DIO channel to keep the DUT pin voltage to a level that is safe for the DUT.  A small negative current (-0.5mA) is applied to the DIO channel, and the resulting voltage is measured.  Once the measurement is complete, the DIO channel is returned to dynamic mode (default) and the measured voltage is returned to the calling command.  The full ATEasy algorithm is shown below:

Procedure TestContinuity(nDutNumber, varDutPin, pnDutPin, psDutPin): Double
--------------------------------------------------------------------------------
nDutNumber: Val Short          !DUT device number
varDutPin: Val Variant         !DUT Pin ("Name", "Number" or valNumber)
pnDutPin: Var Short            !Returned DUT pin number
psDutPin: Var String           !Returned DUT pin name
nDioPin: Short                 !DIO Channel number
dContinuity: Double            !Continuity voltage measurement
nHandle: Short                 !DIO handle
{
! Get the DIO session handle
Dio Get MasterHandle(nHandle)

_GetPinInfo(nDutNumber,varDutPin,nDioPin,pnDutPin,psDutPin)

! The DIO channel is placed in the Force Current mode and...
Dio Setup Channels Mode PmuForceCurrentMode RangeOfChannels(nHandle,nDioPin,nDioPin)
! commutating voltages (voltage clamps) of +5V and -2V are defined
Dio Setup Channels PMU ForcedCurrentCommutatingVoltage RangeOfChannels(nHandle,nDioPin,nDioPin,5.0,-2.0)
! A small negative current (-0.5mA) is applied to the DIO channel, and...
Dio Setup Channels PMU ForceCurrent RangeOfChannels(nHandle,nDioPin,nDioPin,-0.5,aPmuCurrentRange_n2ma_to_p2ma)

! the resulting voltage is measured
Dio Measure PmuVoltage(nHandle,nDioPin,dContinuity,250)

! The DIO channel is returned to dynamic (default) mode and...
Dio Setup Channels Mode DynamicIo RangeOfChannels(nHandle,nDioPin,nDioPin)

!  the measured voltage is returned to the calling command

Return dContinuity
}


Results

ATEasy automatically evaluates the measurement returned to TestResult against the test’s Min/Max parameters to determine the Pass/Fail status of each continuity measurement, and reports the results of the evaluation to the Test Log (standard output) or Test Executive (ATEasy’s Test Management driver utility).  Figure 2 shows the Test Executive output with a DUT open continuity failure for pin 2, and a DUT short continuity failure for pin 9.

Test Executive Output with Failures
Figure 2:  ATEasy Test Executive Output with DUT continuity Failures


The ATEasy project files for this article can be downloaded Downloadhere.

How to Display an Animated GIF File in an ATEasy Form - Published on 4/16/2014

$
0
0
In ATEasy form's, animated GIF files are supported by the ALog control. To display an animated GIF in a log control, set the control to HTML mode (PlainText property set to False), and then append an image tag with the GIF file.
The image file is defined using the HTML IMG tag and can then be inserted into the ALog control using the Append method.

The height and width of the image can be specified using the height and width attributes.
For example, the following line links the image to the "C:\geotest.gif" file and sets the image height and width to 42.

  


The image is then appended to the ALog control using the Append control as follows:

  log1.Append("")


To hide the ALog's scrollbar, which is displayed by default, insert the following into ALog's OnLoad event:

  log1.Document.body.setAttribute("scroll", "no")


The image can be positioned in the ALog control by setting the ALog control margins. For example, inserting the following settings into AForm's OnLoad event will align the image in the Top-Left corner of ALog control :

  log1.Document.Body.LeftMargin=0
  log1.Document.Body.TopMargin=0


Here is the complete code for displaying the animated GIF in a log control:

  ! set the ALog Window to HTML mode to display the animated image file
  logAnimated.PlainText=False
  ! remove the Scroll bar
  logAnimated.Document.body.setAttribute("scroll", "no")
  ! position the image in the Top-Left corner of the ALog control
  logAnimated.Document.Body.LeftMargin=0                
  logAnimated.Document.Body.TopMargin=0                
  ! get the dimensions of the ALog control for the image height and width settings
  fHeight=logAnimated.Height-4
  fWidth=logAnimated.Width-4
  ! place the image in the ALog window
  sText=""
  logAnimated.Append(sText)


An ATEasy application that demonstrates how to load an animated GIF file into a form can be downloaded by clicking on this link DownloadQ200225.zip. The application opens a window that displays a spinning hourglass. The main section of code can be found in the OnLoad event for the program form.

Programming I/O Width on the GX5290 Series - Published on 4/16/2014

$
0
0
The GX5290 series of DIO cards have a programmable I/O width feature that allows the user to trade I/O channel width for vector memory depth. The GX5292, GX5292e, GX5293 and GX5295 cards each offer 256MB of vector memory and the GX5291 offers 128MB of vector memory. Under software control, the vector memory can be configured to support channel widths shown in the table below.
Vector Width
GX5292/GX5292e/GX5293/GX5295 Vector Depth
GX5291 Vector Depth
Corresponding DIO Channels
32 Ch
64Mbit/Ch
32Mbit/Ch
Ch0-31
16 Ch
128Mbit/ch
64Mbit/ch
Ch0-15
8 Ch
256Mbit/ch
128Mbit/ch
Ch0-7
4 Ch
512Mbit/ch
256Mbit/ch
Ch0-3
2 Ch
1Gbit/ch
512Mbit/ch
Ch0-1
1 Ch
2Gbit/ch
1Gbit/ch
Ch0


Additional information on this subject can be found in the GTDIO Programmers Reference Manual under the DIOWriteOutMemory() and DIOWriteDirectionMemory() functions.

Configuring DIO cards for vector widths of 4, 2 or 1

To utilize all of the vector memory when using vector widths of 4, 2 or 1 channel(s), the vector data needs to be packed into a DWORD array (32-bit boundary) before it can be transmitted. The vector data is packed into the DWORD array starting at the LSB of the first DWORD array element. For example, a vector array with the following 32 4-bit hexadecimal values starting at element 0  as shown here in this ATEasy example:

0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F,0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F

will be packed into the DWORD array called adwTxData[] starting at element 0, as follows:

adwTxData[0] = 0x76543210
adwTxData[1] = 0xFEDCBA98
adwTxData[2] = 0x76543210
adwTxData[3] = 0xFEDCBA98

From the above example, it is clear that the packing process is very straightforward and utilizes all available vector memory. To perform the packing function the programmer can use either the GX529x driver DioDataPack() function or can write a custom function to pack the data. Direction control information will also need to be packed into a DWORD array in the same way as the transmit data array. It is important to note that when writing the DWORD array to the DIO cards Output Memory (DioWriteOutMemory()) or to the Direction Control Memory (DioWriteDirectionMemory()) that the dwSize parameter is the number of vectors to transmit not the number of elements in the DWORD array. For example, using the data from the above array the DioWriteOutMemory() and DioWriteDirectionMemory() functions will be as follows:

DioWriteOutMemory(nMasterHandle,adwTxData,0, 32, nStatus)
DioWriteDirectionMemory(nMasterHandle, adwDirCtrl, 0, 32, nStatus)

Notice the dwSize parameter is 32 not 4.

Note: If the DIO card is receiving data, this data will be stored in the receive memory in a packed format in the same way the transmit data is packed above. To analyze the received data it can be unpacked from the DWORD format to its original width using the DioDataUnpack() function.

Configuring the DIO cards for vector widths of 8 and 16 channels

When using vector widths of 8 and 16 channels the transmit data and direction control data does not need to be packed as this process is done automatically by the DioWriteOutMemory() and DioWriteDirectionMemory() functions. The only requirements for using these widths are:
1) When using a vector width of 8 channels the vector data must be in a BYTE array and
2) When using a vector width of 16 channels the vector data must be in a WORD (16-bit) array.

Below are two examples showing how the data can be packed. Example 1 uses the DioDataPack() function and Example 2 uses standard compiler shift commands.  

Example 1: Transmit a number of 4-bit elements previously stored in BYTE array called aucFileData[]. The number of elements to transmit is indicated by dwFileSize. This example assumes that the vector data is stored as one 4-bit vector per array element.

To pack the 4-bit data, 8 elements at a time are transferred to a temporary BYTE array (aucTemp[]) and then the DioDataPack() function is used to write the data to each element of the adwTxData[] DWORD array.

!Pack the 4-bit data into adwTxData[] (a DWORD (32-bit) array)
k=0
for i=0 to dwFileSize-1
   !Transfer 8 4-bit elements to be packed into a temporary array aucTemp[]
   for j=0 to 7 do
       aucTemp[j] = aucFileData[i]
        i=i+1
   next
  !Now pack the lower 4 bits of the first eight elements of the aucTemp[] array
  !into the adwTxData[] array starting at location 0. This is the data to be transmitted.
  DioDataPack(4, 8, 0, 1, adwTxData[k], aucTemp, nStatus)
  k=k+1
  !Undo the last increment from the above For {j} loop because For {i} loop will also increment i
  i=i-1
next

!Write the adwTxData array to the Output memory. Remember the dwSize parameter is the
!number of vectors to be transmitted not the number of elements in the adwTxData array.
DioWriteOutMemory(nMasterHandle,adwTxData,0, dwFileSize,nStatus)


Example 2: Transmit a number of n-bit wide elements (where n=4,2 or 1) previously stored in BYTE array called aucFileData[]. The number of elements to transmit is indicated by dwFileSize. This ATEasy example assumes that the vector data is stored as one vector per array element.

This example is written using standard compiler shift commands instead of using the DioDataPack() function. It uses the ATEasy GX529x driver commands but also expands on the above example by working with vector widths of 4, 2 or 1. First, the DIO instrument I/O configuration is read and based on the channel width value (nChWidth), the data mask (nMask) and number of channels (nNumCh) variables are assigned appropiate values. nMask is used to mask the unwanted vector data bits in each aucFileData[] array element and nNumCh is used to shift the data during the packing process.  

!Get the DIO I/O Configuration information
DIO Get IOConfiguration(nMasterHandle, nChWidth, nDir)

!Set the nMask and nNumCh variables depending on the channel width
select nChWidth
  Case aChannelsWidth4  !Using a vector width of 4 Channels
      nMask = 0x0f  !Mask out upper 4 bits. In this example data is in lower 4 bits
      nNumCh = 4    !Number of DIO channels. Used to shift data for packing purposes
  Case aChannelsWidth2  !Using a vector width of 2 Channels
     nMask = 0x03   !Mask out upper 6 bits. Data is in the lower 2 bits
     nNumCh = 2     !Number of DIO channels. Used to shift data for packing purposes
  Case aChannelsWidth1  !Using a vector width of 1 Channel
     nMask = 0x01   !Mask out upper 7 bits. Data is in the LSB
     nNumCh = 1     !Number of DIO channels.
endselect

!Now pack the vector data into DWORD (32-bit) array called adwTxData[]
i=0  !Used to count through the vector data array dwFileData[]
k=0  !Used to count through the adwTxData[] as data gets packed
while i < dwFileSize
    j=0
    !Pack aucFileData[] elements into 32bit boundaries
    while j<(32 div nNumCh) and i < dwFileSize
      adwTxData[k]=adwTxData[k] or ((aucFileData[i] and nMask) shl (j*nNumCh))
      i=i+1 !Increment aucFileData[] counter
      j=j+1 !Increment while loop counter
    endwhile
    k=k+1   !Increment adwTxData[] counter
endwhile

!Write the adwTxData array to the Output memory. Remember the dwSize parameter is the
!number of vectors to be transmitted (dwFileSize) not the number of elements in the
!adwTxData array.
DIO Write Memory Out (nMasterHandle,adwTxData,0,dwFileSize)


Program examples

An ATEasy application that demonstrates how to setup a GX5295 DIO card for various vector widths can be downloaded by clicking on this link DownloadQ200226.zip. The application has three tests
  • InitializeDIO. This initializes the GX5295.
  • 4ChWidthDLL: This is example 1 above. This uses the GTDIO DLL commands to setup the card for a 4 channel vector width and to transmit a clock pattern on all four channels.
  • nChWidthATEasy: This is example 2 above. It uses the GX5295 ATEasy commands to setup the card for a 4 channel vector width and to transmit a clock pattern on all four channels. To change the configuration to output on two channels or only one channel, replace the aChannelsWidth4 parameter value in the configuration setup line
DIO Setup IOConfiguration(nMasterHandle,aChannelsWidth4, 0x0)

with aChannelsWidth2 for a two channel vector width or to aChannelsWidth1 for a single channel vector width.

Using Excel File to Load Test Parameters to an ATEasy Program - Published on 4/16/2014

$
0
0
The article show how to read Microsoft Excel file that has test parameters such as min, max values and to modify the program tests requirements dynamically.

The example reads a Microsoft  Excel file and store the new parameters in the program test objects. Each row in the Excel file contains the test id (test to read the parameters to) , test min, test max and additional extra parameter that is loaded to the ATest.Tag property (access from the test using test.tag).

Excel Spreasheet with ATEasy Test Parameters


Using the Example

The code to read the Excel file and apply the parameters reside in the ExcelTestParameters.drv driver and it uses the ATEasy EXCEL driver. To use the driver:
1. Insert the ExcelTestParameters.drv to your system
2. Insert the Excel.drv to your system
3. To load the parameters to your program use the following code:

if not EXCELTESTS ReadTestParametersFile("C:\\ExcelTestParameters.xlsx", "Sheet1")
    abort
endif


this code typically can reside in Program.OnInit event.

Example Code

The  ExcelTestParameters.drv export one command / procedure that is used to load the parameters:

Procedure ReadExcelTestParametersFile(sFile, sSheet): Bool
--------------------------------------------------------------------------------
    sFile: Val String
    sSheet: [Val] String = "Sheet1"
    xlwb: Excel.Workbook
    xls: Excel.Worksheet
    vrA: Variant
    vrB: Variant
    vrC: Variant
    vrD: Variant
    iRow: Long
    sRow: String
{
    EXCEL Initialize()
    ! open excel file
    try
        EXCEL File Open Existing(, sFile, xlwb)
    catch else
    endtry
    if not xlwb
        MsgBox("Unable to open Excel Workbook File: '"+sFile+"'")
        EXCEL Quit()
        return False
    endif

    ! verify the worksheet exist and get the object
    try
        xls=xlwb.Sheets.Item(sSheet)
    catch else
        MsgBox("Bad Excel Worksheet: '"+sSheet+"' found in File: '"+sFile+"'")
        EXCEL File Close(xlwb, False)
        EXCEL Quit()
        return False
    endtry

    ! read row B to empty row
    ! each row has columns: 1=testid, 2=min, 3=max, 4=parameters
    for iRow=2 to 9999
        sRow=str(iRow)
        EXCEL Get Value(xlwb, sSheet, "A"+sRow, vrA)
        if vrA=""
            exitloop ! last test
        endif

        EXCEL Get Value(xlwb, sSheet, "B"+sRow, vrB)
        EXCEL Get Value(xlwb, sSheet, "C"+sRow, vrC)
        EXCEL Get Value(xlwb, sSheet, "D"+sRow, vrD)
        try
            Program.Tests(vrA).Min=vrB
            Program.Tests(vrA).Max=vrC
            Program.Tests(vrA).Tag=vrD ! extra parameters
        catch else
            MsgBox("Bad Test ID: '"+vrA+"' found in Row: '"+sRow+"', in File: '"+sFile+"', Sheet: '"+sSheet+"'")
            EXCEL File Close(xlwb, False)
            EXCEL Quit()
            return False
        endtry
    next

    EXCEL File Close(xlwb, False)
    EXCEL Quit()
    return True
}


Running the Example

Running the example will open the ATEasy Test Executive with the new test parameters as specified in the spreadsheet:

Excel Spreadsheet with ATEasy Test Parameters Test Log


How to Improve the Example

1. Use the program name as the sheet name, every sheet in the workbook can be used for one program.
2. Add support for other test type. Once the test was located the routine can check the test type and load parameters accordingly
3. You can use the testid also for sequencing (similar to the profile driver)

Example Files

DownloadDownload ATEasy ExeclTestParametrs project files

Calling Agilent VEE UserFunctions from ATEasy - Published on 4/16/2014

$
0
0
Installing Agilent VEE will allow the installation of an ActiveX automation server that can be used to run UserFunction from environments other than the VEE development environment, such as ATEasy and Visual Studio.  An ATEasy driver (VEE.drv) has been created as a wrapper providing an interoperability tool that can perform the majority of the overhead associated with starting and communicating with the VEE Run-time.  This allows you to reuse existing test application code in ATEasy projects with the addition of only a few lines of code.

Example VEE library

For example, we have “VEE_ATEasyExample.vee” which contains three UserFunctions:
  • AddTwo: Adds two numbers and outputs the sum (a+b=result)
  • ExpTwo: Outputs the first input raised to the power of the second input (a^b=result)
  • MultiplyTwo: Multiplies two numbers and outputs the product (a*b=result)
Screenshot of VEE Project Navigator

Image 1: VEE Project Navigator


Flow of data

To call a VEE function from ATEasy, you would implement the following prototype:
VEE Call (sLibFile, sUserFunction, inputs, outputs)

The sLibFile defines the .VEE file that contains the target UserFunction, sUserFunction specifies the VEE function that will be executed, and the inputs and outputs represent the input and output terminals as arrays of variants.

Flow of data between ATEasy and VEE

Image 2: Flow of data between ATEasy and VEE

Example Code

The following code will pass the integers 3 and 5 to the AddTwo function in the VEE_ATEasyExample.vee and should assign the value {8} back to the outputs variable.

sLibFile : String   ! Contains the path to the VEE file
sUserFunction : String   ! Contains the name of the VEE UserFunction
avrInputs : Variant[2]   ! The input parameters, where 2 is the number of parameters passed to the VEE function
vrOutputs : Variant      ! The returned output parameters array stored to a variant

sLibFile=GetDir(0)+"\\VEE_ATEasyExample.vee" ! vee in current directory
sUserFunction="AddTwo"   ! VEE function name
avrInputs={3,5}          ! input parameters
VEE Call(sLibFile, sUserFunction, aVarInputs, vrOutputs)
TestResult=vrOutputs[0]  ! store returned value

ATEasy Project and Example

DownloadATEasy and VEE Example

Using MATLAB from ATEasy - Published on 4/16/2014

$
0
0
Installing MathWorks MATLAB® will also install an ActiveX control “Matlab Application Type Library” that can be used to write and retrieve variables from environments other than the MATLAB command window, such as ATEasy.  An ATEasy driver (MATLAB.drv) has been created as a wrapper for this interoperability tool to perform the majority of the overhead of starting and communicating with the MATLAB utility.  This allows you to reuse existing test application code in ATEasy projects with only a few lines of code.

Manipulating the MATLAB Command Window

Upon launching the ATEasy, the MATLAB driver will open a MATLAB command window that will open and run in the background until the termination of the ATEasy Application.  If your project requires direct interaction with the command window, there are two ATEasy commands for command window manipulation:
MATLAB Window Maximize(): Maximizes command window and brings it to the front.
MATLAB Window Minimize(): Minimizes the command window.


Send Instructions to the MATLAB Command Window

Text-based instructions can be sent to the MATLAB window from ATEasy using the Execute command.  
MATLAB Execute (sCommand, psResponse)

Where sCommand is the string sent to the MATLAB window and psResponse is MATLAB’s response.
For instance, the following code in MATLAB:
>> a=1

a =
     1

>> b=3*a

b =
     3

Can be executed in ATEasy with the following commands:
MATLAB Execute(“a=1”, sResponse1)
MATLAB Execute(“b=3*a”, sResponse2)

Example Code

The following code with pass the integers 3 and 5 to the ExpTwo function in ExpTwo.m and return back the value to the TestResult variable.
dwLength : DWord ! The length of the directory string name
sCommand : String ! The command that is sent to the command window
s : String ! The response from the command window

dwLength=GetShortPathNameA(GetDir(0), NULL, 0)
dwLength=GetShortPathNameA(GetDir(0), sCommand, dwLength)   ! HPVEE requires  short file names 8.3 use Windows API to retrieve it
sCommand="cd "+sCommand
MATLAB Execute(sCommand, s)
sCommand="result=ExpTwo(3,5)"
MATLAB Execute(sCommand, s)
MATLAB Get Variable("result", TestResult)

ATEasy Project and Example

DownloadATEasy and MATLAB Example

Using an XML File to Load Test Parameters to an ATEasy Program - Published on 4/16/2014

$
0
0
This example reads a XML file and stores the new parameters in the program test objects. The parameters which will be updated by the XML file are grouped into a Test node and the specific test which will be updated is identified by an ID attribute.  Each child node that is grouped within a Test node can be used to update a Test properties.  For instance:


   3
   3.6
   3.3



This XML Test node, when used with the XMLTestParameters.drv, will update the the Test whose ID properties equals "PS1".  It will update the Test's Min, Max and Tag properties with 3, 3.6, and 3.3 respectively.

Using the Example

The code to read the XML file and apply the parameters reside in the XMLTestParameters.drv driver.  The XMLTestParameters driver utilizes the XML.drv, a general purpose XML file reader.  This driver uses the functionality of Microsoft's System.Xml namespace, documentation here.  Functionality includes the ability to create, open, read and write XML files.  Additional methods and properties can be added by the user to expand the driver functionality.

To use the driver:
1. Insert the XMLTestParameters.drv to your system
2. Insert the XML.drv to your system
3. To load the parameters to your program use the following code:

if not XMLTESTS ReadTestParametersFile(GetDir(0)+"\\TestParameters.xml")
    abort
endif


This code typically resides in Program.OnInit() event.

Example Code

The  XMLTestParameters.drv export one command / procedure that is used to load the parameters:

--------------------------------------------------------------------------------
Procedure ReadTestParametersFile(sFile): Bool
--------------------------------------------------------------------------------
sFile: Val String
sProperty: String
sTest: String
s: String
enNodeType: Long
{
  ! open the test properties file
  try
    XML Reader Open(sFile)
  catch else
    MsgBox("Unable to open XML File: '"+sFile+"'")
    return False
  endtry

  !Iterate through the open XML file
  while (XML Reader Next())
    enNodeType=XML Reader Get NodeType()
    select enNodeType
    Case XmlNodeType.Element
      ! Keep track of the element that the user is on.
      s = XML Reader Get Name()
      if s="Test"
        !If the element is a new test, store the ID attribute
        sTest=XML Reader Get Attribute("ID")
      else
        !Store the name of the element as a property
        sProperty=s
      endif
    Case XmlNodeType.Text
      !If the node is text, it is a value that should be updated
      !use the Test ID and property name to decide where to assign the value
      select sProperty
      case "min"
        Program.Tests(sTest).Min=Val(XML Reader Get Value())
      case "max"
        Program.Tests(sTest).Max=Val(XML Reader Get Value())
      case "tag"
        Program.Tests(sTest).Tag=XML Reader Get Value()
      case else
        !More customization can be here
      endselect
    EndSelect
  EndWhile
  XML Reader Close()
  return True
}


Where to Go From Here

This example only allows you to update a Min/Max type tests properties.  If the ability to update the properties of another test type were needed, the code within the sProperty case statement would need to be updated.  To add the ability to set the ValuePlus and ValueMinus property of a Tolerance type test, the user would need to add a 'case "valueplus"' and a 'case "valueminus"'.

Download the Example and the XML drivers:  DownloadClick Here

Logging ATEasy Test Results to a CSV file, Excel worksheet, or a Database - Published on 4/16/2014

$
0
0
This article demonstrates, through a programming example, a method for the automatic logging of test results to a records based  format.  The techniques presented in this article can be adapted to work with any data storage mechanism.  Specifically, the example creates, opens and appends test results to a local CSV file, an ADODB based database, an Excel file, or some combination of the preceding. The code presented in this example reside in the AUTOLOG driver that is included with this article below.

Algorithm

The process for automatic test logging is as follows:
  • Create the log file
  • Log the test results as they are accumulated
  • Finalize the log file

Create the log file

To ensure that a new record is created each time we run the test program, a new external log file is created in the OnInitProgram() event.  In the example, we use three functions within OnInitProgram() to create three different logs: CreateNewCsvFile(), CreateNewExcelFile(), and CreateNewDBTable().

The purpose of creating the log before the tests are run is to both ensure that we are going to be able to save to the target location and to allow ourselves an opportunity to record any header data before the test data begins accumulating.

In the case of logging to a text file, a file needs to be created (storing the file handle in a global variable) and header information including the serial number, start time, program name is recorded.  The log file will remain open for the duration of the program execution; we can append test results to the file using the file handle created.  CSV is an example of a text file and CreateNewCsvFile() demonstrates this method behavior:

m_hCsv=FileCreate(sFilename)
FileWrite(m_hCsv, "Test Id,Test Name,Pin,Unit,Min,Result,Max,Status",,"\r\n")


Accumulating results

By the time the OnEndTest() event is called, the Test object will be updated with the latest test results.  This is an ideal place to record the latest test results to the log file.  In our example, we use three functions within OnEndTest() to append to the logs: AppendCsvResults(), AppendExcelResults(), AppendDBResults().

In the case of appending to a compliant ADODB, the record needs to be accessed and then a new record can be created and filled out.  AppendDBResults demonstrates this method:

obRecordSet.Open("SELECT * FROM TestsResults", sConnection, ,adOpenDynamic)
obRecordSet.AddNew()

obRecordSet.Fields.Item("TestId").Value=Test.Id
...
obRecordSet.Fields.Item("Result").Value=Test.Resul
...
obRecordSet.Update()
t


Or Using EXCEL driver (AppendExcelResults()) :

EXCEL Set Value(m_xlWorkbook,,"A"+sCurrentExcelRow, Test.Id)
...
EXCEL Set Value(m_xlWorkbook,,"F"+sCurrentExcelRow, Test.Result)


Closing the log file

Depending of the record type that you are utilizing, you may need to perform some sort of termination procedure such as writing footers, closing file handles, and releasing objects that were instantiated during the creation phase of the algorithm.  This is the complement to the Create- type procedures so it is appropriate to put it in to the OnEndProgram() event.

Using the Example

This example workspace attached to this article uses The AUTOLOG Driver Shortcut properties to enable/disable the logging.  If the Driver Shortcut properties are empty, no automatic logging will be performed.  By default, the properties should be entered as followed: If you like to use the logging in your application, include the AUTOLOG.drv in your project System.
  • DatabaseConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=c:\\MyLog"
  • ExcelFile = "C:\MyLog"
  • CsvFile = "C:\\MyLog"
Using these properties will create three files in the C:\ root directory: MyLog.mdb, MyLog.xls and MyLog.csv.

The XLS created by the Autologger driver

Figure 1. Microsoft Execl XLS File Output


The MDB created by the Autologger driver

Figure 2. Microsoft Access MDB Database File Output


Where to Go From Here

This example only allows you to log results from Min/Max test types.  If the ability to update the properties of another test type were needed, the code in the various Create- and Append- procedures would need to be updated.

Download the AutoLogger Example Files:  Click Here

Testing Multiple UUT's in ATEasy - Published on 4/17/2014

$
0
0

Introduction

ATEasy 8.0 adds Multiple UUT Testing feature – the ability to test Multiple UUT’s in Sequential, Parallel or Mixed mode, using common test processes.  This article provide an introduction to Multiple UUT testing, illustrating the capability with a simple test example that can be download and run on any Windows©  platform.

ATEasy Structure Overview

When developing test application using ATEasy, the test processes are organized into easy to read sequences of measurements.  This is possible because of the structured development environment provided by ATEasy.  The structure is achieved by using different Modules to organize code and test objects specific to the processes designed for the modules.  The three modules used for holding the test objects are the Driver module, the System module and the Program module.  

Driver modules are used to hold any reusable code; for example, instrument drivers (collection of API functions specific to a particular instrument), application drivers (like the Excel® driver) and commonly used procedures and utilities, such as the ATEasy Test Executive.  The System module contains hardware configuration objects; i.e., objects used to control the configuration of the system.  Common System module objects are procedures that initialize instruments as part of a power-up or shut-down sequence, or in this example, procedures for opening and closing the Excel spreadsheet for data collection.  The Program module contains objects for making measurement and testing or validating the Unit Under Test (UUT), or Device Under Test (DUT) - the two terms are used interchangeably in this article.  Additional information about the ATEasy modules can be found in the ATEasy On-Line documentation.

The example presented here uses two drivers, one for the ATEasy Test Executive and an Excel spreadsheet driver based on the Excel ActiveX library.  The drivers are installed in the Driver folder under the System module.  The System module itself contains the code for opening and closing an Excel spreadsheet - not explicitly part of the test or measurement process, but used for collecting the test results for each of the DUT's being tested.  The Program module contains the actual test code, or more accurately, the measurement code and pass/fail evaluation parameters.  It is the System and Program modules that we will focus on for code development in the example.  We will also focus on how to use the ATEasy Test Executive to enable testing multiple devices - without additional code development.

Figure 1 below shows the ATEasy Workspace window, which highlights the structure of the ATEasy application discussed above.  Easily identifiable are the Program module - called Multi_Uut, the System module, and the Excel and Test Executive drivers installed in the Driver folder under the System module.

ATEasy Workspace and application structure
Figure 1:  ATEasy Application Structure

System Module

Before discussing the System module code, we need to insert the drivers mentioned above.  These are the Test Executive driver and the Excel driver.  The Test Executive driver is included with the ATEasy installation and is located in the "Drivers" folder under the ATEasy folder.  The Excel driver is also included with the ATEasy installation, but is located in the "Examples" folder under the ATEasy folder.  The Excel driver utilizes the Excel Active-X library that comes installed with the Microsoft Excel application - implying that this example will not run without Excel having been installed in the system.  A copy of the Excel driver is included with this article as additional functions specific to the example program were added to the driver.

Another aspect of ATEasy's embedded structure are Module Events.  While a detailed discussion of module events is well beyond the scope of this article (refer to the ATEasy On-Line help), the general definition of a module event is a container for code that will be executed in a deterministic order within the application.  The primary System Events used are the OnInitProgram event (executed whenever a Program Module starts), and the OnEndProgram event (executed whenever a Program module ends).

The System.OnInitProgram event opens an Excel spreadsheet (Workbook) called "MultiUUT.xlsx", and creates a Worksheet for each UUT being tested.  Each worksheet is renamed with the UUT number associated with the worksheet.  The System.OnInitProgram event also initializes a System variable to the number of devices being tested.  As testing for each device initiates a unique thread, i.e., a copy of the Program module, for executing test code, the variable is called m_nThreadCount.  The System.OnInitProgram event code is shown below:

Procedure OnInitProgram(): Void Public ! Occurs when a program has started.
--------------------------------------------------------------------------------
sPath: String: 256
nRow: Short
nColumn: Short
nSheet: Short

{
If m_nThreadCount=0

  m_nThreadCount=App.UutCount ! The number of devices being tested
  sPath=GetDir(aGetDirCurrent)+"\\MultiUUT.xlsx"
  FileRemove(sPath) ! Delete old versions of the Workbook file

  Excel File Open New(, App.UutCount, xlwb) ! Create a new Workbook file
  Excel Show Application(True) ! Show the Workbook - comment to hide the Workbook

  For nSheet=1 to App.UutCount ! Repeat for each device - rename the Worksheet to UUT #
    Excel Set Worksheet Name(xlwb,nSheet,"UUT "+Str(nSheet)) ! New function added to Excel driver
    For nColumn=1 to 2 ! Repeat for each Task - add Worksheet column headers
      Excel Set Value(xlwb,nSheet,Chr('A'+nColumn)+"1","Task "+Str(nColumn))
      For nRow=1 to 16 ! Repeat for each device pin - add Worksheet row headers
        Excel Set Value(xlwb,nSheet,"A"+Str(nRow+1),"Pin "+Str(nRow))
      Next
    Next
  Next

  Excel File SaveAs(xlwb,sPath) ! Save the Workbook
EndIf
}


The System.OnEndProgram event counts down the m_nThreadCount variable as each Program module thread completes.  When the last thread closes, the System.OnEndProgram event saves the Workbook and closes the Excel application.  There is also a System.OnAbort event that is executed in the event that the operator aborts the test process.  As the code performs the same function as the System.OnEndProgram event, only the System.OnEndProgram event code is shown below:

Procedure OnEndProgram(): Void Public ! Occurs when a program has completed.
--------------------------------------------------------------------------------
{
m_nThreadCount=m_nThreadCount-1 ! Decrement the thread count by 1

If m_nThreadCount=0 ! If the last Program thread is complete, save the workbook and close Excel
  Excel File Save(xlwb)
  Excel File Close(xlwb,True)
EndIf
}


In addition to the m_nThreadCount System variable, another System variable, "xlwb" is defined to hold the Excel Workbook object.  For completeness, the definition for both System variables is shown below:

Variables
--------------------------------------------------------------------------------
xlwb: EXCEL.Workbook Public
m_nThreadCount: Short Public


Program Module

The Program module executes code for controlling instruments in order to make a measurement.  Each measurement is compared against a pass/fail parameters to determine is the measured value is within defined limits.  For this reason, each measurement is contained in an object called a Test.  The Test object contains the code for controlling source and measurements and the pass/fail parameters.  This example simulates performing a continuity test on a 16-pin IC.  The measurement is simulated using a random number generator that produces mostly pass results, with some fail results thrown in for completeness.  As in a real test case, continuity is checked against the Vcc and Gnd power pins, which produce positive voltage in the range of 0.6V to 0.7V, or negative voltage in the range of -0.7V to -0.6V, respectively.  The code for the simulated measurements for Pin 1 are shown below:

!"Task 1 : "Continuity Vcc"
--------------------------------------------------------------------------------
Test 1.1 : "Pin 1"
--------------------------------------------------------------------------------
Min = 0.6
Max = 0.7
{
    TestResult=0.599+(Rnd()/321254.9)
}

...

Task 2 : "Continuity Gnd"
--------------------------------------------------------------------------------
Test 2.1 : "Pin 1"
--------------------------------------------------------------------------------
Min = -0.7
Max = -0.6
{
    TestResult=-0.701+(Rnd()/321254.9)
}

...



The Vcc and Gnd continuity measurements are organized into another structure called a Task.  A Task is a collection of measurements that are organized by some common theme - in this case, the tests are organized by the power pin the continuity is being measured against - Vcc and Gnd.  Figure 2 below shows the example Program Module Task/Test structure.  The tasks are "Continuity Vcc" and "Continuity Gnd", while the tests are Pin 1 to Pin 16.

Program module Task/Test structures organize tests according to a common test process
Figure 2:  Program Module Task/Test Structure


Like the System module, the Program module also supports module events.  The Program.OnEndTest event will execute at to conclusion of each and every test in the task/test sequence.  This is a logical place to collect the results of each test and write them to the Excel workbook.  The data is organized in the workbook by UUT number (worksheets), the task (columns) and the UUT pin number (rows).

Three properties within the application facilitate this organizational capability.  They are the App.UutIndex, Task.Index and Test.Index properties.  The App.UutIndex keeps track of which UUT is being tested.  Using the value of this property, you can point to the worksheet associated with the UUT currently being tested.  The Task.Index keeps track of which Task is currently being executed.  You can use this property, with some minimal conversion, to point the worksheet column to store the test results in.  And, likewise, the Test.Index can be used to point to the worksheet row to store the test results to.  The Program.OnEndTest code is shown below:

Procedure OnEndTest(): Void Public ! Occurs when a program test has completed.
--------------------------------------------------------------------------------
sRow: String: 8
sColumn: String: 8
{
sColumn=Chr('B'+Task.Index) ! Convert the Task.Index to Excel column characters - works up to "Z" columns
sRow=Str(Test.Index+2) ! Convert the Test.Index to Excel row string

! Write TestResult to worksheet referenced by App.UutIndex, column sColumn, row sRow
Excel Set Value(System.xlwb,App.UutIndex+1,sColumn+sRow,TestResult)
}


Program modules, by default, run tasks and tests in sequential mode, and will run the task/test in the same thread.  ATEasy supports two types of sequencing for Multiple UUT testing, sequential and parallel.  Sequential sequencing is as described above and runs the task/test in a common thread, while parallel sequencing runs tasks and tests in different threads.  For Multiple UUT testing, ATEasy supports these test methods using a combination of special module events, synchronization classes, and application properties.  These synchronization classes and events are described in the ATEasy on-line documentation, and are beyond the scope of this introductory article.

Test Executive

In this simple application, Multiple UUT synchronization is handled by the ATEasy Test Executive.  The ATEasy Test Executive must be properly configured in order to test multiple UUT's.  First, you must make sure to include the ATEasy Test Executive driver in the drivers list, run the application - typically it is the last driver in the list of drivers included in the System:Driver folder.  When an ATEasy application is run with the Test Executive included, the Test Executive user interface will be displayed, allowing control of the test process and a test log report of the test results - as shown in figure 3 below.  

Standard Test Executive showing a single UUT test sequence
Figure 3:  Standard Test Executive


For the following instructions, refer to figure 4 below.  To configure the Test Executive for Multiple UUT support, while the Test Executive is visible, then from the Test Executive toolbar or menu list, open the Tools:Customize:Options menu, and from the list of parameters, select and set the Enable Multiple UUT's parameter True.  The default number of UUT's is 4, although the default can be changed and saved, so may not be the same as in this example. Also set Default UUT Switch Level to Test .  After closing the Customize dialog, the Test Executive user interface will update to show a tab for each UUT.  Each UUT's tab shows the test log test results and a tree of the UUT program tests, the tab caption shows the UUT index number, the program name and an icon that will show whether the UUT is running (right box), stopped (box). The icon is colored by the UUT status: green for PASS red for FAIL, black for None as shown in figure 5 and 6 below.

Test Executive Multi-UUT configuration parameters
Figure 4:  Test Executive Configuration


Modified Test Executive showing multiple UUT test sequences
Figure 5:  Multi-UUT Test Executive


Running the tests using the default sequential test mode will run all of the Tests and Tasks for each UUT in sequence.  You may notice an Excel workbook was opened when the ATEasy tests were started.  If you click on the Excel workbook to give it focus, you will see the test results being populated in sequential worksheets in Task/Test sequential order.  Figures 6 and 7 illustrate this process.

When all of the tests have completed for each UUT, the Excel workbook is saved and closed.  You can open the workbook to review the test results.  By design, each time the tests are run, the old workbook is deleted and a new workbook created, so if you want to keep the old test results, make sure to create a backup of the file before running the Test Executive again.  

Test Executive results for multiple UUT test sequences are shown in their own tabbed window
Figure 6:  Multi-UUT Test Executive


Excel workbook showing a worksheet for each UUT, with Task/Test results in the respective worksheet columns and rows
Figure 7:  Excel Workbook with Captured Test Results


The test mode can be changed from sequential to parallel, and and UUT count can be changed from 4 to up to 10 in the Tools:Controls:Option, as shown in figure 8.  Observing the Excel workbook while running in parallel mode shown the worksheets being updated in a scattered appearing manner. Each UUT's tasks/tests are being run in their own thread, and update their respective worksheet when a measurement is completed.  As this happens very rapidly, the worksheet updates appear scattered, but are actually following a the processes defined.

Select different UUT counts and/or Parallel sequencing modifies the behavior of the Test Executive without writing additional code
Figure 8:  Changing UUT Count and Test Sequencing


You can also change the UUT count and the program associated to each UUT can be different (if your project have multiple programs). This can be done from the Test Executive Select Program dialog (see the Test Executive on-line help). In addition, you can set the UUT count and the program associated with each index programmatically, See the ATEasy TestExecMultipleUuts.prj example located in the ATEasy Examples folder..  

This example can be run on any system with Microsoft Office (ATEasy EXCEL driver) installed and running a licensed or evaluation version of ATEasy.  Additional information about ATEasy's Multiple UUT testing capabilities and synchronization objects can be found in the ATEasy on-line documentation.

Download the Multi-UUT.zip Example Files:  Click Here

How do I force a Task or a Test to run in ATEasy Test Executive? - Published on 4/17/2014

$
0
0
The ATEasy Test Executive provides a way for users to check and uncheck a Task or a Test by clicking on the Tests pane check boxes. The Tests pane displays a tree control (TreeView) nodes that represents a Program, Task or Test. This article describes how to check and disable a TreeView node to force a Task or a Test to run and to prevent  the user from un-checking the node.

The example assumes you are running a program with a task ID "SystemBIT" and we want to prevent users from un-checking it. The code can be placed in Program.OnInit():

1. Define a program variable:

node: MSComctlLib.Node


2. Insert the following cod to the Program.OnInit() event:


! force task with an id of "SystemBit" to run, prevent the user from un-checking it
! find the node for SystemBIT, replace this name with your task ID
node=TestExec.m_frmMain.FindNode(Program, Program.Tests("SystemBIT"))
! check the node
TestExec.CheckTreeNode(node)  
! prevent the user from un-checking it
TestExec.SetNodeData(node, ateNodeFieldDisable, True)

What is HW driver? - Published on 5/12/2014

$
0
0
The HW package - MTS (Marvin Test Solutions) Hardware Access Driver, is used by all MTS instrument drivers and ATEasy to access to the PC resources (memory, IO ports, DMA etc), PCI/PXI configuration and more.  The HW package includes libraries used to program and create instrument drivers for PC/PCI/PXI based instruments. A PXI/PCI Explorer utility to configure and display PXI/PC based systems is also included.  The utility includes a VISA configuration utility for PXI and PXI express instruments (similar to NI-MAX) and support for MTS and other vendors PXI chassis, controllers and expanders.

The HW driver supports running on Windows 9x-Windows 8/Server 2012 and support 16, 32 and 64 bit Windows applications.

The following files are installed when running the HwSetup.exe setup for HW:

HwSetup.exe - A command line utility to install, uninstall and check the status of the HW driver.

HwTest.exe - A program to test the HW driver and to read/write to I/O ports, memory and to display PCI resources.

Hw.sys and Hw64.sys - Windows kernel mode device drivers, provides access to I/O ports, memory and PCI resources, installed to the Windows System Drivers directory.

HwDevice.sys and HwDevice64.sys - Windows kernel mode device driver for HW.INF boards, installed to the Windows System Drivers directory.

HwPxiExpress.dll - Provides information to MTS Chassis, Controller and Peripheral PXIe devices, installed to the Windows System directory.

Hw.vxd - Windows 9x/Me virtual device driver provides access for memory and PCI resources, installed to the Windows System directory.

HwCIns16.dll - Windows 9x/Me Class Installer for HW.

HwCIns32.dll and HwClins64.dll - Windows Class Installer for HwDevice.sys and HwDevice64.sys.

HwVdd.dll - VDD for 16 app running on 2000-Vista, installed to the Windows System directory.

Hw.inf - Driver information files for MTS's PXI/PCI boards.  Installed to the Windows System\INF directory.

Hw.cat - Windows digitally signed catalog file.

HwPciExplorer.cpl and HwPciExplorer64.cpl - PXI/PCI Explorer - Windows Control Panel applet to display the current PXI/PCI devices and to assign slot numbers to device resources. Slots numbers are required to identify a PCI/PXI board when using MTS board driver. Installed to the Windows System directory.

Hw.dll and Hw64.Dll -  Library with API defined in hw.h, installed in Windows System folder.

Hw.h -  Include file, to include in your C/C++ project provides functions prototypes to Hw.dll  and Hw64.dll files.

Hw.lib and Hw64.lib -  import library for C/C++ application using the HW.dll and Hw64.dll.

ReadMe.txt - Contains the latest release information about the HW package.

There are many functions within the HW library that are useful for determining the system configuration.  This article discusses the most important procedures, the structHWPCIDEVICE data structure, and provides an example of using the objects listed below for querying the PXI system resources:

Initialize():
Initializes the HW library

PciGetSlotNumbers([Val] Word wVendorId, [Val] Word wDeviceId, Var Short panSlotNumbers[], Var Word pwDevicesFound):
Returns an array of slot number(s) for the devices with the specified Vendor ID and specified Device ID.

PciGetSlotDevice(Val Long lSlot, Var structHWPCIDEVICE pstPciDev):
Returns the device information for the instrument in the specified slot.

Struct structHWPCIDEVICE:
A data type structure that contains information about devices (instruments) installed in a PXI system.  While the procedures above are used to obtain information about a PXI device, it is the structHWPCIDEVICE data structure where that information is stored.  So knowing the structure of the data type is key to fully utilizing the HW driver.  The full structure is provided in the ATEasy HW driver, and provided below for review:

Struct structHWPCIDEVICE
  Dword dwVendorId
  Dword dwDeviceId
  Dword dwBus
  Struct structPciSlotNumber stPciSn
    Dword dwAsUlong
  Struct strictPciCommonConfig stPciCfg
    Word wVendorId
    Word wDeviceId
    Word wCommand
    Word wStatus
    Byte ucRevisionId
    Byte ucProgIf
    Byte ucSubClass
    Byte ucBaseClass
    Byte ucCacheLineSize
    Byte ucLatencyTimer
    Byte ucHeaderType
    Byte ucBIST
    Struct structPciHeaderType0 stType0
      Dword adwBaseAddresses[6]
      Dword dwSubSystem
      Dword dwSubVendorID
      Dword dwROMBaseAddress
      Dword adwReserved2[2]
      Byte ucInterruptLine
      Byte ucInterruptPin
      Byte ucInterruptPin
      Byte ucMinimumGrant
      Byte ucMaxinumLatency
    Byte dwDeviceSpecific[192]
  Struct structCmPartialResourceDescriptor  aResDesc[8]
    Byte ucType
    Byte ucShareDisposition
    Word wFlags
    DWord Address1
    DWord Address2
    DWord Address3
  Struct structHwMemoryDesc aMemDesc[8]
    DWord dwPhAddrLow
    Long lPhAddrHigh
    DWord dwLength
    DWord pvVirtualAddress
  Char szId[256]


To demonstrate the utility of the HW driver, let's review a common task confronting anyone writing a program to control PXI test instruments.  When writing a test program, the programmer is always faced with having to identify what instruments are installed in the PXI chassis.  This information is essential to the test program so it knows how to establish a communication link between the host computer (i.e., the test program) and the instruments.  Instrument identification can take one of several forms; slot numbers can identify instruments, instruments can be identified by a resource descriptor (VISA) and board numbers can be used - these are the most common means of identification.

The HW library also supports a simplified means of referencing a device; by it's Alias.  An alias is a text name that can be assigned to any instrument in a PXI chassis using PXI/PCI Explorer, a PXI resource utility that is installed with the HW package.  A detailed explanation of how to do this is discussed in Knowledge Base article #Q200187.


Figure 1:  Using PXI/PCI Explorer to assign an instrument Alias


The typical process for establishing communication with an instrument is to “Initialize” the instrument by passing the iappropriate dentification parameter into an initialization procedure, typically contained in the instrument drivers, and having the procedure return a “handle” that is used as a reference for future communication with the instrument.  This process is very similar to that of opening a file, and using the returned “file handle” for subsequent reading or writing to the file.

Identification of instruments can be done at program design time by hard-coding the instrument identification into the test program, or at run time by querying the system resources and dynamically initializing instruments using the information returned by the system query.  To use procedures contained in HW.DLL to query the system resources and identify installed instruments at run time, the HW Initialize() procedure must be called prior to calling any of the other procedures in the HW driver.

Once initialized, the PciGetSlotNumbers() procedure will return an array of PXI slot numbers that contain instruments matching the search criteria – often the Vendor ID and Device ID.  The PciGetSlotDevice() procedure returns the device information for the instrument in the specified slot.  The device information is contained in the structure structHWPCIDEVICE (listed above).  If, for example, you wanted to know how many GX5290 dynamic digital instruments were installed in a PXI chassis, what are their slot numbers, and the firmware revision of each of those instruments, you could use the following code:

Word wVendorId=0x16E2 ! Geotest Vendor ID
Word wDeviceId=0x5290 ! GX5290 Device ID
Short panSlotNumbers[32] ! Array of slot numbers found
Word pwDevicesFound ! Number of slots matching the Vendor and Device ID’s
structHWPCIDEVICE pstPciDev
String sDeviceInfo
Long i

Initialize()
PciGetSlotNumbers(wVendorId, wDeviceId, panSlotNumbers, pwDevicesFound)
If pwDevicesFound<>0
  For i=0 to pwDevicesFound-1
    PciGetSlotDevice(panSlotNumbers[i], pstPciDev)
    sDeviceInfo= pstPciDev.szId
    Print "Slot "+Format(panSlotNumbers[i],"00")+" Firmware: "+Mid(sDeviceInfo,Pos("SUBSYS_",sDeviceInfo)+7,4)
  Next
EndIf


Once the slot number for an instrument is obtained, it would be a simple matter to initialize the instrument by calling the instrument's Initialize() procedure and passing the slot number obtained by scanning the PXI system using the example above.  

For additional information about how to use the HW driver, review the HW programming example installed with ATEasy (Hw.prj) and the HW files installed the Program Files\Marvin Test Solutions\HW. More information is also avilable in the flowing knowledge base articles: Q182, Q187.

White Paper: Upgrading Alstom BTE Functional Test Systems with PXI - Published on 6/9/2014

$
0
0
This technical brief provides an overview of how SNCF railway in France was able to update their current Alstom BTE (Bench Test Equipment) platforms to PXI.

SNCF maintains a wide range of electronic assemblies which are part of the Alstom train sets operated by SNCF. The BTE platform incorporated Geotest’s (now Marvin Test Solutions) GTXI systems and was deployed in world-wide locations. These test sets, which are now over 15 years old, have reached end of life, requiring railway operators to look at upgrade solutions that can be used to continue servicing Alstom’s AGATE (Advanced Generic Alstom Transport Electronics) family of electronic control units. Marvin Test Solutions (MTS) worked with Accelonix, an integrator in Paris, France to upgrade and convert SNCF's existing GTXI systems and ATEasy programs to MTS’ GX7100 PXI platform.

The resulting upgrades provided SNCF with greatly improved test performance and maintainability. Key benefits included:
  • Up to 60% test time reduction
  • Simple program conversion and retention of existing user interface by leveraging ATEasy’s backward compatibility
  • A modern test platform (PXI) architecture, providing a cost effective extension of the test system’s life cycle
To read more about this solution download our test solutions technical brief.
Viewing all 549 articles
Browse latest View live


Latest Images