Mon, 13 Feb 2023 17:49:52 +0100
Reorganized the MicroPython package.
# -*- coding: utf-8 -*- # Copyright (c) 2023 Detlev Offenbach <detlev@die-offenbachs.de> # """ Package containing the device interface modules and device specific dialogs. """ import contextlib import importlib import logging from PyQt6.QtCore import QCoreApplication from PyQt6.QtSerialPort import QSerialPortInfo from eric7 import Preferences from eric7.EricGui import EricPixmapCache from .DeviceBase import BaseDevice SupportedBoards = { "bbc_microbit": { "ids": [ (0x0D28, 0x0204), # micro:bit ], "description": "BBC micro:bit", "icon": "microbitDevice", "port_description": "BBC micro:bit CMSIS-DAP", "module": ".MicrobitDevices", }, "calliope": { "ids": [ (0x0D28, 0x0204), # Calliope mini ], "description": "Calliope mini", "icon": "calliope_mini", "port_description": "DAPLink CMSIS-DAP", "module": ".MicrobitDevices", }, "circuitpython": { "ids": [ (0x0483, 0x572A), # STMicroelectronics NUCLEO-F446RE - CPy (0x04D8, 0xE799), # Cytron Maker Zero SAMD21 (0x04D8, 0xEA2A), # BHDynamics DynaLoRa_USB (0x04D8, 0xEAD1), # BH Dynamics DynOSSAT-EDU-EPS-v1.0 (0x04D8, 0xEAD2), # BH Dynamics DynOSSAT-EDU-OBC-v1.0 (0x04D8, 0xEC44), # maholli PyCubed (0x04D8, 0xEC63), # Kevin Neubauer CircuitBrains Basic (0x04D8, 0xEC64), # Kevin Neubauer CircuitBrains Deluxe (0x04D8, 0xEC72), # XinaBox CC03 (0x04D8, 0xEC75), # XinaBox CS11 (0x04D8, 0xED5F), # Itaca Innovation uChip CircuitPython (0x04D8, 0xED94), # maholli kicksat-sprite (0x04D8, 0xEDB3), # Capable Robot Programmable USB Hub (0x04D8, 0xEDBE), # maholli SAM32 (0x04D8, 0xEE8C), # J&J Studios LLC datum-Distance (0x04D8, 0xEE8D), # J&J Studios LLC datum-IMU (0x04D8, 0xEE8E), # J&J Studios LLC datum-Light (0x04D8, 0xEE8F), # J&J Studios LLC datum-Weather (0x04D8, 0xEF67), # senseBox MCU (0x054C, 0x0BC2), # Sony Spresense (0x1209, 0x2017), # Benjamin Shockley Mini SAM M4 (0x1209, 0x3141), # CrumpSpace CrumpS2 (0x1209, 0x3252), # Targett Module Clip w/Wroom (0x1209, 0x3253), # Targett Module Clip w/Wrover (0x1209, 0x4203), # 42. Keebs Frood (0x1209, 0x4D43), # Robotics Masters Robo HAT MM1 M4 (0x1209, 0x4DDD), # ODT CP Sapling (0x1209, 0x4DDE), # ODT CP Sapling M0 w/ SPI Flash (0x1209, 0x4DDF), # ODT CP Sapling Rev B (0x1209, 0x4DF0), # Oak Dev Tech Pixelwing ESP32S2 (0x1209, 0x4DF1), # Oak Dev Tech BREAD2040 (0x1209, 0x4DF2), # Oak Dev Tech CAST AWAY RP2040 (0x1209, 0x5A52), # ZRichard RP2.65-F (0x1209, 0x5BF0), # Foosn Fomu (0x1209, 0x7150), # Electronic Cats Hunter Cat NFC (0x1209, 0x7382), # Invector Labs AB iLabs Challenger 840 (0x1209, 0x805A), # Electronic Cats BastBLE (0x1209, 0x8CAE), # takayoshiotake Octave RP2040 (0x1209, 0xA182), # Solder Party RP2040 Stamp (0x1209, 0xB182), # Solder Party BBQ20 Keyboard (0x1209, 0xBAB0), # Electronic Cats Bast WiFi (0x1209, 0xBAB1), # Electronic Cats Meow Meow (0x1209, 0xBAB2), # Electronic Cats CatWAN USBStick (0x1209, 0xBAB3), # Electronic Cats Bast Pro Mini M0 (0x1209, 0xBAB6), # Electronic Cats Escornabot Makech (0x1209, 0xBAB8), # Electronic Cats NFC Copy Cat (0x1209, 0xC051), # Betrusted Simmel (0x1209, 0xCB74), # 0xCB Helios (0x1209, 0xD10D), # Diodes Delight Piunora (0x1209, 0xD1B5), # Radomir Dopieralski PewPew LCD (0x1209, 0xE3E3), # StackRduino M0 PRO (0x1209, 0xEF00), # 2231puppy E-Fidget (0x1209, 0xF123), # Electrolama minik (0x1209, 0xF500), # Silicognition LLC M4-Shim (0x1209, 0xF502), # Silicognition LLC RP2040-Shim (0x16D0, 0x08C6), # Pimoroni Keybow 2040 (0x16D0, 0x08C7), # Pimoroni Tiny 2040 (8MB) (0x16D0, 0x08C8), # Pimoroni PicoSystem (0x16D0, 0x10ED), # Mechwild PillBug (0x1915, 0xB001), # Makerdiary Pitaya Go (0x192F, 0xB1B2), # WarmBit BluePixel nRF52840 (0x1B4F, 0x0015), # SparkFun RedBoard Turbo Board (0x1B4F, 0x0016), # SparkFun SAMD51 Thing+ (0x1B4F, 0x0017), # SparkFun LUMIDrive Board (0x1B4F, 0x0020), # SparkFun MicroMod SAMD51 Processor (0x1B4F, 0x0021), # SparkFun MicroMod nRF52840 Processor (0x1B4F, 0x0024), # SparkFun MicroMod RP2040 Processor (0x1B4F, 0x0025), # SparkFun Thing Plus RP2040 (0x1B4F, 0x0026), # SparkFun Pro Micro RP2040 (0x1B4F, 0x0027), # SparkFun STM32 MicroMod Processor (0x1B4F, 0x0028), # SparkFun Thing Plus - STM32 (0x1B4F, 0x002E), # PJRC/Sparkfun Teensy MicroMod (0x1B4F, 0x5289), # SparkFun SFE_nRF52840_Mini (0x1B4F, 0x8D22), # SparkFun SAMD21 Mini Breakout (0x1B4F, 0x8D23), # SparkFun SAMD21 Dev Breakout (0x1B4F, 0x8D24), # SparkFun Qwiic Micro (0x1D50, 0x60E8), # Radomir Dopieralski PewPew M4 (0x1D50, 0x6152), # nrf52.jpconstantineau.com BlueMicro833 (0x1D50, 0x6153), # JPConstantineau PyKey18 (0x1D50, 0x6153), # JPConstantineau PyKey44 (0x1D50, 0x6153), # JPConstantineau PyKey60 (0x1D50, 0x6153), # JPConstantineau PyKey87 (0x1D50, 0x6154), # JPConstantineau EncoderPad RP2040 (0x1D50, 0x6161), # nrf52.jpconstantineau.com BlueMicro840 (0x2019, 0x7103), # Benjamin Shockley Fig Pi (0x2341, 0x8053), # Arduino MKR1300 (0x2341, 0x8057), # Arduino Nano 33 IoT (0x2341, 0x805A), # Arduino Arduino_Nano_33_BLE (0x2341, 0x824D), # Arduino Zero (0x2786, 0x9207), # Switch Sc. BLE-SS dev board Multi Sensor (0x2786, 0x920D), # Switch Sc. SSCI ISP1807 Dev Board (0x2786, 0x920F), # Switch Sc. SSCI ISP1807 Micro Board (0x2886, 0x002F), # Seeed Seeeduino XIAO (0x2886, 0x0042), # Seeed Seeeduino XIAO RP2040 (0x2886, 0x0045), # Seeed XIAO nRF52840 Sense (0x2886, 0x802D), # Seeed Seeeduino Wio Terminal (0x2886, 0x802F), # Seeed Seeeduino XIAO KB (0x2886, 0xF001), # Makerdiary nRF52840 M.2 Developer Kit (0x2886, 0xF002), # Makerdiary M60 Keyboard (0x2B04, 0xC00C), # Particle Argon (0x2B04, 0xC00D), # Particle Boron (0x2B04, 0xC00E), # Particle Xenon (0x2E8A, 0x1000), # Cytron Maker Pi RP2040 (0x2E8A, 0x1002), # Pimoroni Pico LiPo (4MB) (0x2E8A, 0x1003), # Pimoroni Pico LiPo (16MB) (0x2E8A, 0x1005), # Melopero Shake RP2040 (0x2E8A, 0x1006), # Invector Labs Challenger RP2040 WiFi (0x2E8A, 0x1008), # Pimoroni PGA2040 (0x2E8A, 0x1009), # Pimoroni Interstate 75 (0x2E8A, 0x100A), # Pimoroni Plasma 2040 (0x2E8A, 0x100B), # Invector Labs Challenger RP2040 LTE (0x2E8A, 0x100D), # Invector Labs Challenger NB RP2040 WiFi (0x2E8A, 0x100E), # Raspberry Pi Zero (0x2E8A, 0x100F), # Cytron Maker Nano RP2040 (0x2E8A, 0x1012), # Raspberry Pi Compute Module 4 IO Board (0x2E8A, 0x1013), # Raspberry Pi 4B (0x2E8A, 0x1014), # Raspberry Pi Compute Module 4 (0x2E8A, 0x1015), # Raspberry Pi Zero 2W (0x2E8A, 0x1016), # Pimoroni Tiny 2040 (2MB) (0x2E8A, 0x1019), # Pimoroni Motor 2040 (0x2E8A, 0x101A), # Pimoroni Servo 2040 (0x2E8A, 0x101B), # Pimoroni Badger 2040 (0x2E8A, 0x101E), # Raspberry Pi Zero W (0x2E8A, 0x101F), # Waveshare Electronics RP2040-Zero (0x2E8A, 0x1023), # Invector Labs Challenger RP2040 LoRa (0x2E8A, 0x1026), # ELECFREAKS Pico:ed (0x2E8A, 0x1027), # WIZnet W5100S-EVB-Pico (0x2E8A, 0x1029), # WIZnet W5500-EVB-Pico (0x2E8A, 0x102C), # Invector Labs Challenger RP2040 WiFi/BLE (0x2E8A, 0x102D), # Invector Labs Challenger RP2040 SD/RTC (0x2E8A, 0x102E), # VCC-GND Studio YD-RP2040 (0x2E8A, 0x1032), # Invector Labs Challenger RP2040 SubGHz (0x2E8A, 0x1039), # Waveshare Electronics Waveshare RP2040-LCD-1.28 (0x2E8A, 0x1048), # nullbits Bit-C PRO (0x303A, 0x7001), # Espressif ESP32-S2-HMI-DevKit-1 (0x303A, 0x7003), # Espressif ESP32-S3-DevKitC-1 (0x303A, 0x7003), # Espressif ESP32-S3-DevKitC-1-N32R8 (0x303A, 0x7003), # Espressif ESP32-S3-DevKitC-1-N8 (0x303A, 0x7003), # Espressif ESP32-S3-DevKitC-1-N8R2 (0x303A, 0x7003), # Espressif ESP32-S3-DevKitC-1-N8R8 (0x303A, 0x7003), # Espressif ESP32-S3-DevKitC-1-nopsram (0x303A, 0x7005), # Espressif ESP32-S3-Box-2.5 (0x303A, 0x7007), # Espressif ESP32-S3-DevKitM-1-N8 (0x303A, 0x7009), # Espressif ESP32-S2-DevKitC-1-N4 (0x303A, 0x7009), # Espressif ESP32-S2-DevKitC-1-N4R2 (0x303A, 0x7009), # Espressif ESP32-S2-DevKitC-1-N8R2 (0x303A, 0x700B), # Espressif ESP32-S3-USB-OTG-N8 (0x303A, 0x700D), # Espressif ESP32-S3-Box-Lite (0x303A, 0x700F), # Espressif ESP32-S3-EYE (0x303A, 0x8002), # UnexpectedMaker TinyS2 (0x303A, 0x8007), # LILYGO TTGO T8 ESP32-S2 (0x303A, 0x800D), # Gravitech Cucumber RS (0x303A, 0x80A1), # Gravitech Cucumber R (0x303A, 0x80A4), # Gravitech Cucumber M (0x303A, 0x80A7), # Gravitech Cucumber MS (0x303A, 0x80AA), # Espressif Franzininho WIFI w/Wroom (0x303A, 0x80AD), # Espressif Franzininho WIFI w/Wrover (0x303A, 0x80AF), # Artisense Reference Design RD00 (0x303A, 0x80B2), # Muselab nanoESP32-S2 w/Wrover (0x303A, 0x80B5), # UnexpectedMaker FeatherS2 Neo (0x303A, 0x80B7), # MORPHEANS MORPHESP-240 (0x303A, 0x80C3), # Lolin S2 Mini (0x303A, 0x80C6), # Lolin S2 Pico (0x303A, 0x80D1), # UnexpectedMaker TinyS3 (0x303A, 0x80D4), # UnexpectedMaker ProS3 (0x303A, 0x80D7), # UnexpectedMaker FeatherS3 (0x303A, 0x80D9), # FutureKeys HexKy_S2 (0x303A, 0x80E0), # BananaPi BPI-Leaf-S3 (0x303A, 0x80E6), # BananaPi BPI-Bit-S2 (0x303A, 0x80E8), # HiiBot IoTs2 (0x303A, 0x80EA), # LILYGO TTGO T8 ESP32-S2-WROOM (0x303A, 0x80ED), # LILYGO TTGO T8 ESP32-S2 (0x303A, 0x80F9), # Cytron Maker Feather AIoT S3 (0x303A, 0x80FC), # Espressif MixGo CE (0x303A, 0x80FD), # Espressif MixGo CE (0x303A, 0x810A), # Waveshare Electronics ESP32-S2-Pico (0x303A, 0x810C), # Waveshare Electronics ESP32-S2-Pico-LCD (0x303A, 0x8111), # Smart Bee Designs Bee-S3 (0x303A, 0x8114), # Smart Bee Designs Bee-Motion-S3 (0x303A, 0x8117), # WEMOS LOLIN S3 16MB Flash 8MB PSRAM (0x303A, 0x812C), # BananaPi BPI-PicoW-S3 (0x30A4, 0x0002), # Blues Inc. Swan R5 (0x3171, 0x0101), # 8086.net Commander (0x31E2, 0x2001), # BDMICRO LLC VINA-D21 (0x31E2, 0x2011), # BDMICRO LLC VINA-D51 (0x31E2, 0x2021), # BDMICRO LLC VINA-D51 (0x32BD, 0x3001), # Alorium Tech. AloriumTech Evo M51 (0x4097, 0x0001), # TG-Boards Datalore IP M4 (0x612B, 0x80A7), # Ai-Thinker ESP 12k NodeMCU (0x239A, None), # Any Adafruit Boards ], "description": "CircuitPython", "icon": "circuitPythonDevice", "port_description": "", "module": ".CircuitPythonDevices", }, "esp": { "ids": [ (0x0403, 0x6001), # M5Stack ESP32 device"), (0x0403, 0x6001), # FT232/FT245 (XinaBox CW01, CW02) (0x0403, 0x6010), # FT2232C/D/L/HL/Q (ESP-WROVER-KIT) (0x0403, 0x6011), # FT4232 (0x0403, 0x6014), # FT232H (0x0403, 0x6015), # Sparkfun ESP32 (0x0403, 0x601C), # FT4222H (0x10C4, 0xEA60), # CP210x (0x1A86, 0x55D4), # CH343 (0x1A86, 0x7523), # HL-340, CH340 ], "description": "ESP32, ESP8266", "icon": "esp32Device", "port_description": "", "module": ".EspDevices", }, "generic": { # only manually configured devices use this "ids": [], "description": QCoreApplication.translate("MicroPythonDevice", "Generic Board"), "icon": "micropython48", "port_description": "", "module": ".GenericMicroPythonDevices", }, "pyboard": { "ids": [ (0xF055, 0x9800), # Pyboard in CDC mode (0xF055, 0x9801), # Pyboard in CDC+HID mode (0xF055, 0x9802), # Pyboard in CDC+MSC mode ], "description": "PyBoard", "icon": "micropython48", "port_description": "Pyboard", "module": ".PyBoardDevices", }, "rp2040": { "ids": [ (0x2E8A, 0x0005), # Raspberry Pi Pico ], "description": QCoreApplication.translate("MicroPythonDevice", "RP2040 based"), "icon": "rp2040Device", "port_description": "", "module": ".RP2040Devices", }, "teensy": { "ids": [ (0xF055, 0x9802), # Pyboard in CDC+MSC mode ], "description": "Teensy", "icon": "micropython48", "port_description": "Teensy", "module": ".TeensyDevices", }, } IgnoredBoards = ( (0x8086, 0x9C3D), (0x8086, None), ) FirmwareGithubUrls = { "micropython": "https://github.com/micropython/micropython/releases/latest", "circuitpython": "https://github.com/adafruit/circuitpython/releases/latest", "pimoroni_pico": "https://github.com/pimoroni/pimoroni-pico/releases/latest", "microbit_v1": "https://github.com/bbcmicrobit/micropython/releases/latest", "microbit_v2": ( "https://github.com/microbit-foundation/micropython-microbit-v2/releases/latest" ), } def getSupportedDevices(): """ Function to get a list of supported MicroPython devices. @return set of tuples with the board type and description @rtype set of tuples of (str, str) """ boards = [] for board in SupportedBoards: boards.append((board, SupportedBoards[board]["description"])) return boards def getFoundDevices(): """ Function to check the serial ports for supported MicroPython devices. @return tuple containing a list of tuples with the board type, the port description, a description, the serial port it is connected at, the VID and PID for known device types, a list of tuples with VID, PID and description for unknown devices and a list of tuples with VID, PID, description and port name for ports with missing VID or PID @rtype tuple of (list of tuples of (str, str, str, str, int, int), list of tuples of (int, int, str), list of tuples of (int, int, str, str) """ foundDevices = [] unknownDevices = [] unknownPorts = [] manualDevices = {} for deviceDict in Preferences.getMicroPython("ManualDevices"): manualDevices[(deviceDict["vid"], deviceDict["pid"])] = deviceDict availablePorts = QSerialPortInfo.availablePorts() for port in availablePorts: if port.hasVendorIdentifier() and port.hasProductIdentifier(): supported = False vid = port.vendorIdentifier() pid = port.productIdentifier() for board in SupportedBoards: if (vid, pid) in SupportedBoards[board]["ids"] or ( vid, None, ) in SupportedBoards[board]["ids"]: if board in ("bbc_microbit", "calliope") and ( port.description().strip() != SupportedBoards[board]["port_description"] ): # both boards have the same VID and PID # try to differentiate based on port description continue elif board in ("pyboard", "teensy") and ( not port.description().startswith( SupportedBoards[board]["port_description"] ) ): # both boards have the same VID and PID # try to differentiate based on port description continue foundDevices.append( ( board, port.description(), SupportedBoards[board]["description"], port.portName(), vid, pid, port.serialNumber(), ) ) supported = True if not supported and (vid, pid) in manualDevices: # check the locally added ones next board = manualDevices[(vid, pid)]["type"] foundDevices.append( ( board, port.description(), SupportedBoards[board]["description"], port.portName(), vid, pid, port.serialNumber(), ) ) supported = True if not supported: if vid and pid: if (vid, pid) not in IgnoredBoards and ( vid, None, ) not in IgnoredBoards: unknownDevices.append((vid, pid, port.description())) logging.debug( "Unknown device: (0x%04x:0x%04x %s)", vid, pid, port.description(), ) else: # either VID or PID or both not detected desc = port.description() if not desc: desc = QCoreApplication.translate( "MicroPythonDevice", "Unknown Device" ) unknownPorts.append((vid, pid, desc, port.portName())) elif bool(port.portName()) and Preferences.getMicroPython( "EnableManualDeviceSelection" ): # no VID and/or PID available (e.g. in Linux container of ChromeOS) desc = port.description() if not desc: desc = QCoreApplication.translate("MicroPythonDevice", "Unknown Device") unknownPorts.append((0, 0, desc, port.portName())) return foundDevices, unknownDevices, unknownPorts def getDeviceIcon(boardName, iconFormat=True): """ Function to get the icon for the given board. @param boardName name of the board @type str @param iconFormat flag indicating to get an icon or a pixmap @type bool @return icon for the board (iconFormat == True) or a pixmap (iconFormat == False) @rtype QIcon or QPixmap """ iconName = ( SupportedBoards[boardName]["icon"] if boardName in SupportedBoards else # return a generic MicroPython icon "micropython48" ) if iconFormat: return EricPixmapCache.getIcon(iconName) else: return EricPixmapCache.getPixmap(iconName) def getDevice(deviceType, microPythonWidget, vid, pid, boardName="", serialNumber=""): """ Public method to instantiate a specific MicroPython device interface. @param deviceType type of the device interface @type str @param microPythonWidget reference to the main MicroPython widget @type MicroPythonWidget @param vid vendor ID (only used for deviceType 'generic') @type int @param pid product ID (only used for deviceType 'generic') @type int @param boardName name of the board (defaults to "") @type str (optional) @param serialNumber serial number of the board (defaults to "") @type str (optional) @return instantiated device interface @rtype BaseDevice """ with contextlib.suppress(KeyError): mod = importlib.import_module( SupportedBoards[deviceType]["module"], __package__ ) if mod: return mod.createDevice( microPythonWidget, deviceType, vid, pid, boardName, serialNumber ) # nothing specific requested or specific one failed or is not supported yet return BaseDevice(microPythonWidget, deviceType)