diff --git a/buildroot-external/configs/rpi4_64-gui_defconfig b/buildroot-external/configs/rpi4_64-gui_defconfig index 0e4b93c7..c0db087c 100644 --- a/buildroot-external/configs/rpi4_64-gui_defconfig +++ b/buildroot-external/configs/rpi4_64-gui_defconfig @@ -612,7 +612,6 @@ BR2_PACKAGE_USERLAND_TOOLS=y BR2_PACKAGE_VOCALFUSION=y BR2_PACKAGE_WIFI_CONNECT=y BR2_PACKAGE_WIRINGPI2=y -BR2_PACKAGE_XVF3510=y BR2_PACKAGE_PYTHON_ADAPT_PARSER=y BR2_PACKAGE_PYTHON_ASTRAL=y BR2_PACKAGE_PYTHON_CLICK_DEFAULT_GROUP=y @@ -701,7 +700,6 @@ BR2_PACKAGE_MYCROFT_SKILL_IP=y BR2_PACKAGE_MYCROFT_SKILL_JOKE=y BR2_PACKAGE_MYCROFT_SKILL_NAPTIME=y BR2_PACKAGE_MYCROFT_SKILL_NEWS=y -BR2_PACKAGE_MYCROFT_SKILL_OSM=y BR2_PACKAGE_MYCROFT_SKILL_OVOS_COMMON_PLAY=y BR2_PACKAGE_MYCROFT_SKILL_OVOS_ENCLOSURE=y BR2_PACKAGE_MYCROFT_SKILL_OVOS_HOMESCREEN=y diff --git a/buildroot-external/package/vocalfusion/app_xvf3510_int_spi_boot_v4_1_0.bin b/buildroot-external/package/vocalfusion/app_xvf3510_int_spi_boot_v4_1_0.bin new file mode 100644 index 00000000..7a9ef5f6 Binary files /dev/null and b/buildroot-external/package/vocalfusion/app_xvf3510_int_spi_boot_v4_1_0.bin differ diff --git a/buildroot-external/package/vocalfusion/vocalfusion.mk b/buildroot-external/package/vocalfusion/vocalfusion.mk index a463916d..9536bafb 100644 --- a/buildroot-external/package/vocalfusion/vocalfusion.mk +++ b/buildroot-external/package/vocalfusion/vocalfusion.mk @@ -12,6 +12,13 @@ $(eval $(kernel-module)) define VOCALFUSION_INSTALL_TARGET_CMDS $(INSTALL) -D -m 0644 $(@D)/xvf3510.dtbo $(BINARIES_DIR)/overlays/ + + $(INSTALL) -D -m 755 $(BR2_EXTERNAL_OPENVOICEOS_PATH)/package/vocalfusion/xvf3510-flash \ + $(TARGET_DIR)/usr/sbin/xvf3510-flash + + mkdir -p $(TARGET_DIR)/usr/lib/firmware/xvf3510 + $(INSTALL) -D -m 0644 $(BR2_EXTERNAL_OPENVOICEOS_PATH)/package/vocalfusion/app_xvf3510_int_spi_boot_v4_1_0.bin \ + $(TARGET_DIR)/usr/lib/firmware/xvf3510/app_xvf3510_int_spi_boot_v4_1_0.bin endef $(eval $(generic-package)) diff --git a/buildroot-external/package/vocalfusion/xvf3510-flash b/buildroot-external/package/vocalfusion/xvf3510-flash new file mode 100644 index 00000000..11e79f09 --- /dev/null +++ b/buildroot-external/package/vocalfusion/xvf3510-flash @@ -0,0 +1,209 @@ +#!/usr/bin/env python3 +# Copyright (c) 2019-2020, XMOS Ltd, All rights reserved +# 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. +""" + +import sys +import os +import time +import argparse +import spidev +import RPi.GPIO as GPIO +from smbus import SMBus +from pathlib import Path + +if sys.version[0] != '3': + print("Run this script with Python 3") + sys.exit(1) + +def bit_reversed_byte(byte_to_reverse): + """ + Function to reverse the bit-order 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 + + Returns: + None + """ + + 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) + + + +def send_image(bin_filename, verbose=False, max_spi_speed_mhz = 5, block_transfer_pause_ms = 1, direct = False, delay = False): + """ + Function to 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 + """ + + if direct: + #setup GPIO + GPIO.setmode(GPIO.BOARD) + GPIO.setwarnings(False) + + #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! + + if direct: + GPIO.output(rst_n, 0) + GPIO.setup(boot_sel, GPIO.OUT, initial=GPIO.HIGH) + GPIO.output(rst_n, 1) + 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)] + + 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) + + if block_count == 0: + #Long delay for PLL reboot + time.sleep(0.1) + + 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() + 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) + + + + +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') + + 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) + + end_time = time.time() + if args.verbose: + print("Sending image took {:.3} seconds".format(end_time - start_time)) diff --git a/buildroot-external/rootfs-overlay/etc/asound.conf b/buildroot-external/rootfs-overlay/etc/asound.conf deleted file mode 100644 index 23e1f11e..00000000 --- a/buildroot-external/rootfs-overlay/etc/asound.conf +++ /dev/null @@ -1,14 +0,0 @@ -# Use PulseAudio by default -pcm.!default { - type pulse - fallback "sysdefault" - hint { - show on - description "Default ALSA Output (currently PulseAudio Sound Server)" - } -} - -ctl.!default { - type pulse - fallback "sysdefault" -} diff --git a/buildroot-external/rootfs-overlay/etc/pulse/mycroft-sj201-daemon.conf b/buildroot-external/rootfs-overlay/etc/pulse/mycroft-sj201-daemon.conf index 2b50a60c..6972d49a 100644 --- a/buildroot-external/rootfs-overlay/etc/pulse/mycroft-sj201-daemon.conf +++ b/buildroot-external/rootfs-overlay/etc/pulse/mycroft-sj201-daemon.conf @@ -92,8 +92,4 @@ resample-method = ffmpeg default-sample-format = s32le default-sample-rate = 48000 -alternate-sample-rate = 44100 -default-sample-channels = 2 -default-channel-map = front-left,front-right -avoid-resampling = true flat-volumes = no diff --git a/buildroot-external/rootfs-overlay/etc/pulse/mycroft-sj201-default.pa b/buildroot-external/rootfs-overlay/etc/pulse/mycroft-sj201-default.pa deleted file mode 100644 index 326fe0a9..00000000 --- a/buildroot-external/rootfs-overlay/etc/pulse/mycroft-sj201-default.pa +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/pulseaudio -nF -# -# This file is part of PulseAudio. -# -# PulseAudio is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# PulseAudio is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with PulseAudio; if not, see . - -# This startup script is used only if PulseAudio is started in system -# mode. - -### Automatically restore the volume of streams and devices -load-module module-device-restore -load-module module-stream-restore -load-module module-card-restore - -### Automatically load driver modules depending on the hardware available -.ifexists module-udev-detect.so -load-module module-udev-detect tsched=0 -.else -### Use the static hardware detection module (for systems that lack udev/hal support) -load-module module-detect -.endif - -### Load several protocols -.ifexists module-esound-protocol-unix.so -load-module module-esound-protocol-unix -.endif -load-module module-native-protocol-unix auth-anonymous=1 - -### Network access (may be configured with paprefs, so leave this commented -### here if you plan to use paprefs) -#load-module module-esound-protocol-tcp -load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1;192.168.0.0/16;172.16.0.0/12;10.0.0.0/8 auth-anonymous=1 -load-module module-zeroconf-publish - -### Automatically restore the default sink/source when changed by the user -### during runtime -### NOTE: This should be loaded as early as possible so that subsequent modules -### that look up the default sink/source get the right value -load-module module-default-device-restore - -### Automatically move streams to the default sink if the sink they are -### connected to dies, similar for sources -load-module module-rescue-streams - -### Make sure we always have a sink around, even if it is a null sink. -load-module module-always-sink - -### Automatically suspend sinks/sources that become idle for too long -load-module module-suspend-on-idle - -### Enable positioned event sounds -load-module module-position-event-sounds - -### OpenVoiceOS Audio Settings -unload-module module-suspend-on-idle -load-module module-role-ducking -load-module module-combine-sink sink_name=OpenVoiceOS -load-module module-remap-source source_name=VF_ASR_L source_properties="device.description='VocalFusion ASR recording'" master=alsa_input.platform-asoc-simple-card.0.stereo-fallback remix=no master_channel_map=front-left channel_map=mono -load-module module-remap-source source_name=VF_Comms_R source_properties="device.description='VocalFusion Comms recording'" master=alsa_input.platform-asoc-simple-card.0.stereo-fallback remix=no master_channel_map=front-right channel_map=mono -set-default-source VF_ASR_L -set-default-sink OpenVoiceOS - -### Enable Echo/Noise-Cancellation -#load-module module-echo-cancel aec_method=webrtc source_name=echoCancel_source sink_name=echoCancel_sink -#set-default-source echoCancel_source -#set-default-sink echoCancel_sink diff --git a/buildroot-external/rootfs-overlay/etc/pulse/pulseaudio-daemon.conf b/buildroot-external/rootfs-overlay/etc/pulse/pulseaudio-daemon.conf index 00773376..9752e35e 100644 --- a/buildroot-external/rootfs-overlay/etc/pulse/pulseaudio-daemon.conf +++ b/buildroot-external/rootfs-overlay/etc/pulse/pulseaudio-daemon.conf @@ -93,5 +93,4 @@ resample-method = ffmpeg default-sample-format = s16le default-sample-rate = 44100 alternate-sample-rate = 48000 -; avoid-resampling = true flat-volumes = no diff --git a/buildroot-external/rootfs-overlay/usr/bin/tas5806-init b/buildroot-external/rootfs-overlay/usr/bin/tas5806-init index a73c7916..1b6fd4de 100755 --- a/buildroot-external/rootfs-overlay/usr/bin/tas5806-init +++ b/buildroot-external/rootfs-overlay/usr/bin/tas5806-init @@ -181,7 +181,7 @@ class tasTest: return x * p1 + x0 - def setVolume(self, vol=1.0): + def setVolume(self, vol=0.5): # vol takes a float from 0.0 - 1.0 # default vol 0.5 = 50% hw_vol = self.calc_log_y(vol * 100.0) diff --git a/buildroot-external/rootfs-overlay/usr/libexec/ovos-i2csound b/buildroot-external/rootfs-overlay/usr/libexec/ovos-i2csound index 5ef51851..f65a58e2 100755 --- a/buildroot-external/rootfs-overlay/usr/libexec/ovos-i2csound +++ b/buildroot-external/rootfs-overlay/usr/libexec/ovos-i2csound @@ -16,13 +16,9 @@ ########################################################################## # Set default configurations -ASOUND_STATE=/var/lib/alsa/default-asound.state PULSE_SYSTEM=/etc/pulse/pulseaudio-system.pa PULSE_DAEMON=/etc/pulse/pulseaudio-daemon.conf -# Set known hat overlay variables -RPI_HATS="seeed-2mic-voicecard seeed-4mic-voicecard seeed-8mic-voicecard" - # Scanning the I2C bus for know addresses is_1a=$(i2cdetect -y 1 0x1a 0x1a | egrep "(1a|UU)" | awk '{print $2}') # ReSpeaker 2-mic / WM8960 if [ "${is_1a}" == "1a" ] || [ "${is_1a}" == "UU" ] ; then @@ -62,12 +58,6 @@ fi # Remove old configurations -if [ -f /var/lib/alsa/asound.state ] ; then - rm /var/lib/alsa/asound.state -fi -if [ -f /etc/ovos_asound.state ] ; then - rm /etc/ovos_asound.state -fi if [ -f /etc/pulse/system.pa ] ; then rm /etc/pulse/system.pa fi @@ -77,27 +67,19 @@ fi if [ "$RESPEAKER2" == "found" ] && [ "$RESPEAKER4" != "found" ] ; then echo "Installing and configuring ReSpeaker 2-mic" - modprobe snd-soc-wm8960 - OVERLAY=seeed-2mic-voicecard - ASOUND_STATE=/etc/voicecard/wm8960_asound.state + dtoverlay seeed-2mic-voicecard fi if [ "${RESPEAKER6}" == "found" ] && [ "${RESPEAKER4}" != "found" ] ; then echo "Installing and configuring ReSpeaker 4-mic" - modprobe snd-soc-seeed-voicecard - modprobe snd-soc-ac108 - OVERLAY=seeed-4mic-voicecard - ASOUND_STATE=/etc/voicecard/ac108_asound.state + dtoverlay seeed-4mic-voicecard PULSE_SYSTEM=/etc/pulse/seeed-voicecard-4mic-default.pa PULSE_DAEMON=/etc/pulse/seeed-voicecard-4mic-daemon.conf fi if [ "{$RESPEAKER6}" == "found" ] && [ "${RESPEAKER4}" == "found" ] ; then echo "Installing and configuring ReSpeaker 6mic" - modprobe snd-soc-seeed-voicecard - modprobe snd-soc-ac108 - OVERLAY=seeed-8mic-voicecard - ASOUND_STATE=/etc/voicecard/ac108_6mic.state + dtoverlay seeed-8mic-voicecard PULSE_SYSTEM=/etc/pulse/seeed-voicecard-8mic-default.pa PULSE_DAEMON=/etc/pulse/seeed-voicecard-8mic-daemon.conf fi @@ -110,7 +92,8 @@ fi if [ "$TAS5806" ] && [ "$SJ201LED" ]; then echo "Installing and configuring SJ201" # Initializing XMOS xvf3510 - /usr/sbin/xvf3510-start + dtoverlay xvf3510 + xvf3510-flash --direct "/usr/lib/firmware/xvf3510/app_xvf3510_int_spi_boot_v4_1_0.bin" # Initializing Texas Instruments 5806 Amplifier /usr/bin/tas5806-init # Initializing and resetting LED ring @@ -118,27 +101,11 @@ if [ "$TAS5806" ] && [ "$SJ201LED" ]; then # Reset FAN to low speed /usr/sbin/i2cset -a -y 1 0x04 101 30 i - #PULSE_SYSTEM=/etc/pulse/mycroft-sj201-default.pa - #PULSE_DAEMON=/etc/pulse/mycroft-sj201-daemon.conf + PULSE_DAEMON=/etc/pulse/mycroft-sj201-daemon.conf fi -# Load overlay -if [ "$OVERLAY" ]; then - echo Loading $OVERLAY ... - - # Make sure the driver loads correctly - dtoverlay $OVERLAY || true -fi - -# Install soundstate -echo "create asound status file" -ln -s $ASOUND_STATE /etc/ovos_asound.state - # Install pulseaudio files echo "create pulse system file" ln -s $PULSE_SYSTEM /etc/pulse/system.pa echo "create pulse daemon file" ln -s $PULSE_DAEMON /etc/pulse/daemon.conf - -# Restore sound levels -alsactl -E HOME=/run/alsa -f /etc/ovos_asound.state restore