
'
'
'      _                      _____               _                _  _              
'     | |                    / ____|             | |              | || |             
'   __| | _ __  ___   _ __  | |      ___   _ __  | |_  _ __  ___  | || |  ___  _ __    
'  / _` || '__|/ _ \ | '_ \ | |     / _ \ | '_ \ | __|| '__|/ _ \ | || | / _ \| '__|   
' | (_| || |  | (_) || |_) || |____| (_) || | | || |_ | |  | (_) || || ||  __/| |     
'  \__,_||_|   \___/ | .__/  \_____|\___/ |_| |_| \__||_|   \___/ |_||_| \___||_|        
'                    | |                                                                               
'                    |_|                                                                               
'
'
' 
' Release 25.0.0.1
' Major rewirte
' This app requires dropControllerV3 with firmware dC3_fw0250001 or higher
' not compatible with dropControllverV2
'

' increased the max number of drops to 24
' drop data objects now created at run time
' added load/save function
' Change drop labels by double click
'
'
'
' Reminders
' Set version in AssemblyInfo.vb file
' 
'
' To do
' Auto update COM ports
'





Imports System
Imports System.IO
Imports System.IO.Ports
Imports System.Reflection
Imports System.Drawing
Imports System.Text
Imports Microsoft.Win32
Imports System.Net.Mime.MediaTypeNames
Imports System.Windows.Forms.VisualStyles
Imports System.Runtime.InteropServices
Imports System.Net.Security
Imports System.Windows.Forms.VisualStyles.VisualStyleElement.Window
Imports System.Runtime.InteropServices.ComTypes
Imports System.Net.WebRequestMethods
Imports System.Xml.Schema
Imports System.Security.Cryptography




Public Class MainForm

    ' debug
    Dim DEBUG_MASTER As Boolean = False
    Dim widthDebug As Integer = 1156
    Dim widthNormal As Integer = 870

    Dim FirstRun As Boolean = True

    Dim versionNumber As Version
    Dim versionString As String = ""

    Dim numValves As Integer = 6

    Dim comPORT As String
    Dim receivedData As String = ""


    Dim greyedOut As Color = Me.BackColor
    Dim red As Color = Color.FromArgb(255, 150, 150)
    Dim blue As Color = Color.FromArgb(135, 210, 250)
    Dim green As Color = Color.FromArgb(150, 255, 150)


    Dim MaxNumDrops As Integer = 24
    'Dim NumberActiveDrops = 1
    Dim NumberOnDrops = 1


    ' arrays to hold the drop data objects
    ' all drop data objects are created at run time.
    ' Lazy programing. I do not use element(0) in arrays. This means drop 1 is at position 1

    Dim RowLabels_LBL_NEW(MaxNumDrops + 1) As Label
    Dim dropOnOffButtons_BTN(MaxNumDrops + 1) As Button
    Dim solValves_CB(MaxNumDrops + 1) As ComboBox

    Dim StartDash_LBL(MaxNumDrops + 1) As Label
    Dim StartTimes_TB(MaxNumDrops + 1) As TextBox
    Dim StartTimeIncDec_BTN(MaxNumDrops + 1) As Button
    Dim StartTimeIncDecVal_TB(MaxNumDrops + 1) As TextBox

    Dim SizeDash_LBL(MaxNumDrops + 1) As Label
    Dim SizeTimes_TB(MaxNumDrops + 1) As TextBox
    Dim SizeTimeIncDec_BTN(MaxNumDrops + 1) As Button
    Dim SizeTimeIncDecVal_TB(MaxNumDrops + 1) As TextBox


    ' arrays for the actual values
    Dim drop_OnOff(MaxNumDrops + 1) As String
    Dim drop_Sol(MaxNumDrops + 1) As Integer
    Dim drop_StartTime(MaxNumDrops + 1) As Long
    Dim dropStartTimeDelta(MaxNumDrops + 1) As String
    Dim dropStartTimeDeltaVal(MaxNumDrops + 1) As Long
    Dim drop_SizeTime(MaxNumDrops + 1) As Long
    Dim drop_SizeTime_Delta(MaxNumDrops + 1) As String
    Dim dropSizeDeltaVal(MaxNumDrops + 1) As Long

    Dim drop_StopTime(MaxNumDrops + 1) As Long

    Dim LP_dropRowLabel_LBL(MaxNumDrops + 1) As Label
    Dim LP_dropData_LBL(MaxNumDrops + 1) As Label


    Dim FT1_StartTime As Long = 0
    Dim FT2_StartTime As Long = 0
    Dim FT3_StartTime As Long = 0
    Dim CT_StartTime As Long = 0
    Dim FT1_Size As Long = 0
    Dim FT2_Size As Long = 0
    Dim FT3_Size As Long = 0
    Dim CT_Size As Long = 0


    'Loop Mode
    Dim sequenceAborted As Boolean = False







    ' __  __
    '|  \/  |                    
    '| \  / |  ___  _ __   _   _ 
    '| |\/| | / _ \| '_ \ | | | |
    '| |  | ||  __/| | | || |_| |
    '|_|  |_| \___||_| |_| \__,_|
    '

    Private Sub AboutToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles AboutToolStripMenuItem.Click
        AboutBox1.ShowDialog()
    End Sub

    Private Sub OnlineHelpToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles OnlineHelpToolStripMenuItem.Click
        Try
            Process.Start("https://www.dropcontroller.com")
        Catch ex As Exception
            MsgBox("Can't load Web page" & vbCrLf & ex.Message)
        End Try
    End Sub



    ' mode, 1, 2 , 3
    '  Resume 1 	
    ' The operating system Is about To Resume from a suspended state.    

    ' StatusChange 	2 	
    ' A power mode status notification Event has been raised by the operating system. This might indicate a weak Or charging battery, a transition between AC power And battery, Or another change In the status Of the system power supply.

    ' Suspend 	3 	
    ' The operating system Is about To be suspended.

    Private Sub SystemEvents_PowerModeChanged(ByVal sender As Object, ByVal e As PowerModeChangedEventArgs)

        debug("e.mode = " & e.Mode)

        Select Case e.Mode

            Case PowerModes.Suspend
                debug("suspend = " & Now)
                'txtSuspend.Text = Now

            Case PowerModes.Resume
                ' txtResume.Text = Now
                debug("resume = " & Now)

        End Select

    End Sub





    '
    '  __  __         _          ______                        _                        _  
    ' |  \/  |       (_)        |  ____|                      | |                      | | 
    ' | \  / |  __ _  _  _ __   | |__  ___   _ __  _ __ ___   | |      ___    __ _   __| | 
    ' | |\/| | / _` || || '_ \  |  __|/ _ \ | '__|| '_ ` _ \  | |     / _ \  / _` | / _` | 
    ' | |  | || (_| || || | | | | |  | (_) || |   | | | | | | | |____| (_) || (_| || (_| | 
    ' |_|  |_| \__,_||_||_| |_| |_|   \___/ |_|   |_| |_| |_| |______|\___/  \__,_| \__,_| 



    Private Sub MainForm_Load(sender As Object, e As EventArgs) Handles MyBase.Load

        debug("MainForm_Load")


        If (DEBUG_MASTER = True) Then turnDebugOn() Else turnDebugOff()



        Dim toolTip1 As New ToolTip()

        ' Set up the delays for the ToolTip.
        toolTip1.AutoPopDelay = 5000
        toolTip1.InitialDelay = 1000
        toolTip1.ReshowDelay = 500
        ' Force the ToolTip text to be displayed whether or not the form is active.
        toolTip1.ShowAlways = True


        versionNumber = Assembly.GetExecutingAssembly().GetName().Version
        '  versionString = "dropController build " & versionNumber.ToString()
        Me.Text = "dropController"

        TabPanel.Height = 520
        Me.FormBorderStyle = FormBorderStyle.FixedSingle
        MaximizeBox = False

        ' hide the loopPage
        Me.Height = 600



        CreateDropDataObjects()
        InitValues()
        LoadData("SYSTEM")

        ' add handlers to the side panel objects
        InitHandlers()

        For i As Integer = 1 To Val(NumActiveDrops_LBL2.Text)
            showRow(i)
        Next

        UpdateDropTab()
        InitDropDataArrays()

        initGraphObjects()


        ' About page
        About05_LBL.Text = "App version: " & versionNumber.ToString() & vbCrLf




        startBTNoff()
        PopulateCOMport()

        debug("Initialized and ready to start" & vbCrLf)


    End Sub



    Private Sub MainForm_FormClosing(sender As Object, e As FormClosingEventArgs) Handles MyBase.FormClosing
        debug("Close X selected")
        CloseProgram()
    End Sub

    Private Sub ExitButton_BTN_Click(sender As Object, e As EventArgs) Handles ExitToolStripMenuItem.Click
        debug("Menu Exit selected")
        Me.Close()
    End Sub


    Private Sub CloseProgram()
        debug("Program closing")
        closeValves()
        SaveData("SYSTEM")
        Disconnect()
    End Sub








    '   
    '     _____  _   _  _____  _______ 
    '    |_   _|| \ | ||_   _||__   __|
    '      | |  |  \| |  | |     | |   
    '      | |  | . ` |  | |     | |   
    '     _| |_ | |\  | _| |_    | |   
    '    |_____||_| \_||_____|   |_|   
    '   
    '   


    Private Sub CreateDropDataObjects()
        ' create the drop data objects (labels, buttons, textboxes etc)

        For i As Integer = 1 To MaxNumDrops

            RowLabels_LBL_NEW(i) = New Label
            RowLabels_LBL_NEW(i).Name = "Drop " & i.ToString & "Row_LBL"
            RowLabels_LBL_NEW(i).Font = New Font("Segoe UI", 10)
            RowLabels_LBL_NEW(i).AutoSize = False
            RowLabels_LBL_NEW(i).TextAlign = 16
            RowLabels_LBL_NEW(i).Height = 30
            RowLabels_LBL_NEW(i).Width = 82
            RowLabels_LBL_NEW(i).Text = "Drop " & i.ToString
            AddHandler RowLabels_LBL_NEW(i).DoubleClick, AddressOf RowLabelDoubleClick



            dropOnOffButtons_BTN(i) = New Button
            dropOnOffButtons_BTN(i).Name = "D" & i.ToString & "OnOffBtn"
            dropOnOffButtons_BTN(i).Font = New Font("Segoe UI", 10)
            dropOnOffButtons_BTN(i).BackColor = Color.LightSkyBlue
            dropOnOffButtons_BTN(i).Height = 30
            dropOnOffButtons_BTN(i).Width = 56
            AddHandler dropOnOffButtons_BTN(i).Click, AddressOf OnOffButton_Click

            solValves_CB(i) = New ComboBox
            solValves_CB(i).Name = "D" & i.ToString & "Sol_CB"
            solValves_CB(i).Font = New Font("Segoe UI", 10)
            solValves_CB(i).BackColor = Color.White
            solValves_CB(i).Height = 28
            solValves_CB(i).Width = 34
            solValves_CB(i).Items.Add("1")
            solValves_CB(i).Items.Add("2")
            solValves_CB(i).Items.Add("3")
            solValves_CB(i).Items.Add("4")
            solValves_CB(i).Items.Add("5")
            solValves_CB(i).Items.Add("6")
            solValves_CB(i).SelectedIndex = 0

            StartDash_LBL(i) = New Label
            StartDash_LBL(i).Name = "D" & i.ToString & "startDash"
            StartDash_LBL(i).Font = New Font("Segoe UI", 10)
            StartDash_LBL(i).BackColor = Color.Black
            StartDash_LBL(i).Height = 1
            StartDash_LBL(i).Width = 6

            StartTimes_TB(i) = New TextBox
            StartTimes_TB(i).Name = "D" & i.ToString & "StartTimes_TB"
            StartTimes_TB(i).Font = New Font("Segoe UI", 12)
            StartTimes_TB(i).TextAlign = HorizontalAlignment.Center
            StartTimes_TB(i).MaxLength = 4
            StartTimes_TB(i).Height = 28
            StartTimes_TB(i).Width = 50
            AddHandler StartTimes_TB(i).Leave, AddressOf LeaveTextBox_Leave
            AddHandler StartTimes_TB(i).KeyPress, AddressOf TextBox_KeyPress

            StartTimeIncDec_BTN(i) = New Button
            StartTimeIncDec_BTN(i).Name = "D" & i.ToString & "StartTimeIncDecBtn"
            StartTimeIncDec_BTN(i).Font = New Font("Segoe UI", 10)
            StartTimeIncDec_BTN(i).BackColor = Color.LightSkyBlue
            StartTimeIncDec_BTN(i).Height = 30
            StartTimeIncDec_BTN(i).Width = 56
            AddHandler StartTimeIncDec_BTN(i).Click, AddressOf IncDecButton_Click

            ' D4StartIncVal_TB
            StartTimeIncDecVal_TB(i) = New TextBox
            StartTimeIncDecVal_TB(i).Font = New Font("Segoe UI", 12)
            StartTimeIncDecVal_TB(i).TextAlign = HorizontalAlignment.Center
            StartTimeIncDecVal_TB(i).MaxLength = 3
            StartTimeIncDecVal_TB(i).Height = 28
            StartTimeIncDecVal_TB(i).Width = 44
            StartTimeIncDecVal_TB(i).Name = "D" & i.ToString & "StartTimeIncDecVal_TB"
            AddHandler StartTimeIncDecVal_TB(i).Leave, AddressOf LeaveTextBox_Leave
            AddHandler StartTimeIncDecVal_TB(i).KeyPress, AddressOf TextBox_KeyPress

            SizeDash_LBL(i) = New Label
            SizeDash_LBL(i).Name = "D" & i.ToString & "sizeDash"
            SizeDash_LBL(i).Font = New Font("Segoe UI", 10)
            SizeDash_LBL(i).BackColor = Color.Black
            SizeDash_LBL(i).Height = 1
            SizeDash_LBL(i).Width = 6

            SizeTimes_TB(i) = New TextBox
            SizeTimes_TB(i).Name = "D" & i.ToString & "SizeTimes_TB"
            SizeTimes_TB(i).Font = New Font("Segoe UI", 12)
            SizeTimes_TB(i).TextAlign = HorizontalAlignment.Center
            SizeTimes_TB(i).MaxLength = 4
            SizeTimes_TB(i).Height = 28
            SizeTimes_TB(i).Width = 50
            AddHandler SizeTimes_TB(i).Leave, AddressOf LeaveTextBox_Leave
            AddHandler SizeTimes_TB(i).KeyPress, AddressOf TextBox_KeyPress

            SizeTimeIncDec_BTN(i) = New Button
            SizeTimeIncDec_BTN(i).Name = "D" & i.ToString & "SizeIncDecBtn"
            SizeTimeIncDec_BTN(i).Font = New Font("Segoe UI", 10)
            SizeTimeIncDec_BTN(i).BackColor = Color.LightSkyBlue
            SizeTimeIncDec_BTN(i).Height = 30
            SizeTimeIncDec_BTN(i).Width = 56
            AddHandler SizeTimeIncDec_BTN(i).Click, AddressOf IncDecButton_Click

            SizeTimeIncDecVal_TB(i) = New TextBox
            SizeTimeIncDecVal_TB(i).Name = "D" & i.ToString & "SizeIncDecVal_TB"
            SizeTimeIncDecVal_TB(i).Font = New Font("Segoe UI", 12)
            SizeTimeIncDecVal_TB(i).TextAlign = HorizontalAlignment.Center
            SizeTimeIncDecVal_TB(i).MaxLength = 3
            SizeTimeIncDecVal_TB(i).Height = 28
            SizeTimeIncDecVal_TB(i).Width = 44
            AddHandler SizeTimeIncDecVal_TB(i).Leave, AddressOf LeaveTextBox_Leave
            AddHandler SizeTimeIncDecVal_TB(i).KeyPress, AddressOf TextBox_KeyPress


            ' Loop Page

            LP_dropRowLabel_LBL(i) = New Label
            LP_dropRowLabel_LBL(i).Name = "D" & i.ToString & "LP_dropRow_LBL"
            LP_dropRowLabel_LBL(i).Font = New Font("Courier New", 12)
            LP_dropRowLabel_LBL(i).TextAlign = 16  ' text align left middle 
            LP_dropRowLabel_LBL(i).Height = 18
            LP_dropRowLabel_LBL(i).Width = 120
            LP_dropRowLabel_LBL(i).Text = "Drop " & i
            LP_dropRowLabel_LBL(i).Left = 14
            LP_dropRowLabel_LBL(i).Top = (i - 1) * 25 + 10


            LP_dropData_LBL(i) = New Label
            LP_dropData_LBL(i).Name = "D" & i.ToString & "LP_dropData_LBL"
            LP_dropData_LBL(i).Font = New Font("Courier New", 12)
            LP_dropData_LBL(i).TextAlign = 16  ' text align left middle
            LP_dropData_LBL(i).Height = 18
            LP_dropData_LBL(i).Width = 370
            ' LP_dropData_LBL(i).Text = "0   0000 [-123]  0000 [-123]  00000"
            LP_dropData_LBL(i).Text = LP_dropData_LBL(i).Name
            LP_dropData_LBL(i).Left = 140
            LP_dropData_LBL(i).Top = (i - 1) * 25 + 10

        Next

    End Sub





    Private Sub InitDropDataArrays()
        ' initialises the arrays used to store the drop data values
        ' using seperate arrays is a little wasteful but makes life easier when calculation the times

        For i As Integer = 1 To MaxNumDrops + 1
            drop_OnOff(i) = "ON"
            drop_Sol(i) = 1
            drop_StartTime(i) = 0
            dropStartTimeDelta(i) = "OFF"
            dropStartTimeDeltaVal(i) = 0

            drop_SizeTime(i) = 123
            drop_SizeTime_Delta(i) = "OFF"
            dropSizeDeltaVal(i) = 0

            drop_StopTime(i) = 0
        Next

    End Sub







    Private Sub InitHandlers()

        debug("Enter InitHandlers")

        ' side panel
        AddHandler CT_StartTime_TB.KeyPress, AddressOf TextBox_KeyPress
        AddHandler CT_IncDecTime_TB.KeyPress, AddressOf TextBox_KeyPress

        AddHandler CT_StartTime_TB.Leave, AddressOf LeaveTextBox_Leave
        AddHandler CT_IncDecTime_TB.Leave, AddressOf LeaveTextBox_Leave

        AddHandler SyncStartOffset_Time_TB.KeyPress, AddressOf TextBox_KeyPress
        AddHandler BulbStopOffset_Time_TB.KeyPress, AddressOf TextBox_KeyPress
        AddHandler SyncStartOffset_Time_TB.Leave, AddressOf LeaveTextBox_Leave
        AddHandler BulbStopOffset_Time_TB.Leave, AddressOf LeaveTextBox_Leave

        AddHandler FT1_Time_TB.KeyPress, AddressOf TextBox_KeyPress
        AddHandler FT1_Time_TB.Leave, AddressOf LeaveTextBox_Leave
        AddHandler FT1_IncDecTime_TB.KeyPress, AddressOf TextBox_KeyPress
        AddHandler FT1_IncDecTime_TB.Leave, AddressOf LeaveTextBox_Leave

        AddHandler FT2_Time_TB.KeyPress, AddressOf TextBox_KeyPress
        AddHandler FT2_Time_TB.Leave, AddressOf LeaveTextBox_Leave
        AddHandler FT2_IncDecTime_TB.KeyPress, AddressOf TextBox_KeyPress
        AddHandler FT2_IncDecTime_TB.Leave, AddressOf LeaveTextBox_Leave

        AddHandler FT3_Time_TB.KeyPress, AddressOf TextBox_KeyPress
        AddHandler FT3_Time_TB.Leave, AddressOf LeaveTextBox_Leave
        AddHandler FT3_IncDecTime_TB.KeyPress, AddressOf TextBox_KeyPress
        AddHandler FT3_IncDecTime_TB.Leave, AddressOf LeaveTextBox_Leave

        AddHandler LP_waitTimeVal_TB.KeyPress, AddressOf TextBox_KeyPress


        AddHandler FT1_OnOff_BUTTON.Click, AddressOf OnOffButton_Click
        AddHandler FT2_OnOff_BUTTON.Click, AddressOf OnOffButton_Click
        AddHandler FT3_OnOff_BUTTON.Click, AddressOf OnOffButton_Click

        AddHandler CT_IncDec_BTN.Click, AddressOf IncDecButton_Click
        AddHandler FT1_IncDec_BTN.Click, AddressOf IncDecButton_Click
        AddHandler FT2_IncDec_BTN.Click, AddressOf IncDecButton_Click
        AddHandler FT3_IncDec_BTN.Click, AddressOf IncDecButton_Click

        AddHandler LP_waitTimeVal_TB.Leave, AddressOf LeaveTextBox_Leave


        ' Settings
        AddHandler CT_Pulse_TB.KeyPress, AddressOf TextBox_KeyPress
        AddHandler FT1_Pulse_TB.KeyPress, AddressOf TextBox_KeyPress
        AddHandler FT2_Pulse_TB.KeyPress, AddressOf TextBox_KeyPress
        AddHandler FT3_Pulse_TB.KeyPress, AddressOf TextBox_KeyPress


        AddHandler CT_Pulse_TB.Leave, AddressOf LeaveTextBox_Leave
        AddHandler FT1_Pulse_TB.Leave, AddressOf LeaveTextBox_Leave
        AddHandler FT2_Pulse_TB.Leave, AddressOf LeaveTextBox_Leave
        AddHandler FT3_Pulse_TB.Leave, AddressOf LeaveTextBox_Leave

        AddHandler Set_FormatTextBoxes_BTN.Click, AddressOf SET_OnOff_BTN_Click
        AddHandler SET_LEO_BUT.Click, AddressOf SET_OnOff_BTN_Click
        AddHandler SET_SOUND_BTN.Click, AddressOf SET_OnOff_BTN_Click

        AddHandler ValveDrain_BTN_1.Click, AddressOf ValveDrain_BTN_Click
        AddHandler ValveDrain_BTN_2.Click, AddressOf ValveDrain_BTN_Click
        AddHandler ValveDrain_BTN_3.Click, AddressOf ValveDrain_BTN_Click
        AddHandler ValveDrain_BTN_4.Click, AddressOf ValveDrain_BTN_Click
        AddHandler ValveDrain_BTN_5.Click, AddressOf ValveDrain_BTN_Click
        AddHandler ValveDrain_BTN_6.Click, AddressOf ValveDrain_BTN_Click

    End Sub


    Private Sub InitValues()

        For i As Integer = 1 To MaxNumDrops
            RowLabels_LBL_NEW(i).Text = "Drop " & i.ToString
            dropOnOffButtons_BTN(i).Text = "OFF"
            StartTimes_TB(i).Text = "0"
            StartTimeIncDec_BTN(i).Text = "INC"
            StartTimeIncDecVal_TB(i).Text = "0"
            SizeTimes_TB(i).Text = "0"
            SizeTimeIncDec_BTN(i).Text = "INC"
            SizeTimeIncDecVal_TB(i).Text = "0"
        Next

        NumActiveDrops_LBL2.Text = 1

        CT_OnOff_BTN.Text = "OFF"
        CT_StartTime_TB.Text = "0"
        CT_IncDec_BTN.Text = "OFF"
        CT_IncDecTime_TB.Text = "0"
        SyncStartOffset_Time_TB.Text = "0"
        BulbStopOffset_Time_TB.Text = "0"

        FT1_OnOff_BUTTON.Text = "OFF"
        FT1_Time_TB.Text = "0"
        FT1_IncDec_BTN.Text = "OFF"
        FT1_IncDecTime_TB.Text = "0"

        FT2_OnOff_BUTTON.Text = "OFF"
        FT2_Time_TB.Text = "0"
        FT2_IncDec_BTN.Text = "OFF"
        FT2_IncDecTime_TB.Text = "0"

        FT3_OnOff_BUTTON.Text = "OFF"
        FT3_Time_TB.Text = "0"
        FT3_IncDec_BTN.Text = "OFF"
        FT3_IncDecTime_TB.Text = "0"

        LoopMode_BTN.Text = "OFF"
        lp_TimerOrButton_BTN.Text = "BUTTON"
        LP_waitTimeVal_TB.Text = "0"


        CT_Pulse_TB.Text = "10"
        FT1_Pulse_TB.Text = "10"
        FT2_Pulse_TB.Text = "10"
        FT3_Pulse_TB.Text = "10"
        SET_LEO_BUT.Text = "OFF"
        SET_SOUND_BTN.Text = "OFF"
        Set_FormatTextBoxes_BTN.Text = "ON"

    End Sub











    '   _____                                  _            
    '  / ____|                                | |              
    ' | |      ___   _ __   _ __    ___   ___ | |_    
    ' | |     / _ \ | '_ \ | '_ \  / _ \ / __|| __|  
    ' | |____| (_) || | | || | | ||  __/| (__ | |_   
    '  \_____|\___/ |_| |_||_| |_| \___| \___| \__|                                                            
    '                                                                                                                                
    ' After connecting wait for the user to click the start button
    '

#Region "Connect & Disconnect"

    Private Sub RefreshCOM_BTN_Click_1(sender As Object, e As EventArgs) Handles refreshCOM_BTN.Click
        PopulateCOMport()
    End Sub


    Private Sub PopulateCOMport()
        COMport_CB.Text = ""
        COMport_CB.Items.Clear()
        For Each sp As String In My.Computer.Ports.SerialPortNames
            COMport_CB.Items.Add(sp)
        Next

        debug("COM port list updated")

    End Sub


    Private Sub Connect_BTN_Click_1(sender As Object, e As EventArgs) Handles connect_BTN.Click
        debug("connect_BTN_Click")
        debug("  SerialPort1.IsOpen= " & SerialPort1.IsOpen)



        If (connect_BTN.Text = "CONNECT") Then


            If (COMport_CB.SelectedItem = "") Then
                connect_BTN.Text = "CONNECT"
                debug("  ERROR: No COM port selected")
                MsgBox("Select a COM port first", , "ERROR")

            Else

                connect_BTN.Text = "Connecting..."
                connect_BTN.Enabled = False

                ' the timer takes care of the next bit
                ' without a timer, the button text change is too fast (or does not happen)
                timer_updateConnectButton.Enabled = True

            End If

        ElseIf (connect_BTN.Text = "DIS-CONNECT") Then
            Disconnect()
        End If

    End Sub



    Private Sub Timer_updateConnectButton_Tick(sender As Object, e As EventArgs) Handles timer_updateConnectButton.Tick

        ' this is used to change the CONNECT BUTTON text to "Connecting..."
        ' without a timer the text does not change.  The timer is set to 100ms

        timer_updateConnectButton.Enabled = False

        debug("timer_updateConnectButton_Tick")
        If (SerialPort1.IsOpen) Then
            debug("  Error: " & comPORT & " already open")
        End If


        comPORT = COMport_CB.SelectedItem

        If (Not SerialPort1.IsOpen) Then

            SerialPort1.PortName = comPORT
            SerialPort1.BaudRate = 9600
            SerialPort1.DataBits = 8
            SerialPort1.Parity = Parity.None
            SerialPort1.StopBits = StopBits.One
            SerialPort1.Handshake = Handshake.None
            SerialPort1.Encoding = System.Text.Encoding.Default
            SerialPort1.ReadTimeout = 10000

            'Arduino Leonardo
            ' The Arduino Nano fails to connect when DTR and RTS are enabled so have kept as a separate section
            If (SET_LEO_BUT.Text = "ON") Then
                SerialPort1.DtrEnable = True
                SerialPort1.RtsEnable = True
            End If

            ' check if device is available: 
            Try
                SerialPort1.Open()
            Catch ex As Exception
                connect_BTN.Text = "CONNECT"
                connect_BTN.Enabled = True

                debug("  Failed to open" & comPORT)
                debug("  - Error = " & ex.Message)
                MsgBox("Error. Cannot open COM port: " & ex.Message, MsgBoxStyle.Critical, "ERROR")
            End Try


        Else
            debug("  Error: " & comPORT & " already open")
        End If
        If (SerialPort1.IsOpen) Then

            SerialPort1.DiscardInBuffer()
            receivedData = ""

            debug("COM " & comPORT & " opened")


            ' start checkSerialData timer
            Timer_recieveSerialDataOn()

            ' need a delay here

            'See if the dropController is there - send HELLO message and wait for a reply
            debug("HELLO sent" & vbCrLf)

            sendCommandToDropController("[HELLO]")

            ' start connection timeout timer
            Timer_ConnectionTimeoutON()

            ' wait for a reply from the dropController or timeout if no reply received

            ' If a reply is received the process command section handles it
            ' If the reply is not received the timeout function handles it


        End If

    End Sub






    Private Sub Timer_checkConnect_Tick(sender As Object, e As EventArgs) Handles Timer_ConnectionTimeout.Tick

        ' if this fires the HELLO message has not been  received
        ' show error message
        ' reset the buttons etc

        Timer_ConnectionTimeoutOFF()
        Timer_recieveSerialDataOff()

        connect_BTN.Text = "CONNECT"
        debug("HELLO reply message not received from the dropController")
        MsgBox("ERROR!" & vbCrLf & "Cannot connect to the dropController")


        If (SerialPort1.IsOpen) Then
            SerialPort1.Close()
            debug("Serial port closed")
        End If

        PopulateCOMport()
        connect_BTN.Enabled = True

    End Sub





    Private Sub Disconnect()
        'close the connection a reset the button and timer labels

        Timer_ConnectionTimeoutOFF()


        If (SerialPort1.IsOpen) Then
            sendCommandToDropController("[BYE]")
            closeValves()
            receivedData = ""
            SerialPort1.DiscardInBuffer()
            SerialPort1.Close()
            debug("COM port closed")
        End If

        connect_BTN.Text = "CONNECT"
        COMport_CB.Enabled = True
        refreshCOM_BTN.Enabled = True
        startBTNoff()

        disableValveDrainButtons()


    End Sub






#End Region 'Region "Connect & Disconnect"






    ' _____              _                       _____              _         _    _____          _         
    '|  __ \            (_)                     / ____|            (_)       | |  |  __ \        | |        
    '| |__) | ___   ___  _   ___ __   __ ___   | (___    ___  _ __  _   __ _ | |  | |  | |  __ _ | |_  __ _ 
    '|  _  / / _ \ / __|| | / _ \\ \ / // _ \   \___ \  / _ \| '__|| | / _` || |  | |  | | / _` || __|/ _` |
    '| | \ \|  __/| (__ | ||  __/ \ V /|  __/   ____) ||  __/| |   | || (_| || |  | |__| || (_| || |_| (_| |
    '|_|  \_\\___| \___||_| \___|  \_/  \___|  |_____/  \___||_|   |_| \__,_||_|  |_____/  \__,_| \__|\__,_|
    '

    ' CheckReceivedData()
#Region "recieveSerialData"

    Private Sub Timer_recieveSerialData_Tick(sender As Object, e As EventArgs) Handles Timer_recieveSerialData.Tick

        ' receivedData is the buffer used to store what ever data is received via the serial port
        Timer_recieveSerialDataOff()

        Dim Incoming As String = ""

        If (SerialPort1.IsOpen) Then
            Try
                Incoming = SerialPort1.ReadExisting()
                If Incoming Is Nothing Then
                    Incoming = ""
                End If
            Catch ex As TimeoutException
                Incoming = "Error: Serial Port read timed out."
            End Try

            If (Incoming = "Error: Serial Port read timed out.") Then
                MsgBox(Incoming, "COM PORT ERROR")
                Incoming = ""
            End If
        End If

        If (Incoming <> "") Then
            debug("RD=" & Incoming)
        End If

        receivedData = receivedData + Incoming

        ' If (receivedData <> "") Then
        ' debug("RD=" & receivedData)
        ' End If

        CheckReceivedData()

        Timer_recieveSerialDataOn()
    End Sub




    Private Sub CheckReceivedData()
        ' uses the global variable receivedData

        Dim pos1 As Integer
        Dim pos2 As Integer
        Dim length As Integer
        Dim newCommand As String
        Dim done As Boolean = False

        While (Not done)

            pos1 = receivedData.IndexOf("[") + 1
            pos2 = receivedData.IndexOf("]") + 1



            ' do we have a START MARKER and an END MARKER?
            If (pos1 = 0 Or pos2 = 0) Then
                ' we do not have both START and END MARKERS so we are done
                done = True
            End If



            If (Not done) Then

                ' We have a START MARKER and an END MARKER but are they in the correct order?
                ' Occasionally we may not get complete data and the end marker will be in front of the start marker
                ' for example "xx][xxxxx][xx"

                ' if pos2 <pos1 then remove the first part of the string from receivedData
                ' for example.  "xx][xxxxx][xx" to "[xxxxx][xx"

                If (pos1 <> 0 And pos2 <> 0) Then
                    If (pos2 < pos1) Then
                        receivedData = Microsoft.VisualBasic.Mid(receivedData, pos2 + 1)
                        pos1 = receivedData.IndexOf("[") + 1
                        pos2 = receivedData.IndexOf("]") + 1
                    End If
                End If

                ' We may have removed the only END MARKER so need to check again.
                ' This is not the best code but this way keeps the flow easy to see and makes it easier to edit.
                ' (The first check is not really required).


                pos1 = receivedData.IndexOf("[") + 1
                pos2 = receivedData.IndexOf("]") + 1

                If (pos1 = 0 Or pos2 = 0) Then
                    ' we do not have both start and end markers and we are done
                    done = True
                End If

            End If



            ' If we still have a START MARKER and an END MARKER we should have a command
            If (Not done) Then

                length = pos2 - pos1 + 1
                If (length > 0) Then

                    ' get the data from between the first START MARKER and the first END MARKER
                    newCommand = Mid(receivedData, pos1 + 1, length - 2)

                    'remove the command (including MARKERS)from receivedData
                    receivedData = Mid(receivedData, pos2 + 1)

                    debug("New cmd=" & newCommand)

                    If (newCommand = "HELLO") Then

                        ' HELLO received
                        Timer_ConnectionTimeoutOFF()


                        If (SET_SOUND_BTN.Text = "ON") Then
                            My.Computer.Audio.Play(My.Resources.complete, AudioPlayMode.Background)
                        End If

                        startBTNon()
                        refreshCOM_BTN.Enabled = False
                        connect_BTN.Text = "DIS-CONNECT"
                        connect_BTN.Enabled = True
                        COMport_CB.Enabled = False

                        activateValveDrainButtons()


                        ' firmwareVersion_LBL
                    ElseIf (newCommand(0) = "V") Then

                        ' version received
                        ' [V,0001,May  5 2018]
                        Dim tmpSplit() As String = Split(newCommand, ",", -1, CompareMethod.Text)
                        aboutFirmware_02_LBL.Text = "Build " & tmpSplit(1)
                        firwareUpdated = True


                        ' Finished The Sequence
                    ElseIf (newCommand = "FTS") Then

                        Timer_dropAckTimeoutOFF()

                        ' drop sequence completed
                        ' reset for the next drop
                        debug("FTS received")

                        If (sequenceAborted = False) Then
                            debug("if (sequenceAborted = False) ")

                            If (SET_SOUND_BTN.Text = "ON") Then
                                My.Computer.Audio.Play(My.Resources.ready, AudioPlayMode.Background)
                            End If
                            initForNextDrop()
                        Else
                            debug("if (sequenceAborted = True) ")
                            sequenceAborted = False
                            debug("SequenceAborted = False ")
                        End If


                    ElseIf (newCommand(0) = "M") Then
                        debug("MESSAGE: " & newCommand)

                    Else
                        '  debug(">>" & newCommand & "<<")
                    End If

                End If ' (length > 0) 

            End If

        End While

    End Sub



    Function GetSerialInData() As String

        Dim Incoming As String
        Try
            Incoming = SerialPort1.ReadExisting()
            If Incoming Is Nothing Then
                Return "nothing" & vbCrLf
            Else
                Return Incoming
            End If
        Catch ex As TimeoutException
            Return "Error: Serial Port read timed out."
        End Try

    End Function


#End Region ' "recieveSerialData"









    '
    '   _    _        _                       ______                    _    _                    
    '  | |  | |      | |                     |  ____|                  | |  (_)                   
    '  | |__| |  ___ | | _ __    ___  _ __   | |__  _   _  _ __    ___ | |_  _   ___   _ __   ___ 
    '  |  __  | / _ \| || '_ \  / _ \| '__|  |  __|| | | || '_ \  / __|| __|| | / _ \ | '_ \ / __|
    '  | |  | ||  __/| || |_) ||  __/| |     | |   | |_| || | | || (__ | |_ | || (_) || | | |\__ \
    '  |_|  |_| \___||_|| .__/  \___||_|     |_|    \__,_||_| |_| \___| \__||_| \___/ |_| |_||___/
    '                   | |                                                                       
    '                   |_|                                                                       




    Private Sub LeaveTextBox_Leave(sender As Object, e As EventArgs)
        Dim tb = DirectCast(sender, TextBox)
        formatTB(tb)
    End Sub


    Private Sub formatTB(ByVal TB As TextBox)
        If Set_FormatTextBoxes_BTN.Text = "ON" Then
            Dim len As Integer = TB.MaxLength
            If (len = 2) Then TB.Text = Format(Val(TB.Text), "00")
            If (len = 3) Then TB.Text = Format(Val(TB.Text), "000")
            If (len = 4) Then TB.Text = Format(Val(TB.Text), "0000")
        Else
            TB.Text = Val(TB.Text).ToString
        End If

    End Sub




    Private Sub FormatAllTextBoxes()

        debug("Enter FormatAllTextBoxes()")

        Dim tmpVar As Long = 0

        If Set_FormatTextBoxes_BTN.Text = "ON" Then

            For i As Integer = 1 To MaxNumDrops
                StartTimes_TB(i).Text = Format(Val(StartTimes_TB(i).Text), "0000")
                StartTimeIncDecVal_TB(i).Text = Format(Val(StartTimeIncDecVal_TB(i).Text), "000")
                SizeTimes_TB(i).Text = Format(Val(SizeTimes_TB(i).Text), "0000")
                SizeTimeIncDecVal_TB(i).Text = Format(Val(SizeTimeIncDecVal_TB(i).Text), "000")
            Next

            CT_StartTime_TB.Text = Format(Val(CT_StartTime_TB.Text), "0000")
            CT_IncDecTime_TB.Text = Format(Val(CT_IncDecTime_TB.Text), "000")

            SyncStartOffset_Time_TB.Text = Format(Val(SyncStartOffset_Time_TB.Text), "0000")
            BulbStopOffset_Time_TB.Text = Format(Val(BulbStopOffset_Time_TB.Text), "0000")

            FT1_Time_TB.Text = Format(Val(FT1_Time_TB.Text), "0000")
            FT1_IncDecTime_TB.Text = Format(Val(FT1_IncDecTime_TB.Text), "000")

            FT2_Time_TB.Text = Format(Val(FT2_Time_TB.Text), "0000")
            FT2_IncDecTime_TB.Text = Format(Val(FT2_IncDecTime_TB.Text), "000")

            FT3_Time_TB.Text = Format(Val(FT3_Time_TB.Text), "0000")
            FT3_IncDecTime_TB.Text = Format(Val(FT3_IncDecTime_TB.Text), "000")

            LP_waitTimeVal_TB.Text = Format(Val(LP_waitTimeVal_TB.Text), "00")



        ElseIf Set_FormatTextBoxes_BTN.Text = "OFF" Then

            For i As Integer = 1 To MaxNumDrops
                StartTimes_TB(i).Text = Val(StartTimes_TB(i).Text).ToString
                StartTimeIncDecVal_TB(i).Text = Val(StartTimeIncDecVal_TB(i).Text).ToString
                SizeTimes_TB(i).Text = Val(SizeTimes_TB(i).Text).ToString
                SizeTimeIncDecVal_TB(i).Text = Val(SizeTimeIncDecVal_TB(i).Text).ToString
            Next

            CT_StartTime_TB.Text = Val(CT_StartTime_TB.Text).ToString
            CT_IncDecTime_TB.Text = Val(CT_IncDecTime_TB.Text).ToString

            SyncStartOffset_Time_TB.Text = Val(SyncStartOffset_Time_TB.Text).ToString
            BulbStopOffset_Time_TB.Text = Val(BulbStopOffset_Time_TB.Text).ToString

            FT1_Time_TB.Text = Val(FT1_Time_TB.Text).ToString
            FT1_IncDecTime_TB.Text = Val(FT1_IncDecTime_TB.Text).ToString

            FT2_Time_TB.Text = Val(FT2_Time_TB.Text).ToString
            FT2_IncDecTime_TB.Text = Val(FT2_IncDecTime_TB.Text).ToString

            FT3_Time_TB.Text = Val(FT3_Time_TB.Text).ToString
            FT3_IncDecTime_TB.Text = Val(FT3_IncDecTime_TB.Text).ToString

            LP_waitTimeVal_TB.Text = Val(LP_waitTimeVal_TB.Text).ToString

        End If

    End Sub


    '  TextBoxes: key press,  allow only numeric values
    Private Sub TextBox_KeyPress(sender As Object, e As KeyPressEventArgs)
        If Asc(e.KeyChar) <> 13 AndAlso Asc(e.KeyChar) <> 10 AndAlso Asc(e.KeyChar) <> 8 AndAlso Not IsNumeric(e.KeyChar) Then
            e.Handled = True
        End If

    End Sub


    Private Sub SET_OnOff_BTN_Click(sender As Object, e As EventArgs)
        Dim btn = DirectCast(sender, Button)
        If btn.Text = "ON" Then btn.Text = "OFF" Else btn.Text = "ON"
        UpdateSettingsTab()
    End Sub


    Public Function CheckSize(val As Long, low As Long, high As Long) As Long
        If (val < low) Then val = low
        If (val > high) Then val = high
        Return val
    End Function



    Private Sub RowLabelDoubleClick(sender As Object, e As EventArgs)
        Dim lbl = DirectCast(sender, Label)


        ' Display message, title, and default value
        Dim UserInput As String = InputBox("Enter a new description for " & lbl.Text, "Enter drop description", lbl.Text)

        If UserInput.Trim().Length > 0 Then lbl.Text = UserInput.Trim()
        UpdateDropTab()


    End Sub



    Private Sub UpdateDropTab()
        ' after the user makes a change, this updates the objects
        ' updates the drop data table and the side panel

        debug("Enter UpdateDropTab()")


        If Val(NumActiveDrops_LBL2.Text) < 10 Then NumActiveDrops_LBL2.Left = 40 Else NumActiveDrops_LBL2.Left = 36
        If Val(NumActiveDrops_LBL2.Text) = 24 Then AddDrop_BTN.Enabled = False Else AddDrop_BTN.Enabled = True
        If Val(NumActiveDrops_LBL2.Text) = 1 Then RemoveDrop_BTN.Enabled = False Else RemoveDrop_BTN.Enabled = True

        FormatAllTextBoxes()

        ' drop data table

        For i As Integer = 1 To Val(NumActiveDrops_LBL2.Text)

            ' If RowLabels_LBL_NEW(i).Text.Length() > 10 Then RowLabels_LBL_NEW(i).Text = RowLabels_LBL_NEW(i).Text.Substring(0, 10)

            If RowLabels_LBL_NEW(i).Text.Length() > 9 Then
                RowLabels_LBL_NEW(i).Font = New Font("Segoe UI", 8)
            Else
                RowLabels_LBL_NEW(i).Font = New Font("Segoe UI", 10)
            End If



            If (dropOnOffButtons_BTN(i).Text = "ON") Then

                dropOnOffButtons_BTN(i).BackColor = Color.FromArgb(150, 255, 150)

                RowLabels_LBL_NEW(i).Enabled = True
                solValves_CB(i).Enabled = True

                StartTimes_TB(i).Enabled = True
                StartTimeIncDec_BTN(i).Enabled = True
                StartTimeIncDec_BTN(i).BackColor = Color.LightSkyBlue
                StartTimeIncDecVal_TB(i).Enabled = True

                SizeTimes_TB(i).Enabled = True
                SizeTimeIncDec_BTN(i).Enabled = True
                SizeTimeIncDec_BTN(i).BackColor = Color.LightSkyBlue
                SizeTimeIncDecVal_TB(i).Enabled = True

                If (StartTimeIncDec_BTN(i).Text = "OFF") Then StartTimeIncDecVal_TB(i).Enabled = False
                If (SizeTimeIncDec_BTN(i).Text = "OFF") Then SizeTimeIncDecVal_TB(i).Enabled = False

            Else
                dropOnOffButtons_BTN(i).BackColor = Color.FromArgb(255, 150, 150)
                RowLabels_LBL_NEW(i).Enabled = False
                solValves_CB(i).Enabled = False
                StartTimes_TB(i).Enabled = False
                StartTimeIncDec_BTN(i).Enabled = False
                StartTimeIncDec_BTN(i).BackColor = greyedOut
                StartTimeIncDecVal_TB(i).Enabled = False

                SizeTimes_TB(i).Enabled = False
                ' SizeIncTimes(i).Enabled = False
                SizeTimeIncDec_BTN(i).Enabled = False
                SizeTimeIncDec_BTN(i).BackColor = greyedOut
                SizeTimeIncDecVal_TB(i).Enabled = False

            End If
        Next

        ' side panel

        ' ALL OFF
        CT_StartTime_TB.Visible = False
        CT_IncDec_BTN.Visible = False
        CT_IncDecTime_TB.Visible = False
        SyncStartOffset_LBL.Visible = False
        SyncStartOffset_Time_TB.Visible = False
        BulbStopOffset_LBL.Visible = False
        BulbStopOffset_Time_TB.Visible = False

        Dim pos1 As Integer = CT_StartTime_TB.Top
        Dim pos2 As Integer = CT_IncDecTime_TB.Top

        If (CT_OnOff_BTN.Text = "ON") Then
            CT_OnOff_BTN.BackColor = green
            CT_StartTime_TB.Visible = True
            CT_StartTime_TB.Enabled = True
            CT_IncDec_BTN.Visible = True
            CT_IncDec_BTN.BackColor = Color.LightSkyBlue
            CT_IncDec_BTN.Enabled = True

            CT_IncDecTime_TB.Visible = True
            CT_IncDecTime_TB.Enabled = True
            If (CT_IncDec_BTN.Text) = "OFF" Then
                CT_IncDecTime_TB.Enabled = False
            End If


        ElseIf (CT_OnOff_BTN.Text = "SYNC") Then

            CT_OnOff_BTN.BackColor = blue

            SyncStartOffset_LBL.Location = New Point(632, pos1 + 3)
            SyncStartOffset_Time_TB.Location = New Point(764, pos2)

            SyncStartOffset_LBL.Visible = True
            SyncStartOffset_Time_TB.Visible = True

        ElseIf (CT_OnOff_BTN.Text = "BULB") Then

            CT_OnOff_BTN.BackColor = blue
            BulbStopOffset_LBL.Location = New Point(632, pos1 + 3)
            BulbStopOffset_Time_TB.Location = New Point(764, pos2)
            BulbStopOffset_LBL.Visible = True
            BulbStopOffset_Time_TB.Visible = True

        ElseIf (CT_OnOff_BTN.Text = "OFF") Then

            CT_OnOff_BTN.BackColor = red
            CT_StartTime_TB.Visible = True
            CT_IncDec_BTN.Visible = True
            CT_IncDec_BTN.BackColor = greyedOut
            CT_IncDecTime_TB.Visible = True
            CT_StartTime_TB.Enabled = False
            CT_IncDec_BTN.Enabled = False
            CT_IncDecTime_TB.Enabled = False

        End If


        If (FT3_OnOff_BUTTON.Text = "ON") Then
            FT3_Time_TB.Visible = True
            FT3_IncDec_BTN.Visible = True
            FT3_IncDecTime_TB.Visible = True

            FT3_OnOff_BUTTON.BackColor = green
            FT3_Time_TB.Enabled = True
            FT3_IncDec_BTN.Enabled = True
            FT3_IncDecTime_TB.Enabled = True
            FT3_IncDec_BTN.BackColor = Color.LightSkyBlue

            If (FT3_IncDec_BTN.Text) = "OFF" Then
                FT3_IncDecTime_TB.Enabled = False
            Else
                FT3_IncDecTime_TB.Enabled = True
            End If

        ElseIf (FT3_OnOff_BUTTON.Text = "OFF") Then
            FT3_OnOff_BUTTON.BackColor = red
            FT3_Time_TB.Enabled = False
            FT3_IncDec_BTN.Enabled = False
            FT3_IncDecTime_TB.Enabled = False
            FT3_IncDec_BTN.BackColor = greyedOut

        End If


        If (FT2_OnOff_BUTTON.Text = "ON") Then
            FT2_Time_TB.Visible = True
            FT2_IncDec_BTN.Visible = True
            FT2_IncDecTime_TB.Visible = True

            FT2_OnOff_BUTTON.BackColor = green
            FT2_Time_TB.Enabled = True
            FT2_IncDec_BTN.Enabled = True
            FT2_IncDecTime_TB.Enabled = True
            FT2_IncDec_BTN.BackColor = Color.LightSkyBlue

            If (FT2_IncDec_BTN.Text) = "OFF" Then
                FT2_IncDecTime_TB.Enabled = False
            Else
                FT2_IncDecTime_TB.Enabled = True
            End If
        ElseIf (FT2_OnOff_BUTTON.Text = "OFF") Then
            FT2_OnOff_BUTTON.BackColor = red
            FT2_Time_TB.Enabled = False
            FT2_IncDec_BTN.Enabled = False
            FT2_IncDecTime_TB.Enabled = False
            FT2_IncDec_BTN.BackColor = greyedOut

        End If


        If (FT1_OnOff_BUTTON.Text = "ON") Then
            FT1_Time_TB.Visible = True
            FT1_IncDec_BTN.Visible = True
            FT1_IncDecTime_TB.Visible = True

            FT1_OnOff_BUTTON.BackColor = green
            FT1_Time_TB.Enabled = True
            FT1_IncDec_BTN.Enabled = True
            FT1_IncDecTime_TB.Enabled = True
            FT1_IncDec_BTN.BackColor = Color.LightSkyBlue

            If (FT1_IncDec_BTN.Text) = "OFF" Then
                FT1_IncDecTime_TB.Enabled = False
            Else
                FT1_IncDecTime_TB.Enabled = True
            End If

        ElseIf (FT1_OnOff_BUTTON.Text = "OFF") Then
            FT1_OnOff_BUTTON.BackColor = red
            FT1_Time_TB.Enabled = False
            FT1_IncDec_BTN.Enabled = False
            FT1_IncDecTime_TB.Enabled = False
            FT1_IncDec_BTN.BackColor = greyedOut
        End If


        If (LoopMode_BTN.Text = "OFF") Then
            LoopMode_BTN.BackColor = red
            timerButton_LBL.ForeColor = Color.Gray
            lp_TimerOrButton_BTN.Enabled = False
            lp_TimerOrButton_BTN.BackColor = greyedOut

        ElseIf (LoopMode_BTN.Text = "ON") Then
            LoopMode_BTN.BackColor = green
            timerButton_LBL.ForeColor = Color.Black
            lp_TimerOrButton_BTN.Enabled = True
            lp_TimerOrButton_BTN.BackColor = blue
        End If


        If (lp_TimerOrButton_BTN.Enabled = False Or lp_TimerOrButton_BTN.Text = "BUTTON") Then
            waitTime_LBL.ForeColor = Color.Gray
            LP_waitTimeVal_TB.Enabled = False
        Else
            waitTime_LBL.ForeColor = Color.Black
            LP_waitTimeVal_TB.Enabled = True
        End If


    End Sub






























    '  _____   _____    ____   _____      _____         _______           _______         ____  
    ' |  __ \ |  __ \  / __ \ |  __ \    |  __ \    /\ |__   __| /\      |__   __| /\    |  _ \ 
    ' | |  | || |__) || |  | || |__) |   | |  | |  /  \   | |   /  \        | |   /  \   | |_) |
    ' | |  | ||  _  / | |  | ||  ___/    | |  | | / /\ \  | |  / /\ \       | |  / /\ \  |  _ < 
    ' | |__| || | \ \ | |__| || |        | |__| |/ ____ \ | | / ____ \      | | / ____ \ | |_) |
    ' |_____/ |_|  \_\ \____/ |_|        |_____//_/    \_\|_|/_/    \_\     |_|/_/    \_\|____/ 
    '

#Region "DROP DATA TAB"

    Private Sub DropsTab_Enter(sender As Object, e As EventArgs) Handles TAB_DROPS.Enter
        debug(vbCrLf & "Enter Drops TAB")
        UpdateDropTab()
    End Sub


    Private Sub DropsTab_Leave(sender As Object, e As EventArgs) Handles TAB_DROPS.Leave
        SaveData("SYSTEM")
        debug("__Exit Drop TAB")
    End Sub




    Private Sub AddDrop_BTN_Click(sender As Object, e As EventArgs) Handles AddDrop_BTN.Click
        If Val(NumActiveDrops_LBL2.Text) < MaxNumDrops Then
            NumActiveDrops_LBL2.Text = Val(NumActiveDrops_LBL2.Text) + 1
            ' add new row
            showRow(Val(NumActiveDrops_LBL2.Text))
        End If
        UpdateDropTab()
    End Sub

    Private Sub RemoveDrop_BTN_Click(sender As Object, e As EventArgs) Handles RemoveDrop_BTN.Click
        If Val(NumActiveDrops_LBL2.Text) > 1 Then
            RemoveRow(Val(NumActiveDrops_LBL2.Text))
            NumActiveDrops_LBL2.Text = Val(NumActiveDrops_LBL2.Text) - 1
        End If
        UpdateDropTab()
    End Sub



    Private Sub showRow(i As Integer)
        ' display the drop data objects 

        ' panels always uses the visible area which messes up the x/y coordinates for new object
        ' to place the new row at the correct location turn scrolling off first
        ' unfortunately this means the panel auto resets top the top
        ' turn scroll off
        dropData_Panel.AutoScroll = False



        Dim x As Integer = 4
        Dim y As Integer = i * 40 - 30



        RowLabels_LBL_NEW(i).Left = x
        RowLabels_LBL_NEW(i).Top = y + 2
        dropData_Panel.Controls.Add(RowLabels_LBL_NEW(i))

        ' ON/OFF BTN
        dropOnOffButtons_BTN(i).Left = RowLabels_LBL_NEW(i).Left + 84
        dropOnOffButtons_BTN(i).Top = y
        dropData_Panel.Controls.Add(dropOnOffButtons_BTN(i))

        ' SOL VALVE
        solValves_CB(i).Left = dropOnOffButtons_BTN(i).Left + 60
        solValves_CB(i).Top = y + 2
        dropData_Panel.Controls.Add(solValves_CB(i))

        ' SEPERATOR
        StartDash_LBL(i).Left = solValves_CB(i).Left + 42
        StartDash_LBL(i).Top = y + 14
        dropData_Panel.Controls.Add(StartDash_LBL(i))

        ' START TIME
        StartTimes_TB(i).Left = StartDash_LBL(i).Left + 14
        StartTimes_TB(i).Top = y - 1
        dropData_Panel.Controls.Add(StartTimes_TB(i))

        'START TIME INC/DEC BUTTON
        StartTimeIncDec_BTN(i).Left = StartTimes_TB(i).Left + 60
        StartTimeIncDec_BTN(i).Top = y
        dropData_Panel.Controls.Add(StartTimeIncDec_BTN(i))

        ' START TIME INC/DEC TB
        StartTimeIncDecVal_TB(i).Left = StartTimeIncDec_BTN(i).Left + 60
        StartTimeIncDecVal_TB(i).Top = y
        dropData_Panel.Controls.Add(StartTimeIncDecVal_TB(i))

        SizeDash_LBL(i).Left = StartTimeIncDecVal_TB(i).Left + 52
        SizeDash_LBL(i).Top = y + 14
        dropData_Panel.Controls.Add(SizeDash_LBL(i))

        SizeTimes_TB(i).Left = SizeDash_LBL(i).Left + 14
        SizeTimes_TB(i).Top = y - 1
        dropData_Panel.Controls.Add(SizeTimes_TB(i))

        SizeTimeIncDec_BTN(i).Left = SizeTimes_TB(i).Left + 60
        SizeTimeIncDec_BTN(i).Top = y + 0
        dropData_Panel.Controls.Add(SizeTimeIncDec_BTN(i))

        SizeTimeIncDecVal_TB(i).Left = SizeTimeIncDec_BTN(i).Left + 60
        SizeTimeIncDecVal_TB(i).Top = y
        dropData_Panel.Controls.Add(SizeTimeIncDecVal_TB(i))

        ' position the header labels
        '  SOL_LBL.Left = solValves_CB(i).Left

        ' START_LBL.Left = StartTimes_TB(i).Left + 3
        ' StartTimeIncDecBtn_LBL.Left = StartTimeIncDec_BTN(i).Left + 13
        ' StartTimeIncDecVal_LBL.Left = StartTimeIncDecVal_TB(i).Left - 4
        ' Size_LBL.Left = SizeTimes_TB(i).Left + 0
        ' SizeIncDecBtn_LBL.Left = SizeTimeIncDec_BTN(i).Left + 13
        ' SizeIncDecTime_LBL.Left = SizeTimeIncDecVal_TB(i).Left - 4

        ' turn scrol back on
        dropData_Panel.AutoScroll = True

    End Sub


    Private Sub RemoveRow(i As Integer)
        ' remove the last drop
        dropData_Panel.Controls.Remove(RowLabels_LBL_NEW(i))
        dropData_Panel.Controls.Remove(dropOnOffButtons_BTN(i))
        dropData_Panel.Controls.Remove(solValves_CB(i))
        dropData_Panel.Controls.Remove(StartDash_LBL(i))
        dropData_Panel.Controls.Remove(StartTimes_TB(i))
        dropData_Panel.Controls.Remove(StartTimeIncDec_BTN(i))
        dropData_Panel.Controls.Remove(StartTimeIncDecVal_TB(i))
        dropData_Panel.Controls.Remove(SizeDash_LBL(i))
        dropData_Panel.Controls.Remove(SizeTimes_TB(i))
        dropData_Panel.Controls.Remove(SizeTimeIncDec_BTN(i))
        dropData_Panel.Controls.Remove(SizeTimeIncDecVal_TB(i))
    End Sub










    '
    '      _                      _______         ____       _____               _                _      
    '     | |                    |__   __| /\    |  _ \     / ____|             | |              | |     
    '   __| | _ __  ___   _ __      | |   /  \   | |_) |   | |      ___   _ __  | |_  _ __  ___  | | ___ 
    '  / _` || '__|/ _ \ | '_ \     | |  / /\ \  |  _ <    | |     / _ \ | '_ \ | __|| '__|/ _ \ | |/ __|
    ' | (_| || |  | (_) || |_) |    | | / ____ \ | |_) |   | |____| (_) || | | || |_ | |  | (_) || |\__ \
    '  \__,_||_|   \___/ | .__/     |_|/_/    \_\|____/     \_____|\___/ |_| |_| \__||_|   \___/ |_||___/
    '                    | |                                                                             
    '                    |_|                                                                             


    Private Sub OnOffButton_Click(sender As Object, e As EventArgs)
        Dim btn = DirectCast(sender, Button)
        If (btn.Text = "ON") Then btn.Text = "OFF" Else btn.Text = "ON"
        UpdateDropTab()
    End Sub



    Private Sub IncDecButton_Click(sender As Object, e As EventArgs)
        Dim btn = DirectCast(sender, Button)
        If (btn.Text = "INC") Then
            btn.Text = "DEC"
        ElseIf btn.Text = "DEC" Then
            btn.Text = "OFF"
        ElseIf btn.Text = "OFF" Then
            btn.Text = "INC"
        End If
        UpdateDropTab()
    End Sub



    Private Sub CT_BUTTON_Click(sender As Object, e As EventArgs) Handles CT_OnOff_BTN.Click
        If CT_OnOff_BTN.Text = "ON" Then
            CT_OnOff_BTN.Text = "SYNC"
        ElseIf CT_OnOff_BTN.Text = "SYNC" Then
            CT_OnOff_BTN.Text = "BULB"
        ElseIf CT_OnOff_BTN.Text = "BULB" Then
            CT_OnOff_BTN.Text = "OFF"
        ElseIf CT_OnOff_BTN.Text = "OFF" Then
            CT_OnOff_BTN.Text = "ON"
        End If
        UpdateDropTab()
    End Sub




    Private Sub LoopMode_BTN_Click(sender As Object, e As EventArgs) Handles LoopMode_BTN.Click
        If (LoopMode_BTN.Text = "ON") Then
            LoopMode_BTN.Text = "OFF"
        Else
            LoopMode_BTN.Text = "ON"
        End If
        UpdateDropTab()
    End Sub

    Private Sub lp_TimerOrButton_BTN_Click(sender As Object, e As EventArgs) Handles lp_TimerOrButton_BTN.Click
        If (lp_TimerOrButton_BTN.Text = "BUTTON") Then
            lp_TimerOrButton_BTN.Text = "TIMER"
        Else
            lp_TimerOrButton_BTN.Text = "BUTTON"
        End If
        UpdateDropTab()
    End Sub


    Private Sub xxupdateLoopElements()
        If (LoopMode_BTN.Text = "OFF") Then
            LoopMode_BTN.BackColor = red
            timerButton_LBL.ForeColor = Color.Gray
            lp_TimerOrButton_BTN.Enabled = False
            lp_TimerOrButton_BTN.BackColor = greyedOut

        ElseIf (LoopMode_BTN.Text = "ON") Then
            LoopMode_BTN.BackColor = green
            timerButton_LBL.ForeColor = Color.Black
            lp_TimerOrButton_BTN.Enabled = True
            lp_TimerOrButton_BTN.BackColor = blue
        End If


        If (lp_TimerOrButton_BTN.Enabled = False Or lp_TimerOrButton_BTN.Text = "BUTTON") Then
            waitTime_LBL.ForeColor = Color.Gray
            LP_waitTimeVal_TB.Enabled = False
        Else
            waitTime_LBL.ForeColor = Color.Black
            LP_waitTimeVal_TB.Enabled = True
        End If
    End Sub

#End Region 'Region "DROP DATA TAB"

















    '  __  __         _           _____  _                _                ____  _______  _   _ 
    ' |  \/  |       (_)         / ____|| |              | |              |  _ \|__   __|| \ | |
    ' | \  / |  __ _  _  _ __   | (___  | |_  __ _  _ __ | |_             | |_) |  | |   |  \| |
    ' | |\/| | / _` || || '_ \   \___ \ | __|/ _` || '__|| __|            |  _ <   | |   | . ` |
    ' | |  | || (_| || || | | |  ____) || |_| (_| || |   | |_             | |_) |  | |   | |\  |
    ' |_|  |_| \__,_||_||_| |_| |_____/  \__|\__,_||_|    \__|   ------   |____/   |_|   |_| \_|
    '                                                           |______|


    Private Sub startBTNoff()
        debug("MainStart_BTN OFF")
        MainStart_BTN.Enabled = False
        MainStart_BTN.BackColor = Color.FromArgb(200, 220, 200)
        ToolTip1.SetToolTip(MainStart_BTN, "Big Start button. Only works when the dropController is connected")
    End Sub

    Private Sub startBTNon()
        debug("MainStart_BTN ON")
        MainStart_BTN.Enabled = True
        MainStart_BTN.BackColor = Color.FromArgb(128, 255, 128)
        ToolTip1.SetToolTip(MainStart_BTN, "Big Start button. Makes things go.")
    End Sub



    Private Sub MainStart_BTN_Click_1(sender As Object, e As EventArgs) Handles MainStart_BTN.Click

        debug(vbCrLf & "MainStart_BTN clicked")

        FormatAllTextBoxes()
        SaveData("SYSTEM")
        makeDrop()

    End Sub












    '    _____  ______  _______  _______  _____  _   _   _____   _____       _______         ____  
    '   / ____||  ____||__   __||__   __||_   _|| \ | | / ____| / ____|     |__   __| /\    |  _ \ 
    '  | (___  | |__      | |      | |     | |  |  \| || |  __ | (___          | |   /  \   | |_) |
    '   \___ \ |  __|     | |      | |     | |  | . ` || | |_ | \___ \         | |  / /\ \  |  _ < 
    '   ____) || |____    | |      | |    _| |_ | |\  || |__| | ____) |        | | / ____ \ | |_) |
    '  |_____/ |______|   |_|      |_|   |_____||_| \_| \_____||_____/         |_|/_/    \_\|____/ 


#Region "SETTINGS TAB"



    Private Sub SETTINGS_Enter(sender As Object, e As EventArgs) Handles TAB_SETTINGS.Enter
        debug(vbCrLf & "Enter Settings TAB")
        UpdateSettingsTab()
    End Sub


    Private Sub SETTINGS_Leave(sender As Object, e As EventArgs) Handles TAB_SETTINGS.Leave
        closeValves()
        UpdateSettingsTab()
        SaveData("SYSTEM")
        debug("__Exit Settings TAB")
    End Sub





    Private Sub UpdateSettingsTab()
        debug("Enter UpdateSettingsTab()")

        If Set_FormatTextBoxes_BTN.Text = "ON" Then
            FT1_Pulse_TB.Text = Format(Val(FT1_Pulse_TB.Text), "000")
            FT2_Pulse_TB.Text = Format(Val(FT2_Pulse_TB.Text), "000")
            FT3_Pulse_TB.Text = Format(Val(FT3_Pulse_TB.Text), "000")
            CT_Pulse_TB.Text = Format(Val(CT_Pulse_TB.Text), "000")
        End If

        If (SET_LEO_BUT.Text = "ON") Then SET_LEO_BUT.BackColor = green
        If (SET_LEO_BUT.Text = "OFF") Then SET_LEO_BUT.BackColor = red

        If (SET_SOUND_BTN.Text = "ON") Then SET_SOUND_BTN.BackColor = green
        If (SET_SOUND_BTN.Text = "OFF") Then SET_SOUND_BTN.BackColor = red

        If (Set_FormatTextBoxes_BTN.Text = "ON") Then Set_FormatTextBoxes_BTN.BackColor = green
        If (Set_FormatTextBoxes_BTN.Text = "OFF") Then Set_FormatTextBoxes_BTN.BackColor = red

    End Sub


    Private Sub SET_DEBUG_BTN_Click(sender As Object, e As EventArgs) Handles SET_DEBUG_BTN.Click
        If (SET_DEBUG_BTN.Text = "ON") Then
            turnDebugOff()
        Else
            turnDebugOn()
        End If
    End Sub










    '       _              _                        _                  
    '      | |            (_)                      | |                 
    '    __| | _ __  __ _  _  _ __    __   __ __ _ | |__   __ ___  ___ 
    '   / _` || '__|/ _` || || '_ \   \ \ / // _` || |\ \ / // _ \/ __|
    '  | (_| || |  | (_| || || | | |   \ V /| (_| || | \ V /|  __/\__ \
    '   \__,_||_|   \__,_||_||_| |_|    \_/  \__,_||_|  \_/  \___||___/



    Private Sub activateValveDrainButtons()
        debug("Enter activateValveDrainButtons()")
        Dim VD_BUT As Button() = New Button() {ValveDrain_BTN_1, ValveDrain_BTN_1, ValveDrain_BTN_2, ValveDrain_BTN_3, ValveDrain_BTN_4, ValveDrain_BTN_5, ValveDrain_BTN_6}
        For i As Integer = 1 To numValves
            VD_BUT(i).Enabled = True
        Next i
    End Sub

    Private Sub disableValveDrainButtons()
        debug("Enter disableValveDrainButtons()")
        Dim VD_BUT As Button() = New Button() {ValveDrain_BTN_1, ValveDrain_BTN_1, ValveDrain_BTN_2, ValveDrain_BTN_3, ValveDrain_BTN_4, ValveDrain_BTN_5, ValveDrain_BTN_6}
        For i As Integer = 1 To numValves
            VD_BUT(i).Enabled = False
        Next i
    End Sub


    Private Sub ValveDrain_BTN_Click(sender As Object, e As EventArgs)
        Dim btn = DirectCast(sender, Button)
        Dim valve As Integer = Val(btn.Name.Last())
        Dim cmd As String = ""

        If (btn.Text = "OPEN") Then
            btn.Text = "CLOSED"
            btn.BackColor = Color.FromArgb(255, 128, 128)
            cmd = "[O" & valve & "0]"

        ElseIf (btn.Text = "CLOSED") Then
            btn.Text = "OPEN"
            btn.BackColor = Color.FromArgb(128, 255, 128)
            cmd = "[O" & valve & "1]"
        End If

        sendCommandToDropController(cmd)
    End Sub


    Private Sub closeValves()
        debug(vbCrLf & "Enter closeValves()")

        If (SerialPort1.IsOpen) Then
            debug("  serial port is open")

            sendCommandToDropController("[OX]")

            debug(vbCrLf & "disableValveDrainButtons()")
            Dim VD_BUT As Button() = New Button() {ValveDrain_BTN_1, ValveDrain_BTN_1, ValveDrain_BTN_2, ValveDrain_BTN_3, ValveDrain_BTN_4, ValveDrain_BTN_5, ValveDrain_BTN_6}
            For i As Integer = 1 To numValves
                VD_BUT(i).Text = "CLOSED"
                VD_BUT(i).BackColor = Color.FromArgb(255, 128, 128)
            Next i

        Else
            debug("  serial port is closed - Valve close cmd not sent")
        End If
    End Sub









#End Region     ' SETTINGS TAB






    '
    '  _____    ______    _____   ______   _______ 
    ' |  __ \  |  ____|  / ____| |  ____| |__   __|
    ' | |__) | | |__    | (___   | |__       | |   
    ' |  _  /  |  __|    \___ \  |  __|      | |   
    ' | | \ \  | |____   ____) | | |____     | |   
    ' |_|  \_\ |______| |_____/  |______|    |_|   
    '



    Private Sub ResetAll_BTN_Click(sender As Object, e As EventArgs) Handles ResetAll_BTN.Click

        Dim reply = MsgBox("Are you sure you want to reset all values?", 4, "Reset All Values")

        If (reply = vbYes) Then
            debug(vbCrLf & "Enter ResetAll()")

            For i As Integer = 2 To Val(NumActiveDrops_LBL2.Text)
                RemoveRow(i)
            Next

            InitValues()
            UpdateDropTab()

            UpdateSettingsTab()


            SaveData("SYSTEM")

            MsgBox("Reset complete", , "Reset All Values")

        End If

    End Sub


























    '    _____  _____             _____   _    _       _______         ____  
    '   / ____||  __ \     /\    |  __ \ | |  | |     |__   __| /\    |  _ \ 
    '  | |  __ | |__) |   /  \   | |__) || |__| |        | |   /  \   | |_) |
    '  | | |_ ||  _  /   / /\ \  |  ___/ |  __  |        | |  / /\ \  |  _ < 
    '  | |__| || | \ \  / ____ \ | |     | |  | |        | | / ____ \ | |_) |
    '   \_____||_|  \_\/_/    \_\|_|     |_|  |_|        |_|/_/    \_\|____/ 



#Region "Graph"


    Private Sub TAB_GRAPH_Enter(sender As Object, e As EventArgs) Handles TAB_GRAPH.Enter
        debug(vbCrLf & "Enter Graph TAB")
        showGraph()
    End Sub

    Private Sub GRAPH_Leave(sender As Object, e As EventArgs) Handles TAB_GRAPH.Leave
        debug("__Exit GRAPH TAB")

        For i = 2 To Val(NumActiveDrops_LBL2.Text) + 4
            GRF_PB.Controls.Remove(Graph_Axes(i))
            GRF_PB.Controls.Remove(Graph_RowLabel(i))
        Next

    End Sub


    Private Function roundUpNearest100(tmpNum As Integer) As Integer
        Dim tmpFraction As Integer = tmpNum / 100
        tmpFraction = tmpFraction * 100
        If (tmpNum > tmpFraction) Then tmpFraction = tmpFraction + 100
        Return tmpFraction
    End Function



    Dim Graph_RowLabel(MaxNumDrops + 10) As Label
    Dim Graph_Axes(MaxNumDrops + 10) As Label
    Dim col(7) As Color


    Private Sub initGraphObjects()
        debug(vbCrLf & "init graph objects")

        Dim Label_Y_Pos = 0

        ' colours used for the solenoid valves
        col(1) = Color.FromArgb(128, 0, 0, 255)
        col(2) = Color.FromArgb(128, 0, 255, 0)
        col(3) = Color.FromArgb(128, 255, 0, 0)
        col(4) = Color.FromArgb(128, 255, 0, 255)
        col(5) = Color.FromArgb(128, 0, 255, 255)
        col(6) = Color.FromArgb(128, 245, 255, 0)

        ' set the graph key colours
        KEY_LBL_V1.BackColor = col(1)
        KEY_LBL_V2.BackColor = col(2)
        KEY_LBL_V3.BackColor = col(3)
        KEY_LBL_V4.BackColor = col(4)
        KEY_LBL_V5.BackColor = col(5)
        KEY_LBL_V6.BackColor = col(6)


        For i = 1 To MaxNumDrops + 10
            Graph_RowLabel(i) = New Label
            Graph_RowLabel(i).Name = "DropRowLBL" & i.ToString
            Graph_RowLabel(i).Font = New Font("Segoe UI", 10)
            Graph_RowLabel(i).AutoSize = False
            Graph_RowLabel(i).TextAlign = 16
            Graph_RowLabel(i).Height = 20
            Graph_RowLabel(i).Width = 120
            Graph_RowLabel(i).Left = 5
            Graph_RowLabel(i).Top = 0 ' this is updated when the graph is drawn
            Graph_RowLabel(i).Text = "Drop " & i

            ToolTip1.SetToolTip(Graph_RowLabel(i), "ToolTip Row Label")
            Graph_RowLabel(i).BackColor = Color.FromArgb(128, 245, 245, 255)
        Next i

        For i = 1 To MaxNumDrops + 10
            Graph_Axes(i) = New Label
            Graph_Axes(i).Name = "GRF_Axes_LBL" & i.ToString
            Graph_Axes(i).Font = New Font("Segoe UI", 10)
            Graph_Axes(i).AutoSize = False
            Graph_Axes(i).TextAlign = 16
            Graph_Axes(i).Height = 25
            Graph_Axes(i).Width = 100
            Graph_Axes(i).Left = 0
            Graph_Axes(i).Top = 0 ' this is updated when the graph is drawn
            Graph_Axes(i).Text = i.ToString

            ToolTip1.SetToolTip(Graph_Axes(i), "ToolTip Axes Label")

        Next i

    End Sub



    Private Sub showGraph()
        debug("Show Graph")

        Dim NumberOfDrops As Integer = Val(NumActiveDrops_LBL2.Text)
        Dim numRows = Val(NumActiveDrops_LBL2.Text) + 4

        GRF_PB.Width = 785
        GRF_PB.Height = numRows * 30 + 50
        GRF_PB.Left = 5

        Dim GridStart_X As Integer = 130
        Dim GridStart_Y As Integer = 0
        Dim GridRightMargin As Integer = 20

        Dim GRF_RowHeight As Integer = 30

        Dim GRF_Width As Integer = 640
        Dim GRF_Height As Integer = numRows * 30

        Dim i As Integer = 0

        Dim Row_LabelPos As Integer = 5

        Dim GraphBG As New Bitmap(GRF_PB.Width, GRF_PB.Height)
        Dim GRF_Graphics As Graphics = Graphics.FromImage(GraphBG)


        ' get longest time, round up to nearest 100 and scale the graph to longest
        Dim maxTime As Integer = getLongestTime(1)
        Dim max_X As Integer = roundUpNearest100(maxTime)
        If max_X < 1000 Then max_X = 1000

        Dim scale As Double = max_X / GRF_Width

        debug("  max X = " & max_X)
        debug("  Scale = " & scale)

        Dim blackPen1 As New Pen(Color.Black, 1)
        Dim blackPen2 As New Pen(Color.Black, 2)
        Dim grayPen1 As New Pen(Color.LightGray, 1)
        Dim grayPen1Dashed As New Pen(Color.LightGray, 1) : grayPen1Dashed.DashStyle = 4

        ' draw the graph background
        GRF_Graphics.FillRectangle(Brushes.White, 0, 0, GRF_PB.Width, GRF_PB.Height)
        '  GRF_PB.BackColor = Color.White


        ' draw horizontal lines
        For i = 1 To numRows
            GRF_Graphics.DrawLine(grayPen1, GridStart_X, i * GRF_RowHeight, GridStart_X + GRF_Width, i * GRF_RowHeight)
        Next

        ' draw the vertical lines
        For i = 1 To max_X Step 100
            Dim x As Integer = i / scale

            GRF_Graphics.DrawLine(grayPen1, GridStart_X + x, i * GridStart_Y, GridStart_X + x, GRF_Height)

            ' if the graph cell is fairly wide, draw sub division dashed lines 
            If (max_X <= 2000) Then
                x = (i + 50) / scale + 1
                GRF_Graphics.DrawLine(grayPen1Dashed, GridStart_X + x, i * GridStart_Y, GridStart_X + x, GRF_Height)
            End If
        Next i


        ' draw the x axis label ticks
        For i = 0 To max_X Step 100
            Dim x As Integer = i / scale
            GRF_Graphics.DrawLine(blackPen1, GridStart_X + x, GRF_Height, GridStart_X + x, GRF_Height + 6)
        Next i


        ' draw x axis labels 
        Dim x_lbl_Font As New System.Drawing.Font("Courier New", 7)
        Dim drawFormat As New System.Drawing.StringFormat


        Dim y As Integer = 0
        Dim labelStep As Integer = 0

        labelStep = 3
        If (max_X <= 10000) Then labelStep = 2
        If (max_X <= 5500) Then labelStep = 1

        Dim count As Integer = 0
        Dim lw As Integer = 0 ' label width

        For i = 0 To max_X Step 100 * labelStep

            Dim x As Integer = i / scale
            Dim X_lbl_String As String = (count * 100).ToString
            If (count = 0) Then X_lbl_String = "0"


            ' x axis labels can be horzintal or vertical depending on the number of divisions

            If (max_X <= 2500) Then ' use horizontal labels


                ' this is half the width of the label
                lw = 13
                If i < 1000 Then lw = 10
                If i < 100 Then lw = 8
                If i < 10 Then lw = 4

                GRF_Graphics.DrawString(X_lbl_String, x_lbl_Font, Brushes.Black, GridStart_X + x - lw, GridStart_Y + GRF_Height + 7, drawFormat)

            Else ' use vertical labels

                ' draw vertical labels at the bottom of the graph
                lw = 4
                For k = 0 To X_lbl_String.Length - 1
                    ' Ypos = 440 + (10 * k)

                    GRF_Graphics.DrawString(X_lbl_String(k), x_lbl_Font, Brushes.Black, x + GridStart_X - lw, GridStart_Y + GRF_Height + 7 + (9 * k), drawFormat)
                Next k

            End If

            count = count + labelStep
        Next



        ' draw the graph border. Do this last so it does not get over written by the other lines
        GRF_Graphics.DrawRectangle(blackPen1, GridStart_X, GridStart_Y, GRF_Width, GRF_Height)

        GRF_PB.Image = GraphBG





        ' **************************                     ROW LABELS            ************************************************************************

        'reset axes labels
        For i = 1 To NumberOfDrops + 4
            Graph_RowLabel(i).Text = ""
            ToolTip1.SetToolTip(Graph_RowLabel(i), "")

            Graph_Axes(i).Text = ""
            ToolTip1.SetToolTip(Graph_Axes(i), "")
        Next i




        For i = 1 To NumberOfDrops
            Graph_RowLabel(i).Text = RowLabels_LBL_NEW(i).Text
            ToolTip1.SetToolTip(Graph_RowLabel(i), RowLabels_LBL_NEW(i).Text)
            ToolTip1.SetToolTip(Graph_Axes(i), "Valve " & drop_Sol(i) & vbCrLf & "Start = " & drop_StartTime(i) & vbCrLf & "Size = " & drop_SizeTime(i))
        Next i

        i = NumberOfDrops + 1
        Graph_RowLabel(i).Text = "Camera"
        ToolTip1.SetToolTip(Graph_RowLabel(i), "Shutter tigger" & vbCrLf & "Start = " & CT_StartTime_TB.Text)

        i = NumberOfDrops + 2
        Graph_RowLabel(i).Text = "Flash"
        ToolTip1.SetToolTip(Graph_RowLabel(i), "Flash tigger" & vbCrLf & "Start = " & FT1_Time_TB.Text)

        i = NumberOfDrops + 3
        Graph_RowLabel(i).Text = "AUX 1"
        ToolTip1.SetToolTip(Graph_RowLabel(i), "AUX 1 tigger" & vbCrLf & "Start = " & FT2_Time_TB.Text)

        i = NumberOfDrops + 4
        Graph_RowLabel(i).Text = "AUX 2"
        ToolTip1.SetToolTip(Graph_RowLabel(i), "AUX 2 tigger" & vbCrLf & "Start = " & FT3_Time_TB.Text)


        ' Add the row labels to the panel
        For i = 1 To NumberOfDrops + 4
            Graph_RowLabel(i).Top = (i * GRF_RowHeight) - GRF_RowHeight + 4
            GRF_PB.Controls.Add(Graph_RowLabel(i))
        Next




        ' **************************                   Graph Axes            ************************************************************************

        For i = 1 To NumberOfDrops + 4
            Graph_Axes(i).Top = (i * GRF_RowHeight) - GRF_RowHeight + 3
        Next


        For i = 1 To NumberOfDrops
            ' axes start position
            Graph_Axes(i).Left = (drop_StartTime(i) / scale) + GridStart_X + 1
            Graph_Axes(i).Width = drop_SizeTime(i) / scale
            Graph_Axes(i).Text = ""
            Graph_Axes(i).BackColor = col(Val(solValves_CB(i).Text))

            If dropOnOffButtons_BTN(i).Text = "OFF" Then
                Graph_Axes(i).Left = GridStart_X + 4
                Graph_Axes(i).Width = 100
                Graph_Axes(i).BackColor = Color.Transparent
                Graph_Axes(i).Text = "OFF"
            End If
        Next i


        ' Flash trigger
        i = NumberOfDrops + 2
        Graph_Axes(i).Text = ""
        Graph_Axes(i).Left = Val(FT1_Time_TB.Text) / scale + GridStart_X
        Graph_Axes(i).Width = Val(FT1_Pulse_TB.Text) / scale
        Graph_Axes(i).BackColor = Color.Red
        ToolTip1.SetToolTip(Graph_Axes(i), "Flash Trigger" & vbCrLf & "Trigger time = " & FT1_Time_TB.Text)

        If FT1_OnOff_BUTTON.Text = "OFF" Then
            Graph_Axes(i).Width = 100
            Graph_Axes(i).Left = GridStart_X + 4
            Graph_Axes(i).BackColor = Color.Transparent
            Graph_Axes(i).Text = "OFF"
        End If


        ' aux 1 trigger
        i = NumberOfDrops + 3
        Graph_Axes(i).Text = ""
        Graph_Axes(i).Left = Val(FT2_Time_TB.Text) / scale + GridStart_X
        Graph_Axes(i).Width = Val(FT2_Pulse_TB.Text) / scale
        Graph_Axes(i).BackColor = Color.Blue
        ToolTip1.SetToolTip(Graph_Axes(i), "AUX 1 Trigger" & vbCrLf & "Trigger time = " & FT2_Time_TB.Text)

        If FT2_OnOff_BUTTON.Text = "OFF" Then
            Graph_Axes(i).Width = 100
            Graph_Axes(i).Left = GridStart_X + 4
            Graph_Axes(i).BackColor = Color.Transparent
            Graph_Axes(i).Text = "OFF"
        End If


        ' aux 2 trigger
        i = NumberOfDrops + 4
        Graph_Axes(i).Text = ""
        Graph_Axes(i).Left = Val(FT3_Time_TB.Text) / scale + GridStart_X
        Graph_Axes(i).Width = Val(FT3_Pulse_TB.Text) / scale
        Graph_Axes(i).BackColor = Color.Blue
        ToolTip1.SetToolTip(Graph_Axes(i), "AUX 2 Trigger" & vbCrLf & "Trigger time = " & FT3_Time_TB.Text)

        If FT3_OnOff_BUTTON.Text = "OFF" Then
            Graph_Axes(i).Width = 100
            Graph_Axes(i).Left = GridStart_X + 4
            Graph_Axes(i).BackColor = Color.Transparent
            Graph_Axes(i).Text = "OFF"
        End If



        ' shutter trigger
        i = NumberOfDrops + 1
        Graph_Axes(i).Text = ""
        Graph_Axes(i).BackColor = Color.Red


        If CT_OnOff_BTN.Text = "ON" Then
            Graph_Axes(i).Width = Val(CT_Pulse_TB.Text) / scale
            Graph_Axes(i).Left = (Val(CT_StartTime_TB.Text) / scale) + GridStart_X
            ToolTip1.SetToolTip(Graph_Axes(i), "Shutter tigger time = " & CT_StartTime_TB.Text)

        ElseIf CT_OnOff_BTN.Text = "OFF" Then
            Graph_Axes(i).Width = 100
            Graph_Axes(i).Left = GridStart_X + 4
            Graph_Axes(i).BackColor = Color.Transparent
            Graph_Axes(i).Text = "OFF"


        ElseIf CT_OnOff_BTN.Text = "SYNC" Then

            If FT1_OnOff_BUTTON.Text = "ON" Then
                Dim TS As Integer = Val(FT1_Time_TB.Text) - Val(SyncStartOffset_Time_TB.Text)
                If (TS < 0) Then TS = 0
                Graph_Axes(i).Left = (TS / scale) + GridStart_X
                Graph_Axes(i).Width = Val(CT_Pulse_TB.Text) / scale
                ToolTip1.SetToolTip(Graph_Axes(i), "Shutter Trigger" & vbCrLf & "SYNC" & vbCrLf & "Trigger time  " & TS)

            Else
                Graph_Axes(i).BackColor = Color.Transparent
                Graph_Axes(i).Width = 300
                Graph_Axes(i).Left = GridStart_X + 4
                Graph_Axes(i).Text = "Shutter set to SYNC but FT is OFF"

            End If

        ElseIf CT_OnOff_BTN.Text = "BULB" Then
            Graph_Axes(i).Left = GridStart_X + 1
            Graph_Axes(i).Width = (maxTime / scale)
            ToolTip1.SetToolTip(Graph_Axes(i), "Shutter Trigger" & vbCrLf & "BULB" & vbCrLf & "Shutter open " & maxTime & "ms")

        End If




        For i = 1 To NumberOfDrops + 4
            Graph_Axes(i).Top = (i * GRF_RowHeight) - GRF_RowHeight + 3
            GRF_PB.Controls.Add(Graph_Axes(i))
        Next


    End Sub




    Private Sub graphPaint(sender As Object, e As PaintEventArgs) Handles GRF_Panel.Paint


    End Sub









#End Region       ' Graph













    '              ____    ____   _    _  _______      _______         ____  
    '       /\    |  _ \  / __ \ | |  | ||__   __|    |__   __| /\    |  _ \ 
    '      /  \   | |_) || |  | || |  | |   | |          | |   /  \   | |_) |
    '     / /\ \  |  _ < | |  | || |  | |   | |          | |  / /\ \  |  _ < 
    '    / ____ \ | |_) || |__| || |__| |   | |          | | / ____ \ | |_) |
    '   /_/    \_\|____/  \____/  \____/    |_|          |_|/_/    \_\|____/ 
    '  


#Region "ABOUT TAB"


    ' Dim imageCount As Integer = 0
    Dim firwareUpdated As Boolean = False

    Private Sub TAB_ABOUT_Enter(sender As Object, e As EventArgs) Handles TAB_ABOUT.Enter
        debug(vbCrLf & "ENTER ABOUT TAB")

        If (Not firwareUpdated) Then sendCommandToDropController("[VERSION]")


    End Sub


    Private Sub TAB_ABOUT_Leave(sender As Object, e As EventArgs) Handles TAB_ABOUT.Leave

    End Sub




    Private Sub ABOUT_LINK_LBL_Click(sender As Object, e As EventArgs) Handles ABOUT_LINK_LBL.Click
        Try
            Process.Start("http://www.dropcontroller.com")
        Catch ex As Exception
            MsgBox("Can't load Web page" & vbCrLf & ex.Message)
        End Try

    End Sub

    Private Sub ABOUT_LINK_LBL_MouseHover(sender As Object, e As EventArgs) Handles ABOUT_LINK_LBL.MouseHover
        Me.Cursor = Cursors.Hand
    End Sub

    Private Sub ABOUT_LINK_LBL_MouseLeave(sender As Object, e As EventArgs) Handles ABOUT_LINK_LBL.MouseLeave
        Me.Cursor = Cursors.Arrow
    End Sub



#End Region   ' ABOUT TAB


























    ' _______  _____  __  __  ______  _____    _____ 
    '|__   __||_   _||  \/  ||  ____||  __ \  / ____|
    '   | |     | |  | \  / || |__   | |__) || (___  
    '   | |     | |  | |\/| ||  __|  |  _  /  \___ \ 
    '   | |    _| |_ | |  | || |____ | | \ \  ____) |
    '   |_|   |_____||_|  |_||______||_|  \_\|_____/ 


#Region "TIMERS"




    Private Sub Timer_ConnectionTimeoutON()
        Timer_ConnectionTimeout.Enabled = True
        timerConnectFlag.Text = "ON"
    End Sub

    Private Sub Timer_ConnectionTimeoutOFF()
        Timer_ConnectionTimeout.Enabled = False
        timerConnectFlag.Text = "OFF"
    End Sub




    Private Sub Timer_dropAckTimeoutON()
        ' will need to add sequence value
        Timer_dropAckTimeout.Interval = getLongestTime(1) + 2000
        debug("Timer_dropAckTimeout.Interval = " & getLongestTime(1) + 2000)

        Timer_dropAckTimeout.Enabled = True
        TimerACK_LBL.Text = "ON"
    End Sub

    Private Sub Timer_dropAckTimeoutOFF()
        Timer_dropAckTimeout.Enabled = False
        TimerACK_LBL.Text = "OFF"
    End Sub


    Private Sub TimerLoopDelayOn()
        Timer_LoopDelay.Enabled = True
        Timer_LoopDelay_LBL.Text = "ON"
    End Sub

    Private Sub TimerLoopDelayOff()
        Timer_LoopDelay.Enabled = False
        Timer_LoopDelay_LBL.Text = "OFF"
    End Sub


    Private Sub Timer_recieveSerialDataOn()
        Timer_recieveSerialData.Enabled = True
        Timer_SD_IN_LBL.Text = "ON"

    End Sub

    Private Sub Timer_recieveSerialDataOff()
        Timer_recieveSerialData.Enabled = False
        Timer_SD_IN_LBL.Text = "OFF"
    End Sub



#End Region










    '
    '  __  __            _  __ ______    _____   _____    ____   _____  
    ' |  \/  |    /\    | |/ /|  ____|  |  __ \ |  __ \  / __ \ |  __ \ 
    ' | \  / |   /  \   | ' / | |__     | |  | || |__) || |  | || |__) |
    ' | |\/| |  / /\ \  |  <  |  __|    | |  | ||  _  / | |  | ||  ___/ 
    ' | |  | | / ____ \ | . \ | |____   | |__| || | \ \ | |__| || |     
    ' |_|  |_|/_/    \_\|_|\_\|______|  |_____/ |_|  \_\ \____/ |_|     


    ' the main start button has been clicked
    ' the drop data has been checked and is OK

    Private Sub makeDrop()

        SerialPort1.DiscardInBuffer()

        If (LoopMode_BTN.Text = "OFF") Then
            singleDrop()
        Else
            multiDrop()
        End If


    End Sub




    Private Sub singleDrop()

        debug(vbCrLf & "Enter singleDrop()")
        ' no need to open the loop page tab,  just make the drop(s)

        ' init - copy to temp variables ready for send

        ' disable MainStart_BTN
        ' enable ACTIVE button
        ' send data
        ' wait for ACK + timeout: If time out show error message
        ' activate START button

        LP_Sequence_LBL.Text = 1

        MainStart_BTN.Enabled = False
        MainStart_BTN.Text = "A C T I V E"
        MainStart_BTN.BackColor = Color.FromArgb(255, 182, 128)
        ToolTip1.SetToolTip(MainStart_BTN, "Button not active while the drop sequence active.")
        sendDropData()

        ' start Timer_dropAckTimeout
        Timer_dropAckTimeoutON()

    End Sub
















    '
    '  _       ____    ____   _____      _____          _____  ______ 
    ' | |     / __ \  / __ \ |  __ \    |  __ \  /\    / ____||  ____|
    ' | |    | |  | || |  | || |__) |   | |__) |/  \  | |  __ | |__   
    ' | |    | |  | || |  | ||  ___/    |  ___// /\ \ | | |_ ||  __|  
    ' | |____| |__| || |__| || |        | |   / ____ \| |__| || |____ 
    ' |______|\____/  \____/ |_|        |_|  /_/    \_\\_____||______|
    '

