MikrofonSensor und TemperaturSenor die zwei Python programme funktionieren. mit den jeweiligen 2 json Datein. Beim TemperaturSensor wird im Terminal keine Wertre ausgegeben aber in der json Datei kann man die Temp und Hum sehen.
This commit is contained in:
parent
4c654ec969
commit
1751076592
2614 changed files with 349009 additions and 0 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,72 @@
|
|||
# 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 import ContextManaged
|
||||
from .rp2040_u2if import rp2040_u2if
|
||||
|
||||
|
||||
class AnalogIn(ContextManaged):
|
||||
"""AnalogIn Base Class for RP2040 u2if"""
|
||||
|
||||
def __init__(self, pin):
|
||||
self.pin_id = pin.id
|
||||
rp2040_u2if.adc_init_pin(self.pin_id)
|
||||
|
||||
@property
|
||||
def value(self):
|
||||
"""Read the ADC and return the value"""
|
||||
return rp2040_u2if.adc_get_value(self.pin_id) << 4
|
||||
|
||||
# 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):
|
||||
pass
|
||||
|
||||
|
||||
class AnalogIn_Pico(AnalogIn):
|
||||
"""AnalogIn Base Class for Pico u2if"""
|
||||
|
||||
def __init__(self, pin):
|
||||
# per their pinout, why only two?
|
||||
if pin.id not in (26, 27):
|
||||
raise ValueError("Pin does not support ADC.")
|
||||
super().__init__(pin)
|
||||
|
||||
|
||||
class AnalogIn_Feather(AnalogIn):
|
||||
"""AnalogIn Base Class for Feather u2if"""
|
||||
|
||||
def __init__(self, pin):
|
||||
if pin.id not in (26, 27, 28):
|
||||
raise ValueError("Pin does not support ADC.")
|
||||
super().__init__(pin)
|
||||
|
||||
|
||||
class AnalogIn_QTPY(AnalogIn):
|
||||
"""AnalogIn Base Class for QT Py 2040 u2if"""
|
||||
|
||||
def __init__(self, pin):
|
||||
if pin.id not in (26, 27, 28):
|
||||
raise ValueError("Pin does not support ADC.")
|
||||
super().__init__(pin)
|
||||
|
||||
|
||||
class AnalogIn_ItsyBitsy(AnalogIn):
|
||||
"""AnalogIn Base Class for ItsyBitsy 2040 u2if"""
|
||||
|
||||
def __init__(self, pin):
|
||||
if pin.id not in (26, 27, 28):
|
||||
raise ValueError("Pin does not support ADC.")
|
||||
super().__init__(pin)
|
|
@ -0,0 +1,201 @@
|
|||
# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""I2C Classes for RP2040s with u2if firmware"""
|
||||
from .rp2040_u2if import rp2040_u2if
|
||||
|
||||
|
||||
class I2C:
|
||||
"""I2C Base Class for RP2040 u2if"""
|
||||
|
||||
def __init__(self, index, *, frequency=100000):
|
||||
self._index = index
|
||||
rp2040_u2if.i2c_set_port(self._index)
|
||||
rp2040_u2if.i2c_configure(frequency)
|
||||
|
||||
def scan(self):
|
||||
"""Perform an I2C Device Scan"""
|
||||
rp2040_u2if.i2c_set_port(self._index)
|
||||
return rp2040_u2if.i2c_scan()
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def writeto(self, address, buffer, *, start=0, end=None, stop=True):
|
||||
"""Write data from the buffer to an address"""
|
||||
rp2040_u2if.i2c_set_port(self._index)
|
||||
rp2040_u2if.i2c_writeto(address, buffer, start=start, end=end)
|
||||
|
||||
def readfrom_into(self, address, buffer, *, start=0, end=None, stop=True):
|
||||
"""Read data from an address and into the buffer"""
|
||||
rp2040_u2if.i2c_set_port(self._index)
|
||||
rp2040_u2if.i2c_readfrom_into(address, buffer, start=start, end=end)
|
||||
|
||||
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
|
||||
"""
|
||||
rp2040_u2if.i2c_set_port(self._index)
|
||||
rp2040_u2if.i2c_writeto_then_readfrom(
|
||||
address,
|
||||
buffer_out,
|
||||
buffer_in,
|
||||
out_start=out_start,
|
||||
out_end=out_end,
|
||||
in_start=in_start,
|
||||
in_end=in_end,
|
||||
)
|
||||
|
||||
# pylint: enable=unused-argument
|
||||
|
||||
|
||||
class I2C_Pico(I2C):
|
||||
"""I2C Class for Pico u2if"""
|
||||
|
||||
def __init__(self, scl, sda, *, frequency=100000):
|
||||
index = None
|
||||
if scl.id == 5 and sda.id == 4:
|
||||
index = 0
|
||||
if scl.id == 15 and sda.id == 14:
|
||||
index = 1
|
||||
if index is None:
|
||||
raise ValueError("I2C not found on specified pins.")
|
||||
self._index = index
|
||||
|
||||
super().__init__(index, frequency=frequency)
|
||||
|
||||
|
||||
class I2C_Feather(I2C):
|
||||
"""I2C Class for Feather u2if"""
|
||||
|
||||
def __init__(self, scl, sda, *, frequency=100000):
|
||||
index = None
|
||||
if scl.id == 3 and sda.id == 2:
|
||||
index = 1
|
||||
if index is None:
|
||||
raise ValueError("I2C not found on specified pins.")
|
||||
self._index = index
|
||||
|
||||
super().__init__(index, frequency=frequency)
|
||||
|
||||
|
||||
class I2C_Feather_CAN(I2C):
|
||||
"""I2C Class for Feather EPD u2if"""
|
||||
|
||||
def __init__(self, scl, sda, *, frequency=100000):
|
||||
index = None
|
||||
if scl.id == 3 and sda.id == 2:
|
||||
index = 1
|
||||
if index is None:
|
||||
raise ValueError("I2C not found on specified pins.")
|
||||
self._index = index
|
||||
|
||||
super().__init__(index, frequency=frequency)
|
||||
|
||||
|
||||
class I2C_Feather_EPD(I2C):
|
||||
"""I2C Class for Feather EPD u2if"""
|
||||
|
||||
def __init__(self, scl, sda, *, frequency=100000):
|
||||
index = None
|
||||
if scl.id == 3 and sda.id == 2:
|
||||
index = 1
|
||||
if index is None:
|
||||
raise ValueError("I2C not found on specified pins.")
|
||||
self._index = index
|
||||
|
||||
super().__init__(index, frequency=frequency)
|
||||
|
||||
|
||||
class I2C_Feather_RFM(I2C):
|
||||
"""I2C Class for Feather EPD u2if"""
|
||||
|
||||
def __init__(self, scl, sda, *, frequency=100000):
|
||||
index = None
|
||||
if scl.id == 3 and sda.id == 2:
|
||||
index = 1
|
||||
if index is None:
|
||||
raise ValueError("I2C not found on specified pins.")
|
||||
self._index = index
|
||||
|
||||
super().__init__(index, frequency=frequency)
|
||||
|
||||
|
||||
class I2C_QTPY(I2C):
|
||||
"""I2C Class for QT Py 2if"""
|
||||
|
||||
def __init__(self, scl, sda, *, frequency=100000):
|
||||
index = None
|
||||
if scl.id == 25 and sda.id == 24:
|
||||
index = 0
|
||||
if scl.id == 23 and sda.id == 22:
|
||||
index = 1
|
||||
if index is None:
|
||||
raise ValueError("I2C not found on specified pins.")
|
||||
self._index = index
|
||||
|
||||
super().__init__(index, frequency=frequency)
|
||||
|
||||
|
||||
class I2C_ItsyBitsy(I2C):
|
||||
"""I2C Class for ItsyBitsy u2if"""
|
||||
|
||||
def __init__(self, scl, sda, *, frequency=100000):
|
||||
index = None
|
||||
if scl.id == 3 and sda.id == 2:
|
||||
index = 1
|
||||
if index is None:
|
||||
raise ValueError("I2C not found on specified pins.")
|
||||
self._index = index
|
||||
|
||||
super().__init__(index, frequency=frequency)
|
||||
|
||||
|
||||
class I2C_MacroPad(I2C):
|
||||
"""I2C Class for MacroPad u2if"""
|
||||
|
||||
def __init__(self, scl, sda, *, frequency=100000):
|
||||
index = None
|
||||
if scl.id == 21 and sda.id == 20:
|
||||
index = 0
|
||||
if index is None:
|
||||
raise ValueError("I2C not found on specified pins.")
|
||||
self._index = index
|
||||
super().__init__(index, frequency=frequency)
|
||||
|
||||
|
||||
class I2C_QT2040_Trinkey(I2C):
|
||||
"""I2C Class for QT2040 Trinkey u2if"""
|
||||
|
||||
def __init__(self, scl, sda, *, frequency=100000):
|
||||
index = None
|
||||
if scl.id == 17 and sda.id == 16:
|
||||
index = 0
|
||||
if index is None:
|
||||
raise ValueError("I2C not found on specified pins.")
|
||||
self._index = index
|
||||
|
||||
super().__init__(index, frequency=frequency)
|
||||
|
||||
|
||||
class I2C_KB2040(I2C):
|
||||
"""I2C Class for KB2040 u2if"""
|
||||
|
||||
def __init__(self, scl, sda, *, frequency=100000):
|
||||
index = None
|
||||
if scl.id == 13 and sda.id == 12:
|
||||
index = 0
|
||||
if index is None:
|
||||
raise ValueError("I2C not found on specified pins.")
|
||||
self._index = index
|
||||
|
||||
super().__init__(index, frequency=frequency)
|
|
@ -0,0 +1,20 @@
|
|||
# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""NeoPixel write for Pico u2if."""
|
||||
|
||||
from .rp2040_u2if import rp2040_u2if
|
||||
|
||||
|
||||
def neopixel_write(gpio, buf):
|
||||
"""NeoPixel Writing Function"""
|
||||
|
||||
# pad output buffer from 3 bpp to 4 bpp
|
||||
buffer = []
|
||||
for i in range(0, len(buf), 3):
|
||||
buffer.append(0)
|
||||
buffer.append(buf[i + 2])
|
||||
buffer.append(buf[i + 1])
|
||||
buffer.append(buf[i])
|
||||
|
||||
rp2040_u2if.neopixel_write(gpio, buffer)
|
|
@ -0,0 +1,95 @@
|
|||
# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""Generic RP2040 pin names"""
|
||||
from .rp2040_u2if import rp2040_u2if
|
||||
|
||||
|
||||
class Pin:
|
||||
"""A basic Pin class for use with RP2040 with u2if firmware."""
|
||||
|
||||
# pin modes
|
||||
IN = 0
|
||||
OUT = 1
|
||||
# pin values
|
||||
LOW = 0
|
||||
HIGH = 1
|
||||
# pin pulls
|
||||
PULL_NONE = 0
|
||||
PULL_UP = 1
|
||||
PULL_DOWN = 2
|
||||
|
||||
def __init__(self, pin_id=None):
|
||||
self.id = pin_id
|
||||
self._mode = None
|
||||
self._pull = None
|
||||
|
||||
# pylint:disable = no-self-use
|
||||
def _u2if_open_hid(self, vid, pid):
|
||||
rp2040_u2if.open(vid, pid)
|
||||
|
||||
def init(self, mode=IN, pull=PULL_NONE):
|
||||
"""Initialize the Pin"""
|
||||
pull = Pin.PULL_NONE if pull is None else pull
|
||||
if self.id is None:
|
||||
raise RuntimeError("Can not init a None type pin.")
|
||||
if mode not in (Pin.IN, Pin.OUT):
|
||||
raise ValueError("Incorrect mode value.")
|
||||
if pull not in (Pin.PULL_NONE, Pin.PULL_UP, Pin.PULL_DOWN):
|
||||
raise ValueError("Incorrect pull value.")
|
||||
|
||||
rp2040_u2if.gpio_init_pin(self.id, mode, pull)
|
||||
|
||||
self._mode = mode
|
||||
self._pull = pull
|
||||
|
||||
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 rp2040_u2if.gpio_get_pin(self.id)
|
||||
# digital write
|
||||
if val in (Pin.LOW, Pin.HIGH):
|
||||
rp2040_u2if.gpio_set_pin(self.id, val)
|
||||
return None
|
||||
# nope
|
||||
raise ValueError("Invalid value for pin.")
|
||||
|
||||
raise RuntimeError(
|
||||
"No action for mode {} with value {}".format(self._mode, val)
|
||||
)
|
||||
|
||||
|
||||
# create pin instances for each pin
|
||||
GP0 = Pin(0)
|
||||
GP1 = Pin(1)
|
||||
GP2 = Pin(2)
|
||||
GP3 = Pin(3)
|
||||
GP4 = Pin(4)
|
||||
GP5 = Pin(5)
|
||||
GP6 = Pin(6)
|
||||
GP7 = Pin(7)
|
||||
GP8 = Pin(8)
|
||||
GP9 = Pin(9)
|
||||
GP10 = Pin(10)
|
||||
GP11 = Pin(11)
|
||||
GP12 = Pin(12)
|
||||
GP13 = Pin(13)
|
||||
GP14 = Pin(14)
|
||||
GP15 = Pin(15)
|
||||
GP16 = Pin(16)
|
||||
GP17 = Pin(17)
|
||||
GP18 = Pin(18)
|
||||
GP19 = Pin(19)
|
||||
GP20 = Pin(20)
|
||||
GP21 = Pin(21)
|
||||
GP22 = Pin(22)
|
||||
GP23 = Pin(23)
|
||||
GP24 = Pin(24)
|
||||
GP25 = Pin(25)
|
||||
GP26 = Pin(26)
|
||||
GP27 = Pin(27)
|
||||
GP28 = Pin(28)
|
||||
GP29 = Pin(29)
|
|
@ -0,0 +1,50 @@
|
|||
# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""PWMOut Class for RP2040s with u2if"""
|
||||
from .rp2040_u2if import rp2040_u2if
|
||||
|
||||
|
||||
class PWMOut:
|
||||
"""Base Pulse Width Modulation Output Class"""
|
||||
|
||||
def __init__(self, pin, *, frequency=500, duty_cycle=0, variable_frequency=False):
|
||||
rp2040_u2if.pwm_configure(
|
||||
pin,
|
||||
frequency=frequency,
|
||||
duty_cycle=duty_cycle,
|
||||
variable_frequency=variable_frequency,
|
||||
)
|
||||
|
||||
self._pin = pin
|
||||
|
||||
def __del__(self):
|
||||
self.deinit()
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, t, value, traceback):
|
||||
self.deinit()
|
||||
|
||||
def deinit(self):
|
||||
"""Deinit PWM."""
|
||||
rp2040_u2if.pwm_deinit(self._pin)
|
||||
|
||||
@property
|
||||
def duty_cycle(self):
|
||||
"""The PWM's output duty cycle, 16-bit."""
|
||||
return rp2040_u2if.pwm_get_duty_cycle(self._pin)
|
||||
|
||||
@duty_cycle.setter
|
||||
def duty_cycle(self, duty_cycle):
|
||||
rp2040_u2if.pwm_set_duty_cycle(self._pin, duty_cycle)
|
||||
|
||||
@property
|
||||
def frequency(self):
|
||||
"""The PWM's output frequency in Hertz."""
|
||||
return rp2040_u2if.pwm_get_frequency(self._pin)
|
||||
|
||||
@frequency.setter
|
||||
def frequency(self, frequency):
|
||||
rp2040_u2if.pwm_set_frequency(self._pin, frequency)
|
|
@ -0,0 +1,509 @@
|
|||
# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""Helper class for use with RP2040 running u2if firmware"""
|
||||
# https://github.com/execuc/u2if
|
||||
|
||||
import os
|
||||
import time
|
||||
import hid
|
||||
|
||||
# Use to set delay between reset and device reopen. if negative, don't reset at all
|
||||
RP2040_U2IF_RESET_DELAY = float(os.environ.get("RP2040_U2IF_RESET_DELAY", 1))
|
||||
|
||||
# pylint: disable=import-outside-toplevel,too-many-branches,too-many-statements
|
||||
# pylint: disable=too-many-arguments,too-many-function-args, too-many-public-methods
|
||||
|
||||
|
||||
class RP2040_u2if:
|
||||
"""Helper class for use with RP2040 running u2if firmware"""
|
||||
|
||||
# MISC
|
||||
RESP_OK = 0x01
|
||||
SYS_RESET = 0x10
|
||||
|
||||
# GPIO
|
||||
GPIO_INIT_PIN = 0x20
|
||||
GPIO_SET_VALUE = 0x21
|
||||
GPIO_GET_VALUE = 0x22
|
||||
|
||||
# ADC
|
||||
ADC_INIT_PIN = 0x40
|
||||
ADC_GET_VALUE = 0x41
|
||||
|
||||
# I2C
|
||||
I2C0_INIT = 0x80
|
||||
I2C0_DEINIT = 0x81
|
||||
I2C0_WRITE = 0x82
|
||||
I2C0_READ = 0x83
|
||||
I2C0_WRITE_FROM_UART = 0x84
|
||||
I2C1_INIT = I2C0_INIT + 0x10
|
||||
I2C1_DEINIT = I2C0_DEINIT + 0x10
|
||||
I2C1_WRITE = I2C0_WRITE + 0x10
|
||||
I2C1_READ = I2C0_READ + 0x10
|
||||
I2C1_WRITE_FROM_UART = I2C0_WRITE_FROM_UART + 0x10
|
||||
|
||||
# SPI
|
||||
SPI0_INIT = 0x60
|
||||
SPI0_DEINIT = 0x61
|
||||
SPI0_WRITE = 0x62
|
||||
SPI0_READ = 0x63
|
||||
SPI0_WRITE_FROM_UART = 0x64
|
||||
SPI1_INIT = SPI0_INIT + 0x10
|
||||
SPI1_DEINIT = SPI0_DEINIT + 0x10
|
||||
SPI1_WRITE = SPI0_WRITE + 0x10
|
||||
SPI1_READ = SPI0_READ + 0x10
|
||||
SPI1_WRITE_FROM_UART = SPI0_WRITE_FROM_UART + 0x10
|
||||
|
||||
# WS2812B (LED)
|
||||
WS2812B_INIT = 0xA0
|
||||
WS2812B_DEINIT = 0xA1
|
||||
WS2812B_WRITE = 0xA2
|
||||
|
||||
# PWM
|
||||
PWM_INIT_PIN = 0x30
|
||||
PWM_DEINIT_PIN = 0x31
|
||||
PWM_SET_FREQ = 0x32
|
||||
PWM_GET_FREQ = 0x33
|
||||
PWM_SET_DUTY_U16 = 0x34
|
||||
PWM_GET_DUTY_U16 = 0x35
|
||||
PWM_SET_DUTY_NS = 0x36
|
||||
PWM_GET_DUTY_NS = 0x37
|
||||
|
||||
def __init__(self):
|
||||
self._vid = None
|
||||
self._pid = None
|
||||
self._hid = None
|
||||
self._opened = False
|
||||
self._i2c_index = None
|
||||
self._spi_index = None
|
||||
self._serial = None
|
||||
self._neopixel_initialized = False
|
||||
self._uart_rx_buffer = None
|
||||
|
||||
def _hid_xfer(self, report, response=True):
|
||||
"""Perform HID Transfer"""
|
||||
# first byte is report ID, which =0
|
||||
# remaing bytes = 64 byte report data
|
||||
# https://github.com/libusb/hidapi/blob/083223e77952e1ef57e6b77796536a3359c1b2a3/hidapi/hidapi.h#L185
|
||||
self._hid.write(b"\0" + report + b"\0" * (64 - len(report)))
|
||||
if response:
|
||||
# return is 64 byte response report
|
||||
return self._hid.read(64)
|
||||
return None
|
||||
|
||||
def _reset(self):
|
||||
self._hid_xfer(bytes([self.SYS_RESET]), False)
|
||||
self._hid.close()
|
||||
time.sleep(RP2040_U2IF_RESET_DELAY)
|
||||
start = time.monotonic()
|
||||
while time.monotonic() - start < 5:
|
||||
try:
|
||||
self._hid.open(self._vid, self._pid)
|
||||
except OSError:
|
||||
time.sleep(0.1)
|
||||
continue
|
||||
return
|
||||
raise OSError("RP2040 u2if open error.")
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# MISC
|
||||
# ----------------------------------------------------------------
|
||||
def open(self, vid, pid):
|
||||
"""Open HID interface for given USB VID and PID."""
|
||||
|
||||
if self._opened:
|
||||
return
|
||||
self._vid = vid
|
||||
self._pid = pid
|
||||
self._hid = hid.device()
|
||||
self._hid.open(self._vid, self._pid)
|
||||
if RP2040_U2IF_RESET_DELAY >= 0:
|
||||
self._reset()
|
||||
self._opened = True
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# GPIO
|
||||
# ----------------------------------------------------------------
|
||||
def gpio_init_pin(self, pin_id, direction, pull):
|
||||
"""Configure GPIO Pin."""
|
||||
self._hid_xfer(
|
||||
bytes(
|
||||
[
|
||||
self.GPIO_INIT_PIN,
|
||||
pin_id,
|
||||
direction,
|
||||
pull,
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
def gpio_set_pin(self, pin_id, value):
|
||||
"""Set Current GPIO Pin Value"""
|
||||
self._hid_xfer(
|
||||
bytes(
|
||||
[
|
||||
self.GPIO_SET_VALUE,
|
||||
pin_id,
|
||||
int(value),
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
def gpio_get_pin(self, pin_id):
|
||||
"""Get Current GPIO Pin Value"""
|
||||
resp = self._hid_xfer(
|
||||
bytes(
|
||||
[
|
||||
self.GPIO_GET_VALUE,
|
||||
pin_id,
|
||||
]
|
||||
),
|
||||
True,
|
||||
)
|
||||
return resp[3] != 0x00
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# ADC
|
||||
# ----------------------------------------------------------------
|
||||
def adc_init_pin(self, pin_id):
|
||||
"""Configure ADC Pin."""
|
||||
self._hid_xfer(
|
||||
bytes(
|
||||
[
|
||||
self.ADC_INIT_PIN,
|
||||
pin_id,
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
def adc_get_value(self, pin_id):
|
||||
"""Get ADC value for pin."""
|
||||
resp = self._hid_xfer(
|
||||
bytes(
|
||||
[
|
||||
self.ADC_GET_VALUE,
|
||||
pin_id,
|
||||
]
|
||||
),
|
||||
True,
|
||||
)
|
||||
return int.from_bytes(resp[3 : 3 + 2], byteorder="little")
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# I2C
|
||||
# ----------------------------------------------------------------
|
||||
def i2c_configure(self, baudrate, pullup=False):
|
||||
"""Configure I2C."""
|
||||
if self._i2c_index is None:
|
||||
raise RuntimeError("I2C bus not initialized.")
|
||||
|
||||
resp = self._hid_xfer(
|
||||
bytes(
|
||||
[
|
||||
self.I2C0_INIT if self._i2c_index == 0 else self.I2C1_INIT,
|
||||
0x00 if not pullup else 0x01,
|
||||
]
|
||||
)
|
||||
+ baudrate.to_bytes(4, byteorder="little"),
|
||||
True,
|
||||
)
|
||||
if resp[1] != self.RESP_OK:
|
||||
raise RuntimeError("I2C init error.")
|
||||
|
||||
def i2c_set_port(self, index):
|
||||
"""Set I2C port."""
|
||||
if index not in (0, 1):
|
||||
raise ValueError("I2C index must be 0 or 1.")
|
||||
self._i2c_index = index
|
||||
|
||||
def _i2c_write(self, address, buffer, start=0, end=None, stop=True):
|
||||
"""Write data from the buffer to an address"""
|
||||
if self._i2c_index is None:
|
||||
raise RuntimeError("I2C bus not initialized.")
|
||||
|
||||
end = end if end else len(buffer)
|
||||
|
||||
write_cmd = self.I2C0_WRITE if self._i2c_index == 0 else self.I2C1_WRITE
|
||||
stop_flag = 0x01 if stop else 0x00
|
||||
|
||||
while (end - start) > 0:
|
||||
remain_bytes = end - start
|
||||
chunk = min(remain_bytes, 64 - 7)
|
||||
resp = self._hid_xfer(
|
||||
bytes([write_cmd, address, stop_flag])
|
||||
+ remain_bytes.to_bytes(4, byteorder="little")
|
||||
+ buffer[start : (start + chunk)],
|
||||
True,
|
||||
)
|
||||
if resp[1] != self.RESP_OK:
|
||||
raise RuntimeError("I2C write error")
|
||||
start += chunk
|
||||
|
||||
def _i2c_read(self, address, buffer, start=0, end=None):
|
||||
"""Read data from an address and into the buffer"""
|
||||
# TODO: support chunkified reads
|
||||
if self._i2c_index is None:
|
||||
raise RuntimeError("I2C bus not initialized.")
|
||||
|
||||
end = end if end else len(buffer)
|
||||
|
||||
read_cmd = self.I2C0_READ if self._i2c_index == 0 else self.I2C1_READ
|
||||
stop_flag = 0x01 # always stop
|
||||
read_size = end - start
|
||||
|
||||
resp = self._hid_xfer(bytes([read_cmd, address, stop_flag, read_size]), True)
|
||||
if resp[1] != self.RESP_OK:
|
||||
raise RuntimeError("I2C write error")
|
||||
# move into buffer
|
||||
for i in range(read_size):
|
||||
buffer[start + i] = resp[i + 2]
|
||||
|
||||
def i2c_writeto(self, address, buffer, *, start=0, end=None):
|
||||
"""Write data from the buffer to an address"""
|
||||
self._i2c_write(address, buffer, start, end)
|
||||
|
||||
def i2c_readfrom_into(self, address, buffer, *, start=0, end=None):
|
||||
"""Read data from an address and into the buffer"""
|
||||
self._i2c_read(address, buffer, start, end)
|
||||
|
||||
def i2c_writeto_then_readfrom(
|
||||
self,
|
||||
address,
|
||||
out_buffer,
|
||||
in_buffer,
|
||||
*,
|
||||
out_start=0,
|
||||
out_end=None,
|
||||
in_start=0,
|
||||
in_end=None,
|
||||
):
|
||||
"""Write data from buffer_out to an address and then
|
||||
read data from an address and into buffer_in
|
||||
"""
|
||||
self._i2c_write(address, out_buffer, out_start, out_end, False)
|
||||
self._i2c_read(address, in_buffer, in_start, in_end)
|
||||
|
||||
def i2c_scan(self, *, start=0, end=0x79):
|
||||
"""Perform an I2C Device Scan"""
|
||||
if self._i2c_index is None:
|
||||
raise RuntimeError("I2C bus not initialized.")
|
||||
found = []
|
||||
for addr in range(start, end + 1):
|
||||
# try a write
|
||||
try:
|
||||
self.i2c_writeto(addr, b"\x00\x00\x00")
|
||||
except RuntimeError: # no reply!
|
||||
continue
|
||||
# store if success
|
||||
found.append(addr)
|
||||
return found
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# SPI
|
||||
# ----------------------------------------------------------------
|
||||
def spi_configure(self, baudrate):
|
||||
"""Configure SPI."""
|
||||
if self._spi_index is None:
|
||||
raise RuntimeError("SPI bus not initialized.")
|
||||
|
||||
resp = self._hid_xfer(
|
||||
bytes(
|
||||
[
|
||||
self.SPI0_INIT if self._spi_index == 0 else self.SPI1_INIT,
|
||||
0x00, # mode, not yet implemented
|
||||
]
|
||||
)
|
||||
+ baudrate.to_bytes(4, byteorder="little"),
|
||||
True,
|
||||
)
|
||||
if resp[1] != self.RESP_OK:
|
||||
raise RuntimeError("SPI init error.")
|
||||
|
||||
def spi_set_port(self, index):
|
||||
"""Set SPI port."""
|
||||
if index not in (0, 1):
|
||||
raise ValueError("SPI index must be 0 or 1.")
|
||||
self._spi_index = index
|
||||
|
||||
def spi_write(self, buffer, *, start=0, end=None):
|
||||
"""SPI write."""
|
||||
if self._spi_index is None:
|
||||
raise RuntimeError("SPI bus not initialized.")
|
||||
|
||||
end = end if end else len(buffer)
|
||||
|
||||
write_cmd = self.SPI0_WRITE if self._spi_index == 0 else self.SPI1_WRITE
|
||||
|
||||
while (end - start) > 0:
|
||||
remain_bytes = end - start
|
||||
chunk = min(remain_bytes, 64 - 3)
|
||||
resp = self._hid_xfer(
|
||||
bytes([write_cmd, chunk]) + buffer[start : (start + chunk)], True
|
||||
)
|
||||
if resp[1] != self.RESP_OK:
|
||||
raise RuntimeError("SPI write error")
|
||||
start += chunk
|
||||
|
||||
def spi_readinto(self, buffer, *, start=0, end=None, write_value=0):
|
||||
"""SPI readinto."""
|
||||
if self._spi_index is None:
|
||||
raise RuntimeError("SPI bus not initialized.")
|
||||
|
||||
end = end if end else len(buffer)
|
||||
read_cmd = self.SPI0_READ if self._spi_index == 0 else self.SPI1_READ
|
||||
read_size = end - start
|
||||
|
||||
resp = self._hid_xfer(bytes([read_cmd, write_value, read_size]), True)
|
||||
if resp[1] != self.RESP_OK:
|
||||
raise RuntimeError("SPI write error")
|
||||
# move into buffer
|
||||
for i in range(read_size):
|
||||
buffer[start + i] = resp[i + 2]
|
||||
|
||||
def spi_write_readinto(
|
||||
self,
|
||||
buffer_out,
|
||||
buffer_in,
|
||||
*,
|
||||
out_start=0,
|
||||
out_end=None,
|
||||
in_start=0,
|
||||
in_end=None,
|
||||
):
|
||||
"""SPI write and readinto."""
|
||||
raise NotImplementedError("SPI write_readinto Not implemented")
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# NEOPIXEL
|
||||
# ----------------------------------------------------------------
|
||||
def neopixel_write(self, gpio, buf):
|
||||
"""NeoPixel write."""
|
||||
# open serial (data is sent over this)
|
||||
if self._serial is None:
|
||||
import serial
|
||||
import serial.tools.list_ports
|
||||
|
||||
ports = serial.tools.list_ports.comports()
|
||||
for port in ports:
|
||||
if port.vid == self._vid and port.pid == self._pid:
|
||||
self._serial = serial.Serial(port.device)
|
||||
break
|
||||
if self._serial is None:
|
||||
raise RuntimeError("Could not find Pico com port.")
|
||||
|
||||
# init
|
||||
if not self._neopixel_initialized:
|
||||
# deinit any current setup
|
||||
# pylint: disable=protected-access
|
||||
self._hid_xfer(bytes([self.WS2812B_DEINIT]))
|
||||
resp = self._hid_xfer(
|
||||
bytes(
|
||||
[
|
||||
self.WS2812B_INIT,
|
||||
gpio._pin.id,
|
||||
]
|
||||
),
|
||||
True,
|
||||
)
|
||||
if resp[1] != self.RESP_OK:
|
||||
raise RuntimeError("Neopixel init error")
|
||||
self._neopixel_initialized = True
|
||||
|
||||
self._serial.reset_output_buffer()
|
||||
|
||||
# write
|
||||
# command is done over HID
|
||||
remain_bytes = len(buf)
|
||||
resp = self._hid_xfer(
|
||||
bytes([self.WS2812B_WRITE]) + remain_bytes.to_bytes(4, byteorder="little"),
|
||||
True,
|
||||
)
|
||||
if resp[1] != self.RESP_OK:
|
||||
# pylint: disable=no-else-raise
|
||||
if resp[2] == 0x01:
|
||||
raise RuntimeError(
|
||||
"Neopixel write error : too many pixel for the firmware."
|
||||
)
|
||||
elif resp[2] == 0x02:
|
||||
raise RuntimeError(
|
||||
"Neopixel write error : transfer already in progress."
|
||||
)
|
||||
else:
|
||||
raise RuntimeError("Neopixel write error.")
|
||||
# buffer is sent over serial
|
||||
self._serial.write(buf)
|
||||
# hack (see u2if)
|
||||
if len(buf) % 64 == 0:
|
||||
self._serial.write([0])
|
||||
self._serial.flush()
|
||||
# polling loop to wait for write complete?
|
||||
time.sleep(0.1)
|
||||
resp = self._hid.read(64)
|
||||
while resp[0] != self.WS2812B_WRITE:
|
||||
resp = self._hid.read(64)
|
||||
if resp[1] != self.RESP_OK:
|
||||
raise RuntimeError("Neopixel write (flush) error.")
|
||||
|
||||
# ----------------------------------------------------------------
|
||||
# PWM
|
||||
# ----------------------------------------------------------------
|
||||
# pylint: disable=unused-argument
|
||||
def pwm_configure(self, pin, frequency=500, duty_cycle=0, variable_frequency=False):
|
||||
"""Configure PWM."""
|
||||
self.pwm_deinit(pin)
|
||||
resp = self._hid_xfer(bytes([self.PWM_INIT_PIN, pin.id]), True)
|
||||
if resp[1] != self.RESP_OK:
|
||||
raise RuntimeError("PWM init error.")
|
||||
|
||||
self.pwm_set_frequency(pin, frequency)
|
||||
self.pwm_set_duty_cycle(pin, duty_cycle)
|
||||
|
||||
def pwm_deinit(self, pin):
|
||||
"""Deinit PWM."""
|
||||
self._hid_xfer(bytes([self.PWM_DEINIT_PIN, pin.id]))
|
||||
|
||||
def pwm_get_frequency(self, pin):
|
||||
"""PWM get freq."""
|
||||
resp = self._hid_xfer(bytes([self.PWM_GET_FREQ, pin.id]), True)
|
||||
if resp[1] != self.RESP_OK:
|
||||
raise RuntimeError("PWM get frequency error.")
|
||||
return int.from_bytes(resp[3 : 3 + 4], byteorder="little")
|
||||
|
||||
def pwm_set_frequency(self, pin, frequency):
|
||||
"""PWM set freq."""
|
||||
resp = self._hid_xfer(
|
||||
bytes([self.PWM_SET_FREQ, pin.id])
|
||||
+ frequency.to_bytes(4, byteorder="little"),
|
||||
True,
|
||||
)
|
||||
if resp[1] != self.RESP_OK:
|
||||
# pylint: disable=no-else-raise
|
||||
if resp[3] == 0x01:
|
||||
raise RuntimeError("PWM different frequency on same slice.")
|
||||
elif resp[3] == 0x02:
|
||||
raise RuntimeError("PWM frequency too low.")
|
||||
elif resp[3] == 0x03:
|
||||
raise RuntimeError("PWM frequency too high.")
|
||||
else:
|
||||
raise RuntimeError("PWM frequency error.")
|
||||
|
||||
def pwm_get_duty_cycle(self, pin):
|
||||
"""PWM get duty cycle."""
|
||||
resp = self._hid_xfer(bytes([self.PWM_GET_DUTY_U16, pin.id]), True)
|
||||
if resp[1] != self.RESP_OK:
|
||||
raise RuntimeError("PWM get duty cycle error.")
|
||||
return int.from_bytes(resp[3 : 3 + 4], byteorder="little")
|
||||
|
||||
def pwm_set_duty_cycle(self, pin, duty_cycle):
|
||||
"""PWM set duty cycle."""
|
||||
resp = self._hid_xfer(
|
||||
bytes([self.PWM_SET_DUTY_U16, pin.id])
|
||||
+ duty_cycle.to_bytes(2, byteorder="little"),
|
||||
True,
|
||||
)
|
||||
if resp[1] != self.RESP_OK:
|
||||
raise RuntimeError("PWM set duty cycle error.")
|
||||
|
||||
|
||||
rp2040_u2if = RP2040_u2if()
|
|
@ -0,0 +1,180 @@
|
|||
# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""SPI Classes for RP2040s with u2if firmware"""
|
||||
from .rp2040_u2if import rp2040_u2if
|
||||
|
||||
|
||||
# pylint: disable=protected-access, no-self-use
|
||||
class SPI:
|
||||
"""SPI Base Class for RP2040 u2if"""
|
||||
|
||||
MSB = 0
|
||||
|
||||
def __init__(self, index, *, baudrate=100000):
|
||||
self._index = index
|
||||
self._frequency = baudrate
|
||||
rp2040_u2if.spi_set_port(self._index)
|
||||
rp2040_u2if.spi_configure(self._frequency)
|
||||
|
||||
# pylint: disable=too-many-arguments,unused-argument
|
||||
def init(
|
||||
self,
|
||||
baudrate=1000000,
|
||||
polarity=0,
|
||||
phase=0,
|
||||
bits=8,
|
||||
firstbit=MSB,
|
||||
sck=None,
|
||||
mosi=None,
|
||||
miso=None,
|
||||
):
|
||||
"""Initialize the Port"""
|
||||
self._frequency = baudrate
|
||||
rp2040_u2if.spi_set_port(self._index)
|
||||
rp2040_u2if.spi_configure(self._frequency)
|
||||
|
||||
# pylint: enable=too-many-arguments
|
||||
|
||||
@property
|
||||
def frequency(self):
|
||||
"""Return the current frequency"""
|
||||
return self._frequency
|
||||
|
||||
def write(self, buf, start=0, end=None):
|
||||
"""Write data from the buffer to SPI"""
|
||||
rp2040_u2if.spi_write(buf, start=start, end=end)
|
||||
|
||||
def readinto(self, buf, start=0, end=None, write_value=0):
|
||||
"""Read data from SPI and into the buffer"""
|
||||
rp2040_u2if.spi_readinto(buf, start=start, end=end, write_value=write_value)
|
||||
|
||||
# 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
|
||||
"""
|
||||
rp2040_u2if.spi_write_readinto(
|
||||
buffer_out,
|
||||
buffer_in,
|
||||
out_start=out_start,
|
||||
out_end=out_end,
|
||||
in_start=in_start,
|
||||
in_end=in_end,
|
||||
)
|
||||
|
||||
# pylint: enable=too-many-arguments
|
||||
|
||||
|
||||
class SPI_Pico(SPI):
|
||||
"""SPI Class for Pico u2if"""
|
||||
|
||||
def __init__(self, clock, *, baudrate=100000):
|
||||
index = None
|
||||
if clock.id == 18:
|
||||
index = 0
|
||||
if clock.id == 10:
|
||||
index = 1
|
||||
if index is None:
|
||||
raise ValueError("No SPI port on specified pin.")
|
||||
super().__init__(index, baudrate=baudrate)
|
||||
|
||||
|
||||
class SPI_Feather(SPI):
|
||||
"""SPI Class for Feather u2if"""
|
||||
|
||||
def __init__(self, clock, *, baudrate=100000):
|
||||
index = None
|
||||
if clock.id == 18:
|
||||
index = 0
|
||||
if index is None:
|
||||
raise ValueError("No SPI port on specified pin.")
|
||||
super().__init__(index, baudrate=baudrate)
|
||||
|
||||
|
||||
class SPI_Feather_CAN(SPI):
|
||||
"""SPI Class for Feather EPD u2if"""
|
||||
|
||||
def __init__(self, clock, *, baudrate=100000):
|
||||
index = None
|
||||
if clock.id == 14:
|
||||
index = 1
|
||||
if index is None:
|
||||
raise ValueError("No SPI port on specified pin.")
|
||||
super().__init__(index, baudrate=baudrate)
|
||||
|
||||
|
||||
class SPI_Feather_EPD(SPI):
|
||||
"""SPI Class for Feather EPD u2if"""
|
||||
|
||||
def __init__(self, clock, *, baudrate=100000):
|
||||
index = None
|
||||
if clock.id == 22:
|
||||
index = 0
|
||||
if clock.id == 14:
|
||||
index = 1
|
||||
if index is None:
|
||||
raise ValueError("No SPI port on specified pin.")
|
||||
super().__init__(index, baudrate=baudrate)
|
||||
|
||||
|
||||
class SPI_Feather_RFM(SPI):
|
||||
"""SPI Class for Feather EPD u2if"""
|
||||
|
||||
def __init__(self, clock, *, baudrate=100000):
|
||||
index = None
|
||||
if clock.id == 14:
|
||||
index = 1
|
||||
if index is None:
|
||||
raise ValueError("No SPI port on specified pin.")
|
||||
super().__init__(index, baudrate=baudrate)
|
||||
|
||||
|
||||
class SPI_QTPY(SPI):
|
||||
"""SPI Class for QT Py u2if"""
|
||||
|
||||
def __init__(self, clock, *, baudrate=100000):
|
||||
index = None
|
||||
if clock.id == 6:
|
||||
index = 0
|
||||
if index is None:
|
||||
raise ValueError("No SPI port on specified pin.")
|
||||
super().__init__(index, baudrate=baudrate)
|
||||
|
||||
|
||||
class SPI_ItsyBitsy(SPI):
|
||||
"""SPI Class for ItsyBitsy u2if"""
|
||||
|
||||
def __init__(self, clock, *, baudrate=100000):
|
||||
index = None
|
||||
if clock.id == 18:
|
||||
index = 0
|
||||
if index is None:
|
||||
raise ValueError("No SPI port on specified pin.")
|
||||
super().__init__(index, baudrate=baudrate)
|
||||
|
||||
|
||||
class SPI_MacroPad(SPI):
|
||||
"""SPI Class for MacroPad u2if"""
|
||||
|
||||
def __init__(self, clock, *, baudrate=100000):
|
||||
index = None
|
||||
if clock.id == 26:
|
||||
index = 1
|
||||
if index is None:
|
||||
raise ValueError("No SPI port on specified pin.")
|
||||
super().__init__(index, baudrate=baudrate)
|
||||
|
||||
|
||||
class SPI_KB2040(SPI):
|
||||
"""SPI Class for KB2040 u2if"""
|
||||
|
||||
def __init__(self, clock, *, baudrate=100000):
|
||||
index = None
|
||||
if clock.id == 18:
|
||||
index = 0
|
||||
if index is None:
|
||||
raise ValueError("No SPI port on specified pin.")
|
||||
super().__init__(index, baudrate=baudrate)
|
Loading…
Add table
Add a link
Reference in a new issue