Pulse_Step_Size = 10  #(Hz) Change in frequency with each regulation step when pulsing
Max_Threshold = 10000  #(Hz) Total amount of frequency change before automatically tripping off program
Walk_Threshold = 2.5  #(mV) Deviation from 0 the error signal needs to be before CW regulation kicks in
Pulse_Walk_Threshold = 0.5  #(mV) Deviation from 0 the error signal needs before pulsing regulation kicks in
Wait_after_step = 0.0400  #Seconds, the time waited after a step is taken, necessary to allow oscope measurements to change
Wait_between_reads = 0.0100  #Seconds, currently not used, supplemented by GUI time between reads
Long = False  #The form that our measurement is output from the o-scope, depending on the way it is set up this can be in either a short or long form

GPIB.measurement_setup(
    OS, IF_Channel,
    measurement=Measurement)  #Setting up the required measurement
GPIB.channel_settings_check(
    OS, IF_Channel
)  #Setting up the vertical and horizontal settings for the error signal
GPIB.trigger_settings_set(
    OS, Trigger_Channel, Trigger_Level
)  #Sets up the vertical settings for trigger channel and trigger parameters
GPIB.vertical_marker_pulsing(
    OS, IF_Channel)  #Sets up vertical cursor bars to read edge of pulse

interlock_color = 'MediumPurple1'
global Ups  #Defining global parameters, these ones are not actually necessary but leave them be
global Downs
global i
Ups = 0  #number of steps taken up before taking one down
Downs = 0  #visa versa
i = 0  #total number of iterative loops gone through, only present to show differences in command line readouts
Start_Freq = GPIB.freq(SG)  #taking the start frequency of the signal generator

try:  #Test to see if the short form of the oscilloscope or long form of output
    short_test = float(OS.query("MEASU:MEAS1:VAL?"))
def scanning():  #Defining what is happening when scanning our GUI

    global reset  #Global variables, these first three are necessary but again, leave them all.
    global pulsing
    global running
    global Ups
    global Downs
    global i
    global Error_signal_offset

    #########################################
    # Reset button loop
    #########################################

    if reset:  #Checks the reset parameter and runs if True
        print("-" * 60 + "\n\n\nResetting Oscilloscope\n\n\n" +
              "-" * 60)  #print visual break to indicate reset

        GPIB.measurement_setup(
            OS, IF_Channel,
            measurement=Measurement)  #Same as beginning parameters above
        GPIB.channel_settings_check(OS, IF_Channel)
        GPIB.trigger_settings_set(OS, Trigger_Channel, Trigger_Level)
        GPIB.vertical_marker_pulsing(OS, IF_Channel)

        reset = False  #Sets the reset parameter to false so not looping

    #########################################
    # Checking for the regulation loop if on
    #########################################

    if running:  # running parameter, if True, runs this loop
        root.configure(
            bg='SpringGreen2')  #Sets the background of the GUI to be green

        #########################################
        # Loop for pulsing operation
        #########################################

        if pulsing:  #Checks pulsing tag and runs this loop if true

            read_value = GPIB.cursor_vbar_read_mv(
                OS)  #Takes the current value of oscilloscope vbar

            if read_value > (
                    Error_signal_offset + Pulse_Walk_Threshold
            ):  #Checks to see if that value is outside of threshold
                Ups += 1
                Downs = 0
                if Ups > Loops_Debounce:  #Effective debounce
                    temp_freq = GPIB.freq(SG)  #Gathers the current frequency
                    GPIB.write_frequency(
                        SG, (temp_freq + Pulse_Step_Size), "HZ"
                    )  #Writes calculated frequency to the signal generator
                    print("Raised Frequency ",
                          i)  #Shows that we took a step in frequency
                    if (temp_freq + Pulse_Step_Size) > (
                            Start_Freq + Max_Threshold
                    ):  #Sees if the new frequency is outside of bounds
                        print("Error: Broken on too many steps upward")
                        root.configure(
                            bg=interlock_color)  #Sets to the interlock color
                        running = False  #Breaks loop if true
                    if OS.query(
                            "MEASU:Meas{}:State?".format(Measurement)
                    )[-2] != str(1):  #Sees if the measurement is still active
                        print("Error: Measurement Off")
                        root.configure(
                            bg=interlock_color)  #Sets to the interlock color
                        running = False  #Breaks loop if true
                    if read_value > (Error_signal_offset +
                                     Interlock_Threshold_mv):
                        print("Error: Deviation too far")
                        root.configure(
                            bg=interlock_color)  #Sets to the interlock color
                        running = False
                    time.sleep(
                        Wait_after_step)  #Sleep for after step debounce time

            #########################################
            # Repeat above loop but below the threshold instead of above
            #########################################

            if read_value < (Error_signal_offset - Pulse_Walk_Threshold):
                Downs += 1
                Ups = 0
                if Downs > Loops_Debounce:
                    temp_freq = GPIB.freq(SG)
                    GPIB.write_frequency(SG, (temp_freq - Pulse_Step_Size),
                                         "HZ")
                    print("Lowered Frequency ", i)
                    if (temp_freq - Pulse_Step_Size) < (Start_Freq -
                                                        Max_Threshold):
                        print("Broken on too many steps downward")
                        root.configure(bg=interlock_color)
                        running = False
                    if OS.query("MEASU:Meas{}:State?".format(
                            Measurement))[-2] != str(1):
                        print("Measurement Off")
                        root.configure(bg=interlock_color)
                        running = False
                    if read_value < (Error_signal_offset -
                                     Interlock_Threshold_mv):
                        print("Error: Deviation too far")
                        root.configure(
                            bg=interlock_color)  #Sets to the interlock color
                        running = False
                    time.sleep(Wait_after_step)

            time.sleep(Wait_between_reads)
            i += 1

        #########################################
        # Loop for CW operation, use same logic
        #########################################

        else:
            read_value = GPIB.read_mv(OS, long=Long, measurement=Measurement)

            if read_value > (Error_signal_offset + Walk_Threshold):
                Ups += 1
                Downs = 0
                if Ups > Loops_Debounce:
                    temp_freq = GPIB.freq(SG)
                    GPIB.write_frequency(SG, (temp_freq + Step_size), "HZ")
                    print("Raised Frequency ", i)
                    if (temp_freq + Step_size) > (Start_Freq + Max_Threshold):
                        print("Broken on too many steps upward")
                        root.configure(bg=interlock_color)
                        running = False
                    if OS.query("MEASU:Meas{}:State?".format(
                            Measurement))[-2] != str(1):
                        print("Measurement Off")
                        root.configure(bg=interlock_color)
                        running = False
                    if read_value > (Error_signal_offset +
                                     Interlock_Threshold_mv):
                        print("Error: Deviation too far")
                        root.configure(
                            bg=interlock_color)  #Sets to the interlock color
                        running = False
                    time.sleep(Wait_after_step)

            #########################################
            # Repeat above loop but below the threshold instead of above
            #########################################

            if read_value < (Error_signal_offset - Walk_Threshold):
                Downs += 1
                Ups = 0
                if Downs > Loops_Debounce:
                    temp_freq = GPIB.freq(SG)
                    GPIB.write_frequency(SG, (temp_freq - Step_size), "HZ")
                    print("Lowered Frequency ", i)
                    if (temp_freq - Step_size) < (Start_Freq - Max_Threshold):
                        print("Broken on too many steps downward")
                        root.configure(bg=interlock_color)
                        running = False
                    if OS.query("MEASU:Meas{}:State?".format(
                            Measurement))[-2] != str(1):
                        print("Measurement Off")
                        root.configure(bg=interlock_color)
                        running = False
                    if read_value < (Error_signal_offset -
                                     Interlock_Threshold_mv):
                        print("Error: Deviation too far")
                        root.configure(
                            bg=interlock_color)  #Sets to the interlock color
                        running = False
                    time.sleep(Wait_after_step)

            #time.sleep(Wait_between_reads)
            i += 1  #Update iterator

    # After .1 seconds, call scanning again (create a recursive loop)
    root.after(100,
               scanning)  #Wait the first number of ms, then continue scanning
while True:

    reset = M.Read(Client, Reset_Tag, Bool = True)
    running = M.Read(Client, Running_Tag, Bool = True)
    pulsing = M.Read(Client, Pulsing_Tag, Bool = True)
    regulation_setpoint_change = M.Read(Client, Regulation_Setpoint_Tag, Bool = True)
    Error_signal_offset = M.Read(Client, Regulation_Entry_Tag)
    #print(Error_signal_offset)
    i += 1
    
    if reset: #Checks the reset parameter and runs if True
        print("-"*60 + "\n\n\nResetting Oscilloscope\n\n\n" + "-"*60) #print visual break to indicate reset

        GPIB.measurement_setup(OS,IF_Channel, measurement = Measurement) #Same as beginning parameters above
        GPIB.channel_settings_check(OS, IF_Channel)
        GPIB.trigger_settings_set(OS, Trigger_Channel, Trigger_Level)
        GPIB.vertical_marker_pulsing(OS, IF_Channel)
        os.system('cls')

        M.Write(Client, Reset_Tag, False, Bool = True)
        
    
    #########################################
    # Checking to see if we want to update regulation setpoint
    #########################################
    if regulation_setpoint_change:
        
        if pulsing:
            Error_signal_offset = GPIB.cursor_vbar_read_mv(OS)
            print("New regulation setpoint: {:.3f} mV".format(Error_signal_offset))
        else: