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
|
@ -0,0 +1,36 @@
|
|||
# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""Generic Connection class for Binho Nova to keep track of connection"""
|
||||
|
||||
|
||||
class Connection:
|
||||
"""Connection class"""
|
||||
|
||||
__instance = None
|
||||
|
||||
@staticmethod
|
||||
def getInstance():
|
||||
"""Static access method."""
|
||||
if Connection.__instance is None:
|
||||
Connection()
|
||||
return Connection.__instance
|
||||
|
||||
def __init__(self):
|
||||
"""Virtually private constructor."""
|
||||
if Connection.__instance is not None:
|
||||
raise Exception( # pylint: disable=broad-exception-raised
|
||||
"This class is a singleton!"
|
||||
)
|
||||
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from binhoHostAdapter import binhoHostAdapter
|
||||
from binhoHostAdapter import binhoUtilities
|
||||
|
||||
# pylint: enable=import-outside-toplevel
|
||||
devices = binhoUtilities.listAvailableDevices()
|
||||
|
||||
if len(devices) > 0:
|
||||
Connection.__instance = binhoHostAdapter.binhoHostAdapter(devices[0])
|
||||
else:
|
||||
raise RuntimeError("No Binho Nova found!")
|
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,182 @@
|
|||
# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""I2C Class for Binho Nova"""
|
||||
|
||||
from adafruit_blinka.microcontroller.nova import Connection
|
||||
|
||||
|
||||
class I2C:
|
||||
"""Custom I2C Class for Binho Nova"""
|
||||
|
||||
WHR_PAYLOAD_MAX_LENGTH = 1024
|
||||
|
||||
def __init__(self, *, frequency=400000):
|
||||
self._nova = Connection.getInstance()
|
||||
self._nova.setNumericalBase(10)
|
||||
self._nova.setOperationMode(0, "I2C")
|
||||
self._nova.setPullUpStateI2C(0, "EN")
|
||||
self._nova.setClockI2C(0, frequency)
|
||||
|
||||
self._novaCMDVer = "0"
|
||||
if hasattr(self._nova, "getCommandVer"):
|
||||
response = self._nova.getCommandVer().split(" ")
|
||||
if response[0] != "-NG":
|
||||
self._novaCMDVer = response[1]
|
||||
|
||||
def __del__(self):
|
||||
"""Close Nova on delete"""
|
||||
self._nova.close()
|
||||
|
||||
def scan(self):
|
||||
"""Perform an I2C Device Scan"""
|
||||
scanResults = []
|
||||
|
||||
for i in range(8, 121):
|
||||
result = self._nova.scanAddrI2C(0, i << 1)
|
||||
|
||||
resp = result.split(" ")
|
||||
|
||||
if resp[3] == "OK":
|
||||
scanResults.append(i)
|
||||
|
||||
return scanResults
|
||||
|
||||
def writeto(self, address, buffer, *, start=0, end=None, stop=True):
|
||||
"""Write data from the buffer to an address"""
|
||||
end = end if end else len(buffer)
|
||||
readBytes = 0
|
||||
if int(self._novaCMDVer) >= 1:
|
||||
chunks, rest = divmod(end - start, self.WHR_PAYLOAD_MAX_LENGTH)
|
||||
for i in range(chunks):
|
||||
chunk_start = start + i * self.WHR_PAYLOAD_MAX_LENGTH
|
||||
chunk_end = chunk_start + self.WHR_PAYLOAD_MAX_LENGTH
|
||||
self._nova.writeToReadFromI2C(
|
||||
0,
|
||||
address << 1,
|
||||
stop,
|
||||
readBytes,
|
||||
chunk_end - chunk_start,
|
||||
buffer[chunk_start:chunk_end],
|
||||
)
|
||||
if rest:
|
||||
self._nova.writeToReadFromI2C(
|
||||
0, address << 1, stop, readBytes, rest, buffer[-1 * rest :]
|
||||
)
|
||||
else:
|
||||
self._nova.startI2C(0, address << 1)
|
||||
|
||||
for i in range(start, end):
|
||||
self._nova.writeByteI2C(0, buffer[i])
|
||||
|
||||
if stop:
|
||||
self._nova.endI2C(0)
|
||||
else:
|
||||
self._nova.endI2C(0, True)
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def readfrom_into(self, address, buffer, *, start=0, end=None, stop=True):
|
||||
"""Read data from an address and into the buffer"""
|
||||
end = end if end else len(buffer)
|
||||
result = self._nova.readBytesI2C(0, address << 1, len(buffer[start:end]))
|
||||
|
||||
if result != "-NG":
|
||||
resp = result.split(" ")
|
||||
|
||||
for i in range(len(buffer[start:end])):
|
||||
buffer[start + i] = int(resp[2 + i])
|
||||
else:
|
||||
raise RuntimeError(
|
||||
"Received error response from Binho Nova, result = " + result
|
||||
)
|
||||
|
||||
# pylint: disable=too-many-locals,too-many-branches
|
||||
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
|
||||
"""
|
||||
out_end = out_end if out_end else len(buffer_out)
|
||||
in_end = in_end if in_end else len(buffer_in)
|
||||
if int(self._novaCMDVer) >= 1:
|
||||
totalIn = in_end - in_start
|
||||
totalOut = out_end - out_start
|
||||
totalBytes = totalIn
|
||||
if totalOut > totalIn:
|
||||
totalBytes = totalOut
|
||||
chunks, rest = divmod(totalBytes, self.WHR_PAYLOAD_MAX_LENGTH)
|
||||
if rest > 0:
|
||||
chunks += 1
|
||||
|
||||
for i in range(chunks):
|
||||
# calculate the number of bytes to be written and read
|
||||
numInBytes = self.WHR_PAYLOAD_MAX_LENGTH
|
||||
if totalIn < self.WHR_PAYLOAD_MAX_LENGTH:
|
||||
numInBytes = totalIn
|
||||
numOutBytes = self.WHR_PAYLOAD_MAX_LENGTH
|
||||
if totalOut < self.WHR_PAYLOAD_MAX_LENGTH:
|
||||
numOutBytes = totalOut
|
||||
|
||||
# setup the buffer out chunk offset
|
||||
buffer = "0"
|
||||
if numOutBytes > 0:
|
||||
chunk_start = out_start + i * self.WHR_PAYLOAD_MAX_LENGTH
|
||||
chunk_end = chunk_start + numOutBytes
|
||||
buffer = buffer_out[chunk_start:chunk_end]
|
||||
|
||||
result = self._nova.writeToReadFromI2C(
|
||||
0, address << 1, stop, numInBytes, numOutBytes, buffer
|
||||
)
|
||||
totalIn -= numInBytes
|
||||
totalOut -= numOutBytes
|
||||
|
||||
if result != "-NG":
|
||||
if numInBytes:
|
||||
resp = result.split(" ")
|
||||
resp = resp[2]
|
||||
|
||||
for j in range(numInBytes):
|
||||
buffer_in[
|
||||
in_start + i * self.WHR_PAYLOAD_MAX_LENGTH + j
|
||||
] = int(resp[j * 2] + resp[j * 2 + 1], 16)
|
||||
else:
|
||||
raise RuntimeError(
|
||||
"Received error response from Binho Nova, result = " + result
|
||||
)
|
||||
else:
|
||||
self._nova.startI2C(0, address << 1)
|
||||
|
||||
for i in range(out_start, out_end):
|
||||
self._nova.writeByteI2C(0, buffer_out[i])
|
||||
|
||||
if stop:
|
||||
self._nova.endI2C(0)
|
||||
else:
|
||||
self._nova.endI2C(0, True)
|
||||
|
||||
result = self._nova.readBytesI2C(
|
||||
0, address << 1, len(buffer_in[in_start:in_end])
|
||||
)
|
||||
|
||||
if result != "-NG":
|
||||
resp = result.split(" ")
|
||||
|
||||
for i in range(len(buffer_in[in_start:in_end])):
|
||||
buffer_in[in_start + i] = int(resp[2 + i])
|
||||
else:
|
||||
raise RuntimeError(
|
||||
"Received error response from Binho Nova, result = " + result
|
||||
)
|
||||
|
||||
|
||||
# pylint: enable=unused-argument,too-many-locals,too-many-branches
|
|
@ -0,0 +1,85 @@
|
|||
# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""Binho Nova pin names"""
|
||||
|
||||
|
||||
class Pin:
|
||||
"""A basic Pin class for use with Binho Nova."""
|
||||
|
||||
IN = "DIN"
|
||||
OUT = "DOUT"
|
||||
AIN = "AIN"
|
||||
AOUT = "AOUT"
|
||||
PWM = "PWM"
|
||||
LOW = 0
|
||||
HIGH = 1
|
||||
|
||||
_nova = None
|
||||
|
||||
def __init__(self, pin_id=None):
|
||||
if not Pin._nova:
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from adafruit_blinka.microcontroller.nova import Connection
|
||||
|
||||
# pylint: enable=import-outside-toplevel
|
||||
|
||||
Pin._nova = Connection.getInstance()
|
||||
# check if pin is valid
|
||||
if pin_id > 4:
|
||||
raise ValueError("Invalid pin {}.".format(pin_id))
|
||||
|
||||
self.id = pin_id
|
||||
|
||||
def init(self, mode=IN, pull=None):
|
||||
"""Initialize the Pin"""
|
||||
if self.id is None:
|
||||
raise RuntimeError("Can not init a None type pin.")
|
||||
# Nova does't have configurable internal pulls for
|
||||
if pull:
|
||||
raise ValueError("Internal pull up/down not currently supported.")
|
||||
Pin._nova.setIOpinMode(self.id, mode)
|
||||
|
||||
def value(self, val=None):
|
||||
"""Set or return the Pin Value"""
|
||||
if self.id is None:
|
||||
raise RuntimeError("Can not access a None type pin.")
|
||||
# read
|
||||
if val is None:
|
||||
return int(Pin._nova.getIOpinValue(self.id).split("VALUE ")[1])
|
||||
# write
|
||||
if val in (self.LOW, self.HIGH):
|
||||
Pin._nova.setIOpinValue(self.id, val)
|
||||
return None
|
||||
raise RuntimeError("Invalid value for pin")
|
||||
|
||||
|
||||
# create pin instances for each pin
|
||||
IO0 = Pin(0)
|
||||
IO1 = Pin(1)
|
||||
IO2 = Pin(2)
|
||||
IO3 = Pin(3)
|
||||
IO4 = Pin(4)
|
||||
|
||||
SCL = IO2
|
||||
SDA = IO0
|
||||
SCK = SCLK = IO3
|
||||
MOSI = IO4
|
||||
MISO = IO2
|
||||
SS0 = IO0
|
||||
SS1 = IO1
|
||||
|
||||
PWM0 = IO0
|
||||
# No PWM support on IO1
|
||||
PWM2 = IO2
|
||||
PWM3 = IO3
|
||||
PWM4 = IO4
|
||||
|
||||
# orderd as (channel, pin), id
|
||||
pwmOuts = (((1, 0), PWM0), ((1, 2), PWM2), ((1, 3), PWM3), ((1, 4), PWM4))
|
||||
|
||||
UART1_TX = IO4
|
||||
UART1_RX = IO3
|
||||
|
||||
# ordered as uartId, txId, rxId
|
||||
uartPorts = ((0, UART1_TX, UART1_RX),)
|
|
@ -0,0 +1,241 @@
|
|||
# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""PWMOut Class for Binho Nova"""
|
||||
|
||||
try:
|
||||
from microcontroller.pin import pwmOuts
|
||||
except ImportError:
|
||||
raise RuntimeError("No PWM outputs defined for this board") from ImportError
|
||||
|
||||
from microcontroller.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"""
|
||||
|
||||
# Nova instance
|
||||
_nova = None
|
||||
MAX_CYCLE_LEVEL = 1024
|
||||
|
||||
def __init__(self, pin, *, frequency=750, duty_cycle=0, variable_frequency=False):
|
||||
"""Instantiate a PWM object and open the sysfs PWM corresponding to the
|
||||
specified channel and pin.
|
||||
|
||||
Args:
|
||||
pin (Pin): CircuitPython Pin object to output to
|
||||
duty_cycle (int) : The fraction of each pulse which is high. 16-bit
|
||||
frequency (int) : target frequency in Hertz (32-bit)
|
||||
variable_frequency (bool) : True if the frequency will change over time
|
||||
|
||||
Returns:
|
||||
PWMOut: PWMOut object.
|
||||
|
||||
Raises:
|
||||
PWMError: if an I/O or OS error occurs.
|
||||
TypeError: if `channel` or `pin` types are invalid.
|
||||
ValueError: if PWM channel does not exist.
|
||||
|
||||
"""
|
||||
if PWMOut._nova is None:
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from adafruit_blinka.microcontroller.nova import Connection
|
||||
|
||||
# pylint: enable=import-outside-toplevel
|
||||
|
||||
PWMOut._nova = Connection.getInstance()
|
||||
|
||||
PWMOut._nova.setOperationMode(0, "IO")
|
||||
self._pwmpin = None
|
||||
self._channel = None
|
||||
self._enable = False
|
||||
self._open(pin, duty_cycle, frequency, variable_frequency)
|
||||
|
||||
def __del__(self):
|
||||
self.deinit()
|
||||
PWMOut._nova.close()
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, t, value, traceback):
|
||||
self.deinit()
|
||||
|
||||
def _open(self, pin, duty=0, freq=750, variable_frequency=False):
|
||||
self._channel = None
|
||||
for pwmpair in pwmOuts:
|
||||
if pwmpair[1] == pin:
|
||||
self._channel = pwmpair[0][0]
|
||||
self._pwmpin = pwmpair[0][1]
|
||||
|
||||
self._pin = pin
|
||||
if self._channel is None:
|
||||
raise RuntimeError("No PWM channel found for this Pin")
|
||||
|
||||
if variable_frequency:
|
||||
print("Variable Frequency is not supported, continuing without it...")
|
||||
|
||||
PWMOut._nova.setIOpinMode(self._pwmpin, Pin.PWM)
|
||||
|
||||
# set frequency
|
||||
self.frequency = freq
|
||||
# set period
|
||||
self._period = self._get_period()
|
||||
|
||||
# set duty
|
||||
self.duty_cycle = duty
|
||||
|
||||
self._set_enabled(True)
|
||||
|
||||
def deinit(self):
|
||||
"""Deinit the Nova PWM."""
|
||||
# pylint: disable=broad-except
|
||||
try:
|
||||
if self._channel is not None:
|
||||
# self.duty_cycle = 0
|
||||
self._set_enabled(False) # make to disable before unexport
|
||||
|
||||
except Exception as e:
|
||||
# due to a race condition for which I have not yet been
|
||||
# able to find the root cause, deinit() often fails
|
||||
# but it does not effect future usage of the pwm pin
|
||||
print(
|
||||
"warning: failed to deinitialize pwm pin {0}:{1} due to: {2}\n".format(
|
||||
self._channel, self._pwmpin, type(e).__name__
|
||||
)
|
||||
)
|
||||
finally:
|
||||
self._channel = None
|
||||
self._pwmpin = None
|
||||
# pylint: enable=broad-except
|
||||
|
||||
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."
|
||||
)
|
||||
|
||||
# Mutable properties
|
||||
|
||||
def _get_period(self):
|
||||
return 1.0 / self._get_frequency()
|
||||
|
||||
def _set_period(self, period):
|
||||
if not isinstance(period, (int, float)):
|
||||
raise TypeError("Invalid period type, should be int or float.")
|
||||
|
||||
self._set_frequency(1.0 / period)
|
||||
|
||||
period = property(_get_period, _set_period)
|
||||
|
||||
"""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
|
||||
"""
|
||||
|
||||
def _get_duty_cycle(self):
|
||||
duty_cycle = Pin._nova.getIOpinValue(self._pwmpin)
|
||||
|
||||
# Convert duty cycle to ratio from 0.0 to 1.0
|
||||
duty_cycle = duty_cycle / PWMOut.MAX_CYCLE_LEVEL
|
||||
|
||||
# convert to 16-bit
|
||||
duty_cycle = int(duty_cycle * 65535)
|
||||
return duty_cycle
|
||||
|
||||
def _set_duty_cycle(self, duty_cycle):
|
||||
if not isinstance(duty_cycle, (int, float)):
|
||||
raise TypeError("Invalid duty cycle type, should be int or float.")
|
||||
|
||||
# convert from 16-bit
|
||||
duty_cycle /= 65535.0
|
||||
if not 0.0 <= duty_cycle <= 1.0:
|
||||
raise ValueError("Invalid duty cycle value, should be between 0.0 and 1.0.")
|
||||
|
||||
# Convert duty cycle from ratio to 1024 levels
|
||||
duty_cycle = duty_cycle * PWMOut.MAX_CYCLE_LEVEL
|
||||
|
||||
# Set duty cycle
|
||||
# pylint: disable=protected-access
|
||||
Pin._nova.setIOpinValue(self._pwmpin, duty_cycle)
|
||||
# pylint: enable=protected-access
|
||||
|
||||
duty_cycle = property(_get_duty_cycle, _set_duty_cycle)
|
||||
"""Get or set the PWM's output duty cycle as a ratio from 0.0 to 1.0.
|
||||
|
||||
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
|
||||
"""
|
||||
|
||||
def _get_frequency(self):
|
||||
return int(PWMOut._nova.getIOpinPWMFreq(self._pwmpin).split("PWMFREQ ")[1])
|
||||
|
||||
def _set_frequency(self, frequency):
|
||||
if not isinstance(frequency, (int, float)):
|
||||
raise TypeError("Invalid frequency type, should be int or float.")
|
||||
|
||||
PWMOut._nova.setIOpinPWMFreq(self._pwmpin, frequency)
|
||||
|
||||
frequency = property(_get_frequency, _set_frequency)
|
||||
"""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
|
||||
"""
|
||||
|
||||
def _get_enabled(self):
|
||||
enabled = self._enable
|
||||
|
||||
if enabled == "1":
|
||||
return True
|
||||
if enabled == "0":
|
||||
return False
|
||||
|
||||
raise PWMError(None, 'Unknown enabled value: "%s"' % enabled)
|
||||
|
||||
def _set_enabled(self, value):
|
||||
"""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
|
||||
"""
|
||||
if not isinstance(value, bool):
|
||||
raise TypeError("Invalid enabled type, should be string.")
|
||||
self._enable = value
|
||||
if not self._enable:
|
||||
self._set_duty_cycle(0.0)
|
||||
|
||||
# String representation
|
||||
|
||||
def __str__(self):
|
||||
return "PWM%d, pin %s (freq=%f Hz, duty_cycle=%f%%)" % (
|
||||
self._pin,
|
||||
self._pin,
|
||||
self.frequency,
|
||||
self.duty_cycle * 100,
|
||||
)
|
|
@ -0,0 +1,218 @@
|
|||
# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""SPI Class for Binho Nova"""
|
||||
from adafruit_blinka.microcontroller.nova import Connection
|
||||
|
||||
|
||||
class SPI:
|
||||
"""Custom SPI Class for Binho Nova"""
|
||||
|
||||
MSB = 0
|
||||
BUFFER_PAYLOAD_MAX_LENGTH = 64
|
||||
WHR_PAYLOAD_MAX_LENGTH = 1024
|
||||
|
||||
def __init__(self, clock):
|
||||
self._nova = Connection.getInstance()
|
||||
self._nova.setNumericalBase(10)
|
||||
self._nova.setOperationMode(0, "SPI")
|
||||
self._nova.setClockSPI(0, clock)
|
||||
self._nova.setModeSPI(0, 0)
|
||||
self._nova.setIOpinMode(0, "DOUT")
|
||||
self._nova.setIOpinMode(1, "DOUT")
|
||||
self._nova.beginSPI(0)
|
||||
self._novaCMDVer = "0"
|
||||
if hasattr(self._nova, "getCommandVer"):
|
||||
response = self._nova.getCommandVer().split(" ")
|
||||
if response[0] != "-NG":
|
||||
self._novaCMDVer = response[1]
|
||||
|
||||
# Cpol and Cpha set by mode
|
||||
# Mode Cpol Cpha
|
||||
# 0 0 0
|
||||
# 1 0 1
|
||||
# 2 1 0
|
||||
# 3 1 1
|
||||
|
||||
def __del__(self):
|
||||
"""Close Nova on delete"""
|
||||
self._nova.close()
|
||||
|
||||
# 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._nova.setClockSPI(0, baudrate)
|
||||
self._nova.setModeSPI(0, (polarity << 1) | (phase))
|
||||
|
||||
# pylint: enable=too-many-arguments,unused-argument
|
||||
|
||||
@staticmethod
|
||||
def get_received_data(lineOutput):
|
||||
"""Return any received data"""
|
||||
return lineOutput.split("RXD ")[1]
|
||||
|
||||
@property
|
||||
def frequency(self):
|
||||
"""Return the current frequency"""
|
||||
return self._nova.getClockSPI(0).split("CLK ")[1]
|
||||
|
||||
def write(self, buf, start=0, end=None):
|
||||
"""Write data from the buffer to SPI"""
|
||||
end = end if end else len(buf)
|
||||
payloadMaxLength = self.BUFFER_PAYLOAD_MAX_LENGTH
|
||||
if int(self._novaCMDVer) >= 1:
|
||||
payloadMaxLength = self.WHR_PAYLOAD_MAX_LENGTH
|
||||
chunks, rest = divmod(end - start, payloadMaxLength)
|
||||
|
||||
for i in range(chunks):
|
||||
chunk_start = start + i * payloadMaxLength
|
||||
chunk_end = chunk_start + payloadMaxLength
|
||||
if int(self._novaCMDVer) >= 1:
|
||||
self._nova.writeToReadFromSPI(
|
||||
0, True, False, chunk_end - chunk_start, buf[chunk_start:chunk_end]
|
||||
)
|
||||
else:
|
||||
self._nova.clearBuffer(0)
|
||||
self._nova.writeToBuffer(0, 0, buf[chunk_start:chunk_end])
|
||||
self._nova.transferBufferSPI(0, chunk_end - chunk_start + 1)
|
||||
if rest:
|
||||
if int(self._novaCMDVer) >= 1:
|
||||
self._nova.writeToReadFromSPI(0, True, False, rest, buf[-1 * rest :])
|
||||
else:
|
||||
self._nova.clearBuffer(0)
|
||||
self._nova.writeToBuffer(0, 0, buf[-1 * rest :])
|
||||
self._nova.transferBufferSPI(0, rest)
|
||||
|
||||
def readinto(self, buf, start=0, end=None, write_value=0):
|
||||
"""Read data from SPI and into the buffer"""
|
||||
end = end if end else len(buf)
|
||||
if int(self._novaCMDVer) >= 1:
|
||||
chunks, rest = divmod(end - start, self.WHR_PAYLOAD_MAX_LENGTH)
|
||||
i = 0
|
||||
for i in range(chunks):
|
||||
chunk_start = start + i * self.WHR_PAYLOAD_MAX_LENGTH
|
||||
chunk_end = chunk_start + self.WHR_PAYLOAD_MAX_LENGTH
|
||||
result = self._nova.writeToReadFromSPI(
|
||||
0, False, True, chunk_end - chunk_start, write_value
|
||||
)
|
||||
if result != "-NG":
|
||||
resp = result.split(" ")
|
||||
resp = resp[2]
|
||||
# loop over half of resp len as we're reading 2 chars at a time to form a byte
|
||||
loops = int(len(resp) / 2)
|
||||
for j in range(loops):
|
||||
buf[(i * self.WHR_PAYLOAD_MAX_LENGTH) + start + j] = int(
|
||||
resp[j * 2] + resp[j * 2 + 1], 16
|
||||
)
|
||||
else:
|
||||
raise RuntimeError(
|
||||
"Received error response from Binho Nova, result = " + result
|
||||
)
|
||||
if rest:
|
||||
result = self._nova.writeToReadFromSPI(
|
||||
0, False, True, rest, write_value
|
||||
)
|
||||
if result != "-NG":
|
||||
resp = result.split(" ")
|
||||
resp = resp[2]
|
||||
|
||||
# loop over half of resp len as we're reading 2 chars at a time to form a byte
|
||||
loops = int(len(resp) / 2)
|
||||
for j in range(loops):
|
||||
buf[(i * self.WHR_PAYLOAD_MAX_LENGTH) + start + j] = int(
|
||||
resp[j * 2] + resp[j * 2 + 1], 16
|
||||
)
|
||||
else:
|
||||
raise RuntimeError(
|
||||
"Received error response from Binho Nova, result = " + result
|
||||
)
|
||||
else:
|
||||
for i in range(start, end):
|
||||
buf[start + i] = int(
|
||||
self.get_received_data(self._nova.transferSPI(0, write_value))
|
||||
)
|
||||
|
||||
# pylint: disable=too-many-arguments,too-many-locals,too-many-branches
|
||||
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
|
||||
"""
|
||||
out_end = out_end if out_end else len(buffer_out)
|
||||
in_end = in_end if in_end else len(buffer_in)
|
||||
readlen = in_end - in_start
|
||||
writelen = out_end - out_start
|
||||
if readlen > writelen:
|
||||
# resize out and pad with 0's
|
||||
tmp = bytearray(buffer_out)
|
||||
tmp.extend([0] * (readlen - len(buffer_out)))
|
||||
buffer_out = tmp
|
||||
|
||||
if int(self._novaCMDVer) >= 1:
|
||||
chunks, rest = divmod(len(buffer_out), self.WHR_PAYLOAD_MAX_LENGTH)
|
||||
i = 0
|
||||
for i in range(chunks):
|
||||
chunk_start = out_start + i * self.WHR_PAYLOAD_MAX_LENGTH
|
||||
chunk_end = chunk_start + self.WHR_PAYLOAD_MAX_LENGTH
|
||||
result = self._nova.writeToReadFromSPI(
|
||||
0,
|
||||
True,
|
||||
True,
|
||||
chunk_end - chunk_start,
|
||||
buffer_out[chunk_start:chunk_end],
|
||||
)
|
||||
|
||||
if result != "-NG":
|
||||
resp = result.split(" ")
|
||||
resp = resp[2]
|
||||
|
||||
# loop over half of resp len as we're reading 2 chars at a time to form a byte
|
||||
loops = int(len(resp) / 2)
|
||||
for j in range(loops):
|
||||
buffer_in[
|
||||
(i * self.WHR_PAYLOAD_MAX_LENGTH) + in_start + j
|
||||
] = int(resp[j * 2] + resp[j * 2 + 1], 16)
|
||||
else:
|
||||
raise RuntimeError(
|
||||
"Received error response from Binho Nova, result = " + result
|
||||
)
|
||||
if rest:
|
||||
result = self._nova.writeToReadFromSPI(
|
||||
0, True, True, rest, buffer_out[-1 * rest :]
|
||||
)
|
||||
if result != "-NG":
|
||||
resp = result.split(" ")
|
||||
resp = resp[2]
|
||||
|
||||
# loop over half of resp len as we're reading 2 chars at a time to form a byte
|
||||
loops = int(len(resp) / 2)
|
||||
for j in range(loops):
|
||||
buffer_in[
|
||||
(i * self.WHR_PAYLOAD_MAX_LENGTH) + in_start + j
|
||||
] = int(resp[j * 2] + resp[j * 2 + 1], 16)
|
||||
else:
|
||||
raise RuntimeError(
|
||||
"Received error response from Binho Nova, result = " + result
|
||||
)
|
||||
print(buffer_in)
|
||||
else:
|
||||
for data_out in buffer_out:
|
||||
data_in = int(
|
||||
self.get_received_data(self._nova.transferSPI(0, data_out))
|
||||
)
|
||||
if i < readlen:
|
||||
buffer_in[in_start + i] = data_in
|
||||
i += 1
|
||||
|
||||
# pylint: enable=too-many-arguments,too-many-locals,too-many-branches
|
|
@ -0,0 +1,87 @@
|
|||
# SPDX-FileCopyrightText: 2021 Melissa LeBlanc-Williams for Adafruit Industries
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
"""UART Class for Binho Nova"""
|
||||
|
||||
from adafruit_blinka.microcontroller.nova import Connection
|
||||
|
||||
|
||||
class UART:
|
||||
"""Custom UART Class for Binho Nova"""
|
||||
|
||||
ESCAPE_SEQUENCE = "+++UART0"
|
||||
|
||||
# pylint: disable=too-many-arguments,unused-argument
|
||||
def __init__(
|
||||
self,
|
||||
portid,
|
||||
baudrate=9600,
|
||||
bits=8,
|
||||
parity=None,
|
||||
stop=1,
|
||||
timeout=1000,
|
||||
read_buf_len=None,
|
||||
flow=None,
|
||||
):
|
||||
self._nova = Connection.getInstance()
|
||||
|
||||
self._id = portid
|
||||
self._baudrate = baudrate
|
||||
self._parity = parity
|
||||
self._bits = bits
|
||||
self._stop = stop
|
||||
self._timeout = timeout
|
||||
|
||||
if flow is not None: # default 0
|
||||
raise NotImplementedError(
|
||||
"Parameter '{}' unsupported on Binho Nova".format("flow")
|
||||
)
|
||||
|
||||
self._nova.setOperationMode(self._id, "UART")
|
||||
self._nova.setBaudRateUART(self._id, baudrate)
|
||||
self._nova.setDataBitsUART(self._id, bits)
|
||||
self._nova.setParityUART(self._id, parity)
|
||||
self._nova.setStopBitsUART(self._id, stop)
|
||||
self._nova.setEscapeSequenceUART(self._id, UART.ESCAPE_SEQUENCE)
|
||||
self._nova.beginBridgeUART(self._id)
|
||||
|
||||
# pylint: enable=too-many-arguments,unused-argument
|
||||
def __del__(self):
|
||||
"""Close Nova on delete"""
|
||||
self.deinit()
|
||||
self._nova.close()
|
||||
|
||||
def deinit(self):
|
||||
"""Deinitialize"""
|
||||
self._nova.writeBridgeUART(UART.ESCAPE_SEQUENCE)
|
||||
self._nova.stopBridgeUART(UART.ESCAPE_SEQUENCE)
|
||||
|
||||
def read(self, nbytes=None):
|
||||
"""Read data from UART and return it"""
|
||||
if nbytes is None:
|
||||
return None
|
||||
data = bytearray()
|
||||
for _ in range(nbytes):
|
||||
data.append(ord(self._nova.readBridgeUART()))
|
||||
return data
|
||||
|
||||
def readinto(self, buf, nbytes=None):
|
||||
"""Read data from UART and into the buffer"""
|
||||
if nbytes is None:
|
||||
return None
|
||||
for _ in range(nbytes):
|
||||
buf.append(ord(self._nova.readBridgeUART()))
|
||||
return buf
|
||||
|
||||
def readline(self):
|
||||
"""Read a single line of data from UART"""
|
||||
out = self._nova.readBridgeUART()
|
||||
line = out
|
||||
while out != "\r":
|
||||
out = self._nova.readBridgeUART()
|
||||
line += out
|
||||
return line
|
||||
|
||||
def write(self, buf):
|
||||
"""Write data from the buffer to UART"""
|
||||
return self._nova.writeBridgeUART(buf)
|
Loading…
Add table
Add a link
Reference in a new issue