]> Repositories - Adafruit_Blinka-hackapet.git/commitdiff
Merge branch 'adafruit:main' into raxda-zero3
authorJens Oberender <1905126+burberius@users.noreply.github.com>
Tue, 28 May 2024 11:58:26 +0000 (13:58 +0200)
committerGitHub <noreply@github.com>
Tue, 28 May 2024 11:58:26 +0000 (13:58 +0200)
19 files changed:
src/adafruit_blinka/board/fake_microchip_mcp2221.py [deleted file]
src/adafruit_blinka/board/generic_agnostic_board.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/fake_mcp2221/fake_mcp2221.py [deleted file]
src/adafruit_blinka/microcontroller/fake_mcp2221/i2c.py [deleted file]
src/adafruit_blinka/microcontroller/fake_mcp2221/pin.py [deleted file]
src/adafruit_blinka/microcontroller/generic_agnostic_board/__init__.py [moved from src/adafruit_blinka/microcontroller/fake_mcp2221/__init__.py with 100% similarity]
src/adafruit_blinka/microcontroller/generic_agnostic_board/analogio.py [moved from src/adafruit_blinka/microcontroller/fake_mcp2221/analogio.py with 79% similarity]
src/adafruit_blinka/microcontroller/generic_agnostic_board/generic_agnostic_board.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/generic_agnostic_board/i2c.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/generic_agnostic_board/pin.py [new file with mode: 0644]
src/analogio.py
src/board.py
src/busio.py
src/digitalio.py
src/microcontroller/__init__.py
src/microcontroller/pin.py
tests/test_generic_agnostic_board_analogio.py [new file with mode: 0644]
tests/test_generic_agnostic_board_digitalio.py [new file with mode: 0644]
tests/test_generic_agnostic_board_i2c.py [new file with mode: 0644]

diff --git a/src/adafruit_blinka/board/fake_microchip_mcp2221.py b/src/adafruit_blinka/board/fake_microchip_mcp2221.py
deleted file mode 100644 (file)
index 6aae9d5..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-# 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/board/generic_agnostic_board.py b/src/adafruit_blinka/board/generic_agnostic_board.py
new file mode 100644 (file)
index 0000000..925e7ba
--- /dev/null
@@ -0,0 +1,38 @@
+# SPDX-FileCopyrightText: 2024 Brent Rubell for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+"""Pin definitions for a generic, os-agnostic, board."""
+from adafruit_blinka.microcontroller.generic_agnostic_board import pin
+
+# Digital pins
+Dx_INPUT_TRUE = pin.D0
+Dx_INPUT_FALSE = pin.D1
+Dx_INPUT_TRUE_PULL_UP = pin.D2
+Dx_INPUT_TRUE_PULL_DOWN = pin.D3
+Dx_OUTPUT = pin.D4
+Dx_INPUT_TOGGLE = pin.D7
+# Special "digital" pins
+NEOPIXEL = pin.D6
+
+
+# Analog pins
+Ax_INPUT_RAND_INT = pin.A0
+Ax_INPUT_FIXED_INT_PI = pin.A1
+Ax_INPUT_WAVE_SINE = pin.A2
+Ax_INPUT_WAVE_SAW = pin.A3
+Ax_OUTPUT = pin.A4
+
+# I2C pins
+SDA = pin.SDA
+SCL = pin.SCL
+
+# SPI pins
+SCLK = pin.SCLK
+SCK = pin.SCK
+MOSI = pin.MOSI
+MISO = pin.MISO
+CS = pin.D6
+
+# UART pins
+UART_TX = pin.UART_TX
+UART_RX = pin.UART_RX
diff --git a/src/adafruit_blinka/microcontroller/fake_mcp2221/fake_mcp2221.py b/src/adafruit_blinka/microcontroller/fake_mcp2221/fake_mcp2221.py
deleted file mode 100644 (file)
index 74a0713..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-# 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
deleted file mode 100644 (file)
index d4b2c6f..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# 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
deleted file mode 100644 (file)
index f522a39..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-# 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()
similarity index 79%
rename from src/adafruit_blinka/microcontroller/fake_mcp2221/analogio.py
rename to src/adafruit_blinka/microcontroller/generic_agnostic_board/analogio.py
index a70d7fc4a34913aa13dd89dc236246796130a8ab..cdaa18878fc34e242d090bb01db50d86237a1602 100644 (file)
@@ -1,4 +1,4 @@
-# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
+# SPDX-FileCopyrightText: 2024 Brent Rubell for Adafruit Industries
 #
 # SPDX-License-Identifier: MIT
 """
@@ -8,7 +8,7 @@ See `CircuitPython:analogio` in CircuitPython for more details.
 * Author(s): Carter Nelson
 """
 
-from adafruit_blinka.microcontroller.fake_mcp2221.pin import Pin
+from adafruit_blinka.microcontroller.generic_agnostic_board.pin import Pin
 from adafruit_blinka import ContextManaged
 
 
@@ -45,9 +45,8 @@ class AnalogOut(ContextManaged):
 
     @property
     def value(self):
-        """Return an error. This is output only."""
-        # emulate what CircuitPython does
-        raise AttributeError("unreadable attribute")
+        """Fake the output."""
+        return self._pin.value()
 
     @value.setter
     def value(self, value):
diff --git a/src/adafruit_blinka/microcontroller/generic_agnostic_board/generic_agnostic_board.py b/src/adafruit_blinka/microcontroller/generic_agnostic_board/generic_agnostic_board.py
new file mode 100644 (file)
index 0000000..40f204c
--- /dev/null
@@ -0,0 +1,20 @@
+# SPDX-FileCopyrightText: 2024 Brent Rubell for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+"""Chip Definition for a generic, os-agnostic, board."""
+
+
+class GENERIC_AGNOSTIC_BOARD:
+    """Generic Agnostic Board Device Class Definition"""
+
+    def __init__(self):
+        pass  # This implementation is for a generic board, no initialization is required
+
+    def __del__(self):
+        # try to close the device before destroying the instance
+        return
+
+    # pylint: enable=unused-argument
+
+
+generic_agnostic_board = GENERIC_AGNOSTIC_BOARD()
diff --git a/src/adafruit_blinka/microcontroller/generic_agnostic_board/i2c.py b/src/adafruit_blinka/microcontroller/generic_agnostic_board/i2c.py
new file mode 100644 (file)
index 0000000..475f414
--- /dev/null
@@ -0,0 +1,26 @@
+# SPDX-FileCopyrightText: 2024 Brent Rubell for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+"""I2C Class for Generic Agnostic Board"""
+from random import randint
+
+# from .generic_agnostic_board.pin import generic_agnostic_board
+
+
+class I2C:
+    """Custom I2C Class for a Generic Agnostic Board"""
+
+    def __init__(self, *, frequency=100000):
+        # self._generic_agnostic_board = generic_agnostic_board
+        self.freq = frequency
+
+    @staticmethod
+    def scan():
+        """Mocks an I2C scan and returns a list of 3 randomly generated
+        I2C addresses from 0x0 to 0x79.
+        """
+        # Generate a list of 3 randomly generated addresses from 0x0 to 0x79
+        address_list = []
+        for _ in range(3):
+            address_list.append(randint(0x0, 0x79))
+        return address_list
diff --git a/src/adafruit_blinka/microcontroller/generic_agnostic_board/pin.py b/src/adafruit_blinka/microcontroller/generic_agnostic_board/pin.py
new file mode 100644 (file)
index 0000000..47d9754
--- /dev/null
@@ -0,0 +1,222 @@
+# SPDX-FileCopyrightText: 2024 Melissa LeBlanc-Williams for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+"""generic_agnostic_board pin interface"""
+import random
+
+# Values for sine wave
+# (data points = 20, amplitude=100, frequency=1)
+sine_wave = [
+    0,
+    31,
+    59,
+    81,
+    95,
+    100,
+    95,
+    81,
+    59,
+    31,
+    0,
+    -31,
+    -59,
+    -81,
+    -95,
+    -100,
+    -95,
+    -81,
+    -59,
+    -31,
+]
+
+# Values for a sawtooth wave
+# (data points = 20, amplitude=100)
+sawtooth_wave = [
+    -100,
+    -80,
+    -60,
+    -40,
+    -20,
+    0,
+    20,
+    40,
+    60,
+    80,
+    -100,
+    -80,
+    -60,
+    -40,
+    -20,
+    0,
+    20,
+    40,
+    60,
+    80,
+]
+
+
+class Pin:
+    """A basic Pin class for use with generic_agnostic_board"""
+
+    # pin modes
+    OUT = 0
+    IN = 1
+    ADC = 2
+    DAC = 3
+    # pin values
+    LOW = 0
+    HIGH = 1
+    # pin pulls
+    PULL_NONE = 0
+    PULL_UP = 1
+    PULL_DOWN = 2
+
+    # pylint: disable=no-self-use
+
+    def return_toggle(self):
+        """Returns the pin's expected value, toggling between True and False"""
+        toggle_state = not self.previous_value
+        return toggle_state
+
+    def return_false(self):
+        """Returns the pin's expected value, False"""
+        return False
+
+    def return_true(self):
+        """Returns the pin's expected value, True"""
+        return True
+
+    def return_random_int(self):
+        """Returns a random integer"""
+        return random.randint(0, 65535)
+
+    def return_fixed_int_pi(self):
+        """Returns the first five digits of Pi, 31415"""
+        return 31415
+
+    def return_sine_wave(self):
+        """Returns the next value in the sine wave"""
+        if self._wave_idx is None:
+            self._wave_idx = 0
+        else:
+            self._wave_idx = (self._wave_idx + 1) % len(sine_wave)
+        return sine_wave[self._wave_idx]
+
+    def return_sawtooth_wave(self):
+        """Returns the next value in the sawtooth wave"""
+        if self._wave_idx is None:
+            self._wave_idx = 0
+        else:
+            self._wave_idx = (self._wave_idx + 1) % len(sawtooth_wave)
+        return sawtooth_wave[self._wave_idx]
+
+    def __init__(self, pin_id=None):
+        self.id = pin_id
+        self._mode = None
+        self._pull = None
+        self.previous_value = False
+        self.current_value = None
+        self._wave_idx = None
+
+        # mapping of pin definition names to expected behavior
+        self.pin_behavior = {
+            0: self.return_true,  # Dx_INPUT_TRUE
+            1: self.return_false,  # Dx_INPUT_FALSE
+            2: self.return_true,  # Dx_INPUT_TRUE_PULL_UP
+            3: self.return_true,  # Dx_INPUT_TRUE_PULL_DOWN
+            4: self.return_true,  # Dx_OUTPUT
+            7: self.return_random_int,  # Ax_INPUT_RAND_INT
+            8: self.return_fixed_int_pi,  # Ax_INPUT_FIXED_INT_PI
+            9: self.return_sine_wave,  # Ax_INPUT_WAVE_SINE
+            10: self.return_sawtooth_wave,  # Ax_INPUT_WAVE_SAW
+            11: self.return_toggle,  # Dx_INPUT_TOGGLE
+        }
+
+    def init(self, mode=IN, pull=None):
+        """Initialize the Pin"""
+        if self.id is None:
+            raise RuntimeError("Can not init a None type pin.")
+        pull = Pin.PULL_NONE if pull is None else pull
+        self._pull = pull
+        self._mode = mode
+
+    def write(self, new_value):
+        """Saves the new_value to the pin for subsequent calls to .value"""
+        self.previous_value = self.current_value
+        self.current_value = new_value
+
+    def read(self):
+        """Returns the pin's expected value."""
+        self.previous_value = self.current_value
+        # perform a lookup on the pin_behavior dict to get the value
+        self.current_value = self.pin_behavior.get(self.id)()
+
+        # is pin a pull up and pin is LOW?
+        if self._pull == Pin.PULL_UP and self.current_value is False:
+            self.current_value = False
+        # is pin a pull down and pin is HIGH?
+        if self._pull == Pin.PULL_DOWN and self.current_value is True:
+            self.current_value = False
+        return self.current_value
+
+    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:
+                return self.read()
+            # digital write
+            if val in (Pin.LOW, Pin.HIGH):
+                return self.write(val)
+            # nope
+            raise ValueError("Invalid value for pin.")
+        # Analog In
+        if self._mode == Pin.ADC:
+            if val is None:
+                return self.read()
+            # read only
+            raise AttributeError("'AnalogIn' object has no attribute 'value'")
+        # Analog Out
+        if self._mode == Pin.DAC:
+            if val is None:
+                self.previous_value = self.current_value
+                return self.current_value
+            self.write(val)
+            return None
+        raise RuntimeError(
+            "No action for mode {} with value {}".format(self._mode, val)
+        )
+
+
+# create pin instances for each pin
+D0 = Pin(0)
+D1 = Pin(1)
+D2 = Pin(2)
+D3 = Pin(3)
+D4 = Pin(4)
+# Special "digital" pins
+D6 = Pin(6)
+# Analog pins
+A0 = Pin(7)
+A1 = Pin(8)
+A2 = Pin(9)
+A3 = Pin(10)
+A4 = Pin(12)
+
+D7 = Pin(11)
+
+# I2C pins
+SDA = Pin()
+SCL = Pin()
+
+# SPI pins
+SCLK = Pin()
+SCK = Pin()
+MOSI = Pin()
+MISO = Pin()
+CS = Pin()
+
+# UART pins
+UART_TX = Pin()
+UART_RX = Pin()
index c132ba38e19770235f135c966b3154cb8bbfb37f..f1b9a55986fe9370e144230abd11ee4430fa360e 100644 (file)
@@ -17,15 +17,8 @@ from adafruit_blinka.agnostic import detector
 # pylint: disable=ungrouped-imports,wrong-import-position,unused-import
 
 if detector.board.microchip_mcp2221:
-    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
+    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
@@ -70,5 +63,13 @@ elif detector.board.itsybitsy_u2if:
     from adafruit_blinka.microcontroller.rp2040_u2if.analogio import (
         AnalogIn_ItsyBitsy as AnalogIn,
     )
+elif (
+    "BLINKA_FORCECHIP" in os.environ
+    and os.environ["BLINKA_FORCEBOARD"] == "GENERIC_AGNOSTIC_BOARD"
+):
+    from adafruit_blinka.microcontroller.generic_agnostic_board.analogio import AnalogIn
+    from adafruit_blinka.microcontroller.generic_agnostic_board.analogio import (
+        AnalogOut,
+    )
 else:
     raise NotImplementedError("analogio not supported for this board.")
index 46e9c101f8b484aa05be7c7e50bc80a930d4fea7..085743a693b60d263f25ca785036602923b289b4 100644 (file)
@@ -224,13 +224,7 @@ elif board_id == ap_board.BINHO_NOVA:
     from adafruit_blinka.board.binho_nova import *
 
 elif board_id == ap_board.MICROCHIP_MCP2221:
-    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 *
+    from adafruit_blinka.board.microchip_mcp2221 import *
 
 elif board_id == ap_board.GREATFET_ONE:
     from adafruit_blinka.board.greatfet_one import *
