]> Repositories - Adafruit_Blinka-hackapet.git/commitdiff
Added support for Siemens Simatic IOT2050 Basic/Advanced
authorMartin Schnur <schnurma@gmx.de>
Wed, 21 Sep 2022 17:28:18 +0000 (19:28 +0200)
committerMartin Schnur <schnurma@gmx.de>
Wed, 21 Sep 2022 17:28:18 +0000 (19:28 +0200)
Added support for GPIO, AIO, I2C, SPI, UART, PWM, NeoPixels

15 files changed:
src/adafruit_blinka/board/siemens/__init__.py [new file with mode: 0644]
src/adafruit_blinka/board/siemens/siemens_iot2050.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/am65xx/__init__.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/am65xx/analogio.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/am65xx/i2c.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/am65xx/pin.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/am65xx/pwmout.py [new file with mode: 0644]
src/adafruit_blinka/microcontroller/am65xx/spi.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
src/pwmio.py

diff --git a/src/adafruit_blinka/board/siemens/__init__.py b/src/adafruit_blinka/board/siemens/__init__.py
new file mode 100644 (file)
index 0000000..83d86e7
--- /dev/null
@@ -0,0 +1,4 @@
+# SPDX-FileCopyrightText: 2022 Martin Schnur for Siemens AG
+#
+# SPDX-License-Identifier: MIT
+"""Boards definition from Siemens AG"""
diff --git a/src/adafruit_blinka/board/siemens/siemens_iot2050.py b/src/adafruit_blinka/board/siemens/siemens_iot2050.py
new file mode 100644 (file)
index 0000000..80a288d
--- /dev/null
@@ -0,0 +1,60 @@
+# SPDX-FileCopyrightText: 2022 Martin Schnur for Siemens AG
+#
+# SPDX-License-Identifier: MIT
+"""Pin definitions for the Siemens Simatic IOT2050 Basic/Advanced."""
+# Output Pins are the same as Arduino Uno R3,Overall 31 + 1 Pins !
+
+from adafruit_blinka.microcontroller.am65xx import pin
+
+# Digital Pins
+D0 = pin.D0
+D1 = pin.D1
+D2 = pin.D2
+D3 = pin.D3
+D4 = pin.D4
+D5 = pin.D5
+D6 = pin.D6
+D7 = pin.D7
+D8 = pin.D8
+D9 = pin.D9
+D10 = pin.D10
+D11 = pin.D11
+D12 = pin.D12
+D13 = pin.D13
+D14 = pin.D14
+D15 = pin.D15
+D16 = pin.D16
+D17 = pin.D17
+D18 = pin.D18
+D19 = pin.D19
+
+# Analog Pins
+A0 = pin.A0
+A1 = pin.A1
+A2 = pin.A2
+A3 = pin.A3
+A4 = pin.A4
+A5 = pin.A5
+
+# I2C allocation
+SCL = pin.I2C_SCL
+SDA = pin.I2C_SDA
+
+# SPI allocation
+SCLK = pin.SPIO_SCLK
+MOSI = pin.SPIO_MOSI
+MISO = pin.SPIO_MISO
+SS = pin.SPIO_SS
+
+# UART allocation
+UART_TX = pin.UART_TX
+UART_RX = pin.UART_RX
+
+
+# PWM allocation
+PWM_4 = pin.PWM_4
+PWM_5 = pin.PWM_5
+PWM_6 = pin.PWM_6
+PWM_7 = pin.PWM_7
+PWM_8 = pin.PWM_8
+PWM_9 = pin.PWM_9
diff --git a/src/adafruit_blinka/microcontroller/am65xx/__init__.py b/src/adafruit_blinka/microcontroller/am65xx/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/src/adafruit_blinka/microcontroller/am65xx/analogio.py b/src/adafruit_blinka/microcontroller/am65xx/analogio.py
new file mode 100644 (file)
index 0000000..aab050e
--- /dev/null
@@ -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): Martin Schnur
+"""
+
+from adafruit_blinka.microcontroller.am65xx.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("AM65xx doesn't have an DAC! No Analog Output possible!")
+
+    @value.setter
+    def value(self, value):
+        self._pin.value(value)
+
+    def deinit(self):
+        del self._pin
diff --git a/src/adafruit_blinka/microcontroller/am65xx/i2c.py b/src/adafruit_blinka/microcontroller/am65xx/i2c.py
new file mode 100644 (file)
index 0000000..f4dbd25
--- /dev/null
@@ -0,0 +1,94 @@
+# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+"""Generic Linux I2C class using PureIO's smbus class"""
+from Adafruit_PureIO import smbus
+
+
+class I2C:
+    """I2C class"""
+
+    MASTER = 0
+    SLAVE = 1
+    _baudrate = None
+    _mode = None
+    _i2c_bus = None
+
+    # pylint: disable=unused-argument
+    def __init__(self, bus_num, mode=MASTER, baudrate=None):
+        if mode != self.MASTER:
+            raise NotImplementedError("Only I2C Master supported!")
+        _mode = self.MASTER
+
+        # if baudrate != None:
+        #    print("I2C frequency is not settable in python, ignoring!")
+
+        try:
+            self._i2c_bus = smbus.SMBus(bus_num)
+        except FileNotFoundError:
+            raise RuntimeError(
+                "I2C Bus #%d not found, check if enabled in config!" % bus_num
+            ) from RuntimeError
+
+    # pylint: enable=unused-argument
+
+    def scan(self):
+        """Try to read a byte from each address, if you get an OSError
+        it means the device isnt there"""
+        found = []
+        for addr in range(0, 0x80):
+            try:
+                self._i2c_bus.read_byte(addr)
+            except OSError:
+                continue
+            found.append(addr)
+        return found
+
+    # pylint: disable=unused-argument
+    def writeto(self, address, buffer, *, start=0, end=None, stop=True):
+        """Write data from the buffer to an address"""
+        if end is None:
+            end = len(buffer)
+        self._i2c_bus.write_bytes(address, buffer[start:end])
+
+    def readfrom_into(self, address, buffer, *, start=0, end=None, stop=True):
+        """Read data from an address and into the buffer"""
+        if end is None:
+            end = len(buffer)
+
+        readin = self._i2c_bus.read_bytes(address, end - start)
+        for i in range(end - start):
+            buffer[i + start] = readin[i]
+
+    # pylint: enable=unused-argument
+
+    def writeto_then_readfrom(
+        self,
+        address,
+        buffer_out,
+        buffer_in,
+        *,
+        out_start=0,
+        out_end=None,
+        in_start=0,
+        in_end=None,
+        stop=False
+    ):
+        """Write data from buffer_out to an address and then
+        read data from an address and into buffer_in
+        """
+        if out_end is None:
+            out_end = len(buffer_out)
+        if in_end is None:
+            in_end = len(buffer_in)
+        if stop:
+            # To generate a stop in linux, do in two transactions
+            self.writeto(address, buffer_out, start=out_start, end=out_end, stop=True)
+            self.readfrom_into(address, buffer_in, start=in_start, end=in_end)
+        else:
+            # To generate without a stop, do in one block transaction
+            readin = self._i2c_bus.read_i2c_block_data(
+                address, buffer_out[out_start:out_end], in_end - in_start
+            )
+            for i in range(in_end - in_start):
+                buffer_in[i + in_start] = readin[i]
diff --git a/src/adafruit_blinka/microcontroller/am65xx/pin.py b/src/adafruit_blinka/microcontroller/am65xx/pin.py
new file mode 100644 (file)
index 0000000..7040e25
--- /dev/null
@@ -0,0 +1,199 @@
+# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+# SPDX-FileCopyrightText: 2022 Martin Schnur for Siemens AG
+#
+# SPDX-License-Identifier: MIT
+"""TI AM65XX pin names"""
+
+import mraa
+
+
+class Pin:
+    """Pins don't exist in CPython so...lets make our own!"""
+
+    # pin modes
+    IN = 0
+    OUT = 1
+    ADC = 2
+    DAC = 3
+    PWM = 4
+    # pin values
+    LOW = 0
+    HIGH = 1
+    # pin pulls
+    PULL_NONE = 0
+    PULL_UP = 1
+    PULL_DOWN = 2
+
+    id = None
+    _value = LOW
+    _mode = IN
+
+    def __init__(self, pin_id=None):
+        self.id = pin_id
+        self._mode = None
+        self._pull = None
+        self._pin = None
+
+    def __repr__(self):
+        return str(self.id)
+
+    def __eq__(self, other):
+        return self.id == other
+
+    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 mode is not None:
+            if mode == self.IN:
+                self._mode = self.IN
+                mypin = mraa.Gpio(self.id)
+                mypin.dir(mraa.DIR_IN)
+            elif mode == self.OUT:
+                self._mode = self.OUT
+                mypin = mraa.Gpio(self.id)
+                mypin.dir(mraa.DIR_OUT)
+            elif mode in (self.ADC, self.DAC):
+                # ADC (DAC not available) only available on Pin 0-5 (X12 Pin 1-6)
+                if self.id not in (0, 1, 2, 3, 4, 5):
+                    raise ValueError("Pin does not have ADC capabilities")
+                self._pin = mraa.Aio(self.id)
+            elif mode == self.PWM:
+                # PWM only available on Pin 4-9 (X10 Pin 1-2, X11 Pin 5-8)
+                if self.id not in (4, 5, 6, 7, 8, 9):
+                    raise ValueError("Pin does not have PWM capabilities")
+                return
+            else:
+                raise RuntimeError("Invalid mode for pin: %s" % self.id)
+            self._mode = mode
+        if pull is not None:
+            if self._mode != self.IN:
+                raise RuntimeError("Cannot set pull resistor on output")
+            if pull == self.PULL_UP:
+                mypin = mraa.Gpio(self.id)
+                mypin.dir(mraa.DIR_IN)
+            elif pull == self.PULL_DOWN:
+                mypin = mraa.Gpio(self.id)
+                mypin.dir(mraa.DIR_IN)
+            else:
+                raise RuntimeError("Invalid pull for pin: %s" % self.id)
+
+    def value(self, val=None):
+        """Set or return the Pin Value"""
+        # Digital In / Out
+        if self._mode in (Pin.IN, Pin.OUT):
+            if val is not None:
+                if val == self.LOW:
+                    self._value = val
+                    mypin = mraa.Gpio(self.id)
+                    mypin.write(0)
+                elif val == self.HIGH:
+                    self._value = val
+                    mypin = mraa.Gpio(self.id)
+                    mypin.write(1)
+                else:
+                    raise RuntimeError("Invalid value for pin")
+                return None
+            return mraa.Gpio.read(mraa.Gpio(self.id))
+        # Analog In
+        if self._mode == Pin.ADC:
+            if val is None:
+                # Read ADC here
+                mypin = mraa.Aio(self.id)
+                mypin.read()
+                return mypin.read()
+            # 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")
+            # Set DAC here
+            mypin = mraa.Aio(self.id)
+            mypin.setBit(val)"""
+            raise AttributeError(
+                "AM65xx doesn't have an DAC! No Analog Output possible!"
+            )
+        raise RuntimeError(
+            "No action for mode {} with value {}".format(self._mode, val)
+        )
+
+
+# Digital Pins (GPIO 0-19)
+D0 = Pin(0)
+D1 = Pin(1)
+D2 = Pin(2)
+D3 = Pin(3)
+D4 = Pin(4)
+D5 = Pin(5)
+D6 = Pin(6)
+D7 = Pin(7)
+D8 = Pin(8)
+D9 = Pin(9)
+D10 = Pin(10)
+D11 = Pin(11)
+D12 = Pin(12)
+D13 = Pin(13)
+D14 = Pin(14)
+D15 = Pin(15)
+D16 = Pin(16)
+D17 = Pin(17)
+D18 = Pin(18)
+D19 = Pin(19)
+
+# Analog Pins (AIO 0-5, only ADC!)
+A0 = Pin(0)
+A1 = Pin(1)
+A2 = Pin(2)
+A3 = Pin(3)
+A4 = Pin(4)
+A5 = Pin(5)
+
+# I2C allocation
+I2C_SCL = "SCL"
+I2C_SDA = "SDA"
+
+# SPI allocation
+SPIO_SCLK = D13
+SPIO_MISO = D12
+SPIO_MOSI = D11
+SPIO_SS = D10
+
+# UART allocation
+UART_TX = "TX"
+UART_RX = "RX"
+
+# pwmOuts (GPIO 4-9)
+PWM_4 = D4
+PWM_5 = D5
+PWM_6 = D6
+PWM_7 = D7
+PWM_8 = D8
+PWM_9 = D9
+
+# I2C
+# ordered as sclID, sdaID
+# i2c-4 (/dev/i2c-4) -> X10 Pin9, Pin10 (SDA, SCL)
+i2cPorts = ((4, I2C_SCL, I2C_SDA),)
+
+# SPI
+# ordered as spiId, sckId, mosiID, misoID
+spiPorts = ((0, SPIO_SCLK, SPIO_MOSI, SPIO_MISO),)
+
+# UART
+# use pySerial = dev/ttyS1
+# ordered as uartID, txID, rxID
+uartPorts = ((0, UART_TX, UART_RX),)
+
+# PWM
+pwmOuts = (
+    ((0, 0), PWM_4),
+    ((0, 1), PWM_5),
+    ((2, 0), PWM_6),
+    ((2, 1), PWM_7),
+    ((4, 0), PWM_8),
+    ((4, 1), PWM_9),
+)
diff --git a/src/adafruit_blinka/microcontroller/am65xx/pwmout.py b/src/adafruit_blinka/microcontroller/am65xx/pwmout.py
new file mode 100644 (file)
index 0000000..264f16d
--- /dev/null
@@ -0,0 +1,177 @@
+# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+# SPDX-FileCopyrightText: 2022 Martin Schnur for Siemens AG
+#
+# SPDX-License-Identifier: MIT
+"""Custom PWMOut Wrapper for am65xx"""
+"""
+Much code from https://github.com/vsergeev/python-periphery/blob/master/periphery/pwm.py
+Copyright (c) 2015-2016 vsergeev / Ivan (Vanya) A. Sergeev
+License: MIT
+"""
+
+import mraa
+from adafruit_blinka.microcontroller.am65xx.pin import Pin
+
+
+# pylint: disable=unnecessary-pass
+class PWMError(IOError):
+    """Base class for PWM errors."""
+
+    pass
+
+
+# pylint: enable=unnecessary-pass
+
+
+class PWMOut:
+    """Pulse Width Modulation Output Class"""
+
+    def __init__(self, pin, *, frequency=500, duty_cycle=0, variable_frequency=False):
+        self._frequency = None
+        self._duty_cycle = None
+        self._pwmpin = None
+        self._period = 0
+        self._enabled = False
+        self._varfreq = variable_frequency
+        # check pin for PWM support
+        self._pin = Pin(pin.id)
+        self._pin.init(mode=Pin.PWM)
+        # initialize pin
+        self._open(pin, duty_cycle, frequency, variable_frequency)
+
+    def __del__(self):
+        self.deinit()
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, t, value, traceback):
+        self.deinit()
+
+    def _open(self, pin, duty=0, freq=500, variable_frequency=False):
+        self._pwmpin = mraa.Pwm(pin.id)
+        self.frequency = freq
+        self.enabled = True
+        self._varfreq = variable_frequency
+        self.duty_cycle = duty
+
+    def deinit(self):
+        """Deinit the PWM."""
+        if self._pwmpin is not None:
+            self._pwmpin.enable(False)
+            self._pwmpin = None
+
+    def _is_deinited(self):
+        if self._pwmpin is None:
+            raise ValueError(
+                "Object has been deinitialize and can no longer "
+                "be used. Create a new object."
+            )
+
+    @property
+    def period(self):
+        """Get or set the PWM's output period in seconds.
+
+        Raises:
+            PWMError: if an I/O or OS error occurs.
+            TypeError: if value type is not int or float.
+
+        :type: int, float
+        """
+        return 1.0 / self.frequency
+
+    @period.setter
+    def period(self, period):
+        if not isinstance(period, (int, float)):
+            raise TypeError("Invalid period type, should be int or float.")
+
+        self.frequency = 1.0 / period
+
+    @property
+    def duty_cycle(self):
+        """Get or set the PWM's output duty cycle which is the fraction of
+        each pulse which is high. 16-bit
+
+        Raises:
+            PWMError: if an I/O or OS error occurs.
+            TypeError: if value type is not int or float.
+            ValueError: if value is out of bounds of 0.0 to 1.0.
+
+        :type: int, float
+        """
+        return int(self._duty_cycle * 65535)
+
+    @duty_cycle.setter
+    def duty_cycle(self, duty_cycle):
+        if not isinstance(duty_cycle, (int, float)):
+            raise TypeError("Invalid duty cycle type, should be int or float.")
+
+        if not 0 <= duty_cycle <= 65535:
+            raise ValueError("Invalid duty cycle value, should be between 0 and 65535")
+
+        # convert from 16-bit
+        duty_cycle /= 65535.0
+
+        self._duty_cycle = duty_cycle
+        # self._pwmpin.ChangeDutyCycle(round(self._duty_cycle * 100))
+        self._pwmpin.write(self._duty_cycle)  # mraa duty_cycle 0.0f - 1.0f
+
+    @property
+    def frequency(self):
+        """Get or set the PWM's output frequency in Hertz.
+
+        Raises:
+            PWMError: if an I/O or OS error occurs.
+            TypeError: if value type is not int or float.
+
+        :type: int, float
+        """
+
+        return self._frequency
+
+    @frequency.setter
+    def frequency(self, frequency):
+        if not isinstance(frequency, (int, float)):
+            raise TypeError("Invalid frequency type, should be int or float.")
+
+        if self._enabled and not self._varfreq:
+            raise TypeError(
+                " Set variable_frequency = True to allow changing frequency "
+            )
+        # mraa has different variants in seconds,milli(_ms),micro(_us)
+        self._pwmpin.period((1 / frequency))
+        self._frequency = frequency
+
+    @property
+    def enabled(self):
+        """Get or set the PWM's output enabled state.
+
+        Raises:
+            PWMError: if an I/O or OS error occurs.
+            TypeError: if value type is not bool.
+
+        :type: bool
+        """
+        return self._enabled
+
+    @enabled.setter
+    def enabled(self, value):
+        if not isinstance(value, bool):
+            raise TypeError("Invalid enabled type, should be string.")
+
+        if value:
+            self._pwmpin.enable(True)
+            self._enabled = value
+        else:
+            self._pwmpin.enable(False)
+            self._enabled(False)
+
+    # String representation
+    def __str__(self):
+        return "pin %s (freq=%f Hz, duty_cycle=%f%%)" % (
+            self._pin,
+            self.frequency,
+            self.duty_cycle,
+        )
diff --git a/src/adafruit_blinka/microcontroller/am65xx/spi.py b/src/adafruit_blinka/microcontroller/am65xx/spi.py
new file mode 100644 (file)
index 0000000..d1fa0b1
--- /dev/null
@@ -0,0 +1,144 @@
+# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
+#
+# SPDX-License-Identifier: MIT
+"""am65xx SPI class using PureIO's SPI class"""
+
+from Adafruit_PureIO import spi
+
+# import Adafruit_PureIO.spi as spi
+from adafruit_blinka.agnostic import detector
+
+
+class SPI:
+    """SPI Class"""
+
+    MSB = 0
+    LSB = 1
+    CPHA = 1
+    CPOL = 2
+
+    baudrate = 100000
+    mode = 0
+    bits = 8
+
+    def __init__(self, portid):
+        if isinstance(portid, tuple):
+            self._spi = spi.SPI(device=portid)
+        else:
+            self._spi = spi.SPI(device=(portid, 0))
+        self.clock_pin = None
+        self.mosi_pin = None
+        self.miso_pin = None
+        self.chip = None
+
+    # pylint: disable=too-many-arguments,unused-argument
+    def init(
+        self,
+        baudrate=100000,
+        polarity=0,
+        phase=0,
+        bits=8,
+        firstbit=MSB,
+        sck=None,
+        mosi=None,
+        miso=None,
+    ):
+        """Initialize SPI"""
+        mode = 0
+        if polarity:
+            mode |= self.CPOL
+        if phase:
+            mode |= self.CPHA
+        self.baudrate = baudrate
+        self.mode = mode
+        self.bits = bits
+        self.chip = detector.chip
+
+        # Pins are not used
+        self.clock_pin = sck
+        self.mosi_pin = mosi
+        self.miso_pin = miso
+
+    # pylint: enable=too-many-arguments,unused-argument
+
+    # pylint: disable=unnecessary-pass
+    def set_no_cs(self):
+        """Setting so that SPI doesn't automatically set the CS pin"""
+        # No kernel seems to support this, so we're just going to pass
+        pass
+
+    # pylint: enable=unnecessary-pass
+
+    @property
+    def frequency(self):
+        """Return the current baudrate"""
+        return self.baudrate
+
+    def write(self, buf, start=0, end=None):
+        """Write data from the buffer to SPI"""
+        if not buf:
+            return
+        if end is None:
+            end = len(buf)
+        try:
+            # self._spi.open(self._port, 0)
+            self.set_no_cs()
+            self._spi.max_speed_hz = self.baudrate
+            self._spi.mode = self.mode
+            self._spi.bits_per_word = self.bits
+            self._spi.writebytes(buf[start:end])
+            # self._spi.close()
+        except FileNotFoundError:
+            print("Could not open SPI device - check if SPI is enabled in kernel!")
+            raise
+
+    def readinto(self, buf, start=0, end=None, write_value=0):
+        """Read data from SPI and into the buffer"""
+        if not buf:
+            return
+        if end is None:
+            end = len(buf)
+        try:
+            # self._spi.open(self._port, 0)
+            # self.set_no_cs()
+            self._spi.max_speed_hz = self.baudrate
+            self._spi.mode = self.mode
+            self._spi.bits_per_word = self.bits
+            data = self._spi.transfer([write_value] * (end - start))
+            for i in range(end - start):  # 'readinto' the given buffer
+                buf[start + i] = data[i]
+            # self._spi.close()
+        except FileNotFoundError:
+            print("Could not open SPI device - check if SPI is enabled in kernel!")
+            raise
+
+    # pylint: disable=too-many-arguments
+    def write_readinto(
+        self, buffer_out, buffer_in, out_start=0, out_end=None, in_start=0, in_end=None
+    ):
+        """Perform a half-duplex write from buffer_out and then
+        read data into buffer_in
+        """
+        if not buffer_out or not buffer_in:
+            return
+        if out_end is None:
+            out_end = len(buffer_out)
+        if in_end is None:
+            in_end = len(buffer_in)
+        if out_end - out_start != in_end - in_start:
+            raise RuntimeError("Buffer slices must be of equal length.")
+        try:
+            # self._spi.open(self._port, 0)
+            # self.set_no_cs()
+            self._spi.max_speed_hz = self.baudrate
+            self._spi.mode = self.mode
+            self._spi.bits_per_word = self.bits
+            data = self._spi.transfer(list(buffer_out[out_start : out_end + 1]))
+            for i in range((in_end - in_start)):
+                buffer_in[i + in_start] = data[i]
+            # self._spi.close()
+        except FileNotFoundError:
+            print("Could not open SPI device - check if SPI is enabled in kernel!")
+            raise
+
+    # pylint: enable=too-many-arguments
index 23dfb0d5161bd9191b11755c714ffbfb50eb202d..4b7f9b06615dc33176557f4c024ac1cbb14ae025 100644 (file)
@@ -22,6 +22,9 @@ if detector.board.microchip_mcp2221:
 elif detector.board.greatfet_one:
     from adafruit_blinka.microcontroller.nxp_lpc4330.analogio import AnalogIn
     from adafruit_blinka.microcontroller.nxp_lpc4330.analogio import AnalogOut
+elif detector.board.any_siemens_simatic_iot2000:
+    from adafruit_blinka.microcontroller.am65xx.analogio import AnalogIn
+    from adafruit_blinka.microcontroller.am65xx.analogio import AnalogOut
 elif detector.chip.RK3308:
     from adafruit_blinka.microcontroller.generic_linux.sysfs_analogin import AnalogIn
 elif detector.chip.RK3399:
index 36aca248265cad1693107906df20f6a3759af9d0..4b8ae56a92433459a9b0dc6ebde460de58d15282 100644 (file)
@@ -277,6 +277,9 @@ elif board_id == ap_board.QT2040_TRINKEY_U2IF:
 elif board_id == ap_board.LICHEE_RV:
     from adafruit_blinka.board.lichee_rv import *
 
+elif board_id == ap_board.SIEMENS_SIMATIC_IOT2050_ADV:
+    from adafruit_blinka.board.siemens.siemens_iot2050 import *
+
 elif "sphinx" in sys.modules:
     pass
 
index dd748a596f0d51a798bb246e363c14f813a8bc23..75b08cba3222746b610e79ee53aa630064c608e1 100644 (file)
@@ -100,6 +100,12 @@ class I2C(Lockable):
 
             self._i2c = _I2C(scl, sda, frequency=frequency)
             return
