__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])