@@ -397,6 +391,12 @@ elif board_id == ap_board.LICHEEPI_4A:
 elif board_id == ap_board.MILKV_DUO:
     from adafruit_blinka.board.milkv_duo import *
 
+elif (
+    "BLINKA_FORCECHIP" in os.environ
+    and os.environ["BLINKA_FORCEBOARD"] == "GENERIC_AGNOSTIC_BOARD"
+):
+    from adafruit_blinka.board.generic_agnostic_board import *
+
 elif "sphinx" in sys.modules:
     pass
 
index 0a3f52991820fb23edf7188664ac73ade7610946..70ead8822875364f40ebb40bdf109db15ad05b25 100644 (file)
@@ -51,15 +51,22 @@ class I2C(Lockable):
             self._i2c = _I2C(frequency=frequency)
             return
         if detector.board.microchip_mcp2221:
-            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
+            from adafruit_blinka.microcontroller.mcp2221.i2c import I2C as _I2C
+
+            self._i2c = _I2C(frequency=frequency)
+            return
+
+        if (
+            "BLINKA_FORCECHIP" in os.environ
+            and os.environ["BLINKA_FORCEBOARD"] == "GENERIC_AGNOSTIC_BOARD"
+        ):
+            from adafruit_blinka.microcontroller.generic_agnostic_board.i2c import (
+                I2C as _I2C,
+            )
+
             self._i2c = _I2C(frequency=frequency)
             return
+
         if detector.board.greatfet_one:
             from adafruit_blinka.microcontroller.nxp_lpc4330.i2c import I2C as _I2C
 
index 7f57e31500daeef16c7f4ca2889b0cf7a7685832..ecdc98e9003d22f6ab1d3468d94562c8aac5e9df 100644 (file)
@@ -127,13 +127,7 @@ elif detector.board.binho_nova:
 elif detector.board.greatfet_one:
     from adafruit_blinka.microcontroller.nxp_lpc4330.pin import Pin
 elif detector.board.microchip_mcp2221:
-    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
+    from adafruit_blinka.microcontroller.mcp2221.pin import Pin
 elif detector.chip.RP2040_U2IF:
     from adafruit_blinka.microcontroller.rp2040_u2if.pin import Pin
 # MicroPython Chips
@@ -143,6 +137,11 @@ elif detector.chip.RP2040:
     from machine import Pin
 elif detector.chip.CV1800B:
     from adafruit_blinka.microcontroller.cv1800b.pin import Pin
+elif (
+    "BLINKA_FORCECHIP" in os.environ
+    and os.environ["BLINKA_FORCEBOARD"] == "GENERIC_AGNOSTIC_BOARD"
+):
+    from adafruit_blinka.microcontroller.generic_agnostic_board.pin import Pin
 
 from adafruit_blinka import Enum, ContextManaged
 
index 5ab316c928d07ad6b38980ad815a600d28071d4e..394d2746a3cd859ffee705ec82685bdfc41bcd02 100644 (file)
@@ -123,13 +123,7 @@ elif chip_id == ap_chip.BINHO:
 elif chip_id == ap_chip.LPC4330:
     from adafruit_blinka.microcontroller.nxp_lpc4330 import *
 elif chip_id == ap_chip.MCP2221:
-    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 *
+    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:
@@ -156,6 +150,11 @@ elif chip_id == ap_chip.TH1520:
     from adafruit_blinka.microcontroller.thead.th1520 import *
 elif chip_id == ap_chip.GENERIC_X86:
     print("WARNING: GENERIC_X86 is not fully supported. Some features may not work.")
+elif (
+    "BLINKA_FORCECHIP" in os.environ
+    and os.environ["BLINKA_FORCEBOARD"] == "GENERIC_AGNOSTIC_BOARD"
+):
+    from adafruit_blinka.microcontroller.generic_agnostic_board import *
 elif chip_id is None:
     print(
         "WARNING: chip_id == None is not fully supported. Some features may not work."
index 8d30cbb2c80c0ed3eb4bb3ab9b5fb91bf3e245be..0d083a0ad3a9b6b557e745f953c1abb7e4babdc5 100644 (file)
@@ -97,13 +97,7 @@ elif chip_id == ap_chip.BINHO:
 elif chip_id == ap_chip.LPC4330:
     from adafruit_blinka.microcontroller.nxp_lpc4330.pin import *
 elif chip_id == ap_chip.MCP2221:
-    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 *
+    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:
@@ -155,6 +149,11 @@ elif "sphinx" in sys.modules:
 elif chip_id == ap_chip.GENERIC_X86:
     print("WARNING: GENERIC_X86 is not fully supported. Some features may not work.")
     from adafruit_blinka.microcontroller.generic_micropython import Pin
+elif (
+    "BLINKA_FORCECHIP" in os.environ
+    and os.environ["BLINKA_FORCEBOARD"] == "GENERIC_AGNOSTIC_BOARD"
+):
+    from adafruit_blinka.microcontroller.generic_agnostic_board.pin import *
 elif chip_id is None:
     print(
         "WARNING: chip_id == None is not fully supported. Some features may not work."
diff --git a/tests/test_generic_agnostic_board_analogio.py b/tests/test_generic_agnostic_board_analogio.py
new file mode 100644 (file)
index 0000000..3658380
--- /dev/null
@@ -0,0 +1,126 @@
+# SPDX-FileCopyrightText: 2024 Brent Rubell for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+import pytest  # pylint: disable=unused-import
+import board
+import analogio
+
+
+# Analog Outputs
+def test_Ax_OUTPUT():
+    """Test analog output pin functionality."""
+    assert board.board_id == "GENERIC_AGNOSTIC_BOARD"
+    pin_out = analogio.AnalogOut(board.Ax_OUTPUT)
+
+    # Test boundaries of setting the value and reading it back
+    pin_out.value = 0
+    assert pin_out.value == 0
+    pin_out.value = 65535
+    assert pin_out.value == 65535
+
+    pin_out.deinit()
+
+
+# Analog Inputs
+
+# Values for sine wave
+# (data points = 20, amplitude=100, frequency=1)
+sine_wave = [
+    0,
+    31,
+    59,
+    81,
+    95,
+    100,
+    95,
+    81,
+    59,
+    31,
+    0,
+    -31,
+    -59,
+    -81,
+    -95,
+    -100,
+    -95,
+    -81,
+    -59,
+    -31,
+]
+
+# Values for a sawtooth wave
+# (data points = 20, amplitude=100)
+sawtooth_wave = [
+    -100,
+    -80,
+    -60,
+    -40,
+    -20,
+    0,
+    20,
+    40,
+    60,
+    80,
+    -100,
+    -80,
+    -60,
+    -40,
+    -20,
+    0,
+    20,
+    40,
+    60,
+    80,
+]
+
+
+def test_Ax_INPUT_RAND_INT():
+    """Test random integer from pin Ax_INPUT_RAND_INT"""
+    assert board.board_id == "GENERIC_AGNOSTIC_BOARD"
+    pin_random = analogio.AnalogIn(board.Ax_INPUT_RAND_INT)
+
+    assert isinstance(pin_random.value, int)
+
+    pin_random.deinit()
+
+
+def test_Ax_INPUT_FIXED_INT_PI():
+    """Test fixed integer from pin Ax_INPUT_FIXED_INT_PI"""
+    assert board.board_id == "GENERIC_AGNOSTIC_BOARD"
+    pin_pi = analogio.AnalogIn(board.Ax_INPUT_FIXED_INT_PI)
+
+    assert pin_pi.value == 31415
+
+    pin_pi.deinit()
+
+
+def test_Ax_INPUT_WAVE_SINE():
+    """Test sine wave from pin Ax_INPUT_WAVE_SINE"""
+    assert board.board_id == "GENERIC_AGNOSTIC_BOARD"
+    pin_sine_wave = analogio.AnalogIn(board.Ax_INPUT_WAVE_SINE)
+
+    # Run through the sine wave once
+    for expected_value in sine_wave:
+        assert pin_sine_wave.value == expected_value
+
+    # Run through the sine wave again to ensure it loops back correctly
+    for expected_value in sine_wave:
+        assert pin_sine_wave.value == expected_value
+
+    pin_sine_wave.deinit()
+
+
+def test_Ax_INPUT_WAVE_SAW():
+    """Test sawtooth wave from pin Ax_INPUT_WAVE_SAW"""
+    assert board.board_id == "GENERIC_AGNOSTIC_BOARD"
+    pin_saw_wave = analogio.AnalogIn(board.Ax_INPUT_WAVE_SAW)
+
+    # Run through the sine wave once
+    for expected_value in sawtooth_wave:
+        assert pin_saw_wave.value == expected_value
+
+    # Run through the sine wave again to ensure it loops back correctly
+    for expected_value in sawtooth_wave:
+        assert pin_saw_wave.value == expected_value
+
+    pin_saw_wave.deinit()
diff --git a/tests/test_generic_agnostic_board_digitalio.py b/tests/test_generic_agnostic_board_digitalio.py
new file mode 100644 (file)
index 0000000..a9ebb32
--- /dev/null
@@ -0,0 +1,80 @@
+# SPDX-FileCopyrightText: 2024 Brent Rubell for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+import pytest  # pylint: disable=unused-import
+import board
+import digitalio
+
+# Digital output pins
+
+
+def test_Dx_OUTPUT_TRUE():
+    """Test digital output pin functionality."""
+    assert board.board_id == "GENERIC_AGNOSTIC_BOARD"
+    pin_out = digitalio.DigitalInOut(board.Dx_OUTPUT)
+    pin_out.direction = digitalio.Direction.OUTPUT
+    # Test setting the value and reading it back
+    pin_out.value = True
+    assert pin_out.value is True
+    pin_out.value = False
+    assert pin_out.value is True
+    pin_out.deinit()
+
+
+# Digital Input Pins
+
+
+def test_Dx_INPUT_TRUE():
+    """Test digital input pin Dx_INPUT_TRUE."""
+    assert board.board_id == "GENERIC_AGNOSTIC_BOARD"
+    pin_true = digitalio.DigitalInOut(board.Dx_INPUT_TRUE)
+    pin_true.direction = digitalio.Direction.INPUT
+    assert pin_true.value is True
+    assert pin_true.value is True  # Test subsequent call does not change value
+    pin_true.deinit()
+
+
+def test_Dx_INPUT_TRUE_PULL_DOWN():
+    """Test digital input pin Dx_INPUT_TRUE w/pull down."""
+    assert board.board_id == "GENERIC_AGNOSTIC_BOARD"
+    pin_true = digitalio.DigitalInOut(board.Dx_INPUT_TRUE)
+    pin_true.direction = digitalio.Direction.INPUT
+    assert pin_true.value is True
+    assert pin_true.value is True  # Test subsequent call does not change value
+    pin_true.pull = digitalio.Pull.DOWN
+    assert pin_true.value is False
+    pin_true.deinit()
+
+
+def test_Dx_INPUT_FALSE_PULL_UP():
+    """Test digital input pin Dx_INPUT_FALSE w/pull up."""
+    assert board.board_id == "GENERIC_AGNOSTIC_BOARD"
+    pin_false = digitalio.DigitalInOut(board.Dx_INPUT_FALSE)
+    pin_false.direction = digitalio.Direction.INPUT
+    assert pin_false.value is False
+    assert pin_false.value is False  # Test subsequent call does not change value
+    pin_false.pull = digitalio.Pull.UP
+    assert pin_false.value is False
+    pin_false.deinit()
+
+
+def test_Dx_INPUT_FALSE():
+    """Test digital input pin Dx_INPUT_FALSE"""
+    assert board.board_id == "GENERIC_AGNOSTIC_BOARD"
+    pin_false = digitalio.DigitalInOut(board.Dx_INPUT_FALSE)
+    pin_false.direction = digitalio.Direction.INPUT
+    assert pin_false.value is False
+    assert pin_false.value is False  # Test subsequent call does not change value
+    pin_false.deinit()
+
+
+def test_Dx_INPUT_TOGGLE():
+    """Test digital input pin Dx_INPUT_TOGGLE"""
+    assert board.board_id == "GENERIC_AGNOSTIC_BOARD"
+    pin_toggle = digitalio.DigitalInOut(board.Dx_INPUT_TOGGLE)
+    pin_toggle.direction = digitalio.Direction.INPUT
+    assert pin_toggle.value is True
+    assert (
+        pin_toggle.value is False
+    )  # Test subsequent call does change value for this pin
+    pin_toggle.deinit()
diff --git a/tests/test_generic_agnostic_board_i2c.py b/tests/test_generic_agnostic_board_i2c.py
new file mode 100644 (file)
index 0000000..12136bd
--- /dev/null
@@ -0,0 +1,18 @@
+# SPDX-FileCopyrightText: 2024 Brent Rubell for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+import pytest  # pylint: disable=unused-import
+import busio
+from board import SCL, SDA
+
+
+def test_i2c_scan_random():
+    i2c = busio.I2C(SCL, SDA)
+    i2c.try_lock()
+    addr_list = i2c.scan()
+    assert len(addr_list) == 3
+    for addr in addr_list:
+        assert addr >= 0x0
+        assert addr <= 0x79
+    i2c.unlock()
+    i2c.deinit()