Пример #1
0
    def __init__(self, bManualStartupForTests=False):
        self.logger = logging.getLogger()
        self.logger.addHandler(
            logging.handlers.SysLogHandler(address=(SYSLOG_IP, SYSLOG_PORT)))
        self.logger_name = ''  # To be replaced with FPGA's shorthand

        # Create the object that handles the communication with the FPGA board:
        self.sl = SuperLaserLand_JD_RP(self)
        self.updateDeviceData()

        self.sp = SLLSystemParameters()

        self.reconnection_attempts = 0
        self.timerReconnect = None

        # Start Qt:
        self.app = QtCore.QCoreApplication.instance()
        if self.app is None:
            print("QCoreApplication not running yet. creating.")
            self.bEventLoopWasRunningAlready = False
            self.app = QtWidgets.QApplication(sys.argv)
        else:
            self.bEventLoopWasRunningAlready = True
            print("QCoreApplication already running.")

        self.initUI()

        if bManualStartupForTests == False:
            self.runEventLoop()
Пример #2
0
    def __init__(self):
        # Create the object that handles the communication with the FPGA board:
        self.sl = SuperLaserLand_JD_RP(controller=self)
        self.updateDeviceData()

        self.sp = SLLSystemParameters(self.sl)

        # Start Qt:
        self.app = QtCore.QCoreApplication.instance()
        if self.app is None:
            self.app = QtWidgets.QApplication(sys.argv)

        self.main()
Пример #3
0
    @logCommsErrorsAndBreakoutOfFunction()
    def mux_pll2_Action(self, checked=False):
        if self.qradio_ddc1_to_pll2.isChecked():
            data = 1
        elif self.qradio_pll1_to_pll2.isChecked():
            data = 2
        else:  #self.qradio_ddc2_to_pll2.isChecked()
            data = 0
        self.sl.set_mux_pll2(data)

    @logCommsErrorsAndBreakoutOfFunction()
    def setSATA(self, value):
        index = self.qcombo_SATA.currentIndex()
        self.sl.set_SATA(index)


if __name__ == '__main__':

    #app = QApplication(sys.argv)
    app = QtCore.QCoreApplication.instance()
    if app is None:
        app = QtWidgets.QApplication(sys.argv)

    sl = SuperLaserLand_JD_RP()
    w = ConfigRPSettingsUI(sl)
    w.show()
    w.resize(800, 300)

    app.exec_()
