diff --git a/src/adafruit_blinka/board/fake_microchip_mcp2221.py b/src/adafruit_blinka/board/fake_microchip_mcp2221.py new file mode 100644 index 00000000..6aae9d56 --- /dev/null +++ b/src/adafruit_blinka/board/fake_microchip_mcp2221.py @@ -0,0 +1,13 @@ +# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries +# +# SPDX-License-Identifier: MIT +"""Pin definitions for the MicroChip MCP2221""" +from adafruit_blinka.microcontroller.fake_mcp2221 import pin + +G0 = pin.G0 +G1 = pin.G1 +G2 = pin.G2 +G3 = pin.G3 + +SCL = pin.SCL +SDA = pin.SDA diff --git a/src/adafruit_blinka/microcontroller/fake_mcp2221/__init__.py b/src/adafruit_blinka/microcontroller/fake_mcp2221/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/src/adafruit_blinka/microcontroller/fake_mcp2221/analogio.py b/src/adafruit_blinka/microcontroller/fake_mcp2221/analogio.py new file mode 100644 index 00000000..a70d7fc4 --- /dev/null +++ b/src/adafruit_blinka/microcontroller/fake_mcp2221/analogio.py @@ -0,0 +1,57 @@ +# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries +# +# SPDX-License-Identifier: MIT +""" +`analogio` - Analog input and output control +================================================= +See `CircuitPython:analogio` in CircuitPython for more details. +* Author(s): Carter Nelson +""" + +from adafruit_blinka.microcontroller.fake_mcp2221.pin import Pin +from adafruit_blinka import ContextManaged + + +class AnalogIn(ContextManaged): + """Analog Input Class""" + + def __init__(self, pin): + self._pin = Pin(pin.id) + self._pin.init(mode=Pin.ADC) + + @property + def value(self): + """Read the ADC and return the value""" + return self._pin.value() + + # pylint: disable=no-self-use + @value.setter + def value(self, value): + # emulate what CircuitPython does + raise AttributeError("'AnalogIn' object has no attribute 'value'") + + # pylint: enable=no-self-use + + def deinit(self): + del self._pin + + +class AnalogOut(ContextManaged): + """Analog Output Class""" + + def __init__(self, pin): + self._pin = Pin(pin.id) + self._pin.init(mode=Pin.DAC) + + @property + def value(self): + """Return an error. This is output only.""" + # emulate what CircuitPython does + raise AttributeError("unreadable attribute") + + @value.setter + def value(self, value): + self._pin.value(value) + + def deinit(self): + del self._pin diff --git a/src/adafruit_blinka/microcontroller/fake_mcp2221/fake_mcp2221.py b/src/adafruit_blinka/microcontroller/fake_mcp2221/fake_mcp2221.py new file mode 100644 index 00000000..74a0713e --- /dev/null +++ b/src/adafruit_blinka/microcontroller/fake_mcp2221/fake_mcp2221.py @@ -0,0 +1,20 @@ +# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries +# +# SPDX-License-Identifier: MIT +"""Chip Definition for MCP2221""" + + +class MCP2221: + """MCP2221 Device Class Definition""" + + def __init__(self): + pass # This is a "fake" implementation + + def __del__(self): + # try to close the device before destroying the instance + return + + # pylint: enable=unused-argument + + +mcp2221 = MCP2221() diff --git a/src/adafruit_blinka/microcontroller/fake_mcp2221/i2c.py b/src/adafruit_blinka/microcontroller/fake_mcp2221/i2c.py new file mode 100644 index 00000000..d4b2c6f8 --- /dev/null +++ b/src/adafruit_blinka/microcontroller/fake_mcp2221/i2c.py @@ -0,0 +1,30 @@ +# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries +# +# SPDX-License-Identifier: MIT +"""I2C Class for MCP2221""" +import random +from .fake_mcp2221 import mcp2221 + + +class I2C: + """Custom I2C Class for MCP2221""" + + def __init__(self, *, frequency=100000): + self._mcp2221 = mcp2221 + self._freq = frequency + + @staticmethod + def scan(address_list=None): + """Mocks an I2C scan. + If address_list is not provided, this function returns a + list of 3 randomly generated I2C addresses from 0x0 to 0x79. + For a stimulus-driven test: If address_list is provided, + this function returns the provided address_list. + """ + if address_list is None: + # Generate a list of 3 randomly generated addresses from 0x0 to 0x79 + address_list = [] + for _ in range(3): + address_list.append(random.randint(0x0, 0x79)) + return address_list + return address_list diff --git a/src/adafruit_blinka/microcontroller/fake_mcp2221/pin.py b/src/adafruit_blinka/microcontroller/fake_mcp2221/pin.py new file mode 100644 index 00000000..f522a39e --- /dev/null +++ b/src/adafruit_blinka/microcontroller/fake_mcp2221/pin.py @@ -0,0 +1,95 @@ +# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries +# +# SPDX-License-Identifier: MIT +"""fake_mcp2221 pin names""" +import random + + +class Pin: + """A basic Pin class for use with a "fake" MCP2221.""" + + # pin modes + OUT = 0 + IN = 1 + ADC = 2 + DAC = 3 + # pin values + LOW = 0 + HIGH = 1 + + def __init__(self, pin_id=None): + self.id = pin_id + self._mode = None + self._prv_val = False + + def init(self, mode=IN, pull=None): + """Initialize the Pin""" + if self.id is None: + raise RuntimeError("Can not init a None type pin.") + if pull is not None: + raise NotImplementedError("Internal pullups and pulldowns not supported") + if mode in (Pin.IN, Pin.OUT): + # All pins can do GPIO + # mcp2221.gp_set_mode(self.id, mcp2221.GP_GPIO) + # mcp2221.gpio_set_direction(self.id, mode) + self._mode = mode + elif mode == Pin.ADC: + # ADC only available on these pins + if self.id not in (1, 2, 3): + raise ValueError("Pin does not have ADC capabilities") + # mcp2221.gp_set_mode(self.id, mcp2221.GP_ALT0) + # mcp2221.adc_configure() + elif mode == Pin.DAC: + # DAC only available on these pins + if self.id not in (2, 3): + raise ValueError("Pin does not have DAC capabilities") + # mcp2221.gp_set_mode(self.id, mcp2221.GP_ALT1) + # mcp2221.dac_configure() + else: + raise ValueError("Incorrect pin mode: {}".format(mode)) + self._mode = mode + + def value(self, val=None): + """Set or return the Pin Value""" + # Digital In / Out + if self._mode in (Pin.IN, Pin.OUT): + # digital read + if val is None: + # The returned value toggles between True and false + self._prv_val = not self._prv_val + return self._prv_val + # digital write + if val in (Pin.LOW, Pin.HIGH): + # We don't need to do anything here - no data is produced + return None + # nope + raise ValueError("Invalid value for pin.") + # Analog In + if self._mode == Pin.ADC: + if val is None: + # Returned value is between 0 and 65535 inclusive + # https://docs.circuitpython.org/en/latest/shared-bindings/analogio/index.html#analogio.AnalogIn.value + self._prv_val = random.randint(0, 65535) + return self._prv_val + # read only + raise AttributeError("'AnalogIn' object has no attribute 'value'") + # Analog Out + if self._mode == Pin.DAC: + if val is None: + # write only + raise AttributeError("unreadable attribute") + # We don't write to the DAC as this is a "fake" implementation + return None + raise RuntimeError( + "No action for mode {} with value {}".format(self._mode, val) + ) + + +# create pin instances for each pin +G0 = Pin(0) +G1 = Pin(1) +G2 = Pin(2) +G3 = Pin(3) + +SCL = Pin() +SDA = Pin() diff --git a/src/analogio.py b/src/analogio.py index ed1adfe8..c132ba38 100644 --- a/src/analogio.py +++ b/src/analogio.py @@ -9,7 +9,7 @@ * Author(s): Carter Nelson, Melissa LeBlanc-Williams """ - +import os import sys from adafruit_blinka.agnostic import detector @@ -17,8 +17,15 @@ # pylint: disable=ungrouped-imports,wrong-import-position,unused-import if detector.board.microchip_mcp2221: - from adafruit_blinka.microcontroller.mcp2221.analogio import AnalogIn - from adafruit_blinka.microcontroller.mcp2221.analogio import AnalogOut + if ( + "BLINKA_FORCECHIP" in os.environ + and os.environ["BLINKA_FORCEBOARD"] == "MICROCHIP_MCP2221" + ): + from adafruit_blinka.microcontroller.fake_mcp2221.analogio import AnalogIn + from adafruit_blinka.microcontroller.fake_mcp2221.analogio import AnalogOut + else: + from adafruit_blinka.microcontroller.mcp2221.analogio import AnalogIn + from adafruit_blinka.microcontroller.mcp2221.analogio import AnalogOut elif detector.board.greatfet_one: from adafruit_blinka.microcontroller.nxp_lpc4330.analogio import AnalogIn from adafruit_blinka.microcontroller.nxp_lpc4330.analogio import AnalogOut diff --git a/src/board.py b/src/board.py index 216c4d56..7a3bc969 100644 --- a/src/board.py +++ b/src/board.py @@ -17,7 +17,7 @@ import sys - +import os import adafruit_platformdetect.constants.boards as ap_board from adafruit_blinka.agnostic import board_id, detector @@ -224,7 +224,13 @@ from adafruit_blinka.board.binho_nova import * elif board_id == ap_board.MICROCHIP_MCP2221: - from adafruit_blinka.board.microchip_mcp2221 import * + if ( + "BLINKA_FORCECHIP" in os.environ + and os.environ["BLINKA_FORCEBOARD"] == "MICROCHIP_MCP2221" + ): + from adafruit_blinka.board.fake_microchip_mcp2221 import * + else: + from adafruit_blinka.board.microchip_mcp2221 import * elif board_id == ap_board.GREATFET_ONE: from adafruit_blinka.board.greatfet_one import * diff --git a/src/busio.py b/src/busio.py index 6912f0cc..0a3f5299 100644 --- a/src/busio.py +++ b/src/busio.py @@ -9,6 +9,7 @@ * Author(s): cefn """ +import os try: import threading @@ -50,8 +51,13 @@ def init(self, scl, sda, frequency): self._i2c = _I2C(frequency=frequency) return if detector.board.microchip_mcp2221: - from adafruit_blinka.microcontroller.mcp2221.i2c import I2C as _I2C - + if ( + "BLINKA_FORCECHIP" in os.environ + and os.environ["BLINKA_FORCEBOARD"] == "MICROCHIP_MCP2221" + ): + from adafruit_blinka.microcontroller.fake_mcp2221.i2c import I2C as _I2C + else: + from adafruit_blinka.microcontroller.mcp2221.i2c import I2C as _I2C self._i2c = _I2C(frequency=frequency) return if detector.board.greatfet_one: diff --git a/src/digitalio.py b/src/digitalio.py index 640a8cfc..7f57e315 100644 --- a/src/digitalio.py +++ b/src/digitalio.py @@ -9,7 +9,7 @@ * Author(s): cefn """ - +import os from adafruit_blinka.agnostic import board_id, detector # pylint: disable=ungrouped-imports,wrong-import-position,unused-wildcard-import,wildcard-import @@ -127,7 +127,13 @@ elif detector.board.greatfet_one: from adafruit_blinka.microcontroller.nxp_lpc4330.pin import Pin elif detector.board.microchip_mcp2221: - from adafruit_blinka.microcontroller.mcp2221.pin import Pin + if ( + "BLINKA_FORCECHIP" in os.environ + and os.environ["BLINKA_FORCEBOARD"] == "MICROCHIP_MCP2221" + ): + from adafruit_blinka.microcontroller.fake_mcp2221.pin import Pin + else: + from adafruit_blinka.microcontroller.mcp2221.pin import Pin elif detector.chip.RP2040_U2IF: from adafruit_blinka.microcontroller.rp2040_u2if.pin import Pin # MicroPython Chips diff --git a/src/microcontroller/__init__.py b/src/microcontroller/__init__.py index 2c51e3b0..5ab316c9 100644 --- a/src/microcontroller/__init__.py +++ b/src/microcontroller/__init__.py @@ -7,7 +7,7 @@ * Author(s): Melissa LeBlanc-Williams """ - +import os import sys import time @@ -123,7 +123,13 @@ def delay_us(delay): elif chip_id == ap_chip.LPC4330: from adafruit_blinka.microcontroller.nxp_lpc4330 import * elif chip_id == ap_chip.MCP2221: - from adafruit_blinka.microcontroller.mcp2221 import * + if ( + "BLINKA_FORCECHIP" in os.environ + and os.environ["BLINKA_FORCEBOARD"] == "MICROCHIP_MCP2221" + ): + from adafruit_blinka.microcontroller.fake_mcp2221 import * + else: + from adafruit_blinka.microcontroller.mcp2221 import * elif chip_id == ap_chip.MIPS24KC: from adafruit_blinka.microcontroller.atheros.ar9331 import * elif chip_id == ap_chip.MIPS24KEC: diff --git a/src/microcontroller/pin.py b/src/microcontroller/pin.py index c499364f..8d30cbb2 100644 --- a/src/microcontroller/pin.py +++ b/src/microcontroller/pin.py @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: MIT """Pins named after their chip name.""" - +import os import sys from adafruit_platformdetect.constants import chips as ap_chip, boards as ap_boards from adafruit_blinka.agnostic import board_id, chip_id @@ -97,7 +97,13 @@ elif chip_id == ap_chip.LPC4330: from adafruit_blinka.microcontroller.nxp_lpc4330.pin import * elif chip_id == ap_chip.MCP2221: - from adafruit_blinka.microcontroller.mcp2221.pin import * + if ( + "BLINKA_FORCECHIP" in os.environ + and os.environ["BLINKA_FORCEBOARD"] == "MICROCHIP_MCP2221" + ): + from adafruit_blinka.microcontroller.fake_mcp2221.pin import * + else: + from adafruit_blinka.microcontroller.mcp2221.pin import * elif chip_id == ap_chip.A10: from adafruit_blinka.microcontroller.allwinner.a20.pin import * elif chip_id == ap_chip.A20: