Merge remote-tracking branch 'BohdanBuinich/xvf3510-rpi5-compatibility' into fix/gpio
This commit is contained in:
commit
75479afcfd
|
@ -136,6 +136,7 @@ endmenu
|
|||
menu "Additional external python modules"
|
||||
source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/python-adafruit-blinka/Config.in"
|
||||
source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/python-adafruit-circuitpython-neopixel/Config.in"
|
||||
source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/python-adafruit-circuitpython-typing/Config.in"
|
||||
source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/python-adafruit-platformdetect/Config.in"
|
||||
source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/python-adafruit-pureio/Config.in"
|
||||
source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/python-adapt-parser/Config.in"
|
||||
|
@ -173,6 +174,7 @@ menu "Additional external python modules"
|
|||
source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/python-google-auth-httplib2/Config.in"
|
||||
source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/python-google-auth/Config.in"
|
||||
source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/python-google-trans-new/Config.in"
|
||||
source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/python-gpiod/Config.in"
|
||||
source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/python-gpsdclient/Config.in"
|
||||
source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/python-gtts/Config.in"
|
||||
source "$BR2_EXTERNAL_OPENVOICEOS_PATH/package/python-gtts_token/Config.in"
|
||||
|
|
|
@ -333,3 +333,5 @@ BR2_PACKAGE_USERLAND_TOOLS=y
|
|||
BR2_PACKAGE_VOCALFUSION=y
|
||||
BR2_PACKAGE_WIFI_CONNECT=y
|
||||
BR2_PACKAGE_PYTHON_SMBUS2=y
|
||||
BR2_PACKAGE_PYTHON_ADAFRUIT_BLINKA=y
|
||||
BR2_PACKAGE_PYTHON_GPIOD=y
|
|
@ -333,3 +333,5 @@ BR2_PACKAGE_USERLAND_TOOLS=y
|
|||
BR2_PACKAGE_VOCALFUSION=y
|
||||
BR2_PACKAGE_WIFI_CONNECT=y
|
||||
BR2_PACKAGE_PYTHON_SMBUS2=y
|
||||
BR2_PACKAGE_PYTHON_ADAFRUIT_BLINKA=y
|
||||
BR2_PACKAGE_PYTHON_GPIOD=y
|
|
@ -1,11 +1,14 @@
|
|||
config BR2_PACKAGE_PYTHON_ADAFRUIT_BLINKA
|
||||
bool "python-adafruit-blinka"
|
||||
select BR2_PACKAGE_PYTHON_ADAFRUIT_CIRCUITPYTHON_TYPING # runtime
|
||||
select BR2_PACKAGE_PYTHON_ADAFRUIT_PLATFORMDETECT # runtime
|
||||
select BR2_PACKAGE_PYTHON_ADAFRUIT_PUREIO # runtime
|
||||
select BR2_PACKAGE_PYTHON_PYFTDI # runtime
|
||||
select BR2_PACKAGE_PYTHON_ADAFRUIT_CIRCUITPYTHON_TYPING
|
||||
select BR2_PACKAGE_PYTHON_ADAFRUIT_PLATFORMDETECT
|
||||
select BR2_PACKAGE_PYTHON_ADAFRUIT_PUREIO
|
||||
select BR2_PACKAGE_PYTHON_PYFTDI
|
||||
select BR2_PACKAGE_PYTHON_RPI_GPIO
|
||||
select BR2_PACKAGE_PYTHON_SYSV_IPC
|
||||
select BR2_PACKAGE_PYTHON_GPIOD
|
||||
help
|
||||
CircuitPython APIs for non-CircuitPython versions of Python
|
||||
such as CPython on Linux and MicroPython.
|
||||
CircuitPython APIs for non-CircuitPython versions of Python such as
|
||||
CPython on Linux and MicroPython.
|
||||
|
||||
https://github.com/adafruit/Adafruit_Blinka
|
||||
https://pypi.org/project/Adafruit-Blinka
|
|
@ -1,5 +1,5 @@
|
|||
# md5, sha256 from https://pypi.org/pypi/adafruit-blinka/json
|
||||
md5 b15a11eb7e0910af0d5825ed386b71d6 Adafruit-Blinka-8.6.0.tar.gz
|
||||
sha256 b05f03468edc898aa07af59bafa88ca78e1b50f7d263a53e6573ace0050f64eb Adafruit-Blinka-8.6.0.tar.gz
|
||||
md5 835cabd601befbe78dc64720f7efacd6 Adafruit-Blinka-8.31.0.tar.gz
|
||||
sha256 720edca821066022e912dffcb364ea04bd3e3f208132b975876a21b2a2daa850 Adafruit-Blinka-8.31.0.tar.gz
|
||||
# Locally computed sha256 checksums
|
||||
sha256 50e0c3b5b4486be0ed420639f8a1f6f115f29101feee6bcd954a4b81db04d0f3 LICENSE
|
||||
|
|
|
@ -4,11 +4,13 @@
|
|||
#
|
||||
################################################################################
|
||||
|
||||
PYTHON_ADAFRUIT_BLINKA_VERSION = 8.6.0
|
||||
PYTHON_ADAFRUIT_BLINKA_VERSION = 8.31.0
|
||||
PYTHON_ADAFRUIT_BLINKA_SOURCE = Adafruit-Blinka-$(PYTHON_ADAFRUIT_BLINKA_VERSION).tar.gz
|
||||
PYTHON_ADAFRUIT_BLINKA_SITE = https://files.pythonhosted.org/packages/76/29/541a6a22d923fbe0d4cf52f953a2c737370cb717f8df1cbd95ab97fe2fba
|
||||
PYTHON_ADAFRUIT_BLINKA_SITE = https://files.pythonhosted.org/packages/74/ed/e51689be726338ba16f2a88373ad4690702c5ddf8668be1b0289cb279840
|
||||
PYTHON_ADAFRUIT_BLINKA_SETUP_TYPE = setuptools
|
||||
PYTHON_ADAFRUIT_BLINKA_LICENSE = MIT
|
||||
PYTHON_ADAFRUIT_BLINKA_LICENSE_FILES = LICENSE
|
||||
PYTHON_ADAFRUIT_BLINKA_BIN_ARCH_EXCLUDE = usr/lib/python$(PYTHON3_VERSION_MAJOR)/site-packages/adafruit_blinka/microcontroller/bcm283x/pulseio
|
||||
PYTHON_ADAFRUIT_BLINKA_BIN_ARCH_EXCLUDE += usr/lib/python$(PYTHON3_VERSION_MAJOR)/site-packages/adafruit_blinka/microcontroller/amlogic/a311d/pulseio
|
||||
|
||||
$(eval $(python-package))
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
config BR2_PACKAGE_PYTHON_ADAFRUIT_CIRCUITPYTHON_TYPING
|
||||
bool "python-adafruit-circuitpython-typing"
|
||||
help
|
||||
Types needed for type annotation that are not in `typing`
|
||||
|
||||
https://pypi.org/project/adafruit-circuitpython-typing
|
|
@ -0,0 +1,5 @@
|
|||
# md5, sha256 from https://pypi.org/pypi/adafruit-circuitpython-typing/json
|
||||
md5 3ff67f52cdb0ece5df86a477b1be5572 adafruit-circuitpython-typing-1.9.6.tar.gz
|
||||
sha256 dc69ed6362dcb890f7103d4da0db94b7d1849bc66804598d34508f413724d152 adafruit-circuitpython-typing-1.9.6.tar.gz
|
||||
# Locally computed sha256 checksums
|
||||
sha256 50e0c3b5b4486be0ed420639f8a1f6f115f29101feee6bcd954a4b81db04d0f3 LICENSE
|
|
@ -0,0 +1,14 @@
|
|||
################################################################################
|
||||
#
|
||||
# python-adafruit-circuitpython-typing
|
||||
#
|
||||
################################################################################
|
||||
|
||||
PYTHON_ADAFRUIT_CIRCUITPYTHON_TYPING_VERSION = 1.9.6
|
||||
PYTHON_ADAFRUIT_CIRCUITPYTHON_TYPING_SOURCE = adafruit-circuitpython-typing-$(PYTHON_ADAFRUIT_CIRCUITPYTHON_TYPING_VERSION).tar.gz
|
||||
PYTHON_ADAFRUIT_CIRCUITPYTHON_TYPING_SITE = https://files.pythonhosted.org/packages/c7/2e/acfeeed27e42cfcb0450bc4afe0746e4d8ddd5d9081b7d7cec01705149e1
|
||||
PYTHON_ADAFRUIT_CIRCUITPYTHON_TYPING_SETUP_TYPE = setuptools
|
||||
PYTHON_ADAFRUIT_CIRCUITPYTHON_TYPING_LICENSE = MIT
|
||||
PYTHON_ADAFRUIT_CIRCUITPYTHON_TYPING_LICENSE_FILES = LICENSE LICENSES/CC-BY-4.0.txt LICENSES/MIT.txt LICENSES/Unlicense.txt
|
||||
|
||||
$(eval $(python-package))
|
|
@ -1,5 +1,5 @@
|
|||
# md5, sha256 from https://pypi.org/pypi/Adafruit-PlatformDetect/json
|
||||
md5 7e7b10a48f6e6a7c650bb6bd432ec613 Adafruit-PlatformDetect-3.32.0.tar.gz
|
||||
sha256 31bad17fb91c3cd61bd62fb9712902bcef5225bbeb3c078a196c6d7e2d4599a4 Adafruit-PlatformDetect-3.32.0.tar.gz
|
||||
md5 4e80a7d7200a67d4528d580b16d3ca98 Adafruit-PlatformDetect-3.60.0.tar.gz
|
||||
sha256 644deb113c00ba1bfba4703fcd80cab52b5638d4a1146f2d58378df4af09746f Adafruit-PlatformDetect-3.60.0.tar.gz
|
||||
# Locally computed sha256 checksums
|
||||
sha256 50e0c3b5b4486be0ed420639f8a1f6f115f29101feee6bcd954a4b81db04d0f3 LICENSE
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
#
|
||||
################################################################################
|
||||
|
||||
PYTHON_ADAFRUIT_PLATFORMDETECT_VERSION = 3.32.0
|
||||
PYTHON_ADAFRUIT_PLATFORMDETECT_VERSION = 3.60.0
|
||||
PYTHON_ADAFRUIT_PLATFORMDETECT_SOURCE = Adafruit-PlatformDetect-$(PYTHON_ADAFRUIT_PLATFORMDETECT_VERSION).tar.gz
|
||||
PYTHON_ADAFRUIT_PLATFORMDETECT_SITE = https://files.pythonhosted.org/packages/15/42/2192f64a9732878ddb39bb4359864d1398849e90f39f5591a23005e65d8e
|
||||
PYTHON_ADAFRUIT_PLATFORMDETECT_SITE = https://files.pythonhosted.org/packages/e5/e3/71ba7ff4cbcecf40783613c192bd0ec6c69a70053915567a998ce41050bc
|
||||
PYTHON_ADAFRUIT_PLATFORMDETECT_SETUP_TYPE = setuptools
|
||||
PYTHON_ADAFRUIT_PLATFORMDETECT_LICENSE = MIT
|
||||
PYTHON_ADAFRUIT_PLATFORMDETECT_LICENSE_FILES = LICENSE
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# md5, sha256 from https://pypi.org/pypi/Adafruit-PureIO/json
|
||||
md5 f7d2f93db567333321b4097b4858bea5 Adafruit_PureIO-1.1.9.tar.gz
|
||||
sha256 2caf22fb07c7f771d83267f331a76cde314723f884a9570ea6f768730c87a879 Adafruit_PureIO-1.1.9.tar.gz
|
||||
md5 f9ddf83f2166ce69522a25f82d1fcdf7 Adafruit_PureIO-1.1.11.tar.gz
|
||||
sha256 c4cfbb365731942d1f1092a116f47dfdae0aef18c5b27f1072b5824ad5ea8c7c Adafruit_PureIO-1.1.11.tar.gz
|
||||
# Locally computed sha256 checksums
|
||||
sha256 aa5e54136c840ed2e333f65d43fecbc6c0e8fff62ebaece4ff281cd2a6672088 LICENSE
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
#
|
||||
################################################################################
|
||||
|
||||
PYTHON_ADAFRUIT_PUREIO_VERSION = 1.1.9
|
||||
PYTHON_ADAFRUIT_PUREIO_VERSION = 1.1.11
|
||||
PYTHON_ADAFRUIT_PUREIO_SOURCE = Adafruit_PureIO-$(PYTHON_ADAFRUIT_PUREIO_VERSION).tar.gz
|
||||
PYTHON_ADAFRUIT_PUREIO_SITE = https://files.pythonhosted.org/packages/df/ca/9162d4648669d12af16d5a66d808bdef6967eb684cbed9b1a3ebc19b361a
|
||||
PYTHON_ADAFRUIT_PUREIO_SITE = https://files.pythonhosted.org/packages/e5/b7/f1672435116822079bbdab42163f9e6424769b7db778873d95d18c085230
|
||||
PYTHON_ADAFRUIT_PUREIO_SETUP_TYPE = setuptools
|
||||
PYTHON_ADAFRUIT_PUREIO_LICENSE = MIT
|
||||
PYTHON_ADAFRUIT_PUREIO_LICENSE_FILES = LICENSE
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
config BR2_PACKAGE_PYTHON_GPIOD
|
||||
bool "python-gpiod"
|
||||
depends on !BR2_PACKAGE_LIBGPIOD
|
||||
help
|
||||
This is a C library that abstracts the GPIO character
|
||||
device operations on linux.
|
||||
|
||||
https://git.kernel.org/pub/scm/libs/libgpiod/libgpiod.git/
|
||||
|
||||
This package is the continuation of the libgpiod package
|
||||
for versions 2.0 and above.
|
||||
|
||||
Note that a kernel of 5.10 or above is required for the
|
||||
ioctls to work.
|
|
@ -0,0 +1,5 @@
|
|||
# md5, sha256 from https://pypi.org/pypi/gpiod/json
|
||||
md5 faf8736f9584a28426e4832fe22f38f4 gpiod-2.1.3.tar.gz
|
||||
sha256 a33193d6cab79d252329f71666a35a3668e04f1f82bf9b93ee2c9ae852398b20 gpiod-2.1.3.tar.gz
|
||||
# Locally computed sha256 checksums
|
||||
sha256 50e0c3b5b4486be0ed420639f8a1f6f115f29101feee6bcd954a4b81db04d0f3 LICENSE
|
|
@ -0,0 +1,13 @@
|
|||
################################################################################
|
||||
#
|
||||
# python-gpiod
|
||||
#
|
||||
################################################################################
|
||||
|
||||
PYTHON_GPIOD_VERSION = 2.1.3
|
||||
PYTHON_GPIOD_SOURCE = gpiod-$(PYTHON_GPIOD_VERSION).tar.gz
|
||||
PYTHON_GPIOD_SITE = https://files.pythonhosted.org/packages/a8/56/730573fe8d03c4d32a31e7182d27317b0cef298c9170b5a2994e2248986f
|
||||
PYTHON_GPIOD_SETUP_TYPE = setuptools
|
||||
#PYTHON_LIBGPIOD_DEPENDENCIES = libgpiod
|
||||
|
||||
$(eval $(python-package))
|
|
@ -1,5 +1,5 @@
|
|||
# md5, sha256 from https://pypi.org/pypi/pyftdi/json
|
||||
md5 d8969beb9cd11c123f1249963bf8c0d8 pyftdi-0.54.0.tar.gz
|
||||
sha256 8df9af22077d17533d2f95b508b1d87959877627ea5dc2369056e90a3b5a232d pyftdi-0.54.0.tar.gz
|
||||
md5 fa9feda5b80db51d538ed9b98e25504e pyftdi-0.55.0.tar.gz
|
||||
sha256 a747bbbccc4eeea26cefa2c8bd3d2b8bef8c94ecb6969bb9c75a63640887519a pyftdi-0.55.0.tar.gz
|
||||
# Locally computed sha256 checksums
|
||||
sha256 7342c9ccf3ec21eee9a23c6c74af15fb08ac1b79ddbccb4e063ddeaa6ef7c52d pyftdi/doc/license.rst
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
#
|
||||
################################################################################
|
||||
|
||||
PYTHON_PYFTDI_VERSION = 0.54.0
|
||||
PYTHON_PYFTDI_VERSION = 0.55.0
|
||||
PYTHON_PYFTDI_SOURCE = pyftdi-$(PYTHON_PYFTDI_VERSION).tar.gz
|
||||
PYTHON_PYFTDI_SITE = https://files.pythonhosted.org/packages/49/a3/6cd09c0493662b285b2ba87a08b1378a5b13e5cab44eb6a3f740c801c804
|
||||
PYTHON_PYFTDI_SITE = https://files.pythonhosted.org/packages/da/db/b900789a154e32dba50f132a2a76837331801f8b521b7e1bcbb852b01a35
|
||||
PYTHON_PYFTDI_SETUP_TYPE = setuptools
|
||||
PYTHON_PYFTDI_LICENSE = FIXME: please specify the exact BSD version
|
||||
PYTHON_PYFTDI_LICENSE_FILES = pyftdi/doc/license.rst
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# md5, sha256 from https://pypi.org/pypi/smbus2/json
|
||||
md5 ea4bba25b43863aecd6ec33b2252fdae smbus2-0.4.1.tar.gz
|
||||
sha256 6276eb599b76c4e74372f2582d2282f03b4398f0da16bc996608e4f21557ca9b smbus2-0.4.1.tar.gz
|
||||
md5 ab83d83e9eb3bd1d0bef8d6fd64b1398 smbus2-0.4.3.tar.gz
|
||||
sha256 36f2288a8e1a363cb7a7b2244ec98d880eb5a728a2494ac9c71e9de7bf6a803a smbus2-0.4.3.tar.gz
|
||||
# Locally computed sha256 checksums
|
||||
sha256 6ee9cf18c3a75dd76fb549a4b607ae34eedc31a796c48157895e2ad28d66ce79 LICENSE
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
#
|
||||
################################################################################
|
||||
|
||||
PYTHON_SMBUS2_VERSION = 0.4.1
|
||||
PYTHON_SMBUS2_VERSION = 0.4.3
|
||||
PYTHON_SMBUS2_SOURCE = smbus2-$(PYTHON_SMBUS2_VERSION).tar.gz
|
||||
PYTHON_SMBUS2_SITE = https://files.pythonhosted.org/packages/d9/33/787448c69603eec96af07d36f7ae3a7e3fce4020632eddb55152dc903233
|
||||
PYTHON_SMBUS2_SITE = https://files.pythonhosted.org/packages/98/17/9663936e52a348b3ad1c85e6ca6071d2abf00a5f64f2df50bec8dcca6e16
|
||||
PYTHON_SMBUS2_SETUP_TYPE = setuptools
|
||||
PYTHON_SMBUS2_LICENSE = MIT
|
||||
PYTHON_SMBUS2_LICENSE_FILES = LICENSE
|
||||
|
|
|
@ -3,207 +3,244 @@
|
|||
# requires dtparam=spi=on in /boot/config.txt
|
||||
|
||||
"""
|
||||
This script configures the XVF3510 board in boot from SPI slave and load a
|
||||
binary file. It requires a bin file as input parameter.
|
||||
This script configures the XVF3510 board to boot from SPI slave and loads a
|
||||
binary file. It requires a bin file as an input parameter.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import argparse
|
||||
import spidev
|
||||
import RPi.GPIO as GPIO
|
||||
from smbus import SMBus
|
||||
from smbus2 import SMBus
|
||||
import digitalio
|
||||
import busio
|
||||
from pathlib import Path
|
||||
import board
|
||||
from typing import Optional
|
||||
|
||||
if sys.version[0] != '3':
|
||||
print("Run this script with Python 3")
|
||||
# Global variables for GPIO pins
|
||||
BOOT_SEL_PIN = digitalio.DigitalInOut(board.D26) # GPIO pin used for boot selection (PIN 37)
|
||||
RST_N_PIN = digitalio.DigitalInOut(board.D27) # GPIO pin used for reset (PIN 13)
|
||||
I2C_ADDRESS = 0x2C # I2C address for the I/O expander. TODO: 0x20 was in original code, misstake?
|
||||
|
||||
if sys.version_info[0] < 3:
|
||||
print("This script requires Python 3.")
|
||||
sys.exit(1)
|
||||
|
||||
def bit_reversed_byte(byte_to_reverse):
|
||||
def bit_reversed_byte(byte_to_reverse: int) -> int:
|
||||
"""
|
||||
Function to reverse the bit-order of a byte
|
||||
Reverse the bits of a byte.
|
||||
|
||||
Args:
|
||||
byte_to_reverse: byte to process
|
||||
|
||||
Retruns:
|
||||
byte in reversed order
|
||||
"""
|
||||
return int('{:08b}'.format(byte_to_reverse)[::-1], 2)
|
||||
|
||||
def set_boot_sel():
|
||||
"""
|
||||
Function to set XVF3510 board in SPI slave boot mode
|
||||
|
||||
Args:
|
||||
None
|
||||
byte_to_reverse (int): The byte to reverse.
|
||||
|
||||
Returns:
|
||||
None
|
||||
int: The reversed byte.
|
||||
"""
|
||||
|
||||
bus = SMBus(1)
|
||||
|
||||
# reset BOOT_SEL
|
||||
bus.write_byte_data(0x20, 3, 0xFE)
|
||||
bus.write_byte_data(0x20, 7, 0xFF)
|
||||
|
||||
state = {}
|
||||
for i in [2, 6]:
|
||||
state[i] = bus.read_byte_data(0x20, i)
|
||||
|
||||
# start reset
|
||||
data_to_write = 0x00 | (state[2] & 0xDF)
|
||||
bus.write_byte_data(0x20, 2, data_to_write)
|
||||
data_to_write = 0x00 | (state[6] & 0xDF)
|
||||
bus.write_byte_data(0x20, 6, data_to_write)
|
||||
# set BOOT_SEL high
|
||||
data_to_write = 0x01
|
||||
bus.write_byte_data(0x20, 3, data_to_write)
|
||||
data_to_write = 0xFE
|
||||
bus.write_byte_data(0x20, 7, data_to_write)
|
||||
# stop reset
|
||||
data_to_write = 0x20 | (state[2] & 0xDF)
|
||||
bus.write_byte_data(0x20, 2, data_to_write)
|
||||
data_to_write = 0x20 | (state[6] & 0xDF)
|
||||
bus.write_byte_data(0x20, 6, data_to_write)
|
||||
return int("{:08b}".format(byte_to_reverse)[::-1], 2)
|
||||
|
||||
|
||||
|
||||
def send_image(bin_filename, verbose=False, max_spi_speed_mhz = 5, block_transfer_pause_ms = 1, direct = False, delay = False):
|
||||
def set_boot_sel() -> None:
|
||||
"""
|
||||
Function to send the given image to the device via SPI slave
|
||||
Set XVF3510 board in SPI slave boot mode using I2C to manipulate BOOT_SEL pin.
|
||||
"""
|
||||
try:
|
||||
with SMBus(1) as bus:
|
||||
# Reset BOOT_SEL to default
|
||||
bus.write_byte_data(I2C_ADDRESS, 3, 0xFE)
|
||||
bus.write_byte_data(I2C_ADDRESS, 7, 0xFF)
|
||||
|
||||
# Preserve other settings while manipulating BOOT_SEL
|
||||
state = {i: bus.read_byte_data(I2C_ADDRESS, i) for i in [2, 6]}
|
||||
|
||||
# Start reset sequence
|
||||
for i in [2, 6]:
|
||||
bus.write_byte_data(I2C_ADDRESS, i, 0x00 | (state[i] & 0xDF))
|
||||
# Set BOOT_SEL high
|
||||
bus.write_byte_data(I2C_ADDRESS, 3, 0x01)
|
||||
bus.write_byte_data(I2C_ADDRESS, 7, 0xFE)
|
||||
# End reset sequence
|
||||
for i in [2, 6]:
|
||||
bus.write_byte_data(I2C_ADDRESS, i, 0x20 | (state[i] & 0xDF))
|
||||
except Exception as e:
|
||||
print(f"Error setting BOOT_SEL via I2C: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def send_image(
|
||||
bin_filename: str,
|
||||
verbose: bool = False,
|
||||
max_spi_speed_mhz: float = 5,
|
||||
block_transfer_pause_ms: float = 1,
|
||||
direct: bool = False,
|
||||
delay: bool = False,
|
||||
) -> None:
|
||||
"""
|
||||
Send the given image to the device via SPI slave.
|
||||
|
||||
Args:
|
||||
bin_filename: binary file containing the image to boot
|
||||
verbose: flag to print debug printouts
|
||||
direct: Use Pi GPIO outputs rather than the XVF3510 Pi HAT
|
||||
delay: Release BootSel early to delay startup on version 4.0.0 onwards
|
||||
|
||||
Returns:
|
||||
None
|
||||
bin_filename (str): Binary file name.
|
||||
verbose (bool, optional): Enable verbose output. Defaults to False.
|
||||
max_spi_speed_mhz (float, optional): Max SPI speed in MHz. Defaults to 5.
|
||||
block_transfer_pause_ms (float, optional): Pause between blocks in milliseconds. Defaults to 1.
|
||||
direct (bool, optional): Direct mode flag. Defaults to False.
|
||||
delay (bool, optional): Delay startup flag. Defaults to False.
|
||||
"""
|
||||
binary_size = Path(bin_filename).stat().st_size
|
||||
print(f'Read file "{bin_filename}" size: {binary_size} Bytes')
|
||||
|
||||
if direct:
|
||||
#setup GPIO
|
||||
GPIO.setmode(GPIO.BOARD)
|
||||
GPIO.setwarnings(False)
|
||||
BOOT_SEL_PIN.switch_to_input()
|
||||
RST_N_PIN.switch_to_output(value=True)
|
||||
|
||||
#boot_sel = 8
|
||||
#rst_n = 10
|
||||
'''
|
||||
Mycroft board update
|
||||
'''
|
||||
#GPIO.setmode(GPIO.BCM)
|
||||
|
||||
boot_sel = 37 #26 #= 25 # fix these numbers to be Wiring Pi
|
||||
rst_n = 13 #27 #= 2
|
||||
GPIO.setup(boot_sel, GPIO.IN) # Normally, the Pi should not drive this
|
||||
GPIO.setup(rst_n, GPIO.OUT, initial=GPIO.HIGH)
|
||||
|
||||
#setup SPI
|
||||
spi = spidev.SpiDev()
|
||||
bus_spi = 0
|
||||
device = 0
|
||||
spi.open(bus_spi, device)
|
||||
|
||||
#SPI Settings
|
||||
spi.max_speed_hz = int(max_spi_speed_mhz * 1000000)
|
||||
spi.mode = 0b00 #XMOS supports 00 or 11
|
||||
|
||||
spi_block_size = 4096 #Limitation in spidev and xfer2 doesn't work!
|
||||
spi = setup_spi(max_spi_speed_mhz)
|
||||
|
||||
if direct:
|
||||
GPIO.output(rst_n, 0)
|
||||
GPIO.setup(boot_sel, GPIO.OUT, initial=GPIO.HIGH)
|
||||
GPIO.output(rst_n, 1)
|
||||
RST_N_PIN.value=False
|
||||
BOOT_SEL_PIN.switch_to_output(value=True)
|
||||
RST_N_PIN.value=True
|
||||
else:
|
||||
set_boot_sel()
|
||||
|
||||
# Create a table to map byte values to their bit-reversed values
|
||||
reverse_table = [bit_reversed_byte(byte) for byte in range(256)]
|
||||
reverse_table = [bit_reversed_byte(byte) for byte in range(256)]
|
||||
|
||||
data = []
|
||||
with open(bin_filename, "rb") as f:
|
||||
bytes_read = f.read()
|
||||
data = list(bytes_read)
|
||||
binary_size = len(data)
|
||||
block_count = 0
|
||||
print('Read file "{0}" size: {1} Bytes'.format(args.bin_filename, binary_size))
|
||||
if binary_size % spi_block_size != 0:
|
||||
print("Warning - binary file not a multiple of {} - {} remainder".format( \
|
||||
spi_block_size, binary_size % spi_block_size))
|
||||
while binary_size > 0:
|
||||
block = [reverse_table[byte] for byte in data[:spi_block_size]]
|
||||
del data[:spi_block_size]
|
||||
binary_size = len(data)
|
||||
if verbose:
|
||||
print("Sending {} Bytes in block {} checksum 0x{:X}".format( \
|
||||
len(block), block_count, sum(block)))
|
||||
spi.xfer(block)
|
||||
try:
|
||||
with open(bin_filename, "rb") as f:
|
||||
data = list(f.read())
|
||||
except Exception as e:
|
||||
print(f"Error reading binary file: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
if block_count == 0:
|
||||
#Long delay for PLL reboot
|
||||
time.sleep(0.1)
|
||||
send_data_over_spi(data, spi, reverse_table, verbose, block_transfer_pause_ms, direct, delay)
|
||||
|
||||
if delay:
|
||||
# release boot_sel early to prevent startup
|
||||
if direct:
|
||||
GPIO.setup(boot_sel, GPIO.IN)
|
||||
else:
|
||||
#bus = smbus.SMBus(1)
|
||||
bus = SMBus(1)
|
||||
data_to_write = 0xFE
|
||||
bus.write_byte_data(0x20, 3, data_to_write)
|
||||
data_to_write = 0xFF
|
||||
bus.write_byte_data(0x20, 7, data_to_write)
|
||||
|
||||
elif binary_size > 0:
|
||||
time.sleep(block_transfer_pause_ms / 1000)
|
||||
block_count += 1
|
||||
print("Sending complete")
|
||||
|
||||
if direct:
|
||||
GPIO.setup(boot_sel, GPIO.IN) # Once booted, the Pi should not need to drive boot_sel
|
||||
GPIO.setup(rst_n, GPIO.OUT, initial=GPIO.HIGH) # Once booted, the Pi should not need to drive reset
|
||||
#GPIO.cleanup()
|
||||
# Once booted, the Pi should not need to drive boot_sel and reset
|
||||
BOOT_SEL_PIN.switch_to_input()
|
||||
RST_N_PIN.value=True
|
||||
else:
|
||||
#bus = smbus.SMBus(1)
|
||||
bus = SMBus(1)
|
||||
|
||||
# reset BOOT_SEL
|
||||
data_to_write = 0xFE
|
||||
bus.write_byte_data(0x20, 3, data_to_write)
|
||||
data_to_write = 0xFF
|
||||
bus.write_byte_data(0x20, 7, data_to_write)
|
||||
# Reset BOOT_SEL to default state
|
||||
with SMBus(1) as bus:
|
||||
bus.write_byte_data(I2C_ADDRESS, 3, 0xFE)
|
||||
bus.write_byte_data(I2C_ADDRESS, 7, 0xFF)
|
||||
|
||||
|
||||
def setup_spi(max_spi_speed_mhz: float) -> busio.SPI:
|
||||
"""
|
||||
Set up the SPI bus.
|
||||
|
||||
Args:
|
||||
max_spi_speed_mhz (float): Max SPI speed in MHz.
|
||||
|
||||
Returns:
|
||||
busio.SPI: Configured SPI bus.
|
||||
"""
|
||||
spi = busio.SPI(board.SCLK, MOSI=board.MOSI, MISO=board.MISO)
|
||||
while not spi.try_lock():
|
||||
pass
|
||||
spi.configure(baudrate=max_spi_speed_mhz * 1_000_000)
|
||||
return spi
|
||||
|
||||
|
||||
def send_data_over_spi(
|
||||
data: list,
|
||||
spi: busio.SPI,
|
||||
reverse_table: list,
|
||||
verbose: bool,
|
||||
pause_ms: float,
|
||||
direct: bool,
|
||||
delay: bool,
|
||||
) -> None:
|
||||
"""
|
||||
Send data over SPI, handling block transfers and optional delays.
|
||||
|
||||
Args:
|
||||
data (list): Data to send.
|
||||
spi (busio.SPI): Configured SPI bus.
|
||||
reverse_table (list): Table of bit-reversed byte values.
|
||||
verbose (bool): Enable verbose output.
|
||||
pause_ms (float): Pause between blocks in milliseconds.
|
||||
direct (bool): Direct mode flag.
|
||||
delay (bool): Delay startup flag.
|
||||
"""
|
||||
spi_block_size = 4096
|
||||
block_count = 0
|
||||
total_data_length = len(data)
|
||||
for i in range(0, total_data_length, spi_block_size):
|
||||
block = [reverse_table[byte] for byte in data[i : i + spi_block_size]]
|
||||
if verbose:
|
||||
print(f"Sending {len(block)} Bytes in block {block_count} checksum 0x{sum(block):X}")
|
||||
spi.write(block)
|
||||
|
||||
# Update the remaining data length after each block transfer
|
||||
remaining_data_length = total_data_length - (i + len(block))
|
||||
handle_block_transfer(
|
||||
block_count, delay, direct, pause_ms, remaining_data_length
|
||||
)
|
||||
block_count += 1
|
||||
|
||||
|
||||
def handle_block_transfer(
|
||||
block_count: int, delay: bool, direct: bool, pause_ms: float, remaining_data_length: int
|
||||
) -> None:
|
||||
"""
|
||||
Handle specifics of block transfer, including initial delays and conditional logic for direct mode.
|
||||
|
||||
Args:
|
||||
block_count (int): Number of blocks sent.
|
||||
delay (bool): Delay startup flag.
|
||||
direct (bool): Direct mode flag.
|
||||
pause_ms (float): Pause between blocks in milliseconds.
|
||||
remaining_data_length (int): Length of remaining data to send.
|
||||
"""
|
||||
if block_count == 0:
|
||||
# Long delay for PLL reboot
|
||||
time.sleep(0.1)
|
||||
|
||||
if delay:
|
||||
# release boot_sel early to prevent startup
|
||||
if direct:
|
||||
# release boot_sel early to prevent startup
|
||||
BOOT_SEL_PIN.switch_to_input()
|
||||
else:
|
||||
# Reset BOOT_SEL to default state
|
||||
with SMBus(1) as bus:
|
||||
bus.write_byte_data(I2C_ADDRESS, 3, 0xFE)
|
||||
bus.write_byte_data(I2C_ADDRESS, 7, 0xFF)
|
||||
|
||||
elif remaining_data_length > 0:
|
||||
time.sleep(pause_ms / 1000)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
start_time = time.time()
|
||||
parser = argparse.ArgumentParser(description='Load an image via SPI slave from an RPi')
|
||||
parser.add_argument('bin_filename', help='binary file name')
|
||||
parser.add_argument('--direct', action='store_true', \
|
||||
help='Use just direct GPIO outputs rather than using the XVF3510 Development Kit Pi HAT')
|
||||
parser.add_argument('--delay', action='store_true', \
|
||||
help='Delay xvf3510 device start. Release the BootSel pin early to prevent the XVF3510 (V4.0.0 onwards) from starting with the default I2S configuration. This gives AP a chance to configure and start the XVF3510 device.')
|
||||
parser.add_argument('--max-spi-speed-mhz', type=float, default=5, \
|
||||
help='Max SPI speed in MHz')
|
||||
parser.add_argument('--block-transfer-pause-ms', type=float, default=1, \
|
||||
help='pause between SPI transfers in milliseconds, default 1ms')
|
||||
parser.add_argument('--verbose', action='store_true', \
|
||||
help='print debug information')
|
||||
|
||||
parser = argparse.ArgumentParser(description="Load an image via SPI slave from an RPi")
|
||||
parser.add_argument("bin_filename", help="binary file name")
|
||||
parser.add_argument("--direct", action="store_true", help="Use direct GPIO outputs rather than the XVF3510 Development Kit Pi HAT")
|
||||
parser.add_argument("--delay", action="store_true", help="Delay xvf3510 device start")
|
||||
parser.add_argument("--max-spi-speed-mhz", type=float, default=5, help="Max SPI speed in MHz")
|
||||
parser.add_argument("--block-transfer-pause-ms", type=float, default=1, help="Pause between SPI transfers in milliseconds")
|
||||
parser.add_argument("--verbose", action="store_true", help="Print debug information")
|
||||
args = parser.parse_args()
|
||||
|
||||
if not Path(args.bin_filename).is_file():
|
||||
print("Error: input file {} not found".format(args.bin_filename))
|
||||
exit(1)
|
||||
|
||||
send_image(args.bin_filename, args.verbose, args.max_spi_speed_mhz, args.block_transfer_pause_ms, args.direct, args.delay)
|
||||
bin_path = Path(args.bin_filename)
|
||||
if not bin_path.is_file():
|
||||
print(f"Error: input file {bin_path} not found")
|
||||
sys.exit(1)
|
||||
|
||||
start_time = time.time()
|
||||
send_image(
|
||||
bin_path,
|
||||
args.verbose,
|
||||
args.max_spi_speed_mhz,
|
||||
args.block_transfer_pause_ms,
|
||||
args.direct,
|
||||
args.delay,
|
||||
)
|
||||
end_time = time.time()
|
||||
|
||||
BOOT_SEL_PIN.deinit()
|
||||
RST_N_PIN.deinit()
|
||||
|
||||
if args.verbose:
|
||||
print("Sending image took {:.3} seconds".format(end_time - start_time))
|
||||
print(f"Sending image took {end_time - start_time:.3f} seconds")
|
||||
|
||||
|
|
Loading…
Reference in New Issue