+        if detector.board.any_siemens_iot2000:
+            from adafruit_blinka.microcontroller.am65xx.i2c import I2C as _I2C
+
+            self._i2c = _I2C(frequency=frequency)
+            return
+
         if detector.board.any_embedded_linux:
             from adafruit_blinka.microcontroller.generic_linux.i2c import I2C as _I2C
         elif detector.board.ftdi_ft2232h:
@@ -270,6 +276,12 @@ class SPI(Lockable):
             self._spi = _SPI(clock, MOSI, MISO)  # Pins configured on instantiation
             self._pins = (clock, clock, clock)  # These don't matter, they're discarded
             return
+        if detector.board.any_siemens_iot2000:
+            from adafruit_blinka.microcontroller.am65xx.spi import SPI as _SPI
+
+            self._spi = _SPI(clock)  # this is really all that's needed
+            self._pins = (clock, clock, clock)  # will determine MOSI/MISO from clock
+            return
         if detector.board.any_embedded_linux:
             from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
         elif detector.board.ftdi_ft2232h:
@@ -332,6 +344,9 @@ class SPI(Lockable):
             from adafruit_blinka.microcontroller.rp2040_u2if.spi import SPI_QTPY as _SPI
         elif detector.chip.id == ap_chip.RP2040:
             from adafruit_blinka.microcontroller.rp2040.spi import SPI as _SPI
+        elif detector.board.any_siemens_iot2000:
+            from adafruit_blinka.microcontroller.am65xx.spi import SPI as _SPI
+            from adafruit_blinka.microcontroller.am65xx.pin import Pin
         elif detector.board.any_embedded_linux:
             from adafruit_blinka.microcontroller.generic_linux.spi import SPI as _SPI
         else:
@@ -486,7 +501,7 @@ class UART(Lockable):
         return self._uart.readinto(buf, nbytes)
 
     def readline(self):
-        """Read a line of characters up to a newline charater from the UART"""
+        """Read a line of characters up to a newline character from the UART"""
         return self._uart.readline()
 
     def write(self, buf):
index 0969f350047fc33fa3ce37a9af25d2f5b7ba75c5..7f64fb106c4463a0ca6358250bfe7f6da9e471c5 100644 (file)
@@ -18,6 +18,8 @@ if detector.chip.BCM2XXX:
     from adafruit_blinka.microcontroller.bcm283x.pin import Pin
 elif detector.chip.AM33XX:
     from adafruit_blinka.microcontroller.am335x.pin import Pin
+elif detector.chip.AM65XX:
+    from adafruit_blinka.microcontroller.am65xx.pin import Pin
 elif detector.chip.JH71x0:
     from adafruit_blinka.microcontroller.starfive.JH71x0.pin import Pin
 elif detector.chip.DRA74X:
index 9bd7d09f04617dd7e26844d3b3ffc25373be569f..debf41c3423ea18a3743d2696eea2a83682887a2 100644 (file)
@@ -44,6 +44,8 @@ elif chip_id == ap_chip.DRA74X:
     from adafruit_blinka.microcontroller.dra74x import *
 elif chip_id == ap_chip.AM33XX:
     from adafruit_blinka.microcontroller.am335x import *
+elif chip_id == ap_chip.AM65XX:
+    from adafruit_blinka.microcontroller.am65xx import *
 elif chip_id == ap_chip.JH71x0:
     from adafruit_blinka.microcontroller.starfive.JH71x0 import *
 elif chip_id == ap_chip.SUN8I:
index 196aa0389ea0a59ec9d5e457c0ed6afe5a74fec1..a46c6cd21fe9cdeeb4bf493dadd549d4dceb1615 100644 (file)
@@ -29,6 +29,8 @@ elif chip_id == ap_chip.DRA74X:
     from adafruit_blinka.microcontroller.dra74x.pin import *
 elif chip_id == ap_chip.AM33XX:
     from adafruit_blinka.microcontroller.am335x.pin import *
+elif chip_id == ap_chip.AM65XX:
+    from adafruit_blinka.microcontroller.am65xx.pin import *
 elif chip_id == ap_chip.JH71x0:
     from adafruit_blinka.microcontroller.starfive.JH71x0.pin import *
 elif chip_id == ap_chip.SUN8I:
index f4d6a8c995a6b68d372065dc5de65b2fe22e022b..ccf44209647be4c9e2987951a4fefc8d897cdc56 100644 (file)
@@ -24,6 +24,8 @@ elif detector.board.any_giant_board:
     from adafruit_blinka.microcontroller.generic_linux.sysfs_pwmout import PWMOut
 elif detector.board.any_beaglebone:
     from adafruit_blinka.microcontroller.am335x.sysfs_pwmout import PWMOut
+elif detector.board.any_siemens_simatic_iot2000:
+    from adafruit_blinka.microcontroller.am65xx.pwmout import PWMOut
 elif detector.board.any_rock_pi_board:
     from adafruit_blinka.microcontroller.rockchip.PWMOut import PWMOut
 elif detector.board.binho_nova: