Imports System
Imports TUSB0214DAMSampleAppVB.TUSB0214DAMSampleApp

' 波形定義
Public Enum WShape As Integer
    Sin
    Rectangle
    Triangle
End Enum

Namespace TUSB0214DAMSampleAppVB
    Module Etc
        ' 周波数値から周波数を表す文字列を生成する
        Public Function GetFrequencyStr(freq As Double) As String
            If freq > 1000000.0 Then ' 1MHzより大はエラー
                Return "Freq. OVF"
            ElseIf freq = 1000000.0 Then ' 1MHzの時
                Return "1.00000MHz"
            ElseIf freq >= 100000.0 Then ' 100KHz以上
                Return (freq / 1000.0).ToString("F3") & "kHz"
            ElseIf freq >= 10000.0 Then ' 10KHz以上
                Return (freq / 1000.0).ToString("F4") & "kHz"
            ElseIf freq >= 1000.0 Then ' 1KHz以上
                Return (freq / 1000.0).ToString("F5") & "kHz"
            ElseIf freq >= 100.0 Then ' 100Hz以上
                Return freq.ToString("F3") & "Hz"
            ElseIf freq >= 10.0 Then ' 10Hz以上
                Return freq.ToString("F4") & "Hz"
            ElseIf freq >= 1.0 Then ' 1Hz以上
                Return freq.ToString("F5") & "Hz"
            ElseIf freq >= 0.1 Then ' 0.1Hz以上
                Return freq.ToString("F6") & "Hz"
            ElseIf freq >= 0.01 Then ' 0.01Hz以上
                Return freq.ToString("F7") & "Hz"
            Else
                Return freq.ToString("F7") & "Hz"
            End If
        End Function

        ' クロックの要求周波数からカウンタの設定値を算出する
        ' freq:要求周波数
        ' kilo:周波数を1000倍するかどうか
        ' setn:設定すべき数値
        ' 範囲外ならfalse
        Public Function GetClockSetting(freq As Double, kilo As Boolean, ByRef setn As UInteger) As Boolean
            If kilo Then
                freq *= 1000.0
            End If
            Dim tmpd As Double = Math.Round(100000000.0 / freq, MidpointRounding.AwayFromZero)
            setn = 0
            If tmpd < 100.0 Then
                Return False
            ElseIf tmpd > 4297296925.0 Then
                Return False
            End If
            setn = CUInt(tmpd)
            Return True
        End Function

        ' 波形イメージの要求周波数から波形に必要なデータ数算出する
        Public Function GetWaveLength(freq As Double, kilo As Boolean, clkfreq As Double, ByRef len As Integer) As Boolean
            If kilo Then
                freq *= 1000.0
            End If
            ' 四捨五入して整数化
            len = CInt(Math.Round(clkfreq / freq, MidpointRounding.AwayFromZero))
            ' 波形個数が2以上、メモリ長以内になければエラー
            If len < 2 OrElse len > 262144 Then
                Return False
            Else
                Return True
            End If
        End Function

        ' クロックの設定値から実際に生成される周波数を算出する
        Public Function GetActualFrequency(setn As UInteger) As Double
            If setn = 0 Then
                Return 0.0
            End If
            Dim tmpd As Double = 100000000.0 / setn
            Return tmpd
        End Function

        ' 電圧レベルがレンジ内であるかどうか確認する
        Public Function VoltRangeChk(range As RangeSel, volt As Double) As Boolean
            Dim VRangeMax() As Double = { ' レンジ毎の最大値
                9.9997, '±10Vレンジ
                4.9998, '±5Vレンジ
                2.4999, '±2.5Vレンジ
                1.25,   '±1.25Vレンジ
                9.9998, '10Vレンジ
                4.9999, '5Vレンジ
                2.5     '2.5Vレンジ
            }
            Dim VRangeMin() As Double = { ' レンジ毎の最小値
                -10.0,  '±10Vレンジ
                -5.0,   '±5Vレンジ
                -2.5,   '±2.5Vレンジ
                -1.25,  '±1.25Vレンジ
                0.0,    '10Vレンジ
                0.0,    '5Vレンジ
                0.0     '2.5Vレンジ
            }

            Dim tmprange As Integer = CInt(range)
            If VRangeMax(tmprange) < volt Then
                Return False
            End If
            If VRangeMin(tmprange) > volt Then
                Return False
            End If
            Return True
        End Function

        ' 電圧値(double)からDACに設定すべき値を算出する
        Public Function DoubleToDacCode(dat As Double, range As RangeSel) As UShort
            Dim tmpd As Double
            Select Case range
                Case RangeSel.Bipol10
                    tmpd = (dat + 10.0) / 20.0 * 16384
                Case RangeSel.Bipol5
                    tmpd = (dat + 5.0) / 10.0 * 16384
                Case RangeSel.Bipol2_5
                    tmpd = (dat + 2.5) / 5.0 * 16384
                Case RangeSel.Bipol1_25
                    tmpd = (dat + 1.25) / 2.5 * 16384
                Case RangeSel.Unipol10
                    tmpd = dat / 10.0 * 16384
                Case RangeSel.Unipol5
                    tmpd = dat / 5.0 * 16384
                Case RangeSel.Unipol2_5
                    tmpd = dat / 2.5 * 16384
                Case Else
                    tmpd = 0.0
            End Select
            Return tmpd.ToUShort()
        End Function

        ' DACの値(ushort)から相当する電圧(double)を算出する
        Public Function DacCodeToVolt(dat As UShort, range As RangeSel) As Double
            Select Case range
                Case RangeSel.Bipol10
                    Return (CDbl(dat) / 16384 * 20.0 - 10.0)
                Case RangeSel.Bipol5
                    Return (CDbl(dat) / 16384 * 10.0 - 5.0)
                Case RangeSel.Bipol2_5
                    Return (CDbl(dat) / 16384 * 5.0 - 2.5)
                Case RangeSel.Bipol1_25
                    Return (CDbl(dat) / 16384 * 2.5 - 1.25)
                Case RangeSel.Unipol10
                    Return (CDbl(dat) / 16384 * 10.0)
                Case RangeSel.Unipol5
                    Return (CDbl(dat) / 16384 * 5.0)
                Case RangeSel.Unipol2_5
                    Return (CDbl(dat) / 16384 * 2.5)
                Case Else
                    Return 0.0
            End Select
        End Function

        ' 波形イメージを生成する
        Public Sub WaveImageGen(shape As WShape, range As RangeSel, offset As Double, amp As Double, ByRef wimage() As UShort, len As Integer)
            Select Case shape
                Case WShape.Sin ' sin
                    For i As Integer = 0 To len - 1
                        wimage(i) = DoubleToDacCode(offset + amp * Math.Sin(2 * Math.PI * CDbl(i) / CDbl(len)), range)
                    Next
                Case WShape.Rectangle ' rectangle
                    Dim HD As UShort = DoubleToDacCode(offset + amp, range)
                    Dim LD As UShort = DoubleToDacCode(offset - amp, range)
                    Dim mid As Integer = len \ 2
                    For i As Integer = 0 To mid - 1
                        wimage(i) = HD
                    Next
                    For i As Integer = mid To len - 1
                        wimage(i) = LD
                    Next
                Case WShape.Triangle ' triangle
                    Dim diff As Double = (amp * 4.0) / CDbl(len)
                    Dim Deg90 As Integer = len \ 4
                    Dim Deg270 As Integer = len * 3 \ 4
                    For i As Integer = 0 To Deg90 - 1
                        wimage(i) = DoubleToDacCode(offset + diff * CDbl(i), range)
                    Next
                    For i As Integer = Deg90 To Deg270 - 1
                        wimage(i) = DoubleToDacCode(offset + 2.0 * amp - diff * CDbl(i), range)
                    Next
                    For i As Integer = Deg270 To len - 1
                        wimage(i) = DoubleToDacCode(offset - 4.0 * amp + diff * CDbl(i), range)
                    Next
                Case Else
                    For i As Integer = 0 To len - 1
                        wimage(i) = 0
                    Next
            End Select
        End Sub
    End Module
End Namespace