Get the sj201 in line / Sound system architecture changes

This commit is contained in:
j1nx 2021-09-04 15:42:24 +02:00
parent 4bd41cf6a8
commit 812e92cbde
10 changed files with 223 additions and 138 deletions

View File

@ -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

View File

@ -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))

View File

@ -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))

View File

@ -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"
}

View File

@ -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

View File

@ -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 <http://www.gnu.org/licenses/>.
# 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

View File

@ -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

View File

@ -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)

View File

@ -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