Пример #4
0
class controller(object):
    """Main class of the GUI. It contains most of the elements of the GUI, the main_window and the communication class"""
    def __init__(self):
        # Create the object that handles the communication with the FPGA board:
        self.sl = SuperLaserLand_JD_RP(controller=self)
        self.updateDeviceData()

        self.sp = SLLSystemParameters(self.sl)

        # Start Qt:
        self.app = QtCore.QCoreApplication.instance()
        if self.app is None:
            self.app = QtWidgets.QApplication(sys.argv)

        self.main()

    def updateDeviceData(self):
        # Hardcoded dictionnary containing the known Red Pitaya
        # TO DO : xml file, user can add RP from the GUI?
        self.devices_data = {}
        devices_xml = devicesData("devices_data.xml")
        self.devices_data = devices_xml.updateDictionnary(self.devices_data)

        # Specify the mapping between the MAC addresses (which are used as a form of serial numbers) and the box data
        # self.devices_data = {}
        # self.devices_data['002632f016dc'] = {'color': '#E37405',
        #                     'name': 'Red Pitaya 0',
        #                     'shorthand': 'RP 0',
        #                     'config file': 'system_parameters_RP_1.xml',
        #                     #'port': 60002
        #                     }

        # self.devices_data['002632f03cc2'] = {'color': '#811CC9',
        #                     'name': 'RP Comb 1',
        #                     'shorthand': 'RPC 1',
        #                     'config file': 'system_parameters_RP_C1.xml',
        #                     #'port': 60002
        #                     }

        # self.devices_data['002632f03d5b'] = {'color': '#1CC981',
        #                     'name': 'RP Comb 2',
        #                     'shorthand': 'RPC 2',
        #                     'config file': 'system_parameters_RP_C2.xml',
        #                     #'port': 60002
        #                     }

    #    serial_to_color_mapping = {}
    #    serial_to_color_mapping['000000054R'] = '#1CC981'
    #    serial_to_color_mapping['000000054S'] = '#811CC9'
    #    # serial_to_color_mapping['124300046U'] = 'blue'
    #    serial_to_color_mapping['12320003SX'] = 'orange'
    #    serial_to_color_mapping['000000054E'] = '#E37405'   # orange high-bandwidth (dark orange)
    #    serial_to_color_mapping['000000054J'] = '#70E7FF'  # blue high-bandwidth (light blue)
    #    serial_to_color_mapping['124300046R'] = '#B572E8'  # purple high-bandwidth (purple)
    #    serial_to_color_mapping['124300046V'] = '#FF0000'
    #    serial_to_color_mapping['124300046S'] = '#0033CC'

    def connectionGUI(self):
        strBroadcastAddress = '192.168.0.255'
        strFPGAFirmware = r'red_pitaya_top.bit'
        strCPUFirmware = u'monitor-tcp'
        self.initial_config = initialConfiguration(self.sl.dev, self,
                                                   self.devices_data,
                                                   strBroadcastAddress,
                                                   strFPGAFirmware,
                                                   strCPUFirmware)

    #    def __init__(self, dev, devices_data={}, strBroadcastAddress="192.168.2.255", strFPGAFirmware='', strCPUFirmware=''):

    # this will remove minimized status
    # and restore window with keeping maximized/normal state
    # allowSetForegroundWindow.allowSetForegroundWindow()
    # self.initial_config.setWindowState(self.initial_config.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive)
    #    # this will activate the window
    ##    self.initial_config.activateWindow()
    ##    self.initial_config.show()
    #  #  self.initial_config.raise_()
    #  #  self.initial_config.show()
    #
    #    SetWindowPos(self.initial_config.winId(),
    #                    win32con.HWND_TOPMOST, # = always on top. only reliable way to bring it to the front on windows
    #                    0, 0, 0, 0,
    #                    win32con.SWP_NOMOVE | win32con.SWP_NOSIZE | win32con.SWP_SHOWWINDOW)
    #    SetWindowPos(self.initial_config.winId(),
    #                    win32con.HWND_NOTOPMOST, # disable the always on top, but leave window at its top position
    #                    0, 0, 0, 0,
    #                    win32con.SWP_NOMOVE | win32con.SWP_NOSIZE | win32con.SWP_SHOWWINDOW)
    #    self.initial_config.raise_()
    #    self.initial_config.show()
    #    self.initial_config.activateWindow()

    #self.initial_config.setWindowState(self.initial_config.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive)
    # Run the event loop for this window
    #self.app.exec_()
    #self.main()

    def main(self):

        ############################################## - OLD CODE - ##############################################
        # this opens the connection to the fpga (hard-coded IP address for now)
        #    strList = self.sl.getDeviceList()
        ###########################################################################
        # Update the FPGA bitfile and the Zynq monitor-tcp C program

        # send new bitfile version
        # try:
        #        self.sl.dev.write_file_on_remote(strFilenameLocal=r'D:\Projects\RedPitaya\fpga\project\redpitaya.runs\impl_1\red_pitaya_top.bit', strFilenameRemote='/opt/red_pitaya_top.bit')
        #        self.sl.dev.write_file_on_remote(strFilenameLocal=r'D:\Projets_Xilinx\RedPitaya\fpga\project\redpitaya.runs\impl_1\red_pitaya_top.bit', strFilenameRemote='/opt/red_pitaya_top.bit')
        #     pass
        # except:
        #     print("warning, could not update fpga bitfile")
        #     pass
        # program FPGA with new bitfile:
        #    self.sl.dev.send_shell_command('cat /opt/red_pitaya_top.bit > /dev/xdevcfg')

        #    time.sleep(3)
        #
        #    # send new monitor-tcp version
        #    self.sl.dev.write_file_on_remote(strFilenameLocal=u'D:\\Université\\Dropbox\\22_H2015\\Red Pitaya\\monitor-tcp\\monitor-tcp', strFilenameRemote='/opt/monitor-tcp-new')
        #
        #    # set executable permissions
        #    self.sl.dev.send_shell_command('chmod +x /opt/monitor-tcp-new')
        #    # copy over old file
        #    self.sl.dev.send_shell_command('mv /opt/monitor-tcp-new /opt/monitor-tcp')
        #
        #    # send reboot command
        #    self.sl.dev.send_reboot_command()
        #    self.sl.dev.sock.shutdown(socket.SHUT_RDWR)
        #    self.sl.dev.sock.close()
        #
        #    time.sleep(1) # give some time for tcp server to come back up
        ##    return
        #    self.sl.getDeviceList() # reconnect
        #
        #    #self.sl.dev.OpenTCPConnection(self.sl.dev.HOST, self.sl.dev.PORT) # hack to get things working quickly
        ##    self.sl.dev.sock.connect((self.sl.dev.HOST, self.sl.dev.PORT))
        #
        ##    return  # for quick debug tests

        ############################################## - OLD CODE - ##############################################
        # Start the User Interface

        bTriggerEvents = False
        bConnectedRP = False
        self.strSelectedSerial = "000000000000"

        # if self.initial_config.bOk == False:
        #     # User clicked cancel. simply close the program:
        #     return

        # if self.initial_config.qradio_pushValue.isChecked():
        #     print("Push")
        #     bTriggerEvents = True
        #     bConnectedRP = True
        #     self.loadDefaultValueFromConfigFile(self.initial_config.strSelectedSerial)
        # elif self.initial_config.qradio_existingRP.isChecked():
        #     print("Reconnection")
        #     bTriggerEvents = False
        #     bConnectedRP = True
        # elif self.initial_config.qradio_noRP.isChecked():
        #     print("No RP")
        #     bTriggerEvents = False
        #     bConnectedRP = False

        bUpdateFPGA = bTriggerEvents
        bSendToFPGA = bTriggerEvents

        ###########################################################################
        # Create the object which handles the configuration parameters (DAC offsets, DAC gains, beat frequency modulation range, etc):
        #sp = SLLSystemParameters()

        #    config_window = SLLConfigurationWindow()
        #    config_window.loadParameters(sp)
        #    config_window.hide()

        ###########################################################################
        # Load all our windows:

        # Style sheet which includes the color scheme for each specific box:
        try:
            # custom_style_sheet = ('#MainWindow {color: white; background-color: %s;}' % self.devices_data[self.initial_config.strSelectedSerial]['color'])
            custom_style_sheet = (
                '#MainWindow {color: white; background-color: %s;}' %
                self.devices_data[self.strSelectedSerial]['color'])
        except KeyError:
            custom_style_sheet = ''

        # The shorthand name which gets added to the window names:
        try:
            # custom_shorthand = self.devices_data[self.initial_config.strSelectedSerial]['shorthand']
            custom_shorthand = self.devices_data[
                self.strSelectedSerial]['shorthand']
        except KeyError:
            custom_shorthand = ''

        # Have to be careful with the modulus setting (double-check with a scope to make sure the output frequency is right)
        # I think the output frequency for the square wave mode is given by:
        # 200 MHz/(2*(modulus+1))
        # While for the pulsed mode (bPulses = 1), the frequency is:
        # 200 MHz/(modulus+1)
        self.divider_settings_window = DisplayDividerAndResidualsStreamingSettingsWindow(
            self.sl,
            self.sp,
            clk_divider_modulus=67e3,
            bDividerOn=0,
            bPulses=0,
            custom_style_sheet=custom_style_sheet,
            custom_shorthand=custom_shorthand)

        # Optical lock window
        # self.xem_gui_mainwindow2 = XEM_GUI_MainWindow(self.sl, custom_shorthand + ': Optical lock', 1, (False, True, False), sp, custom_style_sheet, self.initial_config.strSelectedSerial, bUpdateFPGA = bSendToFPGA, bConnectedRP = bConnectedRP)
        self.xem_gui_mainwindow2 = XEM_GUI_MainWindow(
            self.sl, custom_shorthand + ': Optical lock', 1,
            (False, True, False), self.sp, custom_style_sheet,
            self.strSelectedSerial)

        # CEO Lock window
        # self.xem_gui_mainwindow = XEM_GUI_MainWindow(self.sl, custom_shorthand + ': CEO lock', 0, (True, False, False), sp, custom_style_sheet, self.initial_config.strSelectedSerial, bUpdateFPGA = bSendToFPGA, bConnectedRP = bConnectedRP)
        self.xem_gui_mainwindow = XEM_GUI_MainWindow(
            self.sl, custom_shorthand + ': CEO lock', 0, (True, False, False),
            self.sp, custom_style_sheet, self.strSelectedSerial)

        #    ###########################################################################
        #    # For testing the Red Pitaya with the built-in DDS:
        #
        #    addr_vco = 2
        #    addr_vco_amplitude = 0x0000
        #    addr_vco_freq_msb  = 0x0004
        #    addr_vco_freq_lsb  = 0x0008
        #
        #    vco_amplitude = round(0.01*(2**15-1))
        ##   vco_freq_word = np.array([round((15e6/100e6+1./600.)*2.**48)]).astype(np.int64)
        ##   # break vco word into msbs and lsbs:
        ##   vco_freq_word_msbs = vco_freq_word >> 32
        ##   vco_freq_word_lsbs = np.bitwise_and(vco_freq_word, (1<<32)-1)
        #
        #   # write amplitude
        #    address_uint32 = (addr_vco << 20) + addr_vco_amplitude
        #    data_uint32 = vco_amplitude
        #    self.sl.dev.write_Zynq_register_uint32(address_uint32, data_uint32)

        #########################################################
        # The two frequency counter:
        strOfTime = time.strftime("%m_%d_%Y_%H_%M_%S_")

        try:
            # temp_control_port = self.devices_data[self.initial_config.strSelectedSerial]['port']
            temp_control_port = self.devices_data[
                self.strSelectedSerial]['port']
        except:
            temp_control_port = 0

        strNameTemplate = 'data_logging\%s' % strOfTime
        # strNameTemplate = '%s_%s_' % (strNameTemplate, self.initial_config.strSelectedSerial)
        #        strNameTemplate = '%s_%s_' % (strNameTemplate, self.strSelectedSerial)
        self.strNameTemplate = strNameTemplate
        self.freq_error_window1 = FreqErrorWindowWithTempControlV2(
            self.sl, 'CEO beat in-loop counter', self.sp, 0, strNameTemplate,
            custom_style_sheet, 0, self.xem_gui_mainwindow)
        self.freq_error_window2 = FreqErrorWindowWithTempControlV2(
            self.sl, 'Optical beat in-loop counter', self.sp, 1,
            strNameTemplate, custom_style_sheet, temp_control_port,
            self.xem_gui_mainwindow2)

        self.counters_window = Qt.QWidget()
        self.counters_window.setObjectName('MainWindow')
        self.counters_window.setStyleSheet(custom_style_sheet)
        vbox = Qt.QVBoxLayout()
        vbox.addWidget(self.freq_error_window1)
        vbox.addWidget(self.freq_error_window2)
        self.counters_window.setLayout(vbox)
        self.counters_window.setWindowTitle(custom_shorthand +
                                            ': Frequency counters')
        #self.counters_window.setGeometry(993, 40, 800, 1010)
        #self.counters_window.setGeometry(0, 0, 750, 1000)
        #    self.counters_window.resize(600, 1080-100+30)
        #self.counters_window.move(QtGui.QDesktopWidget().availableGeometry().topLeft() + Qt.QPoint(985, 10))
        #self.counters_window.show()

        # Dither windows, this code could be moved to another class/file to help with clutter:
        self.dither_widget0 = DisplayDitherSettingsWindow(
            self.sl,
            self.sp,
            0,
            modulation_frequency_in_hz='1e3',
            output_amplitude='1e-3',
            integration_time_in_seconds='0.1',
            bEnableDither=True,
            custom_style_sheet=custom_style_sheet)
        self.dither_widget1 = DisplayDitherSettingsWindow(
            self.sl,
            self.sp,
            1,
            modulation_frequency_in_hz='5.1e3',
            output_amplitude='1e-3',
            integration_time_in_seconds='0.1',
            bEnableDither=True,
            custom_style_sheet=custom_style_sheet)
        #dither_widget2 = DisplayDitherSettingsWindow(self.sl, self.sp, 2, modulation_frequency_in_hz='110' , output_amplitude='1e-4', integration_time_in_seconds='0.1', bEnableDither=True, custom_style_sheet=custom_style_sheet)

        self.RP_Settings = ConfigRPSettingsUI(
            self.sl,
            self.sp,
            self,
            custom_style_sheet=custom_style_sheet,
            custom_shorthand=custom_shorthand)

        self.settings_window = Qt.QWidget()
        self.settings_window.setObjectName('MainWindow')
        self.settings_window.setStyleSheet(custom_style_sheet)
        vbox1 = Qt.QVBoxLayout()
        vbox1.addWidget(self.dither_widget0)
        vbox1.addWidget(self.dither_widget1)
        #vbox1.addWidget(dither_widget2)
        vbox1.addStretch(1)
        vbox2 = Qt.QVBoxLayout()
        vbox2.addWidget(self.RP_Settings)
        vbox2.addWidget(self.divider_settings_window)
        hbox = Qt.QHBoxLayout()
        hbox.addLayout(vbox1)
        hbox.addLayout(vbox2)
        hbox.addStretch(1)
        self.settings_window.setLayout(hbox)
        self.settings_window.setWindowTitle(custom_shorthand +
                                            ': Dither controls')
        #self.settings_window.show()

        #    ###########################################################################
        #    # For testing out the transfer function window:
        #    frequency_axis = np.logspace(np.log10(10e3), np.log10(2e6), 10e3)
        #    transfer_function = 1/(1 + 1j*frequency_axis/100e3)
        #    window_number = 1
        #    vertical_units = 'V/V'
        #    tf_window1 = DisplayTransferFunctionWindow(frequency_axis, transfer_function, window_number, vertical_units)
        #

        #    # Regroup the two windows into a single one:
        self.main_windows = Qt.QWidget()
        self.main_windows.setObjectName('MainWindow')
        self.main_windows.setStyleSheet(custom_style_sheet)

        tabs = QtGui.QTabWidget()
        # self.xem_gui_mainwindow2.resize(600, 700)

        # self.xem_gui_mainwindow.setContentsMargins(0, 0, 0, 0)
        # self.xem_gui_mainwindow.layout().setContentsMargins(0, 0, 0, 0)
        # self.xem_gui_mainwindow2.setContentsMargins(0, 0, 0, 0)
        # self.xem_gui_mainwindow2.layout().setContentsMargins(0, 0, 0, 0)
        # self.counters_window.setContentsMargins(0, 0, 0, 0)
        # self.counters_window.layout().setContentsMargins(0, 0, 0, 0)
        # dither_window.setContentsMargins(0, 0, 0, 0)
        # dither_window.layout().setContentsMargins(0, 0, 0, 0)
        # dfr_timing_gui.setContentsMargins(0, 0, 0, 0)
        # dfr_timing_gui.layout().setContentsMargins(0, 0, 0, 0)
        # self.divider_settings_window.setContentsMargins(0, 0, 0, 0)
        # self.divider_settings_window.layout().setContentsMargins(0, 0, 0, 0)

        #tabs.setMaximumSize(1920,1080-100+30)

        # self.main_windows.setMaximumSize(600,600)
        # self.xem_gui_mainwindow.setMaximumSize(600,600)
        # self.xem_gui_mainwindow2.setMaximumSize(600,600)
        # self.counters_window.setMaximumSize(600,600)

        # dither_window.setMaximumSize(600,600)
        # dfr_timing_gui.setMaximumSize(600,600)
        # self.divider_settings_window.setMaximumSize(600,600)
        tabs.addTab(self.xem_gui_mainwindow, "Fast EOM Lock")
        tabs.addTab(self.xem_gui_mainwindow2, "Slow Lock")
        tabs.addTab(self.counters_window, "Counters")
        tabs.addTab(self.settings_window, "Settings")
        #FEATURE
        #tabs.addTab(dfr_timing_gui, "DFr trigger generator")
        #tabs.addTab(self.divider_settings_window, "Filter settings")
        # tabs.setGeometry(0, 0, 750, 1000)

        box = QtGui.QHBoxLayout()
        box.addWidget(tabs)
        self.main_windows.setLayout(box)
        self.main_windows.setWindowTitle(custom_shorthand)
        #self.main_windows.move(QtGui.QDesktopWidget().availableGeometry().topLeft() + Qt.QPoint(945-300, 0))
        self.main_windows.move(
            QtGui.QDesktopWidget().availableGeometry().topLeft() +
            Qt.QPoint(800 - 300, 0))

        self.main_windows.show()

        self.connectionGUI()

        # Enter main event loop
        #self.app.exec_()
        try:
            self.app.exec_()
        except:
            print("XEM_GUI3.py: Exception during app.exec_()")

    def loadDefaultValueFromConfigFile(self, strSelectedSerial):
        try:
            # custom_config_file = self.devices_data[self.initial_config.strSelectedSerial]['config file']
            custom_config_file = self.devices_data[strSelectedSerial][
                'config file']
            self.sp.loadFromFile(custom_config_file)
            print('Loaded configuration from %s' % custom_config_file)
        except (KeyError, IOError):
            strFileDefaultConfig = 'system_parameters_RP_Default.xml'
            # print('Warning: Could not parse config file for FPGA serial: %s, loading values from file %s' % (self.initial_config.strSelectedSerial, strFileDefaultConfig))
            # print('Warning: Could not parse config file for FPGA serial: %s, loading values from file %s' % (self.initial_config.strSelectedSerial, strFileDefaultConfig))
            print(
                'Warning: Could not parse config file for FPGA serial: %s, loading values from file %s'
                % (strSelectedSerial, strFileDefaultConfig))
            custom_config_file = ''
            try:
                self.sp.loadFromFile(strFileDefaultConfig)
                print('Loaded configuration from %s' % strFileDefaultConfig)
            except (KeyError, IOError):

                # print('Warning: Could not parse config file "%s" for FPGA serial: %s, falling back on script-defined defaults' % (strFileDefaultConfig, self.initial_config.strSelectedSerial))
                print(
                    'Warning: Could not parse config file "%s" for FPGA serial: %s, falling back on script-defined defaults'
                    % (strFileDefaultConfig, strSelectedSerial))
                self.sp.loadDefaults()

        # self.sp.loadDefaults()
        # self.sp.saveToFile('system_parameters_current.xml')

        self.sp.sendToFPGA(True)

    def setCustomStyleSheet(self, strSelectedSerial):
        # Style sheet which includes the color scheme for each specific box:
        try:
            # custom_style_sheet = ('#MainWindow {color: white; background-color: %s;}' % self.devices_data[self.initial_config.strSelectedSerial]['color'])
            custom_style_sheet = (
                '#MainWindow {color: white; background-color: %s;}' %
                self.devices_data[strSelectedSerial]['color'])
        except KeyError:
            custom_style_sheet = ''

        self.divider_settings_window.setStyleSheet(custom_style_sheet)
        self.freq_error_window1.setStyleSheet(custom_style_sheet)
        self.freq_error_window2.setStyleSheet(custom_style_sheet)
        self.xem_gui_mainwindow2.setStyleSheet(custom_style_sheet)
        self.xem_gui_mainwindow.setStyleSheet(custom_style_sheet)
        self.counters_window.setStyleSheet(custom_style_sheet)
        self.dither_widget0.setStyleSheet(custom_style_sheet)
        self.dither_widget1.setStyleSheet(custom_style_sheet)
        self.RP_Settings.setStyleSheet(custom_style_sheet)
        self.settings_window.setStyleSheet(custom_style_sheet)
        self.main_windows.setStyleSheet(custom_style_sheet)

    def setOutputFileNames(self, MACNameTemplate):
        #        print("MAC Address: %s" % MACNameTemplate)
        strNameTemplate = '%s_%s_' % (self.strNameTemplate, MACNameTemplate)
        self.freq_error_window1.setNameTemplate(strNameTemplate)
        self.freq_error_window2.setNameTemplate(strNameTemplate)

    def pushDefaultValues(self,
                          strSelectedSerial="000000000000",
                          ip_addr="192.168.0.150"):
        self.setCustomStyleSheet(strSelectedSerial)

        if self.sl.dev.valid_socket:
            self.sl.dev.CloseTCPConnection()

        self.sl.dev.OpenTCPConnection(ip_addr)
        # Now we just need to reset the frontend to make sure we start everything in a nice state
        self.sl.reset_front_end()
        self.loadDefaultValueFromConfigFile(strSelectedSerial)

        self.xem_gui_mainwindow2.pushDefaultValues()
        self.xem_gui_mainwindow.pushDefaultValues()
        self.freq_error_window1.pushDefaultValues()
        self.freq_error_window2.pushDefaultValues()
        self.RP_Settings.pushDefaultValues()
        self.divider_settings_window.pushDefaultValues()
        self.dither_widget0.pushDefaultValues()
        self.dither_widget1.pushDefaultValues()

    def pushActualValues(self, strSelectedSerial, ip_addr="192.168.0.150"):
        self.setCustomStyleSheet(strSelectedSerial)

        if self.sl.dev.valid_socket:
            self.sl.dev.CloseTCPConnection()
        self.sl.dev.OpenTCPConnection(ip_addr)

        self.xem_gui_mainwindow2.pushActualValues()
        self.xem_gui_mainwindow.pushActualValues()
        self.freq_error_window1.pushValues()
        self.freq_error_window2.pushValues()

    def getActualValues(self, strSelectedSerial, ip_addr="192.168.0.150"):
        self.setCustomStyleSheet(strSelectedSerial)
        if self.sl.dev.valid_socket:
            self.sl.dev.CloseTCPConnection()
        self.sl.dev.OpenTCPConnection(ip_addr)

        self.xem_gui_mainwindow2.getValues()
        self.xem_gui_mainwindow.getValues()
        self.freq_error_window1.getValues()
        self.freq_error_window2.getValues()
        self.RP_Settings.getValues()
        self.divider_settings_window.getValues()
        self.dither_widget0.getValues()
        self.dither_widget1.getValues()

    def retrieveValues(self):
        print('collect for .json button pushed')

        strFilename = self.xem_gui_mainwindow.qedit_export_json.text()
        print(strFilename)

        window1_outs = self.xem_gui_mainwindow.retrieveValues(
        )  # DAC offset, VCO gain, dac low limit, dac high limit, reference frequency, dac_limited, kp, fi, fii, fd, fdf, chkKp, chkKd, chkLock, chkKpCrossing
        window2_outs = self.xem_gui_mainwindow2.retrieveValues()
        freq_window1_outs = self.freq_error_window1.retrieveValues(
        )  # boolean for triangular averaging
        freq_window2_outs = self.freq_error_window2.retrieveValues()
        dither1_outs = self.dither_widget0.retrieveValues(
        )  # modulation_freq, amplitude, integration_time_in_seconds, mode
        dither2_outs = self.dither_widget1.retrieveValues()
        rp_settings_outs = self.RP_Settings.retrieveValues(
        )  # VCO_connection, fan_state, PLL1_connection, VCO_amplitude, VCO_offset
        divider_settings_outs = self.divider_settings_window.retrieveValues(
        )  # filter_select_0, filter_select_1, angle_select_0, angle_select_1

        #        print(window1_outs)
        settings_to_save = {}
        settings_to_save['window1_outs'] = window1_outs
        settings_to_save['window2_outs'] = window2_outs
        settings_to_save['freq_window1_outs'] = freq_window1_outs
        settings_to_save['freq_window2_outs'] = freq_window2_outs
        settings_to_save['dither1_outs'] = dither1_outs
        settings_to_save['dither2_outs'] = dither2_outs
        settings_to_save['rp_settings_outs'] = rp_settings_outs
        settings_to_save['divider_settings_outs'] = divider_settings_outs

        self.sp.Writejson(strFilename, settings_to_save)

    def setValues(self):
        strFilename = self.xem_gui_mainwindow.qedit_import_settings.text()
        print(strFilename)
        self.sl.reset_front_end()
        self.sp.loadFromFile(
            strFilename)  # Write values into system parameters

        # Load values to respective windows and programs:
        self.xem_gui_mainwindow2.pushDefaultValues()
        self.xem_gui_mainwindow.pushDefaultValues()
        self.freq_error_window1.pushDefaultValues()
        self.freq_error_window2.pushDefaultValues()
        self.RP_Settings.pushDefaultValues()
        self.divider_settings_window.pushDefaultValues()
        self.dither_widget0.pushDefaultValues()
        self.dither_widget1.pushDefaultValues()

    def stopCommunication(self):
        if self.sl.dev.valid_socket:
            self.sl.dev.CloseTCPConnection()
        try:
            self.xem_gui_mainwindow2.killTimers()
            self.xem_gui_mainwindow.killTimers()
            self.freq_error_window1.killTimers()
            self.freq_error_window2.killTimers()
        except:
            print("Error while killing the Timers")

    def startCommunication(self, ip_addr="192.168.0.150"):
        self.sl.dev.OpenTCPConnection(ip_addr)
        self.xem_gui_mainwindow2.startTimers()
        self.xem_gui_mainwindow.startTimers()
        self.freq_error_window1.startTimers()
        self.freq_error_window2.startTimers()
