Appendix A Startup Form Code

Appendix A Startup Form Code 67 68 '------------------------------------------------------'Lance Nicholas Covert 'frmSamples7 (samples7.frm) '-----...
Author: Osborne Rice
4 downloads 1 Views 87KB Size
Appendix A Startup Form Code

67

68 '------------------------------------------------------'Lance Nicholas Covert 'frmSamples7 (samples7.frm) '------------------------------------------------------'This is the code for the startup form (the form that 'loads upon program execution). 'This form is displayed on pg. 56 of the Thesis 'This code should be used in conjunction with the 'list of objects and parameters for constructing 'samples7.frm '------------------------------------------------------Option Explicit

'All variables MUST be declared

Const Pi = 3.14159265358979 Dim n As Long Dim k As Integer Dim Largest As Double 'largest value in an array of values Dim scalefactor 'for determining vertical axes of graph Dim Ycenter As Integer Dim vtwips_per_division Dim htwips_per_division Dim volts_per_div Dim Twips_Per_Volt Dim time_per_div_label As Double Dim timestring As String Dim samples_per_div As Double Dim time_per_div As Double Dim time_per_datapoint As Double Dim starting_sample As Double Dim LeftCursorIvalue As Double Dim LeftCursorXvalue As Double Dim RightCursorIvalue As Double Dim RightCursorXvalue As Double Dim LeftCursorSet As Boolean Dim RightCursorSet As Boolean Dim TimeBetweenCursors As Double Dim FrequencyBetweenCursors As Double Dim yzero As Double 'zero-line position for frequency magnitude plot Dim yzeroPhase As Double 'zero-line position for frequency phase plot Dim deltax As Integer Dim actualSampleRate As ViReal64

69

Dim MaxVoltage Dim RealIn() As Double Dim errorSource As String Dim errorcode As ViStatus Dim errorval As ViStatus Dim WaveForm() As ViReal64 Dim FileName As String Dim ExpandGraph As Boolean 'flag used to indicate if # of samples 'can fit in one window or if the graph 'needs to be expanded Dim actualRecordLength As ViInt32

'Output coefficients of fast Fourier transform (FFT) Dim RealOut() As Double Dim ImagOut() As Double Dim LFCR As String 'line feed and carriage return Dim FFTRecordLength As Long 'record length of the FFT Dim F() As Double 'Used to store the magnitude of the FFT outputs Dim Fphase() As Double 'Used to store the phase of the FFT outputs Dim number_of_twips_per_dB 'for frequency plot, vertical axis in dB Dim TwipsPerVolt_FreqPlot 'for frequency plot, vertical axis in volts Dim change_phase_plot As Boolean 'True if phase plot needs to be updated 'False if phase plot does not need to be updated Dim twips_per_180_degrees 'Number of twips per 180 degrees on phase plot Dim logscalex As Double Dim deltaF As Double Dim cursor_freqplot_i As Double 'Stores the i-value (index number of the data point) 'for the cursor on the frequency plot 'in order for it to be redrawn when the plot is 'updated Dim cursor_freqplot_X As Single 'Stores the X-value (x-location of the data point) 'for the cursor on the frequency plot 'in order for it to be redrawn when the plot is 'updated Dim cursor_on_freqplot As Boolean 'True if there is a cursor on the frequency plots 'False if there is not a cursor on the screen

70

Dim scale_value_for_xshift As Integer Dim testgarfield 'These flags are used within the Subroutine: SetTimeComboBox() 'to determine whether or not to update the combo box list Dim time_per_div_combo_flag As Boolean Dim combo_flag_remove_old As Boolean Dim log_base_10() As Double Dim log_of_10 As Double Dim fifty_ohms As Boolean

'flag for 50 ohms or 1 MOhms input impedance

'----------------------------------------------------------------'printing the picture box only Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Private Const WM_PAINT = &HF Private Const WM_PRINT = &H317 Private Const PRF_CLIENT = &H4& ' Draw the window's client area Private Const PRF_CHILDREN = &H10& ' Draw all visible child Private Const PRF_OWNED = &H20& ' Draw all owned windows '-----------------------------------------------------------------

Private Sub AcquireOption_Click() cmdAcquire.Caption = "&Acquire Data" txtMinimumSampleRate.Enabled = True txtMinimumRecordLength.Enabled = True mnuAcquireData.Enabled = True mnuReadData.Enabled = False cboFiftyOhms.Visible = True lblImpedance.Visible = True End Sub Private Sub cboFiftyOhms_Click() 'Subroutine for the input impedance combo box Select Case cboFiftyOhms.ListIndex

71

Case 0 fifty_ohms = False Case 1 fifty_ohms = True End Select End Sub Private Sub cboTimePerDiv_Click() 'Subroutine for the time per division on the 'time-domain plot Select Case cboTimePerDiv.ListIndex Case 0 deltax = 1 Case 1 deltax = 2 Case 2 deltax = 4 Case 3 deltax = 5 Case 4 deltax = 8 Case 5 deltax = 10 Case 6 deltax = 16 Case 7 deltax = 20 Case 8 deltax = 40 Case 9 deltax = 50 Case 10 deltax = 80 Case 11 deltax = 100 End Select If actualRecordLength 0 Then 'if actualrecordlength is not equal to zero Dim LCursorSet As Boolean Dim RCursorSet As Boolean If LeftCursorSet = True Then LCursorSet = True

72 Else LCursorSet = False End If If RightCursorSet = True Then RCursorSet = True Else RCursorSet = False End If 'redraw time-domain plot Call DrawWaveform(RealIn()) 'LeftCursorSet = True If LCursorSet = True Then Call DrawLeftCursor(LeftCursorXvalue, LeftCursorIvalue) End If 'RightCursorSet = True If RCursorSet = True Then Call DrawRightCursor(RightCursorXvalue, RightCursorIvalue) End If End If End Sub Private Sub cboVoltsPerDiv_Click() 'Subroutine for the volts per division on the 'time-domain plot. Select Case cboVoltsPerDiv.ListIndex Case 0 volts_per_div = 0.002 '2 mV Case 1 volts_per_div = 0.005 '5 mV Case 2 volts_per_div = 0.01 '10 mV Case 3 volts_per_div = 0.02 '20 mV Case 4 volts_per_div = 0.05 '50 mV Case 5 volts_per_div = 0.1 '.1 V Case 6 volts_per_div = 0.2 '0.2 V Case 7

73 volts_per_div = 0.5 '0.5 V Case 8 volts_per_div = 1 '1.0 V Case 9 volts_per_div = 2 '2.0 V Case 10 volts_per_div = 5 '5.0 V Case 11 volts_per_div = 6.2 '6.2 V End Select If actualRecordLength 0 Then 'if actualrecordlength is not equal to zero Call DrawWaveform(RealIn()) 'redraw time-domain plot 'redraw left and right cursors Call DrawLeftCursor(LeftCursorXvalue, LeftCursorIvalue) Call DrawRightCursor(RightCursorXvalue, RightCursorIvalue) End If End Sub Public Sub cboExpandYaxis_FreqPlot_Click() 'Subroutine for the magnitude plot on frmFrequency 'This sets the number of twips for the scale on the Y-axis. Select Case frmFrequency.cboExpandYaxis_FreqPlot.ListIndex Case 0 number_of_twips_per_dB = 1 Case 1 number_of_twips_per_dB = 2 Case 2 number_of_twips_per_dB = 4 Case 3 number_of_twips_per_dB = 5 Case 4 number_of_twips_per_dB = 8 Case 5 number_of_twips_per_dB = 10 Case 6 number_of_twips_per_dB = 16 Case 7 number_of_twips_per_dB = 20 Case 8 number_of_twips_per_dB = 25 Case 9 number_of_twips_per_dB = 40 Case 10 number_of_twips_per_dB = 50

74 Case 11 number_of_twips_per_dB = 80 End Select 'redraw frequency plots Call DrawFrequencyPlot(F(), Fphase()) End Sub Public Sub cboExpandYaxis_FreqPlotVolts_Click() 'Subroutine for the magnitude plot on frmFrequency 'This sets the number of twips for the scale on the Y-axis in volts. Select Case frmFrequency.cboExpandYaxis_FreqPlotVolts.ListIndex 'volts per division = 400/TwipsPerVolt_FreqPlot Case 0 TwipsPerVolt_FreqPlot = 50 '8 V Case 1 TwipsPerVolt_FreqPlot = 100 '4 V Case 2 TwipsPerVolt_FreqPlot = 200 '2 V Case 3 TwipsPerVolt_FreqPlot = 400 '1 V Case 4 TwipsPerVolt_FreqPlot = 500 '0.8 V Case 5 TwipsPerVolt_FreqPlot = 800 '0.5 V Case 6 TwipsPerVolt_FreqPlot = 1000 '0.4 V Case 7 TwipsPerVolt_FreqPlot = 2000 '0.2 V Case 8 TwipsPerVolt_FreqPlot = 4000 '0.1 V Case 9 TwipsPerVolt_FreqPlot = 5000 '80 mV Case 10 TwipsPerVolt_FreqPlot = 8000 '50 mV Case 11 TwipsPerVolt_FreqPlot = 10000 '40 mV Case 12 TwipsPerVolt_FreqPlot = 20000 '20 mV Case 13 TwipsPerVolt_FreqPlot = 40000 '10 mV Case 14 TwipsPerVolt_FreqPlot = 80000 '5 mV Case 15 TwipsPerVolt_FreqPlot = 200000 '2 mV End Select

75 'redraw frequency plots Call DrawFrequencyPlot(F(), Fphase()) End Sub Private Sub cmdAcquire_Click() 'This subroutine is executed when the user clicks on the 'Acquire Data or the Read Data button or menu selection. cmdAcquire.Enabled = False cmdQuit.Enabled = False lblActualSampleRate.Caption = "" 'clears out the contents lblActualRecordLength.Caption = "" 'clears out the contents lblErrorMessage = "" hsbExpandGraph.Value = 0 ' Cls

'clear the screen

time_per_div_combo_flag = False Dim errorMessage As String * MAX_ERROR_DESCRIPTION Dim vi As ViSession ' Variables used to get values from the GUI Dim resourceName As String ' Dim actualSampleRate As ViReal64 'these variables are used for horizontal timing setup Dim minRecordlength As ViInt32 Dim minSampleRate As ViReal64 minRecordlength = txtMinimumRecordLength.Text 'check to see if the record length is zero If minRecordlength = 0 Then MsgBox "The minimum record length must be greater than zero.", vbCritical, "Error" GoTo ExitAcquire End If minSampleRate = txtMinimumSampleRate.Text Dim channelName As String channelName = "0" Dim timeout As ViReal64 timeout = 50#

76 'Set up the binary and text file creation. Dim FileNum As Integer Dim wfmInfo As niScope_wfmInfo FileName = Left(txtFilePath.Text, Len(txtFilePath.Text) - 3) FileName = FileName + "BIN" 'Create a duplicate file name with the .txt extension Dim filename2 filename2 = Left(txtFilePath.Text, Len(txtFilePath.Text) - 3) filename2 = filename2 + "txt"

