You can use the Linear Interpolation VI with LabVIEW FPGA to generate a linear waveform by supplying y0 (start point) and y1 (end point), the number of points to interpolate, and the x (fractional) values. The interpolation locations can be determined programmatically, often with a running summation. The Output Linear Waveform VI, shown in Figure 6, utilizes this method. This VI will output the number of points defined in the Number of Points control with the interpolation based on the Start Point and End Point controls. The linear interpolation will initially be done at an x (fractional) value of 0, and that value will increase each iteration by the Interpolation Increment value.
Figure 6. Output Linear Waveform VI
You can execute this VI by manually supplying the control values and running the VI. You can also develop a VI that will be run on the host that programmatically executes and communicates with this VI. The Execute - Output Linear Waveform VI, shown in Figure 7, is developed and run on the host machine. It uses the Open FPGA Reference, Read/Write Control, Invoke Method, and Close FPGA Reference functions. These functions provide all of the necessary control over the FPGA, such as downloading, reading or writing data, and starting or stopping the VI. This method allows you to quickly change the values of the controls required for execution. You could even take this VI and use it in other VIs to perform output on the cRIO-9263 as part of a larger project.
Figure 7. Execute - Output Linear Waveform VI
An Example Interpolation Algorithm
The previous example highlights a generic method to generate a linear waveform based on linear interpolation. You can write your own algorithm to determine the values that you will output along the line defined by the start and end points. A common algorithm to use is one that allows you to add evenly spaced points between the start and end points to output a waveform with more resolution. Determining the evaluation points at can be done with a host VI that will determines the spacing between 0 and 65535 necessary to fit points between the start and end point. You could also have an algorithm in the FPGA VI that determines the evaluation points programmatically. This method enables you to simply tell the FPGA code how many points to place between the start and end point and therefore the sampling rate for the waveform.
One such algorithm can be easily implemented by taking advantage of the binary representations of integers and the Linear Interpolation VI. If you look back to the Linear Interpolation with the LabVIEW FPGA Module section, we discussed the x (fractional) control. It is a 16-bit integer that represents the location between the two points where the interpolation will occur. Recall that a value of 0 represents the starting point (y0) and a value of 32767 represented half way between y0 and y1. The full range of x (fractional) is 65535. Half of this value is 32767, one quarter is 16383, and one-eighth is 8191. If we look at the binary representations of these numbers (Figure 8), we see that the binary representation of these numbers is just the previous shifted one place to the right (divided in half in binary).
Figure 8. Integer and Binary Representations of Interpolation Locations
We can take advantage of this binary shifting to quickly determine what the values of x (fractional) should be to add 1, 3, 7, (2^n -1) etc. points between y0 and y1. Notice that if we are to add 1 point, it would be at x (fractional) value of 32767 (65535 shifted right once). If we were to add 3 points, the x (fractional) values would be at 16383, 32767, and 49151 to represent 1/4, 1/2 and 3/4 of the way between y0 and y1. If you look closely at the binary representation of these numbers you will notice that 32767 is 16383 + 16383 with a 1 ORed in the least significant place, and 49151 is 32767 + 16383 with a 1 ORed in the least significant place. This same pattern surfaces for any 2^n - 1 points that are to be added between the start and end point. Therefore, if you wanted to add 2^n-1 points between the start and end point you could shift 65535 right by n places to get the first interpolation point. You then determine the rest of the points by adding this initial value and doing an OR with a value of 1. When you get to 65535, the largest value that can be interpolated at, the interpolation value is replaced with the value at the End Point. The reason for this replacement is because the interpolation interval, [y0,y1), does not include the end value, so we configure the output to be the end point for the final update.
The Linear Output - Adding Points VI, shown in Figure 9, uses this algorithm to output the start point, the 2^n -1 (for n = 0:15) points in between, and the end point. The Points to Add (2^n-1) control determines the number of points included between the start and end point. Notice that it is negated and then the value 65535 is shifted by this amount, which amounts to a right-shift by n places. The Sequence structure inside the while loop includes two sequences. The first sequence (not shown) has a Loop Timer VI and a Period Update (mSec). This sequence is used to create a timed update rate of the points, similar to the other two examples in this tutorial. The second sequence is where the actual output is done. Each iteration, the interpolation is done at the location passed into the x (fractional) terminal of the Linear Interpolation VI. This value is output on channel 0 of the cRIO-9263 module. The next interpolation value is calculated by adding the result of the initial shifting of 65535 and then that result is ORed with 1 and wired to the shift register for the next iteration. In the final iteration (when the interpolation point is 65535), the value in the End Point control is output and the program ends.
Figure 9. Linear Output - Adding Points VI
Once again, you can develop a VI that can be run on a host that will programmatically execute this VI. The following VI, Execute Linear Output - Adding Points, is developed and run on the host machine. With this VI on the host, you can call the VI multiple times without having to manually interface with the VI on the FPGA, and you can use this VI as a SubVI in other VIs.