Пример #5
0
def main():

    # Create the object that handles the communication with the FPGA board:
    sl = SuperLaserLand_JD_RP()

    # Specify the mapping between the MAC addresses (which are used as a form of serial numbers) and the box data
    devices_data = {}
    devices_data['002632f016dc'] = {
        'color': '#1CC981',
        'name': 'Red Pitaya 0',
        'shorthand': 'RP 0',
        'config file': 'system_parameters_RP_1.xml',
        #'port': 60002
    }

    devices_data['002632f03cc2'] = {
        'color': '#1CC981',
        'name': 'RP Comb 1',
        'shorthand': 'RPC 1',
        'config file': 'system_parameters_RP_C1.xml',
        #'port': 60002
    }

    devices_data['002632f03d5b'] = {
        'color': '#1CC981',
        'name': 'RP Comb 2',
        'shorthand': 'RPC 2',
        'config file': 'system_parameters_RP_C3.xml',
        #'port': 60002
    }

    #    serial_to_color_mapping = {}
    #    serial_to_color_mapping['000000054R'] = '#1CC981'
    #    serial_to_color_mapping['000000054S'] = '#811CC9'
    #    # serial_to_color_mapping['124300046U'] = 'blue'
    #    serial_to_color_mapping['12320003SX'] = 'orange'
    #    serial_to_color_mapping['000000054E'] = '#E37405'   # orange high-bandwidth (dark orange)
    #    serial_to_color_mapping['000000054J'] = '#70E7FF'  # blue high-bandwidth (light blue)
    #    serial_to_color_mapping['124300046R'] = '#B572E8'  # purple high-bandwidth (purple)
    #    serial_to_color_mapping['124300046V'] = '#FF0000'
    #    serial_to_color_mapping['124300046S'] = '#0033CC'

    # this opens the connection to the fpga (hard-coded IP address for now)
    #    strList = sl.getDeviceList()

    ###########################################################################
    # Update the FPGA bitfile and the Zynq monitor-tcp C program

    # send new bitfile version
    try:
        #        sl.dev.write_file_on_remote(strFilenameLocal=r'D:\Projects\RedPitaya\fpga\project\redpitaya.runs\impl_1\red_pitaya_top.bit', strFilenameRemote='/opt/red_pitaya_top.bit')
        #        sl.dev.write_file_on_remote(strFilenameLocal=r'D:\Projets_Xilinx\RedPitaya\fpga\project\redpitaya.runs\impl_1\red_pitaya_top.bit', strFilenameRemote='/opt/red_pitaya_top.bit')
        pass
    except:
        print "warning, could not update fpga bitfile"
        pass
    # program FPGA with new bitfile:
#    sl.dev.send_shell_command('cat /opt/red_pitaya_top.bit > /dev/xdevcfg')

#    time.sleep(3)

#
#    # send new monitor-tcp version
#    sl.dev.write_file_on_remote(strFilenameLocal=u'D:\\Université\\Dropbox\\22_H2015\\Red Pitaya\\monitor-tcp\\monitor-tcp', strFilenameRemote='/opt/monitor-tcp-new')
#
#    # set executable permissions
#    sl.dev.send_shell_command('chmod +x /opt/monitor-tcp-new')
#    # copy over old file
#    sl.dev.send_shell_command('mv /opt/monitor-tcp-new /opt/monitor-tcp')
#
#    # send reboot command
#    sl.dev.send_reboot_command()
#    sl.dev.sock.shutdown(socket.SHUT_RDWR)
#    sl.dev.sock.close()
#
#    time.sleep(1) # give some time for tcp server to come back up
##    return
#    sl.getDeviceList() # reconnect
#
#    #sl.dev.OpenTCPConnection(sl.dev.HOST, sl.dev.PORT) # hack to get things working quickly
##    sl.dev.sock.connect((sl.dev.HOST, sl.dev.PORT))
#
##    return  # for quick debug tests

###########################################################################
# Start the User Interface
    allowSetForegroundWindow.allowSetForegroundWindow()

    # Start Qt:
    app = QtGui.QApplication(sys.argv)

    strBroadcastAddress = '192.168.0.255'
    strFPGAFirmware = r'red_pitaya_top.bit'
    strCPUFirmware = u'monitor-tcp'
    initial_config = initialConfiguration(sl.dev, devices_data,
                                          strBroadcastAddress, strFPGAFirmware,
                                          strCPUFirmware)

    #    def __init__(self, dev, devices_data={}, strBroadcastAddress="192.168.2.255", strFPGAFirmware='', strCPUFirmware=''):

    #    # this will remove minimized status
    #    # and restore window with keeping maximized/normal state
    #    allowSetForegroundWindow.allowSetForegroundWindow()
    ##    initial_config.setWindowState(initial_config.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive)
    #    # this will activate the window
    ##    initial_config.activateWindow()
    ##    initial_config.show()
    #  #  initial_config.raise_()
    #  #  initial_config.show()
    #
    #    SetWindowPos(initial_config.winId(),
    #                    win32con.HWND_TOPMOST, # = always on top. only reliable way to bring it to the front on windows
    #                    0, 0, 0, 0,
    #                    win32con.SWP_NOMOVE | win32con.SWP_NOSIZE | win32con.SWP_SHOWWINDOW)
    #    SetWindowPos(initial_config.winId(),
    #                    win32con.HWND_NOTOPMOST, # disable the always on top, but leave window at its top position
    #                    0, 0, 0, 0,
    #                    win32con.SWP_NOMOVE | win32con.SWP_NOSIZE | win32con.SWP_SHOWWINDOW)
    #    initial_config.raise_()
    #    initial_config.show()
    #    initial_config.activateWindow()

    #initial_config.setWindowState(initial_config.windowState() & ~QtCore.Qt.WindowMinimized | QtCore.Qt.WindowActive)
    # Run the event loop for this window
    app.exec_()

    if initial_config.bOk == False:
        # User clicked cancel. simply close the program:
        return

    # Start the init process (this sets the PLL gain/settings registers and the residuals streaming)
    sl.initSubModules(initial_config.bSendDefaultValues)

    ###########################################################################
    # Create the object which handles the configuration parameters (DAC offsets, DAC gains, beat frequency modulation range, etc):
    sp = SLLSystemParameters()
    #    # Send the values to the FPGA only if we have just re-programmed it. Otherwise we use whatever value is already in so we don't disturb the operation
    #    bTriggerEvents = False
    #    if initial_config.bSendFirmware:
    #
    #        bTriggerEvents = True
    bTriggerEvents = True

    # Lookup filename and load if file is there:
    try:
        custom_config_file = devices_data[
            initial_config.strSelectedSerial]['config file']
        sp.loadFromFile(custom_config_file)
        print('Loaded configuration from %s' % custom_config_file)
    except KeyError:
        custom_config_file = ''
        print 'Warning: Could not find config file "%s" for FPGA serial: %s, loading default values' % (
            custom_config_file, initial_config.strSelectedSerial)
        sp.loadDefaults()

    sp.loadDefaults()
    # sp.saveToFile('system_parameters_current.xml')

    bSendToFPGA = bTriggerEvents
    sp.sendToFPGA(sl, bSendToFPGA)

    #    config_window = SLLConfigurationWindow()
    #    config_window.loadParameters(sp)
    #    config_window.hide()

    ###########################################################################
    # Load all our windows:

    # Style sheet which includes the color scheme for each specific box:
    try:
        custom_style_sheet = (
            '#MainWindow {color: white; background-color: %s;}' %
            devices_data[initial_config.strSelectedSerial]['color'])
    except KeyError:
        custom_style_sheet = ''

    # The shorthand name which gets added to the window names:
    try:
        custom_shorthand = devices_data[
            initial_config.strSelectedSerial]['shorthand']
    except KeyError:
        custom_shorthand = ''

    # Have to be careful with the modulus setting (double-check with a scope to make sure the output frequency is right)
    # I think the output frequency for the square wave mode is given by:
    # 200 MHz/(2*(modulus+1))
    # While for the pulsed mode (bPulses = 1), the frequency is:
    # 200 MHz/(modulus+1)


#    sl.set_clk_divider_settings(bOn=1, bPulses=0, modulus=67e3-1)
#    sl.set_clk_divider_settings(bOn=1, bPulses=0, modulus=67e3+1-1)
    divider_settings_window = DisplayDividerAndResidualsStreamingSettingsWindow(
        sl,
        clk_divider_modulus=67e3,
        bDividerOn=0,
        bPulses=0,
        custom_style_sheet=custom_style_sheet,
        custom_shorthand=custom_shorthand,
        bUpdateFPGA=bSendToFPGA)

    # Optical lock window
    xem_gui_mainwindow2 = XEM_GUI_MainWindow(
        sl, custom_shorthand + ': Optical lock', 1, (False, True, False), sp,
        custom_style_sheet, initial_config.strSelectedSerial)
    xem_gui_mainwindow2.initSL(bTriggerEvents)

    # CEO Lock window
    xem_gui_mainwindow = XEM_GUI_MainWindow(sl,
                                            custom_shorthand + ': CEO lock', 0,
                                            (True, False, False), sp,
                                            custom_style_sheet,
                                            initial_config.strSelectedSerial)
    xem_gui_mainwindow.initSL(bTriggerEvents)

    #    ###########################################################################
    #    # For testing the Red Pitaya with the built-in DDS:
    #
    #    addr_vco = 2
    #    addr_vco_amplitude = 0x0000
    #    addr_vco_freq_msb  = 0x0004
    #    addr_vco_freq_lsb  = 0x0008
    #
    #    vco_amplitude = round(0.01*(2**15-1))
    ##   vco_freq_word = np.array([round((15e6/100e6+1./600.)*2.**48)]).astype(np.int64)
    ##   # break vco word into msbs and lsbs:
    ##   vco_freq_word_msbs = vco_freq_word >> 32
    ##   vco_freq_word_lsbs = np.bitwise_and(vco_freq_word, (1<<32)-1)
    #
    #   # write amplitude
    #    address_uint32 = (addr_vco << 20) + addr_vco_amplitude
    #    data_uint32 = vco_amplitude
    #    sl.dev.write_Zynq_register_uint32(address_uint32, data_uint32)

    #########################################################
    # The two frequency counter:
    strOfTime = time.strftime("%m_%d_%Y_%H_%M_%S_")

    try:
        temp_control_port = devices_data[
            initial_config.strSelectedSerial]['port']
    except:
        temp_control_port = 0

    strNameTemplate = 'data_logging\%s' % strOfTime
    strNameTemplate = '%s_%s_' % (strNameTemplate,
                                  initial_config.strSelectedSerial)
    freq_error_window1 = FreqErrorWindowWithTempControlV2(
        sl, 'CEO beat in-loop counter', 0, strNameTemplate, custom_style_sheet,
        0, xem_gui_mainwindow)
    freq_error_window2 = FreqErrorWindowWithTempControlV2(
        sl, 'Optical beat in-loop counter', 1, strNameTemplate,
        custom_style_sheet, temp_control_port, None)

    counters_window = Qt.QWidget()
    counters_window.setObjectName('MainWindow')
    counters_window.setStyleSheet(custom_style_sheet)
    vbox = Qt.QVBoxLayout()
    vbox.addWidget(freq_error_window1)
    vbox.addWidget(freq_error_window2)
    counters_window.setLayout(vbox)
    counters_window.setWindowTitle(custom_shorthand + ': Frequency counters')
    #counters_window.setGeometry(993, 40, 800, 1010)
    #counters_window.setGeometry(0, 0, 750, 1000)
    #    counters_window.resize(600, 1080-100+30)
    counters_window.move(QtGui.QDesktopWidget().availableGeometry().topLeft() +
                         Qt.QPoint(985, 10))
    counters_window.show()

    # Dither windows, this code could be moved to another class/file to help with clutter:
    dither_widget0 = DisplayDitherSettingsWindow(
        sl,
        0,
        modulation_frequency_in_hz='1e3',
        output_amplitude='1e-3',
        integration_time_in_seconds='0.1',
        bEnableDither=True,
        custom_style_sheet=custom_style_sheet)
    dither_widget1 = DisplayDitherSettingsWindow(
        sl,
        1,
        modulation_frequency_in_hz='5e3',
        output_amplitude='1e-3',
        integration_time_in_seconds='0.1',
        bEnableDither=True,
        custom_style_sheet=custom_style_sheet)
    dither_widget2 = DisplayDitherSettingsWindow(
        sl,
        2,
        modulation_frequency_in_hz='110',
        output_amplitude='1e-4',
        integration_time_in_seconds='0.1',
        bEnableDither=True,
        custom_style_sheet=custom_style_sheet)

    settings_window = Qt.QWidget()
    settings_window.setObjectName('MainWindow')
    settings_window.setStyleSheet(custom_style_sheet)
    vbox = Qt.QVBoxLayout()
    vbox.addWidget(dither_widget0)
    vbox.addWidget(dither_widget1)
    vbox.addWidget(dither_widget2)
    vbox.addStretch(1)
    hbox = Qt.QHBoxLayout()
    hbox.addLayout(vbox)
    hbox.addWidget(divider_settings_window)
    hbox.addStretch(1)
    settings_window.setLayout(hbox)
    settings_window.setWindowTitle(custom_shorthand + ': Dither controls')
    settings_window.show()

    #    ###########################################################################
    #    # For testing out the transfer function window:
    #    frequency_axis = np.logspace(np.log10(10e3), np.log10(2e6), 10e3)
    #    transfer_function = 1/(1 + 1j*frequency_axis/100e3)
    #    window_number = 1
    #    vertical_units = 'V/V'
    #    tf_window1 = DisplayTransferFunctionWindow(frequency_axis, transfer_function, window_number, vertical_units)
    #

    #    # Regroup the two windows into a single one:
    main_windows = Qt.QWidget()
    main_windows.setObjectName('MainWindow')
    main_windows.setStyleSheet(custom_style_sheet)

    #    ###########################################################################
    #    # Select clock source
    #    # clock_source = 0: Internal clock at 100 MHz
    #    # clock_source = 1: External clock at 200 MHz on DIN[0]/CLKIN, divided by 2 internally for a system clock still at 100 MHz
    #    if initial_config.bSendFirmware:
    #        if initial_config.bExternalClock == True:
    #            clock_source = 1
    #            print('External clock mode')
    #        else:
    #            clock_source = 0
    #            print('Internal clock mode')
    #        sl.selectClockSource(clock_source)
    #        # Now we just need to reset the frontend to make sure we start everything in a nice state
    #        sl.resetFrontend()

    sl.resetFrontend()

    tabs = QtGui.QTabWidget()
    # xem_gui_mainwindow2.resize(600, 700)

    # xem_gui_mainwindow.setContentsMargins(0, 0, 0, 0)
    # xem_gui_mainwindow.layout().setContentsMargins(0, 0, 0, 0)
    # xem_gui_mainwindow2.setContentsMargins(0, 0, 0, 0)
    # xem_gui_mainwindow2.layout().setContentsMargins(0, 0, 0, 0)
    # counters_window.setContentsMargins(0, 0, 0, 0)
    # counters_window.layout().setContentsMargins(0, 0, 0, 0)
    # dither_window.setContentsMargins(0, 0, 0, 0)
    # dither_window.layout().setContentsMargins(0, 0, 0, 0)
    # dfr_timing_gui.setContentsMargins(0, 0, 0, 0)
    # dfr_timing_gui.layout().setContentsMargins(0, 0, 0, 0)
    # divider_settings_window.setContentsMargins(0, 0, 0, 0)
    # divider_settings_window.layout().setContentsMargins(0, 0, 0, 0)

    tabs.setMaximumSize(1920, 1080 - 100 + 30)
    # main_windows.setMaximumSize(600,600)
    # xem_gui_mainwindow.setMaximumSize(600,600)
    # xem_gui_mainwindow2.setMaximumSize(600,600)
    # counters_window.setMaximumSize(600,600)
    # dither_window.setMaximumSize(600,600)
    # dfr_timing_gui.setMaximumSize(600,600)
    # divider_settings_window.setMaximumSize(600,600)
    tabs.addTab(xem_gui_mainwindow, "CEO Lock")
    tabs.addTab(xem_gui_mainwindow2, "Optical Lock")
    tabs.addTab(counters_window, "Counters")
    tabs.addTab(settings_window, "Settings")
    #FEATURE
    #tabs.addTab(dfr_timing_gui, "DFr trigger generator")
    #    tabs.addTab(divider_settings_window, "Filter settings")
    # tabs.setGeometry(0, 0, 750, 1000)

    box = QtGui.QHBoxLayout()
    box.addWidget(tabs)
    main_windows.setLayout(box)
    main_windows.setWindowTitle(custom_shorthand)
    main_windows.move(QtGui.QDesktopWidget().availableGeometry().topLeft() +
                      Qt.QPoint(945 - 300, 0))

    main_windows.show()

    # Enter main event loop
    app.exec_()