'testing creating directories here Dim justatest 'justatest = CreatePath("c:\test\lance)

If (AcquireOption.Value = True) Then 'These flags are used within the Subroutine: SetTimeComboBox() 'to determine whether or not to update the combo box list cboTimePerDiv.ListIndex = 0 time_per_div_combo_flag = False 'combo_flag_remove_old = True cboTimePerDiv.Clear ' Obtain the resource name of the device from the user interface resourceName = txtResourceName.Text ' Open the NI-SCOPE instrument handle errorcode = niScope_init(resourceName, False, False, vi) If (handleErr(errorcode, "niScope_init")) Then GoTo Error ' Call auto setup, finds a signal and configures all necessary parameters errorcode = niScope_AutoSetup(vi) If (handleErr(errorcode, "niScope_AutoSetup")) Then GoTo Error

'Set the digitizer's channel 0 input impedance to either '50 ohms or 1 MOhms. If fifty_ohms = False Then 'set input impedance to 1 MOhms errorcode = niScope_ConfigureChanCharacteristics(vi, channelName, 1, 0) ElseIf fifty_ohms = True Then 'set input impedance to 50 Ohms

77 errorcode = niScope_ConfigureChanCharacteristics(vi, channelName, 50, 0) End If

'Configure the digitizer to trigger itself errorcode = niScope_ConfigureTriggerImmediate(vi) If (handleErr(errorcode, "niscope_configuretriggerimmediate")) Then GoTo Error ' Get the actual record length and actual sample rate that will be used 'errorcode = niScope_ActualRecordLength(vi, actualRecordLength) 'If (handleErr(errorcode, "niScope_ActualRecordLength")) Then GoTo Error 'Configure the horizontal parameters: rate, recordLength, refPosition, 'numRecords and enforceRealtime errorcode = niScope_ConfigureHorizontalTiming(vi, minSampleRate, minRecordlength, _ 50#, 1, VI_TRUE) If (handleErr(errorcode, "niScope_ConfigureHorizontalTiming")) Then GoTo Error ' Get the actual record length and actual sample rate that will be used errorcode = niScope_ActualRecordLength(vi, actualRecordLength) If (handleErr(errorcode, "niScope_ActualRecordLength")) Then GoTo Error errorcode = niScope_SampleRate(vi, actualSampleRate) If (handleErr(errorcode, "niScope_SampleRate")) Then GoTo Error lblActualRecordLength.Caption = actualRecordLength lblActualSampleRate.Caption = actualSampleRate ' Allocate space for the waveform array ReDim WaveForm(0 To actualRecordLength - 1) ' Read the data (Initiate the acquisition, and fetch the data) errorcode = niScope_Read(vi, channelName, timeout, actualRecordLength, _ WaveForm(0), wfmInfo) If (handleErr(errorcode, "niScope_Read")) Then GoTo Error 'Transfer contents of the array waveform() to the array 'RealIn() Dim j ReDim RealIn(0 To actualRecordLength - 1) For j = 0 To actualRecordLength - 1 RealIn(j) = WaveForm(j) Next 'Draw the time-domain waveform by calling the

78 'DrawWaveform() subroutine Call DrawWaveform(RealIn()) ' Open the file for text, and write the waveform FileNum = FreeFile Open filename2 For Output As FileNum 'write the .txt file ' Store the waveform into the text file Dim i As ViReal64 Write #FileNum, actualRecordLength ' Str(actualRecordLength) Write #FileNum, actualSampleRate ' Str(actualSampleRate) For i = 0 To wfmInfo.actualSamples - 1 Write #FileNum, WaveForm(i) Next ' Close the file Close FileNum ' Now write to a binary file so that loading the data is easier FileNum = FreeFile 'get a free file number Open FileName For Binary As FileNum 'open file for binary access ' Write the number of samples Put FileNum, , wfmInfo.actualSamples ' Write the sample rate Put FileNum, , actualSampleRate ' Write the waveform Put FileNum, , WaveForm ' Close the file Close FileNum ElseIf (ReadOption.Value = True Or ReadOptionTxt.Value = True) Then 'else if the "read from file" option is selected instead of "acquire 'and write to file" 'These flags are used within the Subroutine: SetTimeComboBox() 'to determine whether or not to update the combo box list cboTimePerDiv.ListIndex = 0 time_per_div_combo_flag = False 'combo_flag_remove_old = True cboTimePerDiv.Clear ' Open the binary file FileNum = FreeFile If ReadOption.Value = True Then Open FileName For Binary As FileNum ' Load the number of points Get FileNum, , actualRecordLength 'MsgBox Str(actualRecordLength) ElseIf ReadOptionTxt.Value = True Then

79 Open filename2 For Input As FileNum Input #FileNum, actualRecordLength Input #FileNum, actualSampleRate End If 'Error trap in case record length is zero If actualRecordLength = 0 Then MsgBox "Either the file " + txtFilePath.Text + " does not exist or the record length = 0", vbCritical, "Error in Loading File" GoTo ExitAcquire End If ' Resize and Load the waveform ReDim WaveForm(0 To actualRecordLength - 1)

' Get the sample rate If ReadOption.Value = True Then Get FileNum, , actualSampleRate Get FileNum, , WaveForm ElseIf ReadOptionTxt.Value = True Then For i = 0 To actualRecordLength - 1 Input #FileNum, WaveForm(i) Next End If 'Get FileNum, , RealIn ' Plot the data

ReDim RealIn(0 To actualRecordLength - 1) For j = 0 To actualRecordLength - 1 RealIn(j) = WaveForm(j) Next 'Plot the time-domain data Call DrawWaveform(RealIn()) 'Update labels for sample rate and record length lblActualSampleRate.Caption = actualSampleRate lblActualRecordLength.Caption = actualRecordLength End If 'Enable the FFT buttons since data has been acquired cmdFFT.Enabled = True cmdFFTSelective.Enabled = True mnuFFT.Enabled = True mnuSelectiveFFT.Enabled = True

80

'Find the largest positive value in the time-domain samples Call FindLargestValue(RealIn(), actualRecordLength) scalefactor = picGraph.ScaleHeight / (Largest * 2) 'scalefactor is used to scale the vertical axes of the graph 'scalefactor is used in the DrawWaveform subroutine 'times 2 because there are positive and negative values ' vsbVoltage.Min = 40 'scalefactor / 4 ' vsbVoltage.Max = scalefactor * 2 ' vsbVoltage.Value = scalefactor 'Redraw time-domain waveform Call DrawWaveform(RealIn()) Error: 'error trapping and reporting for NI 5112 digitizer ' Intrepret the error code. If (errorcode VI_SUCCESS) Then errorcode = niScope_errorHandler(vi, errorval, errorSource, errorMessage) MsgBox errorMessage, vbCritical, "Error in data acquisition" Else errorMessage = "Acquisition Succesful!" lblErrorMessage.Caption = errorMessage End If ' Close the NI-SCOPE instrument handle if it was opened successfully If (vi) Then niScope_close (vi) End If ExitAcquire: 'enable the Acquire data and Quit buttons cmdAcquire.Enabled = True cmdQuit.Enabled = True End Sub

Public Function handleErr(errorcode As ViStatus, fname As String) As Boolean 'Error handle code for the NI 5112 digitizer If (errorcode < 0) Then errorval = errorcode errorSource = fname handleErr = True

81 ElseIf (errorval = 0) Then errorval = errorcode errorSource = fname handleErr = False End If End Function Private Sub cmdFFT_Click() If actualRecordLength = 0 Then MsgBox "To perform the FFT you must first either acquire data or read in a data file.", , "Fast Fourier Transform" GoTo ExitSub End If change_phase_plot = True hsbExpandGraph.Visible = False 'ReDim RealOut(0 To actualRecordLength - 1) 'ReDim ImagOut(0 To actualRecordLength - 1)

Dim ImagIn() As Double ' ReDim ImagIn(0 To actualRecordLength - 1) 'for testing the FFT function 'Dim dog As Complex n = actualRecordLength 'code to check for power of two and pad if not '---------------------------------'is selectionLength a power of 2? '---------------------------------Dim PowerOf2 As Boolean PowerOf2 = IsPowerOfTwo(actualRecordLength) 'n=actualRecordLength ' MsgBox Str(PowerOf2) '------------------------------------------------------------------'If number of samples is a power of two, then call the FFT 'If number of samples is not a power of two, then pad the array ' with zeros and then call the FFT '------------------------------------------------------------------Dim k As Long k=0

82 If PowerOf2 = True Then 'the number of samples is a power of 2 so call the FFT function ' MsgBox "Is a power of 2" FFTRecordLength = actualRecordLength ReDim RealOut(0 To FFTRecordLength - 1) ReDim ImagOut(0 To FFTRecordLength - 1) 'Dim ImagIn() As Double ReDim ImagIn(0 To FFTRecordLength - 1) Call FFT(n, RealIn(), ImagIn(), RealOut(), ImagOut())

'-------------------------------------------------'Calculate the magnitude of the complex FFT outputs '-------------------------------------------------'Dim F() As Double ReDim F(0 To FFTRecordLength - 1) Dim i As Double F(0) = Magnitude(RealOut(0), ImagOut(0)) For i = 1 To FFTRecordLength - 1 F(i) = 2 * Magnitude(RealOut(i), ImagOut(i)) 'The magnitude is actually doubled here since 'the FFT outputs are symmetric about half the sampling 'frequency. To get the correct amplitude, the user must 'add the two symmetric sets together. Since both sets are equal, 'the first set can simply be doubled. Next '------------------------------------------------'---------------------------------------------'Calculate the phase of the complex FFT outputs '---------------------------------------------ReDim Fphase(0 To FFTRecordLength - 1) Fphase(0) = Phase(RealOut(0), ImagOut(0)) ' MsgBox (Fphase(0)) For i = 1 To FFTRecordLength - 1 Fphase(i) = Phase(RealOut(i), ImagOut(i)) ' MsgBox (Fphase(i)) Next '---------------------------------------------'For i = 0 To FFTRecordLength - 1 ' F(i) = F(i) / FFTRecordLength 'multiply output by 1/N (number of samples) 'Next

83 Call DrawFrequencyPlot(F(), Fphase())

'draw the frequency plots

ElseIf PowerOf2 = False Then '-----------------------------------------------------------------'the number of samples is not a power of 2 so pad array with zeroes. '-----------------------------------------------------------------'MsgBox "Not a power of 2, so about to pad with zeros" 'pad fft with zeros here Dim success As Boolean Dim NumberOfZeroes As Long ' difference = 2 ' Dim i i=0 Do While success = False If actualRecordLength < 2 ^ i Then NumberOfZeroes = (2 ^ i) - actualRecordLength 'number of zeros to pad with to make length a power of 2 success = True 'exit while loop End If i=i+1 Loop MsgBox "The number of samples is not a power of two. " _ + LFCR + "The program will now pad the array with " + Str(NumberOfZeroes) _ + " zeroes.", , "Zero-Padding"

ReDim F(0 To actualRecordLength - 1 + NumberOfZeroes) 'K=0 For i = 0 To actualRecordLength - 1 F(i) = RealIn(i) 'K = K + 1 Next For i = actualRecordLength To actualRecordLength - 1 + NumberOfZeroes F(i) = 0 Next FFTRecordLength = actualRecordLength + NumberOfZeroes '------------------------------------------------'Call the FFT function '------------------------------------------------ReDim RealOut(0 To FFTRecordLength - 1)

84 ReDim ImagOut(0 To FFTRecordLength - 1) ' Dim ImagIn() As Double ReDim ImagIn(0 To FFTRecordLength - 1) Call FFT(FFTRecordLength, F(), ImagIn(), RealOut(), ImagOut()) '-------------------------------------------------

'--------------------------------------------'Calculate the magnitude of the FFT output '--------------------------------------------'Dim F() As Double ReDim F(0 To FFTRecordLength - 1) ' Dim i As Double F(0) = Magnitude(RealOut(0), ImagOut(0)) For i = 1 To FFTRecordLength - 1 F(i) = 2 * Magnitude(RealOut(i), ImagOut(i)) 'The magnitude is actually doubled here since 'the FFT outputs are symmetric about half the sampling 'frequency. To get the correct amplitude, the user must 'add the two symmetric sets together. Since both sets are equal, 'the first set can simply be doubled. Next '--------------------------------------------'---------------------------------------------'Calculate the phase of the complex FFT outputs '---------------------------------------------ReDim Fphase(0 To FFTRecordLength - 1) Fphase(0) = Phase(RealOut(0), ImagOut(0)) 'MsgBox (Fphase(0)) For i = 1 To FFTRecordLength - 1 Fphase(i) = Phase(RealOut(i), ImagOut(i)) ' MsgBox (Fphase(i)) Next '---------------------------------------------' For i = 0 To FFTRecordLength - 1 ' F(i) = F(i) / FFTRecordLength 'multiply output by 1/N (number of samples) ' Next Call DrawFrequencyPlot(F(), Fphase()) End If

85

'-----------------------------------------------------------ExitSub: End Sub Private Sub cmdFFTSelective_Click() 'This subroutine sets up and sends the data extracted between the two 'cursors on the time-domain plot to the FFT algorithm. change_phase_plot = True Dim SelectionLength As Long ' Dim F() As Double If LeftCursorSet = False Or RightCursorSet = False Then MsgBox "Please make selection first." _ + LFCR + "Left click the mouse for the left boundary." _ + LFCR + "Right click the mouse for the right boundary.", , _ "Selective FFT" ElseIf LeftCursorSet = True And RightCursorSet = True Then 'ready to perform FFT on selection SelectionLength = Abs(LeftCursorIvalue - RightCursorIvalue) + 1 'the number of selected samples 'txtShowTime.Text = Str(SelectionLength) 'performing the FFT hsbExpandGraph.Visible = False ReDim RealOut(0 To actualRecordLength - 1) ReDim ImagOut(0 To actualRecordLength - 1) '---------------------------------'is selectionLength a power of 2? '---------------------------------Dim PowerOf2 As Boolean PowerOf2 = IsPowerOfTwo(SelectionLength) '------------------------------------------------------------------'put selected samples into an array to be sent to the FFT function '------------------------------------------------------------------Dim k As Long k=0 If LeftCursorIvalue > RightCursorIvalue Then Dim temporary

86 temporary = RightCursorIvalue RightCursorIvalue = LeftCursorIvalue LeftCursorIvalue = temporary End If

If PowerOf2 = True Then 'the number of samples is a power of 2 ' MsgBox "The number of samples is not a power of two.", , "Fast Fourier Transform" ReDim F(0 To SelectionLength - 1) Dim i As Long For i = LeftCursorIvalue To RightCursorIvalue 'alteration F(k) = RealIn(i) ' F(k) = WaveForm(i) k=k+1 Next ElseIf PowerOf2 = False Then 'the number is not a power of 2 so pad array with zeros. 'MsgBox "Not a power of two" 'pad fft with zeros here Dim success As Boolean Dim NumberOfZeroes As Long ' difference = 2 i=0 Do While success = False If SelectionLength < 2 ^ i Then NumberOfZeroes = (2 ^ i) - SelectionLength 'number of zeros to pad with to make length a power of 2 success = True 'exit while loop End If i=i+1 Loop MsgBox "The number of samples is not a power of two. " _ + LFCR + "The program will now pad the array with " + Str(NumberOfZeroes) _ + " zeroes.", , "Zero-Padding" ReDim F(0 To SelectionLength - 1 + NumberOfZeroes) k=0 For i = LeftCursorIvalue To RightCursorIvalue F(k) = RealIn(i) k=k+1 Next

87

For i = SelectionLength - NumberOfZeroes - 1 To SelectionLength - 1 F(i) = 0 Next End If FFTRecordLength = SelectionLength + NumberOfZeroes Dim ImagIn() As Double ' ReDim ImagIn(0 To actualRecordLength - 1) 'for testing the FFT function n = FFTRecordLength ReDim ImagIn(0 To FFTRecordLength - 1) ReDim RealOut(0 To FFTRecordLength - 1) ReDim ImagOut(0 To FFTRecordLength - 1)

Call FFT(n, F(), ImagIn(), RealOut(), ImagOut()) '-------------------------------------------------'Calculate the magnitude of the complex FFT outputs '-------------------------------------------------ReDim F(0 To FFTRecordLength - 1) F(0) = Magnitude(RealOut(0), ImagOut(0)) For i = 1 To FFTRecordLength - 1 F(i) = 2 * Magnitude(RealOut(i), ImagOut(i)) 'The magnitude is actually doubled (except the 'first FFT output) here since 'the FFT output coefficients are symmetric about 'half the sampling frequency. To get the correct 'amplitude, the user must add the two symmetric sets 'together. Since both sets are equal, 'the first set can simply be doubled. Next '-------------------------------------------------'---------------------------------------------'Calculate the phase of the complex FFT outputs '---------------------------------------------ReDim Fphase(0 To FFTRecordLength - 1) Fphase(0) = Phase(RealOut(0), ImagOut(0)) 'MsgBox (Fphase(0)) For i = 1 To FFTRecordLength - 1 Fphase(i) = Phase(RealOut(i), ImagOut(i))

88 ' MsgBox (Fphase(i)) Next '---------------------------------------------'The actual FFT length is the data set length + the number of 'padded zeroes. FFTRecordLength = SelectionLength + NumberOfZeroes 'Draw the Frequency Plot Call DrawFrequencyPlot(F(), Fphase()) End If End Sub Private Sub cmdPrint_Click() '' Printer.ScaleLeft = picGraph.Left '' Printer.ScaleTop = picGraph.Top '' Printer.Width = picGraph.ScaleWidth '' Printer.Height = picGraph.ScaleHeight '------------------------------------------------------------'use these two statements to print the form 'Note: The contents of the picture box will not be printed. frmSamples7.PrintForm Printer.EndDoc '------------------------------------------------------------'------------------------------------------------------------'use this statement to print the contents of the picture box 'PrintPictureBox picGraph, 1000, 1000 'PrintPictureBox frmSamples5, 1000, 1000 '------------------------------------------------------------End Sub Private Sub cmdQuit_Click() End End Sub Private Sub Form_Load() 'This subroutine automatically executes when the startup 'form loads. This subroutine initializes everything 'needed for aligning labels, initializing combo boxes, etc. log_of_10 = Log(10)

'calculates the natural log of 10

LFCR = Chr(13) + Chr(10)

'line feed and carriage return

89 change_phase_plot = True 'AcquireOption.Value = True ReadOption.Value = True picGraph.DrawWidth = 1 Ycenter = Int(picGraph.ScaleHeight / 2) 'calculate center of Y axis vtwips_per_division = Int(picGraph.ScaleHeight / 8) htwips_per_division = Int(picGraph.ScaleWidth / 10) hsbExpandGraph.Visible = False hsbExpandGraph.Value = 0 hsbExpandGraph.SmallChange = 1 hsbExpandGraph.LargeChange = 1 Call DrawGridLines

'clear all labels lblVertDiv0.Caption = "" lblVertDiv1.Caption = "" lblVertDiv2.Caption = "" lblVertDiv3.Caption = "" lblVertDiv4.Caption = "" lblVertDiv1n.Caption = "" lblVertDiv2n.Caption = "" lblVertDiv3n.Caption = "" lblVertDiv4n.Caption = "" Dim L As Integer For L = 1 To 9 lbltimeperdiv(L).Caption = "" Next

'fill the cboVoltsPerDiv combo box cboVoltsPerDiv.AddItem "2 mV/div" cboVoltsPerDiv.AddItem "5 mV/div" cboVoltsPerDiv.AddItem "10 mV/div" cboVoltsPerDiv.AddItem "20 mV/div" cboVoltsPerDiv.AddItem "50 mV/div" cboVoltsPerDiv.AddItem "0.1 V/div" cboVoltsPerDiv.AddItem "0.2 V/div" cboVoltsPerDiv.AddItem "0.5 V/div" cboVoltsPerDiv.AddItem "1.0 V/div" cboVoltsPerDiv.AddItem "2.0 V/div" cboVoltsPerDiv.AddItem "5.0 V/div" cboVoltsPerDiv.AddItem "6.2 V/div"

90

'initialize the cboVoltsPerDiv combo box to 'item #0 cboVoltsPerDiv.ListIndex = 9 volts_per_div = 2

cboTimePerDiv.AddItem testgarfield

cboTimePerDiv.ListIndex = 0 deltax = 1

lbltimeperdiv(0) = "" lbltimeperdiv(10) = "" lblDelta1.Visible = False lbldelta2.Visible = False lblTimeBetweenCursors.Visible = False lblFrequencyBetweenCursors.Visible = False lblDelta1.Top = lblTimeBetweenCursors.Top - 20 lbldelta2.Top = lblFrequencyBetweenCursors.Top - 20

cmdFFT.Enabled = False cmdFFTSelective.Enabled = False mnuFFT.Enabled = False mnuSelectiveFFT.Enabled = False

cboFiftyOhms.AddItem "1 MOhm" cboFiftyOhms.AddItem "50 Ohms" cboFiftyOhms.ListIndex = 0

End Sub Public Sub FindLargestAbsoluteValue(inputArray() As Double, sizeofarray) 'this function finds the largest absolute value in an array of values 'The input parameters are the array and the size of the array.

91

Dim i For i = 0 To sizeofarray - 1 If i = 0 Then Largest = Abs(inputArray(i)) Else If Largest < Abs(inputArray(i)) Then Largest = Abs(inputArray(i)) End If End If Next End Sub

Public Sub FindLargestValue(inputArray() As Double, sizeofarray) 'this function finds the largest value in an array of values 'The input parameters are the array and the size of the array. Dim i For i = 0 To sizeofarray - 1 If i = 0 Then Largest = (inputArray(i)) Else If Largest < (inputArray(i)) Then Largest = (inputArray(i)) End If End If Next End Sub Public Sub DrawWaveform(RealIn() As Double) '''''''''''''''''''''''''''' 'Draw the waveform '''''''''''''''''''''''''''' 'volts_per_div = 6 'Call GetVoltsPerDiv 'cboVoltsPerDiv_Click Twips_Per_Volt = vtwips_per_division / volts_per_div LeftCursorSet = False RightCursorSet = False Dim X, Y '*********************************************' 'align vertical axis labels

92 lblVertDiv0.Left = picGraph.Left - 630 lblVertDiv1.Left = picGraph.Left - 630 lblVertDiv2.Left = picGraph.Left - 630 lblVertDiv3.Left = picGraph.Left - 630 lblVertDiv4.Left = picGraph.Left - 630 lblVertDiv1n.Left = picGraph.Left - 630 lblVertDiv2n.Left = picGraph.Left - 630 lblVertDiv3n.Left = picGraph.Left - 630 lblVertDiv4n.Left = picGraph.Left - 630 lblVertDiv0.Top = picGraph.Top + picGraph.Height / 2 - 100 lblVertDiv1.Top = picGraph.Top + Int(picGraph.Height / 2) - vtwips_per_division 100 lblVertDiv2.Top = picGraph.Top + Int(picGraph.Height / 2) - (vtwips_per_division * 2) - 100 lblVertDiv3.Top = picGraph.Top + Int(picGraph.Height / 2) - (vtwips_per_division * 3) - 100 lblVertDiv4.Top = picGraph.Top + Int(picGraph.Height / 2) - (vtwips_per_division * 4) - 100 lblVertDiv1n.Top = picGraph.Top + Int(picGraph.Height / 2) + (vtwips_per_division) 100 lblVertDiv2n.Top = picGraph.Top + Int(picGraph.Height / 2) + (vtwips_per_division * 2) - 100 lblVertDiv3n.Top = picGraph.Top + Int(picGraph.Height / 2) + (vtwips_per_division * 3) - 100 lblVertDiv4n.Top = picGraph.Top + Int(picGraph.Height / 2) + (vtwips_per_division * 4) - 100 '*********************************************' '*********************************************' 'set values to vertical axis labels lblVertDiv0.Caption = "0 V" lblVertDiv1.Caption = Str(volts_per_div * 1) + " V" lblVertDiv2.Caption = Str(volts_per_div * 2) + " V" lblVertDiv3.Caption = Str(volts_per_div * 3) + " V" lblVertDiv4.Caption = Str(volts_per_div * 4) + " V" lblVertDiv1n.Caption = Str(volts_per_div * -1) + " V" lblVertDiv2n.Caption = Str(volts_per_div * -2) + " V" lblVertDiv3n.Caption = Str(volts_per_div * -3) + " V" lblVertDiv4n.Caption = Str(volts_per_div * -4) + " V" '*********************************************' Dim time_per_twip As Double ' deltax = 1

93 '*********************************************' 'This section determines if all of the data 'points will fit inside one window of the graph. 'If not, a horizontal scroll bar must be displayed in order 'to scroll to see the rest of the waveform 'Since the smallest unit is a twip, the highest # 'of data points that are able to be displayed in one window 'equals the width of the window in twips. '*********************************************' Dim hsbscalefactor 'Dim ExpandGraph As Boolean 'flag used to indicate if # of samples 'can fit in one window or if the graph 'needs to be expanded If actualRecordLength * deltax = 1 Then 'x.xxx 'seconds timestring = " S" 'time_per_div_label = time_per_div * 1 ElseIf time_per_div * 1000 >= 1 Then '0.xxxxx 'milliseconds timestring = " mS" time_per_div_label = time_per_div * 1000 currenttime = currenttime * 1000 ElseIf time_per_div * 10 ^ 6 >= 1 Then '0.00000xxxxx 'microseconds timestring = " uS" time_per_div_label = time_per_div * (10 ^ 6) currenttime = currenttime * (10 ^ 6) Else 'time_per_div * 10 ^ 9 >= 1 Then '0.00000000xxxx 'nanoseconds

96 timestring = " nS" time_per_div_label = time_per_div * (10 ^ 9) currenttime = currenttime * (10 ^ 9) End If Call SetTimeComboBox '********************************************************* 'Update the time per division combo box '********************************************************* '********************************************************* 'Set the time labels '********************************************************* Dim j If ExpandGraph = False Then For j = 0 To 10 lbltimeperdiv(j).Alignment = 2 lbltimeperdiv(j).Top = 4800 lbltimeperdiv(j).Left = picGraph.Left + j * htwips_per_division lbltimeperdiv(j).Width / 2 lbltimeperdiv(j).Caption = Str(time_per_div_label * j) + timestring Next ElseIf ExpandGraph = True Then For j = 0 To 10 lbltimeperdiv(j).Alignment = 2 lbltimeperdiv(j).Top = 4800 lbltimeperdiv(j).Left = picGraph.Left + j * htwips_per_division lbltimeperdiv(j).Width / 2 Dim chewy As String chewy = Str(currenttime + time_per_div_label * j) chewy = Left(chewy, 6) lbltimeperdiv(j).Caption = chewy + timestring Next End If ''''''''''''''''''''''''''''''''''' 'end of drawing waveform code ''''''''''''''''''''''''''''''''''' End Sub '******************************************** 'May be discarded: 'Private Sub vsbVoltage_Change()

97 ' Call DrawWaveform(RealIn()) 'End Sub 'Private Sub vsbVoltage_Scroll() ' vsbVoltage_Change 'End Sub '******************************************** Public Sub DrawGridLines() 'This subroutine draws the grid lines for the graph in picGraph Dim vtwips_per_small_div Dim num_small_vdiv vtwips_per_small_div = vtwips_per_division / 4 num_small_vdiv = picGraph.ScaleHeight / vtwips_per_small_div 'draw the small horizontal lines for the vertical axis Dim i For i = 1 To (num_small_vdiv / 2 - 1) picGraph.Line (0, Ycenter - i * vtwips_per_small_div)-(picGraph.ScaleWidth, Ycenter - i * vtwips_per_small_div), _ RGB(50, 50, 50) picGraph.Line (0, Ycenter + i * vtwips_per_small_div)-(picGraph.ScaleWidth, Ycenter + i * vtwips_per_small_div), _ RGB(50, 50, 50) Next

'draw the small vertical lines for the horizontal axis Dim num_small_hdiv Dim htwips_per_small_div htwips_per_small_div = htwips_per_division / 4 num_small_hdiv = picGraph.ScaleWidth / htwips_per_small_div For i = 1 To (num_small_hdiv - 1) picGraph.Line (i * htwips_per_small_div, 0)-(i * htwips_per_small_div, picGraph.ScaleHeight), _ RGB(50, 50, 50) Next

'*********************************************************************** **' 'This draws the horizontal grid lines (for the vertical axis) on the graph 'draw the center line (0 volts)

98 picGraph.Line (0, Ycenter)-(picGraph.ScaleWidth, Ycenter), _ RGB(150, 150, 150) For i = 1 To 4 picGraph.Line (0, Ycenter + i * vtwips_per_division)-(picGraph.ScaleWidth, Ycenter + i * vtwips_per_division), _ RGB(100, 100, 100) picGraph.Line (0, Ycenter - i * vtwips_per_division)-(picGraph.ScaleWidth, Ycenter i * vtwips_per_division), _ RGB(100, 100, 100) Next picGraph.Line (0, Ycenter + 4 * vtwips_per_division)-(picGraph.ScaleWidth, Ycenter + 4 * vtwips_per_division), _ RGB(150, 150, 150) picGraph.Line (0, Ycenter - 4 * vtwips_per_division)-(picGraph.ScaleWidth, Ycenter 4 * vtwips_per_division), _ RGB(150, 150, 150) '*********************************************************************** **'

'*********************************************************************** **' 'This draws the larger vertical grid lines (for the horizontal axis) on the graph For i = 0 To 9 picGraph.Line (0 + i * htwips_per_division, 0)-(0 + i * htwips_per_division, picGraph.ScaleHeight), _ RGB(100, 100, 100) Next '*********************************************************************** **'

End Sub Private Sub hsbExpandGraph_Change() 'This subroutine executes if the horizontal scroll 'bar on the time-domain plot is changed. 'create local variables equivalent to 'LeftCursorSet and RightCursorSet

99 Dim LCursorSet As Boolean Dim RCursorSet As Boolean

'Determine which cursors are set on the time-domain plot If LeftCursorSet = True Then LCursorSet = True Else LCursorSet = False End If If RightCursorSet = True Then RCursorSet = True Else RCursorSet = False End If 'Redraw time-domain plot Call DrawWaveform(RealIn()) 'If the left cursor is set: If LCursorSet = True Then Call DrawLeftCursor(LeftCursorXvalue, LeftCursorIvalue) End If 'If the right cursor is set: If RCursorSet = True Then Call DrawRightCursor(RightCursorXvalue, RightCursorIvalue) End If lblhsbvalue.Caption = hsbExpandGraph.Value End Sub Private Sub hsbExpandGraph_Scroll() 'This subroutine is executed if the horizontal scroll bar 'on the time-domain plot is scrolled. hsbExpandGraph_Change End Sub

Private Sub mnuAbout_Click() 'Executes if "About" is selected under the "Help" menu MsgBox "This program was developed for a Master's thesis under Dr. Larry Wurtz." + LFCR + _ LFCR + "University of Alabama" + LFCR + _ "Department of Electrical and Computer Engineering" + LFCR + _

100 "Lance Nicholas Covert, 2003", , "About this program" End Sub Private Sub mnuAcquireData_Click() 'Runs the cmdAcquire_click subroutine if the "Acquire Data" is selected 'under the "Tools" menu. Call cmdAcquire_Click End Sub Private Sub mnuBlackman_Click() 'Apply Blackman Window Function Dim n For n = 0 To actualRecordLength - 1 RealIn(n) = CDbl(RealIn(n)) * (0.42 - 0.5 * Cos(2 * Pi * n / actualRecordLength) + 0.08 * Cos(4 * Pi * n / actualRecordLength)) Next Call DrawWaveform(RealIn()) End Sub Private Sub mnuExit_Click() 'Exit the program End End Sub Private Sub mnuFFT_Click() 'Perform the FFT on the entire data set Call cmdFFT_Click End Sub Private Sub mnuFindLargestAbsValue_Click() 'Finds the largest absolute value of the samples in the data set '(time-domain) Call FindLargestAbsoluteValue(RealIn(), actualRecordLength) MsgBox "The largest absolute value is " + Str(Round(Largest, 6)) + " volts.", , "Largest Absolute Value" End Sub Private Sub mnuFindLargestValue_Click() 'Finds the largest value of the samples in the data set '(time-domain) Call FindLargestValue(RealIn(), actualRecordLength) MsgBox "The largest value is " + Str(Round(Largest, 6)) + " volts.", , "Largest Value" End Sub

101 Private Sub mnuHamming_Click() 'Apply Hamming Window Function Dim n For n = 0 To actualRecordLength - 1 RealIn(n) = CDbl(RealIn(n)) * (0.54 - 0.46 * Cos(2 * Pi * n / actualRecordLength)) Next Call DrawWaveform(RealIn()) End Sub Private Sub mnuHanning_Click() 'Apply Hanning Window Function Dim n For n = 0 To actualRecordLength - 1 RealIn(n) = CDbl(RealIn(n)) * (0.5) * (1 - Cos((Pi * n) / actualRecordLength)) Next Call DrawWaveform(RealIn()) End Sub Private Sub mnuHowDoIUseTheCursors_Click() 'Help Topic: How to use the cursors MsgBox "The program has two cursors in the time-domain plot" + LFCR + _ "and one cursor on the frequency plots." + LFCR + LFCR + _ "For the time-domain plot, click the left mouse button to place" + LFCR + _ "the left cursor and click the right mouse button to place the right cursor." + LFCR + _ LFCR + "On the frequency plots, the left mouse button places the cursor" + LFCR + _ "and the right mouse button hides the cursor.", , "How to use the cursors" End Sub Private Sub mnuPurpose_Click() 'Help Topic: Purpose of the software MsgBox "This program can acquire data in two ways:" + LFCR + _ "1) From the National Instruments 100 MHz digitizer card" + LFCR + _ "2) From a text (.txt) or binary (.bin) file stored locally" + LFCR + LFCR + _ "This program then displays the time-domain information and allows" + LFCR + _ "the user to perform spectral analysis on that data via a Fast" + LFCR + _ "Fourier Transform (FFT) algorithm." + LFCR + LFCR + _ "The program displays both the magnitude and phase of the signal" + LFCR + _ "in the frequency-domain.", , "What does this software do?" End Sub Private Sub mnuReadData_Click() 'Read data from file Call cmdAcquire_Click End Sub

102

Private Sub mnuRectangular_Click() 'Apply the Rectangular window function 'Since using the rectangular window function is 'simply the input data unmodified, this function 'just reads in the original data from the file to restore 'the original waveform. If AcquireOption.Value = True Then ReadOption.Value = True End If Call cmdAcquire_Click End Sub Private Sub mnuSelectiveFFT_Click() 'Perform the selective FFT on the data points between the 'two cursors in the time-domain Call cmdFFTSelective_Click End Sub Private Sub mnuSineCubed_Click() 'Apply Sine Cubed Window Function Dim n For n = 0 To actualRecordLength - 1 RealIn(n) = CDbl(RealIn(n)) * ((Sin(n * Pi / actualRecordLength)) ^ 3) Next 'picGraph.Cls Call DrawWaveform(RealIn()) End Sub Private Sub mnuSineLobe_Click() 'Apply Sine Lobe Window Function Dim i For i = 0 To actualRecordLength - 1 RealIn(i) = CDbl(RealIn(i)) * Sin((Pi * i) / actualRecordLength) Next 'picGraph.Cls Call DrawWaveform(RealIn()) End Sub Private Sub mnuSinetotheFourth_Click() 'Apply Sine to the 4th Window Function Dim n For n = 0 To actualRecordLength - 1 RealIn(n) = CDbl(RealIn(n)) * ((Sin(n * Pi / actualRecordLength)) ^ 4)

103 Next 'picGraph.Cls Call DrawWaveform(RealIn()) End Sub Private Sub mnuTriangular_Click() 'Apply Triangle Window Function Dim n For n = 0 To actualRecordLength / 2 RealIn(n) = CDbl(RealIn(n)) * (2 * n) / actualRecordLength Next For n = (actualRecordLength / 2) + 1 To actualRecordLength - 1 RealIn(n) = CDbl(RealIn(n)) * 2 * (actualRecordLength - n) / actualRecordLength Next Call DrawWaveform(RealIn()) End Sub Private Sub mnuWhatIsTheResourceName_Click() 'Help Topic: What is the resource name? MsgBox "The Resource Name field directs the software to the correct" + LFCR + _ "NI 5112 digitizer. This field should normally contain 'DAQ::1' unless" + LFCR + _ "more than one NI 5112 digitizers are present in the system.", , "Resource Name" End Sub Private Sub mnuWriteYourOwnTextFile_Click() 'Help Topic: How to write your own text file for input MsgBox "Text (.txt) files can be written by the user " + _ "for importing " + LFCR + "data into the program. This allows the user " + _ "to use the program" + LFCR + "to analyze data that was previously" + LFCR + _ "gathered or created outside of this data acquisition system." + LFCR + _ LFCR + "To create your own .txt file do the following:" + LFCR + _ "1) Create a new .txt file" + LFCR + _ "2) The first line should contain the number of samples" + LFCR + _ "3) The second line should contain the sample rate" + LFCR + _ "4) The third line should contain the first sample" + LFCR + _ "5) The fourth line should contain the second sample, and so on" + LFCR + LFCR + _ "To import the new .txt file into the program:" + LFCR + _ "1) Type in the path and filename of the .txt file" + LFCR + _ "2) Click the 'Read waveform from .txt file and plot' radio button", , "How do I write my own .txt files for input?" End Sub Private Sub picGraph_MouseDown(Button As Integer, Shift As Integer, X As Single, Y As Single)

104 'This subroutine is executed if either mouse button is pressed over 'the time-domain plot window. Dim i If ExpandGraph = False Then i = (X / deltax) i = Int(i) X = Int(X) If i 0 Then X = X - logscalex X = ((Log((i * deltaF))) / (log_of_10)) * logscalex + logscalex CDbl(scale_value_for_xshift) * frmFrequency.hsbScroll_FreqPlot.Value Else X=0 End If

cursor_freqplot_X = X cursor_on_freqplot = True 'there is a cursor on the screen Call DrawLeftCursor_FreqPlot(X, i) End If ElseIf Button = 2 Then 'right mouse button was pressed 'so erase the cursor from the frequency plots cursor_on_freqplot = False

127 change_phase_plot = True Call DrawFrequencyPlot(F(), Fphase()) End If End Sub Public Sub DrawLeftCursor_FreqPlot(X As Single, i As Double) 'This subroutine draws the left cursor on the magnitude and phase 'plots Dim red Dim green Dim blue red = 175 'bright grey green = 175 blue = 175 Dim Y Dim Yphase If i > 0 Then 'X = X - logscalex X = ((Log((i * deltaF))) / (log_of_10)) * logscalex + logscalex CDbl(scale_value_for_xshift) * frmFrequency.hsbScroll_FreqPlot.Value ' MsgBox (X) Else X=0 End If If frmFrequency.chkDecibels = 0 Then Y = yzero - F(i) * TwipsPerVolt_FreqPlot 'one twip per volt ElseIf frmFrequency.chkDecibels = 1 Then If F(i) = 0 Then 'This would cause an error when Log(0) was calculated. 'The limit of log(x) as x approaches zero is not bound. 'The limit approaches negative (-) infinity. 'In this case, let 20*(log(0)/log_of_10) = -1000 dB Y = yzero - Int(number_of_twips_per_dB * (-1000)) Else Y = yzero - Int(number_of_twips_per_dB * 20 * CDbl(Log(F(i))) / log_of_10) End If End If Yphase = yzeroPhase - Fphase(i) * twips_per_180_degrees frmFrequency.picGraph2.Circle (X, Y), 40, QBColor(15) frmFrequency.picGraph3.Circle (X, Yphase), 40, QBColor(15) 'Draw the Cursor Line on both the magnitude and phase plots

128 frmFrequency.picGraph2.Line (X, 0)-(X, frmFrequency.picGraph2.ScaleHeight), RGB(red, green, blue) frmFrequency.picGraph3.Line (X, 0)-(X, frmFrequency.picGraph3.ScaleHeight), RGB(red, green, blue) If frmFrequency.chkDecibels = 0 Then frmFrequency.lblCursorMag.Caption = Str(Round(F(i), 5)) ElseIf frmFrequency.chkDecibels = 1 Then If F(i) = 0 Then 'This would cause an error when Log(0) was calculated. 'The limit of log(x) as x approaches zero is not bound. 'The limit approaches negative (-) infinity. 'In this case, let 20*(log(0)/log_of_10) = -1000 dB frmFrequency.lblCursorMag.Caption = Str(Round(-1000, 5)) Else frmFrequency.lblCursorMag.Caption = Str(Round(20 * (Log(F(i)) / log_of_10), 5)) End If End If frmFrequency.lblCursorPhase.Caption = Str(Round(Fphase(i), 5)) frmFrequency.lblCursorIValue.Caption = i frmFrequency.lblCursorFreq.Caption = Str(Round(i * deltaF, 5))

End Sub Public Sub cmdCursorShiftLeft_Click() 'This subroutine shifts the frequency plot cursor to the left 'by one data point If cursor_freqplot_i > 0 Then cursor_freqplot_i = cursor_freqplot_i - 1 Else cursor_freqplot_i = cursor_freqplot_i End If Call picGraph2_MouseDown(2, 0, 0, 0) Call DrawLeftCursor_FreqPlot(cursor_freqplot_X, cursor_freqplot_i) cursor_on_freqplot = True End Sub Public Sub cmdCursorShiftRight_Click() 'This subroutine shifts the frequency plot cursor to the right 'by one data point If cursor_freqplot_i < FFTRecordLength / 2 Then

129 cursor_freqplot_i = cursor_freqplot_i + 1 Else cursor_freqplot_i = cursor_freqplot_i End If Call picGraph2_MouseDown(2, 0, 0, 0) Call DrawLeftCursor_FreqPlot(cursor_freqplot_X, cursor_freqplot_i) cursor_on_freqplot = True End Sub Public Sub mnuDCComponent_click() 'This subroutine reports the DC component 'when selected from the 'Tools' menu on the 'frequency plot window. If F(0) = 0 Then MsgBox "The DC component is " + Str(Round(F(0), 5)) + " volts or " + Str(Round(1000, 5)) + " dB.", , "DC Component" Else MsgBox "The DC component is " + Str(Round(F(0), 5)) + " volts or " + Str(Round(20 * (Log(F(0)) / log_of_10), 5)) + " dB.", , "DC Component" End If End Sub

Public Sub Calculate_Log_base_10() 'This subroutine creates a look-up table for the base-10 logs. ReDim log_base_10(0 To actualRecordLength) End Sub Private Sub ReadOptionTxt_Click() 'The "Read waveform from text file" option was selected. cboFiftyOhms.Visible = False lblImpedance.Visible = False End Sub