Source code for output_channels

__author__ = 'David Tadres'
__project__ = 'PiVR'

import os
import tkinter as tk

from PIL import Image, ImageTk
from pathlib import Path

# this try-except statement checks if the processor is a ARM processor
# (used by the Raspberry Pi) or not.
# Since this command only works in Linux it is caught using
# try-except otherwise it's throw an error in a Windows system.
try:
    if os.uname()[4][:3] == 'arm':
        # This will yield True for both a Raspberry and for M1 Chip
        # Apple devices.
        # Use this code snippet
        # (from https://raspberrypi.stackexchange.com/questions/5100/detect-that-a-python-program-is-running-on-the-pi)
        import re
        CPUINFO_PATH = Path("/proc/cpuinfo")
        if CPUINFO_PATH.exists():
            with open(CPUINFO_PATH) as f:
                cpuinfo = f.read()
            if re.search(r"^Model\s*:\s*Raspberry Pi", cpuinfo, flags=re.M) is not None:
                # if True, is Raspberry Pi
                RASPBERRY = True
                LINUX = True
        else: # Test if one more intendation necessary or not. On Varun's computer
            # is Apple M1 chip (or other Arm CPU device).
            RASPBERRY = False
            LINUX = True
    else:
        # is either Mac or Linux
        RASPBERRY = False
        LINUX = True

    DIRECTORY_INDICATOR = '/'
except AttributeError:
    # is Windows
    RASPBERRY = False
    LINUX = False
    DIRECTORY_INDICATOR = '\\'

if RASPBERRY:
    pass