Пример #6
0
class controller(object):
    """Main class of the GUI. It contains most of the elements of the GUI, the main_window and the communication class"""
    def __init__(self, bManualStartupForTests=False):
        self.logger = logging.getLogger()
        self.logger.addHandler(
            logging.handlers.SysLogHandler(address=(SYSLOG_IP, SYSLOG_PORT)))
        self.logger_name = ''  # To be replaced with FPGA's shorthand

        # Create the object that handles the communication with the FPGA board:
        self.sl = SuperLaserLand_JD_RP(self)
        self.updateDeviceData()

        self.sp = SLLSystemParameters()

        self.reconnection_attempts = 0
        self.timerReconnect = None

        # Start Qt:
        self.app = QtCore.QCoreApplication.instance()
        if self.app is None:
            print("QCoreApplication not running yet. creating.")
            self.bEventLoopWasRunningAlready = False
            self.app = QtWidgets.QApplication(sys.argv)
        else:
            self.bEventLoopWasRunningAlready = True
            print("QCoreApplication already running.")

        self.initUI()

        if bManualStartupForTests == False:
            self.runEventLoop()

    def updateDeviceData(self):
        # xml file containing the known Red Pitaya's and their MAC addresses, UI color and shorthand name
        self.devices_data = {}
        devices_xml = devicesData("devices_data.xml")
        self.devices_data = devices_xml.updateDictionnary(self.devices_data)

    def findMostLikelyLANBroadcastIPAddress(self):
        # list all possible IPv4 addresses and choose the most likely candidate for the subnet on which the red pitaya is
        # heuristics used:
        #   -prefer if the address starts with 192.168
        #   -choose the subnet that has the lowest third byte: eg if there are both 192.168.1.10 and 192.168.2.10, chooose 129.168.1.10 as the correct one
        addrCandidate = '192.168.0.255'

        try:
            listAddr = socket.getaddrinfo(socket.gethostname(), None)
            min_third_byte = 255

            for addr_tuple in listAddr:
                (family, _, _, _, sockaddr) = addr_tuple
                if family == socket.AF_INET:
                    # this is IPv4
                    print('IP candidate: %s' % sockaddr[0])
                    third_byte = int(sockaddr[0].split('.')[2])
                    if third_byte <= min_third_byte:
                        min_third_byte = third_byte
                        addrCandidate = sockaddr[0]
            print('Chosen local IP: %s' % addrCandidate)

        except:
            print(
                "findMostLikelyLANBroadcastIPAddress():Exception trying to find correct broadcast automatically."
            )
        # pass

        # Take this machine's IP address and transform into broadcast address for the whole subnet (change last byte to 255)
        addrSplit = addrCandidate.split('.')
        addrSplit[3] = '255'
        strBroadCastAddress = '.'.join(addrSplit)

        print('Chosen broadcast IP: %s' % strBroadCastAddress)

        return strBroadCastAddress

    def connectionGUI(self):

        strBroadcastAddress = self.findMostLikelyLANBroadcastIPAddress()
        # strBroadcastAddress = "192.168.0.255"
        strFPGAFirmware = r'red_pitaya_top_extint_clk.bit'
        strCPUFirmware = u'monitor-tcp'
        self.initial_config = initialConfiguration(self.sl.dev, self,
                                                   self.devices_data,
                                                   strBroadcastAddress,
                                                   strFPGAFirmware,
                                                   strCPUFirmware)

    def initUI(self):

        # Start the User Interface
        self.strSelectedSerial = "000000000000"

        # Start the init process (this sets the PLL gain/settings registers and the residuals streaming)
        self.sl.initSubModules()

        ###########################################################################
        # Load all our windows:

        # Style sheet which includes the color scheme for each specific box:
        try:
            # custom_style_sheet = ('#MainWindow {color: white; background-color: %s;}' % self.devices_data[self.initial_config.strSelectedSerial]['color'])
            custom_style_sheet = (
                '#MainWindow {color: white; background-color: %s;}' %
                self.devices_data[self.strSelectedSerial]['color'])
        except KeyError:
            custom_style_sheet = ''

        # The shorthand name which gets added to the window names:
        try:
            # custom_shorthand = self.devices_data[self.initial_config.strSelectedSerial]['shorthand']
            custom_shorthand = self.devices_data[
                self.strSelectedSerial]['shorthand']
        except KeyError:
            custom_shorthand = ''

        self.divider_settings_window = DisplayDividerAndResidualsStreamingSettingsWindow(
            self.sl,
            self.sp,
            clk_divider_modulus=67e3,
            bDividerOn=0,
            bPulses=0,
            custom_style_sheet=custom_style_sheet,
            custom_shorthand=custom_shorthand)

        # Optical lock window
        self.xem_gui_mainwindow2 = XEM_GUI_MainWindow(
            self.sl, custom_shorthand + ': Optical lock', 1,
            (False, True, True), self.sp, custom_style_sheet,
            self.strSelectedSerial)

        # CEO Lock window
        self.xem_gui_mainwindow = XEM_GUI_MainWindow(
            self.sl, custom_shorthand + ': CEO lock', 0, (True, False, False),
            self.sp, custom_style_sheet, self.strSelectedSerial)

        #########################################################
        # The two frequency counter:
        strOfTime = time.strftime("%m_%d_%Y_%H_%M_%S_")

        temp_control_port = 0

        strNameTemplate = 'data_logging\\%s' % strOfTime
        # strNameTemplate = '%s_%s_' % (strNameTemplate, self.initial_config.strSelectedSerial)
        strNameTemplate = '%s_%s_' % (strNameTemplate, self.strSelectedSerial)
        self.freq_error_window1 = FreqErrorWindowWithTempControlV2(
            self.sl, 'CEO beat in-loop counter', self.sp, 0, strNameTemplate,
            custom_style_sheet, 0, self.xem_gui_mainwindow)
        self.freq_error_window2 = FreqErrorWindowWithTempControlV2(
            self.sl, 'Optical beat in-loop counter', self.sp, 1,
            strNameTemplate, custom_style_sheet, temp_control_port,
            self.xem_gui_mainwindow2)

        self.counters_window = Qt.QWidget()
        self.counters_window.setObjectName('MainWindow')
        self.counters_window.setStyleSheet(custom_style_sheet)
        vbox = Qt.QVBoxLayout()
        vbox.addWidget(self.freq_error_window1)
        vbox.addWidget(self.freq_error_window2)
        self.counters_window.setLayout(vbox)
        self.counters_window.setWindowTitle(custom_shorthand +
                                            ': Frequency counters')

        # Dither windows, this code could be moved to another class/file to help with clutter:
        self.dither_widget0 = DisplayDitherSettingsWindow(
            self.sl,
            self.sp,
            0,
            modulation_frequency_in_hz='1e3',
            output_amplitude='1e-3',
            integration_time_in_seconds='0.1',
            bEnableDither=True,
            custom_style_sheet=custom_style_sheet)
        self.dither_widget1 = DisplayDitherSettingsWindow(
            self.sl,
            self.sp,
            1,
            modulation_frequency_in_hz='5.1e3',
            output_amplitude='1e-3',
            integration_time_in_seconds='0.1',
            bEnableDither=True,
            custom_style_sheet=custom_style_sheet)
        # dither_widget2 = DisplayDitherSettingsWindow(self.sl, self.sp, 2, modulation_frequency_in_hz='110' , output_amplitude='1e-4', integration_time_in_seconds='0.1', bEnableDither=True, custom_style_sheet=custom_style_sheet)

        self.RP_Settings = ConfigRPSettingsUI(
            self.sl,
            self.sp,
            self,
            custom_style_sheet=custom_style_sheet,
            custom_shorthand=custom_shorthand)

        self.settings_window = Qt.QWidget()
        self.settings_window.setObjectName('MainWindow')
        self.settings_window.setStyleSheet(custom_style_sheet)
        vbox1 = Qt.QVBoxLayout()
        vbox1.addWidget(self.dither_widget0)
        vbox1.addWidget(self.dither_widget1)
        # vbox1.addWidget(dither_widget2)
        vbox1.addStretch(1)
        vbox2 = Qt.QVBoxLayout()
        vbox2.addWidget(self.RP_Settings)
        vbox2.addWidget(self.divider_settings_window)
        hbox = Qt.QHBoxLayout()
        hbox.addLayout(vbox1)
        hbox.addLayout(vbox2)
        hbox.addStretch(1)
        self.settings_window.setLayout(hbox)
        self.settings_window.setWindowTitle(custom_shorthand +
                                            ': Dither controls')
        # self.settings_window.show()

        #    # Regroup the two windows into a single one:
        self.main_windows = Qt.QWidget()
        self.main_windows.setObjectName('MainWindow')
        self.main_windows.setStyleSheet(custom_style_sheet)

        tabs = QtGui.QTabWidget()

        tabs.addTab(self.xem_gui_mainwindow, "CEO Lock")
        tabs.addTab(self.xem_gui_mainwindow2, "Optical Lock")
        tabs.addTab(self.counters_window, "Counters")
        tabs.addTab(self.settings_window, "Settings")
        box = QtGui.QHBoxLayout()
        box.addWidget(tabs)
        self.main_windows.setLayout(box)
        self.main_windows.setWindowTitle(custom_shorthand)
        # self.main_windows.move(QtGui.QDesktopWidget().availableGeometry().topLeft() + Qt.QPoint(945-300, 0))
        self.main_windows.move(
            QtGui.QDesktopWidget().availableGeometry().topLeft() +
            Qt.QPoint(800 - 300, 0))

        APPID = u'TITLE'
        ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(APPID)

        app_icon = QtGui.QIcon()
        app_icon.addFile('icons/red_pitaya.png', QtCore.QSize(32, 32))
        self.app.setWindowIcon(app_icon)

        self.main_windows.show()

        self.connectionGUI()

    def runEventLoop(self):
        # Main event loop
        try:
            self.app.exec_()
        except Exception as e:
            print("XEM_GUI3.py: Exception during app.exec_():")
            self.logger.error(
                'Red_Pitaya_GUI{}: Exception during app.exec_():{}'.format(
                    self.logger_name, e))
            print(e)

    def loadDefaultValueFromConfigFile(self,
                                       strSelectedSerial,
                                       bSendToFPGA=True):
        try:
            # custom_config_file = self.devices_data[self.initial_config.strSelectedSerial]['config file']
            custom_config_file = self.devices_data[strSelectedSerial][
                'config file']
            self.sp.loadFromFile(custom_config_file)
            print('Loaded configuration from %s' % custom_config_file)
        except (KeyError, IOError):
            strFileDefaultConfig = 'system_parameters_RP_Default.xml'
            # print('Warning: Could not parse config file for FPGA serial: %s, loading values from file %s' % (self.initial_config.strSelectedSerial, strFileDefaultConfig))
            # print('Warning: Could not parse config file for FPGA serial: %s, loading values from file %s' % (self.initial_config.strSelectedSerial, strFileDefaultConfig))
            print(
                'Warning: Could not parse config file for FPGA serial: %s, loading values from file %s'
                % (strSelectedSerial, strFileDefaultConfig))
            custom_config_file = ''
            try:
                self.sp.loadFromFile(strFileDefaultConfig)
                print('Loaded configuration from %s' % strFileDefaultConfig)
            except (KeyError, IOError):

                # print('Warning: Could not parse config file "%s" for FPGA serial: %s, falling back on script-defined defaults' % (strFileDefaultConfig, self.initial_config.strSelectedSerial))
                print(
                    'Warning: Could not parse config file "%s" for FPGA serial: %s, falling back on script-defined defaults'
                    % (strFileDefaultConfig, strSelectedSerial))
                self.sp.populateDefaults()

        # self.sp.loadDefaults()
        # self.sp.saveToFile('system_parameters_current.xml')

        self.sp.sendToFPGA(self.sl, bSendToFPGA)

    def setCustomShorthand(self, strSelectedSerial):
        # The shorthand name which gets added to the window names:
        try:
            # custom_shorthand = self.devices_data[self.initial_config.strSelectedSerial]['shorthand']
            custom_shorthand = self.devices_data[strSelectedSerial][
                'shorthand']
        except KeyError:
            custom_shorthand = ''
            self.logger_name = ''

        self.main_windows.setWindowTitle(custom_shorthand)
        self.xem_gui_mainwindow2.strTitle = custom_shorthand + ': Optical lock'
        self.xem_gui_mainwindow.strTitle = custom_shorthand + ': CEO lock'
        self.counters_window.strTitle = custom_shorthand + ': Frequency counters'

        self.xem_gui_mainwindow2.logger_name = ':' + custom_shorthand + ':Optical lock'
        self.xem_gui_mainwindow.logger_name = ':' + custom_shorthand + ':CEO lock'
        self.freq_error_window1.logger_name = ':' + custom_shorthand + ': Frequency counters'
        self.freq_error_window2.logger_name = ':' + custom_shorthand + ': Frequency counters'

    def setCustomStyleSheet(self, strSelectedSerial):
        # Style sheet which includes the color scheme for each specific box:
        try:
            # custom_style_sheet = ('#MainWindow {color: white; background-color: %s;}' % self.devices_data[self.initial_config.strSelectedSerial]['color'])
            custom_style_sheet = (
                '#MainWindow {color: white; background-color: %s;}' %
                self.devices_data[strSelectedSerial]['color'])
        except KeyError:
            custom_style_sheet = ''

        target_windows = [
            self.divider_settings_window, self.freq_error_window1,
            self.freq_error_window2, self.xem_gui_mainwindow2,
            self.xem_gui_mainwindow, self.counters_window, self.dither_widget0,
            self.dither_widget1, self.RP_Settings, self.settings_window,
            self.main_windows
        ]

        for window in target_windows:
            window.setStyleSheet(custom_style_sheet)

    def setTemperatureControlPort(self, strSelectedSerial):
        try:
            port_number = self.devices_data[strSelectedSerial]['port_temp']
        except Exception:
            port_number = 0
            self.logger.warning(
                'Red_Pitaya_GUI{}: Could not get temperature control port'.
                format(self.logger_name))

        self.freq_error_window2.port_number = int(port_number)

    def pushDefaultValues(self,
                          strSelectedSerial="000000000000",
                          ip_addr="192.168.0.150",
                          port=5000):
        self.strSelectedSerial = strSelectedSerial
        self.ip_addr = ip_addr
        self.port = port

        self.setCustomStyleSheet(strSelectedSerial)
        self.setCustomShorthand(strSelectedSerial)

        self.logger.info(
            'Red_Pitaya_GUI{}: Pushing default values from xml file'.format(
                self.logger_name))
        if self.sl.dev.valid_socket:
            self.sl.dev.CloseTCPConnection()

        self.sl.dev.OpenTCPConnection(ip_addr, port)
        if not self.sl.dev.valid_socket:
            self.logger.error('Connection to host %s, port %s failed.' %
                              (ip_addr, port))
            return
        # Now we just need to reset the frontend to make sure we start everything in a nice state
        self.sl.resetFrontend()

        self.loadDefaultValueFromConfigFile(strSelectedSerial, True)

        target_windows = [
            self.xem_gui_mainwindow2,
            self.xem_gui_mainwindow,
            self.freq_error_window1,
            self.freq_error_window2,
            self.RP_Settings,
            self.divider_settings_window,
            self.dither_widget0,
            self.dither_widget1,
        ]

        for window in target_windows:
            window.pushDefaultValues()

        self.setTemperatureControlPort(strSelectedSerial)

    def getActualValues(self,
                        strSelectedSerial,
                        ip_addr="192.168.0.150",
                        port=5000):

        if self.sl.dev.valid_socket:
            self.sl.dev.CloseTCPConnection()

        self.sl.dev.OpenTCPConnection(ip_addr, port)
        if self.sl.dev.valid_socket == False:
            logging.error('Connection failed.')
            return

        self.logger.info('Red_Pitaya_GUI{}: Updating GUI from FPGA'.format(
            self.logger_name))

        self.strSelectedSerial = strSelectedSerial
        self.ip_addr = ip_addr
        self.port = port

        print("getActualValues: strSelectedSerial = %s" % strSelectedSerial)
        # pdb.set_trace()
        self.setCustomStyleSheet(strSelectedSerial)
        self.setCustomShorthand(strSelectedSerial)

        self.loadDefaultValueFromConfigFile(
            strSelectedSerial, False
        )  # read xml file to update some values. False means not updating the FPGA

        target_windows = [
            self.xem_gui_mainwindow2,
            self.xem_gui_mainwindow,
            self.freq_error_window1,
            self.freq_error_window2,
            self.RP_Settings,
            self.divider_settings_window,
            self.dither_widget0,
            self.dither_widget1,
        ]

        for window in target_windows:
            window.getValues()

        self.setTemperatureControlPort(strSelectedSerial)

    def pushActualValues(self,
                         strSelectedSerial,
                         ip_addr="192.168.0.150",
                         port=5000):
        self.strSelectedSerial = strSelectedSerial
        self.ip_addr = ip_addr
        self.port = port

        self.setCustomStyleSheet(strSelectedSerial)
        self.setCustomShorthand(strSelectedSerial)

        self.logger.info(
            'Red_Pitaya_GUI{}: Pushing actual values from GUI'.format(
                self.logger_name))

        if self.sl.dev.valid_socket:
            self.sl.dev.CloseTCPConnection()
        self.sl.dev.OpenTCPConnection(ip_addr, port)

        target_windows = [
            self.xem_gui_mainwindow2,
            self.xem_gui_mainwindow,
            self.freq_error_window1,
            self.freq_error_window2,
        ]

        for window in target_windows:
            window.pushActualValues()

        self.setTemperatureControlPort(strSelectedSerial)

    def stopCommunication(self):

        self.logger.info('Red_Pitaya_GUI{}: Closing connection'.format(
            self.logger_name))

        if self.timerReconnect is not None:
            self.timerReconnect = None

        self.sl.dev.CloseTCPConnection()

        try:
            self.xem_gui_mainwindow2.killTimers()
            self.xem_gui_mainwindow.killTimers()
            self.freq_error_window1.killTimers()
            self.freq_error_window2.killTimers()
            self.RP_Settings.killTimers()
        except Exception as e:
            print("Error while killing the timers:")
            print(e)

    def socketErrorEvent(self, e):
        print("XEM_GUI3.py:Controller::socketErrorEvent()")
        # this gets called by the socket-using functions in RP_PLL
        # in the event of a socket exception, while we thought we had a valid connection
        # The right things to do in this case is to:
        # -drop the current socket (because the data stream is left in an uncertain state)
        # -start a reconnection timer that will attempt to reconnect automatically
        # -raise a CommsLoggeableError

        # check if we need to start the reconnection attempt timer:
        if self.timerReconnect is None:
            # disconnect from socket, and start reconnection timer:
            self.stopCommunication()

            print("TCP connection lost. Starting reconnection timer")
            self.timerReconnect = QtCore.QTimer()
            self.reconnection_attempts = 0
            self.timerReconnect.timeout.connect(self.reconnectionAttempt)
            self.timerReconnect.start(
                3000
            )  # 3000 ms update period (needs to be longer than the delay...)

            raise CommsLoggeableError

    # target_windows = [
    # 	self.xem_gui_mainwindow2,
    # 	self.xem_gui_mainwindow,
    # 	self.freq_error_window1,
    # 	self.freq_error_window2,
    # 	self.RP_Settings
    # ]
    # print("startCommunication")

    def reconnectionAttempt(self):
        self.reconnection_attempts += 1
        # print("TCP connection lost. Attempting to reconnect %d." % (self.reconnection_attempts))

        try:
            self.getActualValues(self.strSelectedSerial, self.ip_addr,
                                 self.port)
        except:
            print("Reconnection attempt #%d failed." %
                  self.reconnection_attempts)
            self.logger.error(traceback.format_exc())

        if self.sl.dev.valid_socket:
            # success!
            self.timerReconnect.stop()
            self.timerReconnect = None
            return

        if self.reconnection_attempts == 10:
            # switch to a longer timer between reconnection attempt:
            print(
                "%d failed reconnection attempts. Switching to 10 secs between attempts."
                % self.reconnection_attempts)
            self.timerReconnect.stop()
            self.timerReconnect.start(10000)  # 10 seconds update period