diff --git a/CHANGELOG.md b/CHANGELOG.md index d324faa..b0cd13e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # VocalFusion Raspberry Pi Setup Change Log +## 5.0.0 + + * Added support for xvf3610-ua and xvf3615-ua + * Renamed xvf3615 device as xvf3615-int + * Renamed xvf3610 device as xvf3610-int + ## 4.3.1 * Fix comments and reg names in setup_dac.py diff --git a/README.md b/README.md index bf35c2a..23a88d5 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ This setup will perform the following operations: - install the Raspberry Pi kernel headers - install the required packages - compile the I2S drivers +- update the asoundrc file to support I2S devices - add a cron job to load the I2S drivers at boot up For XVF3510 devices these actions will be done as well: @@ -18,9 +19,24 @@ For XVF3510 devices these actions will be done as well: - configure MCLK at 24576kHz from pin 7 (BCM 4) - configure I2S BCLK at 3072kHz from pin 12 (BCM18) - update the alias for Audacity +- update the asoundrc file to support I2S devices - add a cron job to reset the device at boot up - add a cron job to configure the DAC at boot up +For XVF361x-INT devices these actions will be done as well: + +- configure MCLK at 12288kHz from pin 7 (BCM 4) +- configure I2S BCLK at 3072kHz from pin 12 (BCM18) +- update the alias for Audacity +- update the asoundrc file to support I2S devices +- add a cron job to reset the device at boot up +- add a cron job to configure the DAC at boot up + +For XVF361x-UA devices these actions will be done as well: + +- update the asoundrc file to support USB devices +- update udev rules so that root privileges are not needed to access USB control interface + ## Setup 1. First, obtain the required version of the Raspberry Pi operating system, which is available here: @@ -45,7 +61,7 @@ For XVF3510 devices these actions will be done as well: **DO NOT** follow the prompt to update the software on the system. Set up the locale, and setup a network connect, but **DO NOT** update the software on the Raspberry Pi. This will update the kernel, and then the audio sub-system will not work. -3. Clone the Github repository https://github.com/xmos/vocalfusion-rpi-setup: +3. On the Raspberry Pi, clone the Github repository https://github.com/xmos/vocalfusion-rpi-setup: ```git clone https://github.com/xmos/vocalfusion-rpi-setup``` @@ -69,9 +85,21 @@ For XVF3510 devices these actions will be done as well: ```./setup.sh xvf3600-slave``` - For XVF3610 devices, run the installation script as follows: + For XVF3610-UA devices, run the installation script as follows: + + ```./setup.sh xvf3610-ua``` + + For XVF3610-INT devices, run the installation script as follows: + + ```./setup.sh xvf3610-int``` + + For XVF3615-UA devices, run the installation script as follows: + + ```./setup.sh xvf3615-ua``` + + For XVF3615-INT devices, run the installation script as follows: - ```./setup.sh xvf3610``` + ```./setup.sh xvf3615-int``` Wait for the script to complete the installation. This can take several minutes. diff --git a/resources/99-xmos.rules b/resources/99-xmos.rules new file mode 100644 index 0000000..64d7a65 --- /dev/null +++ b/resources/99-xmos.rules @@ -0,0 +1,5 @@ +SUBSYSTEM!="usb|usb_device", GOTO="xmos_rules_end" +ACTION!="add", GOTO="xmos_rules_end" +ATTRS{idVendor}=="20b1", ATTRS{idProduct}=="0014", MODE="0666", SYMLINK+="xvf3510-%n" +ATTRS{idVendor}=="20b1", ATTRS{idProduct}=="0016", MODE="0666", SYMLINK+="xvf3610-%n" +ATTRS{idVendor}=="20b1", ATTRS{idProduct}=="0018", MODE="0666", SYMLINK+="xvf3615-%n" diff --git a/resources/asoundrc_vf_xvf3510 b/resources/asoundrc_vf_xvf3510_int similarity index 100% rename from resources/asoundrc_vf_xvf3510 rename to resources/asoundrc_vf_xvf3510_int diff --git a/resources/asoundrc_vf_xvf3510_ua b/resources/asoundrc_vf_xvf3510_ua new file mode 100644 index 0000000..86a53ce --- /dev/null +++ b/resources/asoundrc_vf_xvf3510_ua @@ -0,0 +1,18 @@ +pcm.!default { + type asym + capture.pcm "mic" + playback.pcm "speaker" +} +pcm.mic { + type plug + slave { + pcm "hw:1,0" + } +} + +pcm.speaker { + type plug + slave { + pcm "hw:1,0" + } +} diff --git a/setup.sh b/setup.sh index f396a72..888365b 100755 --- a/setup.sh +++ b/setup.sh @@ -2,21 +2,70 @@ pushd "$( dirname "${BASH_SOURCE[0]}" )" > /dev/null RPI_SETUP_DIR="$( pwd )" -# Valid values for XMOS device +I2S_MODE= XMOS_DEVICE= -if [[ $# -ge 1 ]]; then + +# Valid values for XMOS device +VALID_XMOS_DEVICES="xvf3100 xvf3500 xvf3510 xvf3600-slave xvf3600-master xvf3610-int xvf3610-ua xvf3615-int xvf3615-ua" + +usage() { + local VALID_XMOS_DEVICES_DISPLAY_STRING= + local NUMBER_OF_VALID_DEVICES=$(echo $VALID_XMOS_DEVICES | wc -w) + local i=1 + local SEP= + # Build a string of valid device options + for d in $VALID_XMOS_DEVICES; do + if [[ $i -eq $NUMBER_OF_VALID_DEVICES ]]; then + SEP=" or " + fi + VALID_XMOS_DEVICES_DISPLAY_STRING=$VALID_XMOS_DEVICES_DISPLAY_STRING$SEP$d + SEP=", " + (( ++i )) + done + + cat < +The DEVICE-TYPE is the XMOS device to setup: $VALID_XMOS_DEVICES_DISPLAY_STRING +EOT +} + +# validate XMOS_DEVICE value +validate_device() { + local DEV=$1 + shift + for d in $*; do + if [[ "$DEV" = "$d" ]]; then + return 0 + fi + done + return 1 +} + +if [[ $# == 1 ]]; then XMOS_DEVICE=$1 + if ! validate_device $XMOS_DEVICE $VALID_XMOS_DEVICES; then + echo "error: $XMOS_DEVICE is not a valid device type." + echo + usage + exit 1 + fi else - echo error: No device type specified. + usage exit 1 fi # Configure device-specific settings case $XMOS_DEVICE in - xvf3[56]10) + xvf3[56]10-ua) + UA_MODE=y + ASOUNDRC_TEMPLATE=$RPI_SETUP_DIR/resources/asoundrc_vf_xvf3510_ua + ;; + + xvf3[56]10-int) I2S_MODE=master DAC_SETUP=y - ASOUNDRC_TEMPLATE=$RPI_SETUP_DIR/resources/asoundrc_vf_xvf3510 + ASOUNDRC_TEMPLATE=$RPI_SETUP_DIR/resources/asoundrc_vf_xvf3510_int ;; xvf3500) I2S_MODE=slave @@ -77,7 +126,7 @@ sudo apt-get install -y python3-numpy sudo apt-get install -y libatlas-base-dev echo "Installing necessary packages for dev kit" -sudo apt-get install -y libusb-1.0-0-dev libreadline-dev libncurses-dev +sudo apt-get install -y libusb-1.0-0-dev libreadline-dev libncurses-dev libevdev-dev libudev-dev # Build I2S kernel module PI_MODEL=$(cat /proc/device-tree/model | awk '{print $3}') @@ -85,38 +134,45 @@ if [[ $PI_MODEL = 4 ]]; then I2S_MODULE_CFLAGS="-DRPI_4B" fi -case $I2S_MODE in - master) - if [[ -z "$I2S_MODULE_CFLAGS" ]]; then - I2S_MODULE_CFLAGS=-DI2S_MASTER - else - I2S_MODULE_CFLAGS="$I2S_MODULE_CFLAGS -DI2S_MASTER" - fi +if [[ -n "$I2S_MODE" ]]; then + case $I2S_MODE in + master) + if [[ -z "$I2S_MODULE_CFLAGS" ]]; then + I2S_MODULE_CFLAGS=-DI2S_MASTER + else + I2S_MODULE_CFLAGS="$I2S_MODULE_CFLAGS -DI2S_MASTER" + fi + ;; + slave) + # no flags needed for I2S slave compilation + ;; + *) + echo error: I2S mode not known for XMOS device $XMOS_DEVICE. + exit 1 ;; - slave) - # no flags needed for I2S slave compilation - ;; - *) - echo error: I2S mode not known for XMOS device $XMOS_DEVICE. + esac + I2S_BUILD_DIR=$RPI_SETUP_DIR/loader/i2s_$I2S_MODE + pushd $I2S_BUILD_DIR > /dev/null + if [[ -n "$I2S_MODULE_CFLAGS" ]]; then + CMD="make CFLAGS_MODULE='$I2S_MODULE_CFLAGS'" + else + CMD=make + fi + echo $CMD + eval $CMD + if [[ $? -ne 0 ]]; then + echo "Error: I2S kernel module build failed" exit 1 - ;; -esac -I2S_BUILD_DIR=$RPI_SETUP_DIR/loader/i2s_$I2S_MODE -pushd $I2S_BUILD_DIR > /dev/null -if [[ -n "$I2S_MODULE_CFLAGS" ]]; then - CMD="make CFLAGS_MODULE='$I2S_MODULE_CFLAGS'" -else - CMD=make -fi -echo $CMD -eval $CMD -if [[ $? -ne 0 ]]; then - echo "Error: I2S kernel module build failed" - exit 1 + fi fi popd > /dev/null +# Copy the udev rules files if device is UA +if [[ -n "$UA_MODE" ]]; then + sudo cp $RPI_SETUP_DIR/resources/99-xmos.rules /etc/udev/rules.d/ +fi + # Move existing files to back up if [[ -e ~/.asoundrc ]]; then chmod a+w ~/.asoundrc @@ -140,28 +196,25 @@ chmod a-w ~/.asoundrc # Apply changes sudo /etc/init.d/alsa-utils restart -# Create the script to run after each reboot and make the soundcard available -i2s_driver_script=$RPI_SETUP_DIR/resources/load_i2s_driver.sh -rm -f $i2s_driver_script +if [[ -n "$I2S_MODE" ]]; then + # Create the script to run after each reboot and make the soundcard available + i2s_driver_script=$RPI_SETUP_DIR/resources/load_i2s_driver.sh + rm -f $i2s_driver_script -# Sometimes with Buster on RPi3 the SYNC bit in the I2S_CS_A_REG register is not set before the drivers are loaded -# According to section 8.8 of https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf -# this bit is set after 2 PCM clocks have occurred. -# To avoid this issue we add a 1-second delay before the drivers are loaded -echo "sleep 1" >> $i2s_driver_script - -if [[ -z "$I2S_MODE" ]]; then - echo error: I2S mode not known for XMOS device $XMOS_DEVICE. - exit 1 -fi + # Sometimes with Buster on RPi3 the SYNC bit in the I2S_CS_A_REG register is not set before the drivers are loaded + # According to section 8.8 of https://cs140e.sergio.bz/docs/BCM2837-ARM-Peripherals.pdf + # this bit is set after 2 PCM clocks have occurred. + # To avoid this issue we add a 1-second delay before the drivers are loaded + echo "sleep 1" >> $i2s_driver_script -I2S_NAME=i2s_$I2S_MODE -I2S_MODULE=$RPI_SETUP_DIR/loader/$I2S_NAME/${I2S_NAME}_loader.ko -echo "sudo insmod $I2S_MODULE" >> $i2s_driver_script + I2S_NAME=i2s_$I2S_MODE + I2S_MODULE=$RPI_SETUP_DIR/loader/$I2S_NAME/${I2S_NAME}_loader.ko + echo "sudo insmod $I2S_MODULE" >> $i2s_driver_script -echo "# Run Alsa at startup so that alsamixer configures" >> $i2s_driver_script -echo "arecord -d 1 > /dev/null 2>&1" >> $i2s_driver_script -echo "aplay dummy > /dev/null 2>&1" >> $i2s_driver_script + echo "# Run Alsa at startup so that alsamixer configures" >> $i2s_driver_script + echo "arecord -d 1 > /dev/null 2>&1" >> $i2s_driver_script + echo "aplay dummy > /dev/null 2>&1" >> $i2s_driver_script +fi if [[ -n "$DAC_SETUP" ]]; then pushd $RPI_SETUP_DIR/resources/clk_dac_setup/ > /dev/null @@ -194,13 +247,19 @@ if [[ -n "$DAC_SETUP" ]]; then fi # Setup the crontab to restart I2S at reboot -rm -f $RPI_SETUP_DIR/resources/crontab -echo "@reboot sh $i2s_driver_script" >> $RPI_SETUP_DIR/resources/crontab -if [[ -n "$DAC_SETUP" ]]; then - echo "@reboot sh $dac_and_clks_script" >> $RPI_SETUP_DIR/resources/crontab -fi -crontab $RPI_SETUP_DIR/resources/crontab +if [ -n "$I2S_MODE" ] || [ -n "$DAC_SETUP" ]; then + rm -f $RPI_SETUP_DIR/resources/crontab -echo "To enable I2S, I2C and SPI, this Raspberry Pi must be rebooted." + if [[ -n "$I2S_MODE" ]]; then + echo "@reboot sh $i2s_driver_script" >> $RPI_SETUP_DIR/resources/crontab + fi + if [[ -n "$DAC_SETUP" ]]; then + echo "@reboot sh $dac_and_clks_script" >> $RPI_SETUP_DIR/resources/crontab + fi + crontab $RPI_SETUP_DIR/resources/crontab popd > /dev/null +fi + +echo "To enable all interfaces, this Raspberry Pi must be rebooted." +