#Region "Loop Page"

    Private Sub multiDrop()

        debug(vbCrLf & "Enter  Loop Page")

        ' position and then show the Loop Page groupbox
        LoopPage_GroupBox.Top = 26
        LoopPage_GroupBox.Left = 8
        LoopPage_GroupBox.Visible = True
        debug("  LoopPage_GroupBox.Visible = True")

        '  Dim valve As Integer = 1
        '  Dim startTime As Long = 0
        '  Dim sizeTime As Long = 0
        '  Dim stopTime As Long = 0

        LP_Sequence_LBL.Text = 1

        updateLoopPage(Val(LP_Sequence_LBL.Text))


        For i As Integer = 1 To Val(NumActiveDrops_LBL2.Text)

            LP_dropRowLabel_LBL(i).Text = RowLabels_LBL_NEW(i).Text

            If dropOnOffButtons_BTN(i).Text = "ON" Then
                LP_dropData_LBL(i).ForeColor = Color.Black
            Else
                LP_dropData_LBL(i).ForeColor = Color.LightGray
            End If

            LP_dropData_Panel.Controls.Add(LP_dropRowLabel_LBL(i))
            LP_dropData_Panel.Controls.Add(LP_dropData_LBL(i))


        Next


        'init all the controls and timers
        LP_START_BTN.Location = New Point(50, 450)
        LP_RESET_BTN.Location = New Point(400, 450)
        LP_EXIT_BTN.Location = New Point(580, 450)


        LP_START_BTN.Enabled = True
        LP_START_BTN.Visible = True
        LP_START_BTN.Text = "S T A R T"
        LP_START_BTN.BackColor = Color.FromArgb(128, 255, 128)

        LP_RESET_BTN.Enabled = False
        LP_RESET_BTN.Visible = True


        Loop_seq_LBL.Text = "Next Sequence = "
        LP_copy_BTN.Enabled = True
        LP_copy_BTN.BackColor = Color.LightSkyBlue


        If (lp_TimerOrButton_BTN.Text = "BUTTON") Then
            debug("  init for button mode")

            progressBar_LBL.Visible = False
            LP_ProgressBar.Visible = False


        ElseIf (lp_TimerOrButton_BTN.Text = "TIMER") Then
            debug("  init for timer mode")

            progressBar_LBL.Visible = True
            LP_ProgressBar.Visible = True

            TimerLoopDelayOff()
            updateProgressBar(0)

        End If

        sequenceAborted = False
        debug("sequenceAborted = False")

    End Sub





    Private Sub updateLoopPage(seq As Integer)
        debug(vbCrLf & "Enter updateLoopPage()")

        Dim stopTime As Long = 0

        UpdateDropDataArrays(seq)

        Dim tmpStr As String = ""
        For i As Integer = 1 To Val(NumActiveDrops_LBL2.Text)

            Dim startDeltaSign As String = " "
            If (dropStartTimeDelta(i) = "INC") Then startDeltaSign = "+"
            If (dropStartTimeDelta(i) = "DEC") Then startDeltaSign = "-"

            Dim sizeDeltaSign As String = " "
            If (drop_SizeTime_Delta(i) = "INC") Then sizeDeltaSign = "+"
            If (drop_SizeTime_Delta(i) = "DEC") Then sizeDeltaSign = "-"

            stopTime = drop_StartTime(i) + drop_SizeTime(i)


            tmpStr = ""
            tmpStr = tmpStr & drop_Sol(i) & "  "
            tmpStr = tmpStr & Format(drop_StartTime(i), "0000") & " [" & startDeltaSign

            If startDeltaSign = " " Then
                tmpStr = tmpStr & "OFF"
            Else
                tmpStr = tmpStr & Format(dropStartTimeDeltaVal(i), "000")
            End If

            tmpStr = tmpStr & "]  " & Format(drop_SizeTime(i), "0000") & " [" & sizeDeltaSign

            If sizeDeltaSign = " " Then
                tmpStr = tmpStr & "OFF"
            Else
                tmpStr = tmpStr & Format(dropSizeDeltaVal(i), "000")
            End If

            tmpStr = tmpStr & "]" & "  " & Format(stopTime, "00000")

            LP_dropData_LBL(i).Text = tmpStr

        Next i



        Dim LBLtext As String = ""
        Dim tmpSign As String = ""


        If (FT1_OnOff_BUTTON.Text = "ON") Then
            Dim incDecString As String = ""

            If (FT1_IncDec_BTN.Text = "INC") Then
                tmpSign = "+"
                incDecString = Format(Val(FT1_IncDecTime_TB.Text), "000")
            End If
            If (FT1_IncDec_BTN.Text = "DEC") Then
                tmpSign = "-"
                incDecString = Format(Val(FT1_IncDecTime_TB.Text), "000")
            End If
            If (FT1_IncDec_BTN.Text = "OFF") Then
                tmpSign = " "
                ' incDecString = "OFF"
                incDecString = "OFF"
            End If

            Loop_FT1_LBL.Text = Format(FT1_StartTime, "0000") + " [" + tmpSign + incDecString + "]"
        Else
            Loop_FT1_LBL.Text = "OFF"
        End If
        '  Loop_FT1_LBL.Text = LBLtext



        If (FT2_OnOff_BUTTON.Text = "ON") Then
            Dim incDecString As String = ""

            If (FT2_IncDec_BTN.Text = "INC") Then
                tmpSign = "+"
                incDecString = Format(Val(FT2_IncDecTime_TB.Text), "000")
            End If
            If (FT2_IncDec_BTN.Text = "DEC") Then
                tmpSign = "-"
                incDecString = Format(Val(FT2_IncDecTime_TB.Text), "000")
            End If
            If (FT2_IncDec_BTN.Text = "OFF") Then
                tmpSign = " "
                incDecString = "OFF"
            End If

            LBLtext = Format(FT2_StartTime, "0000") + " [" + tmpSign + incDecString + "]"
        Else
            LBLtext = "OFF"
        End If
        Loop_FT2_LBL.Text = LBLtext


        If (FT3_OnOff_BUTTON.Text = "ON") Then
            Dim incDecString As String = ""

            If (FT3_IncDec_BTN.Text = "INC") Then
                tmpSign = "+"
                incDecString = Format(Val(FT3_IncDecTime_TB.Text), "000")
            End If
            If (FT3_IncDec_BTN.Text = "DEC") Then
                tmpSign = "-"
                incDecString = Format(Val(FT3_IncDecTime_TB.Text), "000")
            End If
            If (FT3_IncDec_BTN.Text = "OFF") Then
                tmpSign = " "
                incDecString = "OFF"
            End If

            LBLtext = Format(FT3_StartTime, "0000") + " [" + tmpSign + incDecString + "]"
        Else
            LBLtext = "OFF"
        End If
        Loop_FT3_LBL.Text = LBLtext


        If (CT_OnOff_BTN.Text = "OFF") Then
            Loop_CT_LBL.Text = "OFF"

        ElseIf (CT_OnOff_BTN.Text = "ON") Then
            Loop_CT_LBL.Text = Format(CT_StartTime, "0000") & " " & "[" & tmpSign & Format(Val(CT_IncDecTime_TB.Text), "000") & "]"

        ElseIf (CT_OnOff_BTN.Text = "SYNC") Then
            Loop_CT_LBL.Text = "SYNC [FT1-" & Format(Val(SyncStartOffset_Time_TB.Text), "0000") & "]"

        ElseIf (CT_OnOff_BTN.Text = "BULB") Then
            Loop_CT_LBL.Text = "BULB MODE"
        End If


    End Sub






    Private Sub UpdateDropDataArrays(seq As Integer)
        debug("updateDropDataArrays: seq = " & seq)

        For i = 1 To Val(NumActiveDrops_LBL2.Text)

            drop_OnOff(i) = dropOnOffButtons_BTN(i).Text
            drop_Sol(i) = Val(solValves_CB(i).Text)

            drop_StartTime(i) = Val(StartTimes_TB(i).Text)

            dropStartTimeDelta(i) = StartTimeIncDec_BTN(i).Text
            dropStartTimeDeltaVal(i) = Val(StartTimeIncDecVal_TB(i).Text)

            drop_SizeTime(i) = Val(SizeTimes_TB(i).Text)
            drop_SizeTime_Delta(i) = SizeTimeIncDec_BTN(i).Text
            dropSizeDeltaVal(i) = Val(SizeTimeIncDecVal_TB(i).Text)

            If (seq > 1) Then

                If (dropStartTimeDeltaVal(i) > 0) Then
                    If (dropStartTimeDelta(i) = "INC") Then drop_StartTime(i) = Val(StartTimes_TB(i).Text) + ((seq - 1) * Val(StartTimeIncDecVal_TB(i).Text))
                    If (dropStartTimeDelta(i) = "DEC") Then drop_StartTime(i) = Val(StartTimes_TB(i).Text) - ((seq - 1) * Val(StartTimeIncDecVal_TB(i).Text))
                End If

                drop_StartTime(i) = CheckSize(drop_StartTime(i), 0, 9999)

                If (dropSizeDeltaVal(i) > 0) Then
                    If (drop_SizeTime_Delta(i) = "INC") Then drop_SizeTime(i) = Val(SizeTimes_TB(i).Text) + ((seq - 1) * Val(SizeTimeIncDecVal_TB(i).Text))
                    If (drop_SizeTime_Delta(i) = "DEC") Then drop_SizeTime(i) = Val(SizeTimes_TB(i).Text) - ((seq - 1) * Val(SizeTimeIncDecVal_TB(i).Text))
                    'If (drop_SizeTime_Delta(i) = "DEC") Then dropSize(i) = Val(SizeTimes_TB(i).Text) - ((seq - 1) * Val(SizeTimeIncDecVal_TB(i).Text))
                End If

                drop_SizeTime(i) = CheckSize(drop_SizeTime(i), 0, 9999)
            End If
        Next i

        FT1_StartTime = Val(FT1_Time_TB.Text)
        FT2_StartTime = Val(FT2_Time_TB.Text)
        FT3_StartTime = Val(FT3_Time_TB.Text)
        FT1_Size = Val(FT1_Pulse_TB.Text)
        FT2_Size = Val(FT2_Pulse_TB.Text)
        FT3_Size = Val(FT3_Pulse_TB.Text)

        CT_StartTime = Val(CT_StartTime_TB.Text)
        CT_Size = Val(CT_Pulse_TB.Text)


        If (seq > 1) Then

            If (FT1_IncDec_BTN.Text = "INC") Then FT1_StartTime = FT1_StartTime + ((seq - 1) * Val(FT1_IncDecTime_TB.Text))
            If (FT1_IncDec_BTN.Text = "DEC") Then FT1_StartTime = FT1_StartTime - ((seq - 1) * Val(FT1_IncDecTime_TB.Text))

            If (FT2_IncDec_BTN.Text = "INC") Then FT2_StartTime = FT2_StartTime + ((seq - 1) * Val(FT2_IncDecTime_TB.Text))
            If (FT2_IncDec_BTN.Text = "DEC") Then FT2_StartTime = FT2_StartTime - ((seq - 1) * Val(FT2_IncDecTime_TB.Text))

            If (FT3_IncDec_BTN.Text = "INC") Then FT3_StartTime = FT3_StartTime + ((seq - 1) * Val(FT3_IncDecTime_TB.Text))
            If (FT3_IncDec_BTN.Text = "DEC") Then FT3_StartTime = FT3_StartTime - ((seq - 1) * Val(FT3_IncDecTime_TB.Text))

            If (CT_OnOff_BTN.Text = "ON") Then
                If (CT_IncDec_BTN.Text = "INC") Then CT_StartTime = CT_StartTime + ((seq - 1) * Val(CT_IncDecTime_TB.Text))
                If (CT_IncDec_BTN.Text = "DEC") Then CT_StartTime = CT_StartTime - ((seq - 1) * Val(CT_IncDecTime_TB.Text))
            End If

        End If

        FT1_StartTime = CheckSize(FT1_StartTime, 0, 9999)
        FT2_StartTime = CheckSize(FT2_StartTime, 0, 9999)
        FT3_StartTime = CheckSize(FT3_StartTime, 0, 9999)

        If (CT_OnOff_BTN.Text = "BULB") Then
            CT_StartTime = 0
        ElseIf (CT_OnOff_BTN.Text = "SYNC") Then
            CT_StartTime = FT1_StartTime - Val(SyncStartOffset_Time_TB.Text)
        End If

        CT_StartTime = CheckSize(CT_StartTime, 0, 9999)

    End Sub








    '  after start button - when ACK received - if timer start timer not wait for button click
    '  Timer_waitACK
    '  remember to change to active button when sequence is active
    '  



    ' _       _____              _____  _______         _____  _______            ____  _______  _   _ 
    '| |     |  __ \            / ____||__   __| /\    |  __ \|__   __|          |  _ \|__   __|| \ | |
    '| |     | |__) |  ______  | (___     | |   /  \   | |__) |  | |     ______  | |_) |  | |   |  \| |
    '| |     |  ___/  |______|  \___ \    | |  / /\ \  |  _  /   | |    |______| |  _ <   | |   | . ` |
    '| |____ | |                ____) |   | | / ____ \ | | \ \   | |             | |_) |  | |   | |\  |
    '|______||_|               |_____/    |_|/_/    \_\|_|  \_\  |_|             |____/   |_|   |_| \_|


    Private Sub LP_START_BTN_Click(sender As Object, e As EventArgs) Handles LP_START_BTN.Click

        debug("LP_START_BTN clicked")


        If (lp_TimerOrButton_BTN.Text = "BUTTON") Then debug("  button mode")
        If (lp_TimerOrButton_BTN.Text = "TIMER") Then debug("  timer mode")

        If (LP_START_BTN.Text = "S T A R T") Then
            LP_START_BTN_ACTIVE()
            LP_RESET_BTN.Enabled = False
            sendDropData()

            Timer_dropAckTimeoutON()


        ElseIf (LP_START_BTN.Text = "S T O P") Then

            LP_START_BTN.Text = "S T A R T"
            LP_START_BTN.BackColor = Color.FromArgb(128, 255, 128)

            If (Timer_dropAckTimeout.Enabled) Then
                Timer_dropAckTimeoutOFF()
                sequenceAborted = True
                debug("sequenceAborted = True")
            End If

            TimerLoopDelayOff()
            updateProgressBar(0)
            PB_count = 0

            LP_copy_BTN.Enabled = True
            LP_copy_BTN.BackColor = Color.LightSkyBlue

        End If
    End Sub






    Private Sub LP_RESET_BTN_Click(sender As Object, e As EventArgs) Handles LP_RESET_BTN.Click

        If (Timer_dropAckTimeout.Enabled) Then
            Timer_dropAckTimeoutOFF()
            sequenceAborted = True
            debug("sequenceAborted = True")
        End If

        TimerLoopDelayOff()
        updateProgressBar(0)

        debug("LP RESET BTN clicked")
        ' the stop button stops the current loop and resets the sequence to 1

        LP_RESET_BTN.Enabled = False

        LP_START_BTN.Enabled = True
        LP_START_BTN.Text = "S T A R T"

        PB_count = 0
        LP_Sequence_LBL.Text = 1
        multiDrop()

    End Sub



    Private Sub LP_EXIT_BTN_Click(sender As Object, e As EventArgs) Handles LP_EXIT_BTN.Click
        debug("Enter LP_EXIT_BTN_Click")

        ' stop all timers
        If (Timer_dropAckTimeout.Enabled) Then
            Timer_dropAckTimeoutOFF()
            sequenceAborted = True
            debug("sequenceAborted = True")
        End If

        TimerLoopDelayOff()
        updateProgressBar(0)

        LP_RESET_BTN.Enabled = False

        LP_START_BTN.Enabled = True
        LP_START_BTN.Visible = True

        PB_count = 0
        LoopPage_GroupBox.Visible = False
    End Sub





    Private Sub LP_START_BTN_START()
        LP_START_BTN.Enabled = True
        LP_START_BTN.Text = "S T A R T"
        LP_START_BTN.BackColor = Color.FromArgb(128, 255, 128)
        Loop_seq_LBL.Text = "Next Sequence = "
        LP_copy_BTN.Enabled = True
        LP_copy_BTN.BackColor = Color.LightSkyBlue
    End Sub

    Private Sub LP_START_BTN_STOP()
        LP_START_BTN.Enabled = True
        LP_START_BTN.Text = "S T O P"
        LP_START_BTN.BackColor = Color.FromArgb(255, 128, 128)
        Loop_seq_LBL.Text = "Next Sequence = "
        LP_copy_BTN.Enabled = True
        LP_copy_BTN.BackColor = Color.LightSkyBlue

    End Sub

    Private Sub LP_START_BTN_ACTIVE()
        LP_START_BTN.Enabled = False
        LP_START_BTN.Text = "A C T I V E"
        LP_START_BTN.BackColor = Color.FromArgb(255, 182, 128)
        LP_RESET_BTN.Enabled = False
        Loop_seq_LBL.Text = "This Sequence = "
        LP_copy_BTN.Enabled = False
        LP_copy_BTN.BackColor = greyedOut
    End Sub



    Private Sub initForNextDrop()

        If (LoopMode_BTN.Text = "OFF") Then
            MainStart_BTN.Text = "S T A R T"
            MainStart_BTN.BackColor = Color.FromArgb(128, 255, 128)
            MainStart_BTN.Enabled = True
            ToolTip1.SetToolTip(MainStart_BTN, "Big Start button. Makes things go.")
        ElseIf (LoopMode_BTN.Text = "ON") Then

            If (lp_TimerOrButton_BTN.Text = "BUTTON") Then

                LP_START_BTN_START()
                LP_RESET_BTN.Enabled = True

                LP_Sequence_LBL.Text = Val(LP_Sequence_LBL.Text) + 1
                updateLoopPage(Val(LP_Sequence_LBL.Text))

                ' wait for the START button


            ElseIf (lp_TimerOrButton_BTN.Text = "TIMER") Then

                LP_START_BTN_STOP()

                LP_RESET_BTN.Enabled = True

                LP_Sequence_LBL.Text = Val(LP_Sequence_LBL.Text) + 1
                updateLoopPage(Val(LP_Sequence_LBL.Text))

                ' start the drop delay timer
                TimerLoopDelayOn()

            End If

        End If

    End Sub



#End Region ' "Loop Page"




















    '                       _  _____                      _____          _            __ __  
    '                      | ||  __ \                    |  __ \        | |          / / \ \ 
    ' ___   ___  _ __    __| || |  | | _ __  ___   _ __  | |  | |  __ _ | |_  __ _  | |   | |
    '/ __| / _ \| '_ \  / _` || |  | || '__|/ _ \ | '_ \ | |  | | / _` || __|/ _` | | |   | |
    '\__ \|  __/| | | || (_| || |__| || |  | (_) || |_) || |__| || (_| || |_| (_| | | |   | |
    '|___/ \___||_| |_| \__,_||_____/ |_|   \___/ | .__/ |_____/  \__,_| \__|\__,_| | |   | |
    '                                             | |                                \_\ /_/ 
    '                                             |_|                                        


    Private Sub sendDropData()

        Dim sequence As Integer = Val(LP_Sequence_LBL.Text)
        debug(vbCrLf & "Enter sendDropData() - Seq=" & Format(sequence, "0000"))

        UpdateDropDataArrays(sequence)

        Dim activeDrops As Integer = 0
        Dim dropCommandString(MaxNumDrops + 1) As String
        Dim CT_Command As String = ""
        Dim FT1_Command As String = ""
        Dim FT2_Command As String = ""
        Dim FT3_Command As String = ""
        Dim ML_Command As String = ""
        Dim LeadZero As String = "0"

        For i As Integer = 1 To Val(NumActiveDrops_LBL2.Text)
            If (dropOnOffButtons_BTN(i).Text = "ON") Then
                activeDrops = activeDrops + 1
                '[Dn sol start stop]
                '[D2123412345]
                If activeDrops < 9 Then LeadZero = "0" Else LeadZero = ""


                dropCommandString(activeDrops) = "[D" & LeadZero & activeDrops & drop_Sol(i) & Format(drop_StartTime(i), "0000") & Format(drop_StartTime(i) + drop_SizeTime(i), "00000") & "]"
            End If
        Next


        sendCommandToDropController("[S" & sequence & "]")
        sendCommandToDropController("[N" & activeDrops & "]")

        For i As Integer = 1 To activeDrops
            sendCommandToDropController(dropCommandString(i))
        Next i


        ' FT3
        If (FT3_OnOff_BUTTON.Text = "ON") Then

            FT3_Command = "[F3Y" & Format(FT3_StartTime, "0000") & Format(FT3_StartTime + FT3_Size, "00000") & "]"
        Else
            FT3_Command = "[F3N]"
        End If


        ' FT2
        If (FT2_OnOff_BUTTON.Text = "ON") Then

            FT2_Command = "[F2Y" & Format(FT2_StartTime, "0000") & Format(FT2_StartTime + FT2_Size, "00000") & "]"
        Else
            FT2_Command = "[F2N]"
        End If

        ' FT1
        If (FT1_OnOff_BUTTON.Text = "ON") Then

            FT1_Command = "[F1Y" & Format(FT1_StartTime, "0000") & Format(FT1_StartTime + FT1_Size, "00000") & "]"
        Else
            FT1_Command = "[F1N]"
        End If



        If (CT_OnOff_BTN.Text = "ON") Then
            CT_Command = "[CY" & Format(CT_StartTime, "0000") & Format(CT_StartTime + CT_Size, "00000") & "]"

        ElseIf (CT_OnOff_BTN.Text = "BULB") Then
            Dim longestTime As Integer = getLongestTime(sequence)
            CT_Command = "[CB0000" & Format(Val(BulbStopOffset_Time_TB.Text) + longestTime, "00000") & "]"

        ElseIf (CT_OnOff_BTN.Text = "SYNC") Then
            CT_Command = "[CY" & Format(CT_StartTime, "0000") & Format(CT_StartTime + CT_Size, "00000") & "]"
        Else
            '(CT_BUTTON.Text = "OFF") 
            CT_Command = "[CN]"
        End If



        debug("waste some time")
        debug(" now = " & Now)

        'the delay is very minor but it is enough to allow the arduino to process the received data
        Dim wasteSomeTime As Long = 0
        For j As Integer = 1 To 10000000
            wasteSomeTime = wasteSomeTime + j * 2 * 3.14
        Next j
        debug(" now = " & Now)

        sendCommandToDropController(ML_Command)
        sendCommandToDropController(CT_Command)
        sendCommandToDropController(FT1_Command)
        sendCommandToDropController(FT2_Command)
        sendCommandToDropController(FT3_Command)
        sendCommandToDropController("[EOD]")
        sendCommandToDropController("     ")


    End Sub







    '              _     _                                      _     _______  _                     ____  
    '             | |   | |                                    | |   |__   __|(_)                   / /\ \ 
    '  __ _   ___ | |_  | |      ___   _ __    __ _   ___  ___ | |_     | |    _  _ __ ___    ___  | |  | |
    ' / _` | / _ \| __| | |     / _ \ | '_ \  / _` | / _ \/ __|| __|    | |   | || '_ ` _ \  / _ \ | |  | |
    '| (_| ||  __/| |_  | |____| (_) || | | || (_| ||  __/\__ \| |_     | |   | || | | | | ||  __/ | |  | |
    ' \__, | \___| \__| |______|\___/ |_| |_| \__, | \___||___/ \__|    |_|   |_||_| |_| |_| \___| | |  | |
    '  __/ |                                   __/ |                                                \_\/_/ 
    ' |___/                                   |___/                                                        


    Private Function getLongestTime(seq As Integer) As Long
        debug("Enter getLongestTime(). seq = " & seq)

        UpdateDropDataArrays(seq)

        Dim longest As Long = 0
        Dim glStop As Long = 0

        For i As Integer = 1 To Val(NumActiveDrops_LBL2.Text)
            If (drop_OnOff(i) = "ON") Then
                glStop = drop_StartTime(i) + drop_SizeTime(i)

                If (glStop > longest) Then longest = glStop
            End If
        Next i


        If (FT3_OnOff_BUTTON.Text = "ON") Then
            glStop = FT3_StartTime + FT3_Size
            If (glStop > longest) Then longest = glStop
        End If

        If (FT2_OnOff_BUTTON.Text = "ON") Then
            glStop = FT2_StartTime + FT2_Size
            If (glStop > longest) Then longest = glStop
        End If

        If (FT1_OnOff_BUTTON.Text = "ON") Then
            glStop = FT1_StartTime + FT1_Size
            If (glStop > longest) Then longest = glStop
        End If

        If (CT_OnOff_BTN.Text = "ON") Then
            glStop = CT_StartTime + CT_Size
            If (glStop > longest) Then longest = glStop
        End If

        If (CT_OnOff_BTN.Text = "BULB") Then longest = longest + Val(BulbStopOffset_Time_TB.Text)




        debug("  longest = " & longest)
        Return longest

    End Function









    ' _____   _____    ____    _____  _____   ______   _____   _____      ____            _____  
    '|  __ \ |  __ \  / __ \  / ____||  __ \ |  ____| / ____| / ____|    |  _ \    /\    |  __ \ 
    '| |__) || |__) || |  | || |  __ | |__) || |__   | (___  | (___      | |_) |  /  \   | |__) |
    '|  ___/ |  _  / | |  | || | |_ ||  _  / |  __|   \___ \  \___ \     |  _ <  / /\ \  |  _  / 
    '| |     | | \ \ | |__| || |__| || | \ \ | |____  ____) | ____) |    | |_) |/ ____ \ | | \ \ 
    '|_|     |_|  \_\ \____/  \_____||_|  \_\|______||_____/ |_____/     |____//_/    \_\|_|  \_\

#Region "Progress Bar"



    Dim PB_count
    Private Sub Timer_LoopDelay_Tick(sender As Object, e As EventArgs) Handles Timer_LoopDelay.Tick
        PB_count = PB_count + 1
        Dim PB_timePassed As Long = PB_count * 100
        Dim waitTime As Long = Val(LP_waitTimeVal_TB.Text) * 1000
        Dim percent As Integer = PB_timePassed / waitTime * 100

        updateProgressBar(percent)
    End Sub


    Private Sub updateProgressBar(tmpVal As Integer)
        If (tmpVal > 100) Then
            tmpVal = 100
        End If
        LP_ProgressBar.Value = 100 - tmpVal

        If (tmpVal = 100) Then
            TimerLoopDelayOff()
            PB_count = 0

            LP_START_BTN_ACTIVE()
            sendDropData()

            ' start Timer_dropAckTimeout
            Timer_dropAckTimeoutON()

        End If

    End Sub

#End Region    ' "Progress Bar"







    Private Sub Timer_waitACK_Tick(sender As Object, e As EventArgs) Handles Timer_dropAckTimeout.Tick

        Timer_dropAckTimeoutOFF()

        debug("Timer_dropAckTimeout.Tick")
        debug("drop Ack has timed out")

        MsgBox("No acknowledgement from the dropController. Do you want to continue?",, "ERROR")

        initForNextDrop()

    End Sub




    Private Sub sendCommandToDropController(command As String)

        If (SerialPort1.IsOpen) Then
            SerialPort1.Write(command)
            debug("sent com = " & command)
        End If

    End Sub





















    Private Sub LP_copy_BTN_Click(sender As Object, e As EventArgs) Handles LP_copy_BTN.Click
        debug("LP_Copy clicked")

        ' If Timer Then On - pause timer  Timer_LoopDelay.Enabled = True

        If (lp_TimerOrButton_BTN.Text = "TIMER") Then
            TimerLoopDelayOff()
            LP_START_BTN_START()
            LP_ProgressBar.Value = 100
        End If



        Dim reply = MsgBox("Copy current values to main drop data?", 4, "Copy drop data")
        If (reply = vbYes) Then
            debug("Copy Confirmed")

            UpdateDropDataArrays(Val(LP_Sequence_LBL.Text))

            For i = 1 To NumberOnDrops
                If (drop_OnOff(i) = "ON") Then
                    StartTimes_TB(i).Text = Format(drop_StartTime(i), "0000")
                    SizeTimes_TB(i).Text = Format(drop_SizeTime(i), "0000")
                End If
            Next

            If (CT_OnOff_BTN.Text = "ON") Then
                CT_StartTime_TB.Text = Format(CT_StartTime, "0000")
            End If

            If (FT1_OnOff_BUTTON.Text = "ON") Then
                FT1_Time_TB.Text = Format(FT1_StartTime, "0000")
            End If
            If (FT2_OnOff_BUTTON.Text = "ON") Then
                FT2_Time_TB.Text = Format(FT2_StartTime, "0000")
            End If
            If (FT3_OnOff_BUTTON.Text = "ON") Then
                FT3_Time_TB.Text = Format(FT3_StartTime, "0000")
            End If

        End If



    End Sub

















    ' _____         _                   
    '|  __ \       | |                  
    '| |  | |  ___ | |__   _   _   __ _ 
    '| |  | | / _ \| '_ \ | | | | / _` |
    '| |__| ||  __/| |_) || |_| || (_| |
    '|_____/  \___||_.__/  \__,_| \__, |
    '                              __/ |
    '                             |___/ 
    '

#Region "debug"




    Private Sub turnDebugOn()
        Me.Width = widthDebug
        debugTextBox.Visible = True
        SET_DEBUG_BTN.Text = "ON"
        SET_DEBUG_BTN.BackColor = green
        SET_DEBUG_LBL.Visible = True
        SET_DEBUG_BTN.Visible = True
        SET_DEBUG_BTN2.Visible = True
        checkConnected_Timer.Enabled = True
    End Sub

    Private Sub turnDebugOff()
        Me.Width = widthNormal
        debugTextBox.Visible = False
        SET_DEBUG_BTN.Text = "OFF"
        SET_DEBUG_BTN.BackColor = red

        checkConnected_Timer.Enabled = False

        If (DEBUG_MASTER = False) Then
            SET_DEBUG_LBL.Visible = False
            SET_DEBUG_BTN.Visible = False
            SET_DEBUG_BTN2.Visible = False
        End If
    End Sub


    Private Sub BTN_DB_CLR_Click(sender As Object, e As EventArgs) Handles BTN_DB_CLR.Click
        debugTextBox.Text = ""
    End Sub


    Private Sub debug(text As String)
        Dim txt As String = ""
        If (text = "<RESET>") Then
            txt = "<RESET>" & vbCrLf & vbCrLf
        Else
            txt = text & vbCrLf
        End If
        debugTextBox.AppendText(txt)
    End Sub


    Private Sub SET_DEBUG_BTN2_Click(sender As Object, e As EventArgs) Handles SET_DEBUG_BTN2.Click

        Dim i As Integer
        For i = 1 To 10

            dropOnOffButtons_BTN(i).Text = "ON"
            solValves_CB(i).Text = i
            If (i = 7) Then solValves_CB(i).Text = 1
            If (i = 8) Then solValves_CB(i).Text = 2
            If (i = 9) Then solValves_CB(i).Text = 3
            If (i = 10) Then solValves_CB(i).Text = 4
            StartTimes_TB(i).Text = (i - 1) * 250
            SizeTimes_TB(i).Text = "250"
            showRow(i)
        Next

        NumActiveDrops_LBL2.Text = 10

        CT_OnOff_BTN.Text = "ON"
        CT_StartTime_TB.Text = "1500"
        FT1_OnOff_BUTTON.Text = "ON"
        FT2_OnOff_BUTTON.Text = "ON"
        FT3_OnOff_BUTTON.Text = "ON"
        FT1_Time_TB.Text = "1500"
        FT2_Time_TB.Text = "1500"
        FT3_Time_TB.Text = "1500"

        CT_Pulse_TB.Text = "10"
        FT1_Pulse_TB.Text = "10"
        FT2_Pulse_TB.Text = "10"
        FT3_Pulse_TB.Text = "10"


        UpdateDropTab()
        UpdateSettingsTab()
    End Sub


    Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles checkConnected_Timer.Tick
        checkConnected_Timer.Enabled = False
        Dim tmp As Boolean
        tmp = SerialPort1.IsOpen
        If (tmp) Then
            Connected_Flag.Text = "TRUE"
        Else
            Connected_Flag.Text = "FALSE"
        End If
        checkConnected_Timer.Enabled = True
    End Sub


#End Region ' "debug"








    ' 
    '   _       ____            _____                _____      __      __ ______ 
    '  | |     / __ \    /\    |  __ \     ___      / ____|   /\\ \    / /|  ____|
    '  | |    | |  | |  /  \   | |  | |   ( _ )    | (___    /  \\ \  / / | |__   
    '  | |    | |  | | / /\ \  | |  | |   / _ \/\   \___ \  / /\ \\ \/ /  |  __|  
    '  | |____| |__| |/ ____ \ | |__| |  | (_>  <   ____) |/ ____ \\  /   | |____ 
    '  |______|\____//_/    \_\|_____/    \___/\/  |_____//_/    \_\\/    |______|
    '

#Region "LOAD & SAVE"



    Private Sub SAVE_BTN_Click(sender As Object, e As EventArgs) Handles SAVE_BTN.Click
        SaveData("USER")
    End Sub

    Private Sub LOAD_BTN_Click(sender As Object, e As EventArgs) Handles LOAD_BTN.Click
        LoadData("USER")
    End Sub




    '  ___   __ _ __   __ ___ 
    ' / __| / _` |\ \ / // _ \
    ' \__ \| (_| | \ V /|  __/
    ' |___/ \__,_|  \_/  \___|
    '

    Private Sub SaveData(SystemOrUSer As String)

        debug(vbCrLf & "Enter save data() : " & SystemOrUSer)

        ' at max number of drops + other data, 44 elements are required
        ' for now, reserving 50 is more than enough

        Dim data(50) As String
        Dim i As Integer = 0

        ' Header
        Dim currentDate As Date = Format(DateTime.Today, "dd/MM/yyyy")
        Dim CurrentTime As Date = TimeOfDay

        i = i + 1 : data(i) = "dropController Data File"
        i = i + 1 : data(i) = "Saved: " & currentDate & " " & CurrentTime


        ' Drop Data
        FormatAllTextBoxes()

        i = i + 1 : data(i) = "numDrops|" & NumActiveDrops_LBL2.Text
        i = i + 1 : data(i) = "----  -OF-V-STRT-INC-VAL-SIZE-INC-VAL "

        Dim leadZero As String = ""
        Dim tmpStr As String = ""
        Dim j As Integer = 0
        For j = 1 To Val(NumActiveDrops_LBL2.Text)

            ' leadZero = "0" : If j > 9 Then leadZero = ""
            tmpStr = ""

            tmpStr = tmpStr & "D" & j & "|" & RowLabels_LBL_NEW(j).Text & "|" & dropOnOffButtons_BTN(j).Text & "|"
            tmpStr = tmpStr & Val(solValves_CB(j).Text) & "|"
            tmpStr = tmpStr & StartTimes_TB(j).Text & "|"
            tmpStr = tmpStr & StartTimeIncDec_BTN(j).Text & "|"
            tmpStr = tmpStr & StartTimeIncDecVal_TB(j).Text & "|"
            tmpStr = tmpStr & SizeTimes_TB(j).Text & "|"
            tmpStr = tmpStr & SizeTimeIncDec_BTN(j).Text & "|"
            tmpStr = tmpStr & SizeTimeIncDecVal_TB(j).Text
            data(i + j) = tmpStr
        Next j

        i = i + j - 1

        i = i + 1 : data(i) = "CT|" & CT_OnOff_BTN.Text & "|" & CT_StartTime_TB.Text & "|" & CT_IncDec_BTN.Text & "|" & CT_IncDecTime_TB.Text
        i = i + 1 : data(i) = "SYNCoffset|" + SyncStartOffset_Time_TB.Text
        i = i + 1 : data(i) = "BULBoffset|" + BulbStopOffset_Time_TB.Text
        i = i + 1 : data(i) = "FT1|" & FT1_OnOff_BUTTON.Text & "|" & FT1_Time_TB.Text & "|" & FT1_IncDec_BTN.Text & "|" & FT1_IncDecTime_TB.Text
        i = i + 1 : data(i) = "FT2|" & FT2_OnOff_BUTTON.Text & "|" & FT2_Time_TB.Text & "|" & FT2_IncDec_BTN.Text & "|" & FT2_IncDecTime_TB.Text
        i = i + 1 : data(i) = "FT3|" & FT3_OnOff_BUTTON.Text & "|" & FT3_Time_TB.Text & "|" & FT3_IncDec_BTN.Text & "|" & FT3_IncDecTime_TB.Text
        i = i + 1 : data(i) = "Loop|" + LoopMode_BTN.Text
        i = i + 1 : data(i) = "ButOrTimer|" & lp_TimerOrButton_BTN.Text
        i = i + 1 : data(i) = "WaitTime|" & LP_waitTimeVal_TB.Text

        ' Settings Data
        UpdateSettingsTab()

        i = i + 1 : data(i) = "CT_Pulse|" + CT_Pulse_TB.Text
        i = i + 1 : data(i) = "FT1_Pulse|" + FT1_Pulse_TB.Text
        i = i + 1 : data(i) = "FT2_Pulse|" + FT2_Pulse_TB.Text
        i = i + 1 : data(i) = "FT3_Pulse|" + FT3_Pulse_TB.Text
        i = i + 1 : data(i) = "Leo|" + SET_LEO_BUT.Text
        i = i + 1 : data(i) = "Sound|" + SET_SOUND_BTN.Text
        i = i + 1 : data(i) = "FormatTB|" + Set_FormatTextBoxes_BTN.Text

        i = i + 1 : data(i) = "END"
        i = i + 1 : data(i) = " "

        ' The number of array elements
        Dim ArrayLength As Integer = i



        '  USER means the user has clicked the SAVE button. Allow them to save as..
        If SystemOrUSer.ToUpper = "USER" Then

            With SaveFileDialog1
                .FileName = "DropControlerDataFile"
                .Filter = "dropController Data File (*.txt)|*.txt"
                .DefaultExt = "txt"
                .FilterIndex = 2
                .RestoreDirectory = True
            End With

            Try
                If SaveFileDialog1.ShowDialog = DialogResult.OK Then
                    Dim file As System.IO.StreamWriter
                    file = My.Computer.FileSystem.OpenTextFileWriter(SaveFileDialog1.FileName, False)
                    For k As Integer = 1 To ArrayLength
                        file.WriteLine(data(k))
                    Next k
                    file.Close()
                End If

            Catch ex As Exception
                MsgBox(ex.Message)
            End Try

        End If




        '  this is a SYSTEM request so use default file. Does not require user interaction
        If SystemOrUSer.ToUpper = "SYSTEM" Then

            Dim filename As String = "dropControllerDataFile.txt"

            If (System.IO.File.Exists(filename) = False) Then
                System.IO.File.Create(filename).Dispose()
            End If

            Try
                Dim file As System.IO.StreamWriter
                file = My.Computer.FileSystem.OpenTextFileWriter(filename, False)
                For k As Integer = 1 To ArrayLength
                    file.WriteLine(data(k))
                Next k
                file.Close()

            Catch ex As Exception
                MsgBox(ex.Message)
            End Try

        End If

        debug("__EXIT SaveData()")
    End Sub






    '  _                    _ 
    ' | |                  | |
    ' | |  ___    __ _   __| |
    ' | | / _ \  / _` | / _` |
    ' | || (_) || (_| || (_| |
    ' |_| \___/  \__,_| \__,_|
    '

    Private Sub LoadData(SystemOrUser As String)

        debug("Enter LoadData() : " & SystemOrUser)

        Dim DataFromFile(50) As String
        Dim tmp As String = ""
        Dim i As Integer = 0
        Dim LastPos As Integer = 0

        Dim numDrops As Integer = 0
        Dim DropNumber As Integer = 0

        Dim DataFound As Boolean = False


        If SystemOrUser.ToUpper = ("SYSTEM") Then

            Dim filename As String = "dropControllerDataFile.txt"

            If Not System.IO.File.Exists(filename) Then
                debug("  Data file not found")
                debug("  Creating a new file")

                Reset()
                SaveData("SYSTEM")
            Else

                debug("  read the data file")

                Try
                    ' File exists - load the saved data
                    Dim fileReader As System.IO.StreamReader
                    fileReader = My.Computer.FileSystem.OpenTextFileReader(filename)

                    tmp = ""
                    While tmp <> "END" And fileReader.Peek <> -1
                        tmp = fileReader.ReadLine()
                        If InStr(1, tmp, "|", CompareMethod.Text) > 0 Then
                            i = i + 1 : DataFromFile(i) = tmp
                            debug("  in: " & tmp)
                        End If
                    End While
                    LastPos = i
                    fileReader.Close()


                Catch ex As Exception
                    MsgBox(ex.Message)

                End Try


                debug("  data file closed")
            End If
        End If






        If SystemOrUser.ToUpper = ("USER") Then

            With OpenFileDialog1
                .FileName = ""
                .Filter = "dropController Data File (*.txt)|*.txt"
                .DefaultExt = "txt"
                .FilterIndex = 2
                .RestoreDirectory = True
                .Title = "Load drop data"
            End With


            If OpenFileDialog1.ShowDialog = DialogResult.OK Then
                debug("fn - " & OpenFileDialog1.FileName)

                Try

                    ' File exists - load the saved data
                    Dim fileReader As System.IO.StreamReader
                    fileReader = My.Computer.FileSystem.OpenTextFileReader(OpenFileDialog1.FileName)

                    tmp = ""
                    While tmp <> "END" And fileReader.Peek <> -1
                        tmp = fileReader.ReadLine()
                        If InStr(1, tmp, "|", CompareMethod.Text) > 0 Then
                            i = i + 1 : DataFromFile(i) = tmp
                            debug("  in: " & tmp)
                        End If
                    End While
                    LastPos = i
                    fileReader.Close()


                Catch ex As Exception
                    MsgBox(ex.Message)
                End Try

            End If


        End If




        ' Parse the loaded data

        debug("  LastPos = " & LastPos)
        For i = 1 To LastPos

            If InStr(1, DataFromFile(i), "|", CompareMethod.Text) Then

                '  debug("  D = " & DataFromFile(i))
                Dim tmpSplit() As String = Split(DataFromFile(i), "|", -1, CompareMethod.Text)

                'numDrops is used as a basic check to make sure aldrops are loaded
                If (tmpSplit(0) = "numDrops") Then

                    If (Val(tmpSplit(1)) > 0 And Val(tmpSplit(1)) < MaxNumDrops + 1) Then
                        numDrops = Val(tmpSplit(1))
                    Else
                        numDrops = -99  ' error code
                    End If
                    DataFound = True
                End If




                'Drop01|ON|1|0000|INC|000|0000|INC|000
                If (Microsoft.VisualBasic.Strings.Left(tmpSplit(0), 1) = "D") Then

                    DropNumber = DropNumber + 1

                    If tmpSplit(1) <> "" Then RowLabels_LBL_NEW(DropNumber).Text = tmpSplit(1)

                    ' ON/OFF
                    If tmpSplit(2) = "ON" Or tmpSplit(2) = "OFF" Then
                        dropOnOffButtons_BTN(DropNumber).Text = tmpSplit(2)
                    Else
                        dropOnOffButtons_BTN(DropNumber).Text = "OFF"
                    End If

                    ' solenoid valve: 1-6
                    If Val(tmpSplit(3)) > 0 And Val(tmpSplit(3)) <= numValves Then
                        solValves_CB(DropNumber).SelectedIndex = Val(tmpSplit(3)) - 1
                    Else
                        solValves_CB(DropNumber).SelectedIndex = 0
                    End If

                    ' start time: 0000-9999
                    If Val(tmpSplit(4)) >= 0 And Val(tmpSplit(4)) <= 9999 Then
                        StartTimes_TB(DropNumber).Text = Val(tmpSplit(4)).ToString
                    Else
                        StartTimes_TB(DropNumber).Text = "0"
                    End If

                    ' start time inc/dec delta button: INC, DEC, OFF
                    If tmpSplit(5) = "INC" Or tmpSplit(5) = "DEC" Or tmpSplit(5) = "OFF" Then
                        StartTimeIncDec_BTN(DropNumber).Text = tmpSplit(5)
                    Else
                        StartTimeIncDec_BTN(DropNumber).Text = "OFF"
                    End If

                    ' start time inc/dec time: 0000-0000
                    If Val(tmpSplit(6)) >= 0 And Val(tmpSplit(6)) <= 999 Then
                        StartTimeIncDecVal_TB(DropNumber).Text = Val(tmpSplit(6))
                    Else
                        StartTimeIncDecVal_TB(DropNumber).Text = "0"
                    End If

                    ' size time: 0000-9999
                    If Val(tmpSplit(7)) >= 0 And Val(tmpSplit(7)) <= 9999 Then
                        SizeTimes_TB(DropNumber).Text = Val(tmpSplit(7)).ToString
                    Else
                        SizeTimes_TB(DropNumber).Text = "0"
                    End If

                    ' size inc/dec button: INC, DEC, OFF
                    ' start time inc/dec delta button: INC, DEC, OFF

                    If tmpSplit(8) = "INC" Or tmpSplit(8) = "DEC" Or tmpSplit(8) = "OFF" Then
                        SizeTimeIncDec_BTN(DropNumber).Text = tmpSplit(8)
                    Else
                        SizeTimeIncDec_BTN(DropNumber).Text = "OFF"
                    End If

                    'size inc/dec time:  000-999
                    If Val(tmpSplit(9)) >= 0 And Val(tmpSplit(9)) <= 999 Then
                        SizeTimeIncDecVal_TB(DropNumber).Text = Val(tmpSplit(9))
                    Else
                        SizeTimeIncDecVal_TB(DropNumber).Text = "0"
                    End If

                    DataFound = True
                End If  'If (Microsoft.VisualBasic.Strings.Left(tmpSplit(0), 4) = "Drop") Then


                ' camera trigger   CT|0250|INC|000
                If (tmpSplit(0) = "CT") Then

                    If tmpSplit(1) = "ON" Or tmpSplit(1) = "OFF" Or tmpSplit(1) = "SYNC" Or tmpSplit(1) = "BULB" Then
                        CT_OnOff_BTN.Text = tmpSplit(1)
                    Else
                        CT_OnOff_BTN.Text = "OFF"
                    End If

                    If Val(tmpSplit(2)) >= 0 And Val(tmpSplit(2)) <= 9999 Then
                        CT_StartTime_TB.Text = Val(tmpSplit(2))
                    Else
                        CT_StartTime_TB.Text = "0"
                    End If

                    If tmpSplit(3) = "INC" Or tmpSplit(3) = "DEC" Or tmpSplit(3) = "OFF" Then
                        CT_IncDec_BTN.Text = tmpSplit(3)
                    Else
                        CT_IncDec_BTN.Text = "OFF"
                    End If


                    If Val(tmpSplit(4)) >= 0 And Val(tmpSplit(4)) <= 999 Then
                        CT_IncDecTime_TB.Text = Val(tmpSplit(4))
                    Else
                        CT_IncDecTime_TB.Text = "0"
                    End If

                    DataFound = True
                End If  '  If (tmpSplit(0) = "CT") Then


                If (tmpSplit(0) = "SYNCoffset") Then
                    If Val(tmpSplit(1)) >= 0 And Val(tmpSplit(1)) <= 9999 Then
                        SyncStartOffset_Time_TB.Text = Val(tmpSplit(1))
                    Else
                        SyncStartOffset_Time_TB.Text = "0"
                    End If
                    DataFound = True
                End If

                If (tmpSplit(0) = "BULBoffset") Then
                    If Val(tmpSplit(1)) >= 0 And Val(tmpSplit(1)) <= 9999 Then
                        BulbStopOffset_Time_TB.Text = Val(tmpSplit(1))
                    Else
                        BulbStopOffset_Time_TB.Text = "0"
                    End If
                    DataFound = True
                End If


                'FTn|OFF|1234|INC|000
                If (tmpSplit(0) = "FT1") Then

                    If Not IsNumeric(tmpSplit(2)) Then tmpSplit(1) = "0"
                    If Not IsNumeric(tmpSplit(4)) Then tmpSplit(1) = "0"

                    If tmpSplit(1) = "ON" Or tmpSplit(1) = "OFF" Then
                        FT1_OnOff_BUTTON.Text = tmpSplit(1)
                    Else
                        FT1_OnOff_BUTTON.Text = "OFF"
                    End If

                    If Val(tmpSplit(2)) >= 0 And Val(tmpSplit(2)) <= 9999 Then
                        FT1_Time_TB.Text = Val(+tmpSplit(2))
                    Else
                        FT1_Time_TB.Text = "0"
                    End If

                    If tmpSplit(3) = "INC" Or tmpSplit(3) = "DEC" Or tmpSplit(3) = "OFF" Then
                        FT1_IncDec_BTN.Text = tmpSplit(3)
                    Else
                        FT1_IncDec_BTN.Text = "OFF"
                    End If

                    If Val(tmpSplit(4)) >= 0 And Val(tmpSplit(4)) <= 999 Then
                        FT1_IncDecTime_TB.Text = Val(tmpSplit(4))
                    Else
                        FT1_IncDecTime_TB.Text = "0"
                    End If

                    DataFound = True
                End If



                'FTn|OFF|1234|INC|000
                If (tmpSplit(0) = "FT2") Then

                    If Not IsNumeric(tmpSplit(2)) Then tmpSplit(1) = "0"
                    If Not IsNumeric(tmpSplit(4)) Then tmpSplit(1) = "0"

                    If tmpSplit(1) = "ON" Or tmpSplit(1) = "OFF" Then
                        FT2_OnOff_BUTTON.Text = tmpSplit(1)
                    Else
                        FT2_OnOff_BUTTON.Text = "OFF"
                    End If

                    If Val(tmpSplit(2)) >= 0 And Val(tmpSplit(2)) <= 9999 Then
                        FT2_Time_TB.Text = Val(+tmpSplit(2))
                    Else
                        FT2_Time_TB.Text = "0"
                    End If

                    If tmpSplit(3) = "INC" Or tmpSplit(3) = "DEC" Or tmpSplit(3) = "OFF" Then
                        FT2_IncDec_BTN.Text = tmpSplit(3)
                    Else
                        FT2_IncDec_BTN.Text = "OFF"
                    End If

                    If Val(tmpSplit(4)) >= 0 And Val(tmpSplit(4)) <= 999 Then
                        FT2_IncDecTime_TB.Text = Val(tmpSplit(4))
                    Else
                        FT2_IncDecTime_TB.Text = "0"
                    End If

                    DataFound = True
                End If


                'FTn|OFF|1234|INC|000
                If (tmpSplit(0) = "FT3") Then

                    If Not IsNumeric(tmpSplit(2)) Then tmpSplit(1) = "0"
                    If Not IsNumeric(tmpSplit(4)) Then tmpSplit(1) = "0"

                    If tmpSplit(1) = "ON" Or tmpSplit(1) = "OFF" Then
                        FT3_OnOff_BUTTON.Text = tmpSplit(1)
                    Else
                        FT3_OnOff_BUTTON.Text = "OFF"
                    End If

                    If Val(tmpSplit(2)) >= 0 And Val(tmpSplit(2)) <= 9999 Then
                        FT3_Time_TB.Text = Val(+tmpSplit(2))
                    Else
                        FT3_Time_TB.Text = "0"
                    End If

                    If tmpSplit(3) = "INC" Or tmpSplit(3) = "DEC" Or tmpSplit(3) = "OFF" Then
                        FT3_IncDec_BTN.Text = tmpSplit(3)
                    Else
                        FT3_IncDec_BTN.Text = "OFF"
                    End If

                    If Val(tmpSplit(4)) >= 0 And Val(tmpSplit(4)) <= 999 Then
                        FT3_IncDecTime_TB.Text = Val(tmpSplit(4))
                    Else
                        FT3_IncDecTime_TB.Text = "0"
                    End If

                    DataFound = True
                End If



                If tmpSplit(0) = "Loop" Then
                    If tmpSplit(1) = "ON" Or tmpSplit(1) = "OFF" Then
                        LoopMode_BTN.Text = tmpSplit(1)
                    Else
                        LoopMode_BTN.Text = "OFF"
                    End If
                    DataFound = True
                End If

                If tmpSplit(0) = "ButOrTimer" Then
                    If tmpSplit(1) = "BUTTON" Or tmpSplit(1) = "TIMER" Then
                        lp_TimerOrButton_BTN.Text = tmpSplit(1)
                    Else
                        lp_TimerOrButton_BTN.Text = "OFF"
                    End If
                    DataFound = True
                End If



                If (tmpSplit(0) = "WaitTime") Then

                    If Not IsNumeric(tmpSplit(1)) Then tmpSplit(1) = "0"

                    If Val(tmpSplit(1)) >= 0 Or Val(tmpSplit(1)) <= 99 Then
                        LP_waitTimeVal_TB.Text = Val(tmpSplit(1)).ToString
                    Else
                        LP_waitTimeVal_TB.Text = "0"
                    End If
                    DataFound = True
                End If




                ' Settings


                If (tmpSplit(0) = "CT_Pulse") Then
                    If Not IsNumeric(tmpSplit(1)) Then tmpSplit(1) = "0"

                    If Val(tmpSplit(1)) >= 0 And Val(tmpSplit(1)) <= 999 Then
                        CT_Pulse_TB.Text = Val(tmpSplit(1)).ToString
                    Else
                        CT_Pulse_TB.Text = "0"
                    End If
                    DataFound = True
                End If

                If (tmpSplit(0) = "FT1_Pulse") Then
                    If Not IsNumeric(tmpSplit(1)) Then tmpSplit(1) = "0"

                    If Val(tmpSplit(1)) >= 0 And Val(tmpSplit(1)) <= 999 Then
                        FT1_Pulse_TB.Text = Val(tmpSplit(1)).ToString
                    Else
                        FT1_Pulse_TB.Text = "0"
                    End If
                    DataFound = True
                End If

                If tmpSplit(0) = "FT2_Pulse" Then
                    If Not IsNumeric(tmpSplit(1)) Then tmpSplit(1) = "0"

                    If Val(tmpSplit(1)) >= 0 And Val(tmpSplit(1)) <= 999 Then
                        FT2_Pulse_TB.Text = Val(tmpSplit(1)).ToString
                    Else
                        FT2_Pulse_TB.Text = "0"
                    End If

                    DataFound = True
                End If


                If tmpSplit(0) = "FT3_Pulse" Then
                    If Not IsNumeric(tmpSplit(1)) Then tmpSplit(1) = "0"

                    If Val(tmpSplit(1)) >= 0 And Val(tmpSplit(1)) <= 999 Then
                        FT3_Pulse_TB.Text = Val(tmpSplit(1)).ToString
                    Else
                        FT3_Pulse_TB.Text = "0"
                    End If

                    DataFound = True
                End If



                If (tmpSplit(0) = "Sound") Then
                    If tmpSplit(1) = "ON" Or tmpSplit(1) = "OFF" Then
                        SET_SOUND_BTN.Text = tmpSplit(1)
                    Else
                        SET_SOUND_BTN.Text = "OFF"
                    End If
                    DataFound = True
                End If


                If (tmpSplit(0) = "Leo") Then
                    If tmpSplit(1) = "ON" Or tmpSplit(1) = "OFF" Then
                        SET_LEO_BUT.Text = tmpSplit(1)
                    Else
                        SET_LEO_BUT.Text = "OFF"
                    End If
                    DataFound = True
                End If

                If (tmpSplit(0) = "FormatTB") Then
                    If tmpSplit(1) = "ON" Or tmpSplit(1) = "OFF" Then
                        Set_FormatTextBoxes_BTN.Text = tmpSplit(1)
                    Else
                        Set_FormatTextBoxes_BTN.Text = "ON"
                    End If
                    DataFound = True
                End If

                If (tmpSplit(0) = "Debug" Or tmpSplit(0) = "DEBUG") Then
                    If (tmpSplit(1) = "ON" Or tmpSplit(1) = "OFF") Then
                        SET_DEBUG_BTN.Text = tmpSplit(1)
                    Else
                        SET_DEBUG_BTN.Text = "OFF"
                    End If


                    If (tmpSplit(1) = "ON") Then
                        turnDebugOn()
                        DEBUG_MASTER = True
                    End If
                    DataFound = True

                End If



                If (Not DataFound) Then
                    debug(vbCrLf)
                    debug("  NOT FOUND:")
                    debug(DataFromFile(i))
                    debug(vbCrLf)
                End If

            End If  '  If InStr(1, tmp, "|", CompareMethod.Text) Then

        Next

        NumActiveDrops_LBL2.Text = DropNumber.ToString
        If Val(NumActiveDrops_LBL2.Text) < 1 Then NumActiveDrops_LBL2.Text = "1"

        If numDrops <> DropNumber Then
            debug("  ERR: numDrops check failed")
        Else
            debug("  numDrops check OK")
        End If

        UpdateDropTab()
        UpdateSettingsTab()


        debug("__EXIT LoadData()" & vbCrLf)

    End Sub

























#End Region   ' "LOAD & SAVE"











End Class