[docs] class DefineOutputChannels(): """ Let user define which output channel (GPIO18, GPIO17 etc...) corresponds to which Channel (1,2 etc..) The Raspberry Pi has a number of addressable GPIOs. PiVR currently uses 4 of them: GPIO18, GPIO17, GPIO27 and GPIO13. The software has a total of 6 output channels: Background, Background 2, Channel 1, Channel 2, Channel 3 and Channel 4. The user therefore has to decide which GPIO# is addressed by which channel. .. warning:: Only GPIO18 and GPIO13 are capable of hardware PWM. The other GPIOs are limited to a maximum frequency of 40'000Hz .. warning:: The transistor on the PCB has a finite rise and fall time. In theory the transistor should be able to be turned on and off every microsecond (10e-6 seconds) which translates to 1 Million Hz (10e6). However, this will not enable the usage of PWM to control light intensity. For example, if a dutycycle of 10% is chosen, it will lead to the transistor being on for only 10% of 1 us, which will lead to unspecified behavior. We usually use 40'000Hz even on the high speed GPIOs. Background and Background 2 are intended to be used as constant light sources during a recording. Typically one of the two will be used to control illumination for the camera to record in optimal light conditions. As PiVR normally uses infrared light to illuminate the scene many animals wont be able to see at this wavelength. If the experimenter wants to use light of a wavelength that the animal can see (or white light) while using infrared illumination for the camera, the other background channel can be used. Channels 1, 2, 3 and 4 are addressable during a recording. Channel 1 will always be used for Virtual Arenas. The other channels are only useful for time dependent stimulation. In principle each GPIO can have its own Channel. This is only useful if illumination (via background, see above) is optimal without fine grained control. """ def __init__(self, path, controller): # create new window and name it self.child = tk.Toplevel() self.child.wm_title('output channel selection') # disable main window self.child.grab_set() # need the controller from the main loop to be able to write on # variables from it self.controller = controller # well..an explanation self.explanation = tk.Label(self.child, justify = tk.LEFT, text='Please select which GPIO you want to use when ' 'defining output for a given channel.\n' 'It is recommended to have "Background"either on ' 'GPIO#18 or GPIO#13 as these are\n' 'the only two high-speed (3Mhz recommended) capable ' 'PWM pins.\n' 'It is usually advisable to select the highest ' 'possible frequency for virtual reality\n' 'experiments.') self.explanation.grid(row=0, column=0, columnspan=5) # The next couple of lines define the image on the far left - # should show the outputs the user has when it was built as # we describe it image has width of ~55, height of ~145 if LINUX: sketch_vol_in = Image.open( path + 'pics/output_selection/VoltIn.png' ).resize((83, 38)) self.sketch_vol_in = ImageTk.PhotoImage(sketch_vol_in) sketch_gpio18 = Image.open( path + 'pics/output_selection/GPIO18.png' ).resize((75, 30)) self.sketch_gpio18 = ImageTk.PhotoImage(sketch_gpio18) sketch_gpio17 = Image.open( path + 'pics/output_selection/GPIO17.png' ).resize((75, 30)) self.sketch_gpio17 = ImageTk.PhotoImage(sketch_gpio17) sketch_gpio27 = Image.open( path + 'pics/output_selection/GPIO27.png' ).resize((75, 30)) self.sketch_gpio27 = ImageTk.PhotoImage(sketch_gpio27) sketch_gpio13 = Image.open( path + 'pics/output_selection/GPIO13.png' ).resize((75, 30)) self.sketch_gpio13 = ImageTk.PhotoImage(sketch_gpio13) else: sketch_vol_in = Image.open( path + 'pics\\output_selection\\VoltIn.png' ).resize((83,38)) self.sketch_vol_in = ImageTk.PhotoImage(sketch_vol_in) sketch_gpio18 = Image.open( path + 'pics\\output_selection\\GPIO18.png' ).resize((75,30)) self.sketch_gpio18 = ImageTk.PhotoImage(sketch_gpio18) sketch_gpio17 = Image.open( path + 'pics\\output_selection\\GPIO17.png' ).resize((75,30)) self.sketch_gpio17 = ImageTk.PhotoImage(sketch_gpio17) sketch_gpio27 = Image.open( path + 'pics\\output_selection\\GPIO27.png' ).resize((75,30)) self.sketch_gpio27 = ImageTk.PhotoImage(sketch_gpio27) sketch_gpio13 = Image.open( path + 'pics\\output_selection\\GPIO13.png' ).resize((75,30)) self.sketch_gpio13 = ImageTk.PhotoImage(sketch_gpio13) # A couple of variables needed to construct the window, # store values and switch between options: # Switch that indicates whether gpio18 is to be used in high # speed mode self.gpio18_high_speed_bool = tk.IntVar() # variable that stores which name is given to the gpio18 output self.gpio18 = tk.StringVar() # variable that stores which frequency is assigned to the # gpio18 output self.gpio18_freq = tk.IntVar() # variable that stores the high speed PWM frequency of the # gpio18 outpout self.gpio18_freq_high_speed = tk.IntVar() # variable that stores which name is given to the gpio17 output self.gpio17 = tk.StringVar() # variable that stores which frequency is assigned to the # gpio17 output self.gpio17_freq = tk.IntVar() # variable that stores which name is given to the gpio27 output self.gpio27 = tk.StringVar() # variable that stores which frequency is assigned to the # gpio27 output self.gpio27_freq = tk.IntVar() # Switch that indicates whether gpio13 is to be used in high # speed mode self.gpio13_high_speed_bool = tk.IntVar() # variable that stores which name is given to the gpio13 output self.gpio13 = tk.StringVar() # variable that stores which frequency is assigned to the # gpio27 output self.gpio13_freq = tk.IntVar() # variable that stores the high speed PWM frequency of the # gpio13 outpout self.gpio13_freq_high_speed = tk.IntVar() # what channels are available - just for user interface, # shouldn't be changed self.available_channels = ( 'Background', 'Channel 1', 'Channel 2', 'Channel 3', 'Channel 4', 'Background 2') # These values might be changed in the future. Reference here: # http://abyz.me.uk/rpi/pigpio/python.html#set_PWM_frequency # Currently the shortcut that is provided with the software # will start the pigpio daemon using a sample rate of 1us. In # principle this could be changed to either 2, 4, 5, 8 or 10. # The available frequencies parameter must then be changed # according to the table below, taken from the the link above # # Hertz # # 1: 40000 20000 10000 8000 5000 4000 2500 2000 1600 # 1250 1000 800 500 400 250 200 100 50 # # 2: 20000 10000 5000 4000 2500 2000 1250 1000 800 # 625 500 400 250 200 125 100 50 25 # # 4: 10000 5000 2500 2000 1250 1000 625 500 400 # 313 250 200 125 100 63 50 25 13 # sample # rate # (us) 5: 8000 4000 2000 1600 1000 800 500 400 320 # 250 200 160 100 80 50 40 20 10 # # 8: 5000 2500 1250 1000 625 500 313 250 200 # 156 125 100 63 50 31 25 13 6 # # 10: 4000 2000 1000 800 500 400 250 200 160 # 125 100 80 50 40 25 20 10 5 # If sample rate of 1us is chosen, uncomment the below and # comment the line that defines # self.available_frequencies - This is the standard! self.available_frequencies = (40000, 20000, 10000, 8000, 5000, 4000, 2500, 2000, 1600, 1250, 1000, 800, 500, 400, 250, 200, 100, 50) # If sample rate of 2us is chosen, uncomment the below and # comment the line that defines # self.available_frequencies # self.available_frequencies = (20000, 10000, 5000, 4000, 2500, # 2000, 1250, 1000, 800, 625, # 500, 400, 250, 200, 125, 100, # 50, 25) # If sample rate of 4us is chosen, uncomment the below and # comment the line that defines # self.available_frequencies # self.available_frequencies = (10000, 5000, 2500, 2000, 1250, # 1000, 625, 500, 400, 313, 250, # 200, 125, 100, 63, 50, 25, 13) # If sample rate of 5us is chosen, uncomment the below and # comment the line that defines # self.available_frequencies # self.available_frequencies = (8000, 4000, 2000, 1600, 1000, # 800, 500, 400, 320, 250, 200, # 160, 100, 80, 50, 40, 20, 10) # If sample rate of 8us is chosen, uncomment the below and # comment the line that defines # self.available_frequencies #self.available_frequencies = (5000, 2500, 1250, 1000, 625, # 500, 313, 250, 200, 156, 125, # 100, 63, 50, 31, 25, 13, 6) # If sample rate of 10us is chosen, uncomment the below and # comment the line that defines # self.available_frequencies # self.available_frequencies = (4000, 2000, 1000, 800, 500, # 400, 250, 200, 160, 125, 100, # 80, 50, 40, 25, 20, 10, 5) # to not confuse anyone, take the values that are currently # being used and plug them directly in the window for this, # go along each of the four lists (e.g. background, # or channel one) and check if it contains one of the GPIO # numbers. If yes, indicate so in the gpio variable. Also # directly read the frequency that has been used so far check # which GPIO(s) were defined to be background before for i in range(len( self.controller.all_common_variables.background)): if self.controller.all_common_variables.background[i][0] \ == 18: self.gpio18.set(self.available_channels[0]) if self.controller.all_common_variables.background[i][1] \ > 1250: self.gpio18_freq_high_speed.set( self.controller.all_common_variables.background[ i][1]) else: self.gpio18_freq.set( self.controller.all_common_variables.background[ i][1]) elif self.controller.all_common_variables.background[i][ 0] == 17: self.gpio17.set(self.available_channels[0]) self.gpio17_freq.set( self.controller.all_common_variables.background[i][ 1]) elif self.controller.all_common_variables.background[i][ 0] == 27: self.gpio27.set(self.available_channels[0]) self.gpio27_freq.set( self.controller.all_common_variables.background[i][ 1]) elif self.controller.all_common_variables.background[i][ 0] == 13: self.gpio13.set(self.available_channels[0]) if self.controller.all_common_variables.background[i][ 1] > 1250: self.gpio13_freq_high_speed.set( self.controller.all_common_variables.background[ i][1]) else: self.gpio13_freq.set( self.controller.all_common_variables.background[ i][1]) # check which GPIO(s) were defined to be background_two before for i in range(len( self.controller.all_common_variables.background_two)): if self.controller.all_common_variables.background_two[i][ 0] == 18: self.gpio18.set(self.available_channels[5]) if \ self.controller.all_common_variables.background_two[i][ 1] > 1250: self.gpio18_freq_high_speed.set( self.controller.all_common_variables.background_two[ i][1]) else: self.gpio18_freq.set( self.controller.all_common_variables.background_two[ i][1]) elif self.controller.all_common_variables.background_two[i][ 0] == 17: self.gpio17.set(self.available_channels[5]) self.gpio17_freq.set( self.controller.all_common_variables.background_two[ i][1]) elif self.controller.all_common_variables.background_two[i][ 0] == 27: self.gpio27.set(self.available_channels[5]) self.gpio27_freq.set( self.controller.all_common_variables.background_two[ i][1]) elif self.controller.all_common_variables.background_two[i][ 0] == 13: self.gpio13.set(self.available_channels[5]) if \ self.controller.all_common_variables.background_two[i][ 1] > 1250: self.gpio13_freq_high_speed.set( self.controller.all_common_variables.background_two[ i][1]) else: self.gpio13_freq.set( self.controller.all_common_variables.background_two[ i][1]) # check which GPIO(s) were defined to be channel one before for i in range( len(self.controller.all_common_variables.channel_one)): if self.controller.all_common_variables.channel_one[i][ 0] == 18: self.gpio18.set(self.available_channels[1]) if self.controller.all_common_variables.channel_one[i][ 1] > 1250: self.gpio18_freq_high_speed.set( self.controller.all_common_variables.channel_one[ i][1]) else: self.gpio18_freq.set( self.controller.all_common_variables.channel_one[ i][1]) elif self.controller.all_common_variables.channel_one[i][ 0] == 17: self.gpio17.set(self.available_channels[1]) self.gpio17_freq.set( self.controller.all_common_variables.channel_one[i][ 1]) elif self.controller.all_common_variables.channel_one[i][ 0] == 27: self.gpio27.set(self.available_channels[1]) self.gpio27_freq.set( self.controller.all_common_variables.channel_one[i][ 1]) elif self.controller.all_common_variables.channel_one[i][ 0] == 13: self.gpio13.set(self.available_channels[1]) if self.controller.all_common_variables.channel_one[i][ 1] > 1250: self.gpio13_freq_high_speed.set( self.controller.all_common_variables.channel_one[ i][1]) else: self.gpio13_freq.set( self.controller.all_common_variables.channel_one[ i][1]) # check which GPIO(s) were defined to be channel two before for i in range( len(self.controller.all_common_variables.channel_two)): if self.controller.all_common_variables.channel_two[i][ 0] == 18: self.gpio18.set(self.available_channels[2]) if self.controller.all_common_variables.channel_two[i][ 1] > 1250: self.gpio18_freq_high_speed.set( self.controller.all_common_variables.channel_two[ i][1]) else: self.gpio18_freq.set( self.controller.all_common_variables.channel_two[ i][1]) elif self.controller.all_common_variables.channel_two[i][ 0] == 17: self.gpio17.set(self.available_channels[2]) self.gpio17_freq.set( self.controller.all_common_variables.channel_two[i][ 1]) elif self.controller.all_common_variables.channel_two[i][ 0] == 27: self.gpio27.set(self.available_channels[2]) self.gpio27_freq.set( self.controller.all_common_variables.channel_two[i][ 1]) elif self.controller.all_common_variables.channel_two[i][ 0] == 13: self.gpio13.set(self.available_channels[2]) if self.controller.all_common_variables.channel_two[i][ 1] > 1250: self.gpio13_freq_high_speed.set( self.controller.all_common_variables.channel_two[ i][1]) else: self.gpio13_freq.set( self.controller.all_common_variables.channel_two[ i][1]) # check which GPIO(s) were defined to be channel three before for i in range(len( self.controller.all_common_variables.channel_three)): if self.controller.all_common_variables.channel_three[i][ 0] == 18: self.gpio18.set(self.available_channels[3]) if \ self.controller.all_common_variables.channel_three[i][ 1] > 1250: self.gpio18_freq_high_speed.set( self.controller.all_common_variables.channel_three[ i][1]) else: self.gpio18_freq.set( self.controller.all_common_variables.channel_three[ i][1]) elif self.controller.all_common_variables.channel_three[i][ 0] == 17: self.gpio17.set(self.available_channels[3]) self.gpio17_freq.set( self.controller.all_common_variables.channel_three[ i][1]) elif self.controller.all_common_variables.channel_three[i][ 0] == 27: self.gpio27.set(self.available_channels[3]) self.gpio27_freq.set( self.controller.all_common_variables.channel_three[ i][1]) elif self.controller.all_common_variables.channel_three[i][ 0] == 13: self.gpio13.set(self.available_channels[3]) if \ self.controller.all_common_variables.channel_three[i][ 1] > 1250: self.gpio13_freq_high_speed.set( self.controller.all_common_variables.channel_three[ i][1]) else: self.gpio13_freq.set( self.controller.all_common_variables.channel_three[ i][1]) # check which GPIO(s) were defined to be channel four before for i in range( len(self.controller.all_common_variables.channel_four)): if self.controller.all_common_variables.channel_four[i][ 0] == 18: self.gpio18.set(self.available_channels[4]) if self.controller.all_common_variables.channel_four[i][ 1] > 1250: self.gpio18_freq_high_speed.set( self.controller.all_common_variables.channel_four[ i][1]) else: self.gpio18_freq.set( self.controller.all_common_variables.channel_four[ i][1]) elif self.controller.all_common_variables.channel_four[i][ 0] == 17: self.gpio17.set(self.available_channels[4]) self.gpio17_freq.set( self.controller.all_common_variables.channel_four[ i][1]) elif self.controller.all_common_variables.channel_four[i][ 0] == 27: self.gpio27.set(self.available_channels[4]) self.gpio27_freq.set( self.controller.all_common_variables.channel_four[ i][1]) elif self.controller.all_common_variables.channel_four[i][ 0] == 13: self.gpio13.set(self.available_channels[4]) if self.controller.all_common_variables.channel_four[i][ 1] > 1250: self.gpio13_freq_high_speed.set( self.controller.all_common_variables.channel_four[ i][1]) else: self.gpio13_freq.set( self.controller.all_common_variables.channel_four[ i][1]) # check if gpio18 was defined as a high speed (hardware) GPIO if self.gpio18_freq_high_speed.get() > 1250: self.gpio18_high_speed_bool.set(1) else: self.gpio18_high_speed_bool.set(0) # check if gpio13 was defined as a high speed (hardware) GPIO if self.gpio13_freq_high_speed.get() > 1250: self.gpio13_high_speed_bool.set(1) else: self.gpio13_high_speed_bool.set(0) ########################## # Creation of the window # ########################## # display the voltin image just below the text on the far left sketch_displayed_voltin = tk.Label(self.child, image=self.sketch_vol_in) sketch_displayed_voltin.image = self.sketch_vol_in sketch_displayed_voltin.grid(row=1, column=0) # display a label indicating what the checkbuttons do to the # right of that high_speed_label = tk.Label(self.child, text='High\nSpeed\nPWM?') high_speed_label.grid(row=1, column=1) # To the right of that it's indicated that the column below # can be used to indicate output channels channel_label = tk.Label(self.child, text='Select output\nchannel') channel_label.grid(row=1, column=2) # to the right of that it is indicated that the user can # define a PWM frequency freq_label = tk.Label(self.child, text='Define PWM\nFrequency') freq_label.grid(row=1, column=3) # and the GPIO18 image goes below the Voltin image sketch_displayed_gpio18 = tk.Label(self.child, image=self.sketch_gpio18) sketch_displayed_gpio18.image = self.sketch_gpio18 sketch_displayed_gpio18.grid(row=2, column=0) # Checkbutton that lets user decide if gpio18 should be used # as hardware PWM or not gpio18_high_speed_option = tk.Checkbutton(self.child, text='', variable=self.gpio18_high_speed_bool, command=self.gpio18_high_speed) gpio18_high_speed_option.grid(row=2, column=1) # Option menu that lets user decide which channel GPIO18 # should be assigned to gpio18_menu = tk.OptionMenu(self.child, self.gpio18, *self.available_channels) gpio18_menu.grid(row=2, column=2) # if hardware PWM was selected in the past, instead of a # option menu give the option to enter any number # for the frequency if self.gpio18_high_speed_bool.get(): self.gpio18_freq_entry = tk.Entry(self.child, width=10) self.gpio18_freq_entry.grid(row=2, column=3) self.gpio18_freq_entry.insert(tk.END, self.gpio18_freq_high_speed.get()) self.gpio18_freq_menu = None else: # if not hardware PWM treat as the other non-hardware # capable PWMs - one option menu to decide on frequency self.gpio18_freq_menu = tk.OptionMenu(self.child, self.gpio18_freq, *self.available_frequencies) self.gpio18_freq_menu.grid(row=2, column=3) self.gpio18_freq.set(self.available_frequencies[0]) self.gpio18_freq_entry = None self.gpio18_freq_label = None # just a label to indicate that the frequency comes in Hz gpio18_freq_label = tk.Label(self.child, text='Hz') gpio18_freq_label.grid(row=2, column=4) # on the far left gpio17 is indicated using an image sketch_displayed_gpio17 = tk.Label(self.child, image=self.sketch_gpio17) sketch_displayed_gpio17.image = self.sketch_gpio17 sketch_displayed_gpio17.grid(row=3, column=0) # Option menu that lets user decide which channel GPIO17 # should be assigned to gpio17_menu = tk.OptionMenu(self.child, self.gpio17, *self.available_channels) gpio17_menu.grid(row=3, column=2) # as GPIO17 is not hardware PWM capable just present the # simple frequency option menu gpio17_freq_menu = tk.OptionMenu(self.child, self.gpio17_freq, *self.available_frequencies) gpio17_freq_menu.grid(row=3, column=3) # just a label to indicate that the frequency comes in Hz gpio17_freq_label = tk.Label(self.child, text='Hz') gpio17_freq_label.grid(row=3, column=4) # on the far left gpio27 is indicated using an image sketch_displayed_gpio27 = tk.Label(self.child, image=self.sketch_gpio27) sketch_displayed_gpio27.image = self.sketch_gpio27 sketch_displayed_gpio27.grid(row=4, column=0) # Option menu that lets user decide which channel GPIO27 # should be assigned to gpio27_menu = tk.OptionMenu(self.child, self.gpio27, *self.available_channels) gpio27_menu.grid(row=4, column=2) # as GPIO27 is not hardware PWM capable just present the # simple frequency option menu gpio27_freq_menu = tk.OptionMenu(self.child, self.gpio27_freq, *self.available_frequencies) gpio27_freq_menu.grid(row=4, column=3) # just a label to indicate that the frequency comes in Hz gpio27_freq_label = tk.Label(self.child, text='Hz') gpio27_freq_label.grid(row=4, column=4) # on the far left gpio13 is indicated using an image sketch_displayed_gpio13 = tk.Label(self.child, image=self.sketch_gpio13) sketch_displayed_gpio13.image = self.sketch_gpio13 sketch_displayed_gpio13.grid(row=5, column=0) # Checkbutton that lets user decide if gpio13 should be used # as hardware PWM or not gpio13_high_speed_option = tk.Checkbutton(self.child, text='', variable=self.gpio13_high_speed_bool, command=self.gpio13_high_speed) gpio13_high_speed_option.grid(row=5, column=1) # Option menu that lets user decide which channel GPIO13 # should be assigned to gpio13_menu = tk.OptionMenu(self.child, self.gpio13, *self.available_channels) gpio13_menu.grid(row=5, column=2) # if hardware PWM was selected in the past, instead of a # option menu give the option to enter any number # for the frequency if self.gpio13_high_speed_bool.get(): self.gpio13_freq_entry = tk.Entry(self.child, width=10) self.gpio13_freq_entry.grid(row=5, column=3) self.gpio13_freq_entry.insert(tk.END, self.gpio13_freq_high_speed.get()) self.gpio13_freq_label = tk.Label(self.child, text='Hz') self.gpio13_freq_label.grid(row=5, column=4) self.gpio13_freq_menu = None else: # if not hardware PWM treat as the other non-hardware # capable PWMs - one option menu to decide on frequency self.gpio13_freq_menu = tk.OptionMenu(self.child, self.gpio13_freq, *self.available_frequencies) self.gpio13_freq_menu.grid(row=5, column=3) self.gpio13_freq_entry = None self.gpio13_freq_label = None # just a label to indicate that the frequency comes in Hz gpio13_freq_label = tk.Label(self.child, text='Hz') gpio13_freq_label.grid(row=5, column=4) # Let the user confirm explicitly if the new settings should # be accepted confirm_button = tk.Button(self.child, text='Confirm and exit', command=self.confirm) confirm_button.grid(row=6, column=0) # and also be explicit if it should be canceled cancel_button = tk.Button(self.child, text='Cancel', command=self.cancel) cancel_button.grid(row=6, column=3, columnspan=2)
[docs] def cancel(self): ''' Function is called when user presses the 'cancel' button. Destroys the window without saving anything. ''' # set main window active again self.child.grab_release() # close the child window self.child.after(0, self.child.destroy())
[docs] def confirm(self): ''' Function is called when user presses the 'confirm' button. Collects the channels and frequencies and associates it with the proper variable. Specifically it creates one list per channel. Each GPIO in that channel is a nested list. For example, if the user assigns GPIO27 and GPI17 to Channel 1 (with frequency 1250), the channel_one variable will be a nested list in the following form: [[27, 1250][17,1250]] Variables are modified in the instance of the original GUI ''' # create empty lists that can then be used to feed into the # GUI loop background = [] background_two = [] channel_one = [] channel_two = [] channel_three = [] channel_four = [] #print(self.gpio18_high_speed_bool.get()) #print(self.gpio18_freq_entry.get()) # need to collect all the background gpios, the channel one # gpios etc..same block four times over (for each of the four # GPIOs) - in principle it just compares the selection of the # gpioXX to available channels. If it finds a match it will # put it into the prepared list if self.gpio18.get() == self.available_channels[0]: if self.gpio18_high_speed_bool.get(): background.append( [18, int(self.gpio18_freq_entry.get())]) else: background.append([18, self.gpio18_freq.get()]) elif self.gpio18.get() == self.available_channels[5]: if self.gpio18_high_speed_bool.get(): background_two.append( [18, int(self.gpio18_freq_entry.get())]) else: background_two.append([18, self.gpio18_freq.get()]) elif self.gpio18.get() == self.available_channels[1]: if self.gpio18_high_speed_bool.get(): channel_one.append( [18, int(self.gpio18_freq_entry.get())]) else: channel_one.append([18, self.gpio18_freq.get()]) elif self.gpio18.get() == self.available_channels[2]: if self.gpio18_high_speed_bool.get(): channel_two.append( [18, int(self.gpio18_freq_entry.get())]) else: channel_two.append([18, self.gpio18_freq.get()]) elif self.gpio18.get() == self.available_channels[3]: if self.gpio18_high_speed_bool.get(): channel_three.append( [18, int(self.gpio18_freq_entry.get())]) else: channel_three.append([18, self.gpio18_freq.get()]) elif self.gpio18.get() == self.available_channels[4]: if self.gpio18_high_speed_bool.get(): channel_four.append( [18, int(self.gpio18_freq_entry.get())]) else: channel_four.append([18, self.gpio18_freq.get()]) if self.gpio17.get() == self.available_channels[0]: background.append([17, self.gpio17_freq.get()]) elif self.gpio17.get() == self.available_channels[5]: background_two.append([17, self.gpio17_freq.get()]) elif self.gpio17.get() == self.available_channels[1]: channel_one.append([17, self.gpio17_freq.get()]) elif self.gpio17.get() == self.available_channels[2]: channel_two.append([17, self.gpio17_freq.get()]) elif self.gpio17.get() == self.available_channels[3]: channel_three.append([17, self.gpio17_freq.get()]) elif self.gpio17.get() == self.available_channels[4]: channel_four.append([17, self.gpio17_freq.get()]) if self.gpio27.get() == self.available_channels[0]: background.append([27, self.gpio27_freq.get()]) elif self.gpio27.get() == self.available_channels[5]: background_two.append([27, self.gpio27_freq.get()]) elif self.gpio27.get() == self.available_channels[1]: channel_one.append([27, self.gpio27_freq.get()]) elif self.gpio27.get() == self.available_channels[2]: channel_two.append([27, self.gpio27_freq.get()]) elif self.gpio27.get() == self.available_channels[3]: channel_three.append([27, self.gpio27_freq.get()]) elif self.gpio27.get() == self.available_channels[4]: channel_four.append([27, self.gpio27_freq.get()]) if self.gpio13.get() == self.available_channels[0]: if self.gpio13_high_speed_bool.get(): background.append( [13, int(self.gpio13_freq_entry.get())]) else: background.append([13, self.gpio13_freq.get()]) elif self.gpio13.get() == self.available_channels[5]: if self.gpio13_high_speed_bool.get(): background_two.append( [13, int(self.gpio13_freq_entry.get())]) else: background_two.append([13, self.gpio13_freq.get()]) elif self.gpio13.get() == self.available_channels[1]: if self.gpio13_high_speed_bool.get(): channel_one.append( [13, int(self.gpio13_freq_entry.get())]) else: channel_one.append([13, self.gpio13_freq.get()]) elif self.gpio13.get() == self.available_channels[2]: if self.gpio13_high_speed_bool.get(): channel_two.append( [13, int(self.gpio13_freq_entry.get())]) else: channel_two.append([13, self.gpio13_freq.get()]) elif self.gpio13.get() == self.available_channels[3]: if self.gpio13_high_speed_bool.get(): channel_three.append( [13, int(self.gpio13_freq_entry.get())]) else: channel_three.append([13, self.gpio13_freq.get()]) elif self.gpio13.get() == self.available_channels[4]: if self.gpio13_high_speed_bool.get(): channel_four.append( [13, int(self.gpio13_freq_entry.get())]) else: channel_four.append([13, self.gpio13_freq.get()]) # assign the new values to the main GUI loop variables self.controller.all_common_variables.background = background self.controller.all_common_variables.background_two = background_two self.controller.all_common_variables.channel_one = channel_one self.controller.all_common_variables.channel_two = channel_two self.controller.all_common_variables.channel_three = channel_three self.controller.all_common_variables.channel_four = channel_four # set main window active again self.child.grab_release() # close the child window self.child.after(0, self.child.destroy()) # let the user know that the program needs to be restarted tk.messagebox.showinfo('Notification', 'For the changes to take effect\n' 'please save and exit and restart\n' 'the program')
[docs] def gpio18_high_speed(self): ''' Function is called when user uses checkbutton High Speed for GPIO18. This updates the window for the user to either manually enter a frequency (if High Speed PWM is On) or use the list of available frequencies (not High Speed PWM) ''' # check if gpio18 bool is positive if self.gpio18_high_speed_bool.get(): try: # try except as it will fail the first time. Need to # remove the option menu, otherwise ugly self.gpio18_freq_menu.grid_remove() except AttributeError: pass # then add the entry self.gpio18_freq_entry = tk.Entry(self.child, width=10) self.gpio18_freq_entry.grid(row=2, column=3) self.gpio18_freq_entry.insert(tk.END, self.gpio18_freq.get()) else: # or the inverse of the above try: self.gpio18_freq_entry.remove() self.gpio18_freq_label.remove() except AttributeError: pass self.gpio18_freq_menu = tk.OptionMenu(self.child, self.gpio18_freq, *self.available_frequencies) self.gpio18_freq_menu.grid(row=2, column=3) self.gpio18_freq.set(self.available_frequencies[0])
[docs] def gpio13_high_speed(self): ''' Function is called when user uses checkbutton High Speed for GPIO13. This updates the window for the user to either manually enter a frequency (if High Speed PWM is On) or use the list of available frequencies (not High Speed PWM). In principle identical to the gpio18_high_speed function ''' if self.gpio13_high_speed_bool.get(): try: self.gpio13_freq_menu.grid_remove() except AttributeError: pass self.gpio13_freq_entry = tk.Entry(self.child, width=10) self.gpio13_freq_entry.grid(row=5, column=3) self.gpio13_freq_entry.insert(tk.END, self.gpio13_freq.get()) else: try: self.gpio13_freq_entry.remove() self.gpio13_freq_label.remove() except AttributeError: pass self.gpio13_freq_menu = tk.OptionMenu(self.child, self.gpio13_freq, *self.available_frequencies) self.gpio13_freq_menu.grid(row=5, column=3) self.gpio13_freq.set(self.available_frequencies[0])