--- a/src/eric7/MicroPython/RP2040Devices.py Sun Feb 12 18:11:20 2023 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,317 +0,0 @@ -# -*- coding: utf-8 -*- - -# Copyright (c) 2021 - 2023 Detlev Offenbach <detlev@die-offenbachs.de> -# - -""" -Module implementing the device interface class for RP2040 based boards -(e.g. Raspberry Pi Pico). -""" - -from PyQt6.QtCore import QUrl, pyqtSlot -from PyQt6.QtNetwork import QNetworkRequest -from PyQt6.QtWidgets import QMenu - -from eric7 import Globals, Preferences -from eric7.EricWidgets import EricMessageBox -from eric7.EricWidgets.EricApplication import ericApp - -from .MicroPythonDevices import FirmwareGithubUrls, MicroPythonDevice -from .MicroPythonWidget import HAS_QTCHART - - -class RP2040Device(MicroPythonDevice): - """ - Class implementing the device for RP2040 based boards. - """ - - def __init__(self, microPythonWidget, deviceType, parent=None): - """ - Constructor - - @param microPythonWidget reference to the main MicroPython widget - @type MicroPythonWidget - @param deviceType device type assigned to this device interface - @type str - @param parent reference to the parent object - @type QObject - """ - super().__init__(microPythonWidget, deviceType, parent) - - self.__createRP2040Menu() - - def setButtons(self): - """ - Public method to enable the supported action buttons. - """ - super().setButtons() - self.microPython.setActionButtons( - run=True, repl=True, files=True, chart=HAS_QTCHART - ) - - def forceInterrupt(self): - """ - Public method to determine the need for an interrupt when opening the - serial connection. - - @return flag indicating an interrupt is needed - @rtype bool - """ - return False - - def deviceName(self): - """ - Public method to get the name of the device. - - @return name of the device - @rtype str - """ - return self.tr("RP2040") - - def canStartRepl(self): - """ - Public method to determine, if a REPL can be started. - - @return tuple containing a flag indicating it is safe to start a REPL - and a reason why it cannot. - @rtype tuple of (bool, str) - """ - return True, "" - - def canStartPlotter(self): - """ - Public method to determine, if a Plotter can be started. - - @return tuple containing a flag indicating it is safe to start a - Plotter and a reason why it cannot. - @rtype tuple of (bool, str) - """ - return True, "" - - def canRunScript(self): - """ - Public method to determine, if a script can be executed. - - @return tuple containing a flag indicating it is safe to start a - Plotter and a reason why it cannot. - @rtype tuple of (bool, str) - """ - return True, "" - - def runScript(self, script): - """ - Public method to run the given Python script. - - @param script script to be executed - @type str - """ - pythonScript = script.split("\n") - self.sendCommands(pythonScript) - - def canStartFileManager(self): - """ - Public method to determine, if a File Manager can be started. - - @return tuple containing a flag indicating it is safe to start a - File Manager and a reason why it cannot. - @rtype tuple of (bool, str) - """ - return True, "" - - def __createRP2040Menu(self): - """ - Private method to create the RO2040 submenu. - """ - self.__rp2040Menu = QMenu(self.tr("RP2040 Functions")) - - self.__showMpyAct = self.__rp2040Menu.addAction( - self.tr("Show MicroPython Versions"), self.__showFirmwareVersions - ) - self.__rp2040Menu.addSeparator() - self.__bootloaderAct = self.__rp2040Menu.addAction( - self.tr("Activate Bootloader"), self.__activateBootloader - ) - self.__flashMpyAct = self.__rp2040Menu.addAction( - self.tr("Flash MicroPython Firmware"), self.__flashPython - ) - - def addDeviceMenuEntries(self, menu): - """ - Public method to add device specific entries to the given menu. - - @param menu reference to the context menu - @type QMenu - """ - connected = self.microPython.isConnected() - linkConnected = self.microPython.isLinkConnected() - - self.__showMpyAct.setEnabled(connected) - self.__bootloaderAct.setEnabled(connected) - self.__flashMpyAct.setEnabled(not linkConnected) - - menu.addMenu(self.__rp2040Menu) - - def hasFlashMenuEntry(self): - """ - Public method to check, if the device has its own flash menu entry. - - @return flag indicating a specific flash menu entry - @rtype bool - """ - return True - - @pyqtSlot() - def __flashPython(self): - """ - Private slot to flash a MicroPython firmware to the device. - """ - from .UF2FlashDialog import UF2FlashDialog - - dlg = UF2FlashDialog(boardType="rp2040") - dlg.exec() - - def __activateBootloader(self): - """ - Private method to switch the board into 'bootloader' mode. - """ - if self.microPython.isConnected(): - self.microPython.commandsInterface().execute( - [ - "import machine", - "machine.bootloader()", - ] - ) - # simulate pressing the disconnect button - self.microPython.on_connectButton_clicked() - - @pyqtSlot() - def __showFirmwareVersions(self): - """ - Private slot to show the firmware version of the connected device and the - available firmware version. - """ - if self.microPython.isConnected(): - if self._deviceData["mpy_name"] != "micropython": - EricMessageBox.critical( - None, - self.tr("Show MicroPython Versions"), - self.tr( - """The firmware of the connected device cannot be""" - """ determined or the board does not run MicroPython.""" - """ Aborting...""" - ), - ) - else: - if self._deviceData["mpy_variant"] == "Pimoroni": - # MicroPython with Pimoroni add-on libraries - url = QUrl(FirmwareGithubUrls["pimoroni_pico"]) - else: - url = QUrl(FirmwareGithubUrls["micropython"]) - ui = ericApp().getObject("UserInterface") - request = QNetworkRequest(url) - reply = ui.networkAccessManager().head(request) - reply.finished.connect(lambda: self.__firmwareVersionResponse(reply)) - - def __firmwareVersionResponse(self, reply): - """ - Private method handling the response of the latest version request. - - @param reply reference to the reply object - @type QNetworkReply - """ - latestUrl = reply.url().toString() - tag = latestUrl.rsplit("/", 1)[-1] - while tag and not tag[0].isdecimal(): - # get rid of leading non-decimal characters - tag = tag[1:] - latestVersion = Globals.versionToTuple(tag) - - if self._deviceData["mpy_version"] == "unknown": - currentVersionStr = self.tr("unknown") - currentVersion = (0, 0, 0) - else: - currentVersionStr = self._deviceData["mpy_version"] - currentVersion = Globals.versionToTuple(currentVersionStr) - - msg = self.tr( - "<h4>MicroPython Version Information</h4>" - "<table>" - "<tr><td>Installed:</td><td>{0}</td><td></td></tr>" - "<tr><td>Available:</td><td>{1}</td><td>{2}</td></tr>" - "</table>" - ).format( - currentVersionStr, - tag, - self.tr("({0})").format(self._deviceData["mpy_variant"]) - if self._deviceData["mpy_variant"] - else "", - ) - if ( - self._deviceData["mpy_variant"] not in ["Pimoroni"] - and currentVersion < latestVersion - ): - # cannot derive that info for 'Pimoroni' variant - msg += self.tr("<p><b>Update available!</b></p>") - - EricMessageBox.information( - None, - self.tr("MicroPython Version"), - msg, - ) - - def getDocumentationUrl(self): - """ - Public method to get the device documentation URL. - - @return documentation URL of the device - @rtype str - """ - return Preferences.getMicroPython("MicroPythonDocuUrl") - - def getDownloadMenuEntries(self): - """ - Public method to retrieve the entries for the downloads menu. - - @return list of tuples with menu text and URL to be opened for each - entry - @rtype list of tuple of (str, str) - """ - return [ - ( - self.tr("MicroPython Firmware"), - Preferences.getMicroPython("MicroPythonFirmwareUrl"), - ), - ("<separator>", ""), - (self.tr("Pimoroni Pico Firmware"), FirmwareGithubUrls["pimoroni_pico"]), - ("<separator>", ""), - ( - self.tr("CircuitPython Firmware"), - Preferences.getMicroPython("CircuitPythonFirmwareUrl"), - ), - ( - self.tr("CircuitPython Libraries"), - Preferences.getMicroPython("CircuitPythonLibrariesUrl"), - ), - ] - - -def createDevice(microPythonWidget, deviceType, vid, pid, boardName, serialNumber): - """ - Function to instantiate a MicroPython device object. - - @param microPythonWidget reference to the main MicroPython widget - @type MicroPythonWidget - @param deviceType device type assigned to this device interface - @type str - @param vid vendor ID - @type int - @param pid product ID - @type int - @param boardName name of the board - @type str - @param serialNumber serial number of the board - @type str - @return reference to the instantiated device object - @rtype RP2040Device - """ - return RP2040Device(microPythonWidget, deviceType)