Skip to content

Commit

Permalink
Merge pull request #55 from xmos/release/v5.4.0
Browse files Browse the repository at this point in the history
5.4.0 -> Main
  • Loading branch information
ed-xmos authored Jan 3, 2023
2 parents d972c09 + 34dc994 commit 85dad33
Show file tree
Hide file tree
Showing 5 changed files with 148 additions and 41 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# VocalFusion Raspberry Pi Setup Change Log

## 5.4.0

* Add support for XVF3800
* rename setup_dac.py to setup_io_exp_and_dac.py
* Fixed documentation to state use of 12.288MHz instead of 24.576MHz mclk
* Fix and document MCLK phase issue found on raspberry pi 3b

## 5.3.0

* Fix setup_dac.py script for XVF3615
Expand Down
41 changes: 38 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ This setup will perform the following operations:

For XVF3510-INT 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)
- configure MCLK at 12288kHz from pin 7 (BCM 4)
- configure I2S BCLK at 3072kHz from pin 12 (BCM 18)
- update the alias for Audacity
- update the asoundrc file to support I2S devices
- add a cron job to reset the device at boot up
Expand All @@ -26,12 +26,21 @@ For XVF3510-INT devices these actions will be done as well:
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)
- configure I2S BCLK at 3072kHz from pin 12 (BCM 18)
- 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 XVF3800(ALL) 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 (BCM 18)
- 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 IO expander at boot up

For XVF3510-UA and XVF361x-UA devices these actions will be done as well:

- update the asoundrc file to support USB devices
Expand Down Expand Up @@ -101,6 +110,32 @@ For XVF3510-UA and XVF361x-UA devices these actions will be done as well:

```./setup.sh xvf3615-int```

For XVF3800-INTDEV devices, run the installation script as follows:

```./setup.sh xvf3800-intdev```

For XVF3800-INTHOST devices, run the installation script as follows:

```./setup.sh xvf3800-inthost```


Wait for the script to complete the installation. This can take several minutes.

5. Reboot the Raspberry Pi.

## Important note on clocks

The I2S/PCM driver that is provided with rasbian does not support an MCLK output. However the
driver does have full ability to set the BCLK and LRCLK correctly for a given sample rate. As
the driver does not know about the MCLK it is likely to choose dividers for the clocks generators
which are not phase locked to the MCLK. The script in this repo gets around this problem by
configuring the i2s driver to a certain frequency and then overriding the clock registers to force
a phase locked frequency.

This will work until a different sample rate is chosen by an application, then the I2S driver will
write it's own value to the clocks and the MCLK will no longer be phase locked. To solve this problem
the following steps must be taken before connecting an XVF device with a different sample rate:

1. Take a short recording at the new sample rate: `arecord -c2 -fS32_LE -r{sample_rate} -s1 -Dhw:sndrpisimplecar`
2. For 48kHz `./resources/clk_dac_setup/setup_blk`, for 16kHz `./resources/clk_dac_setup/setup_blk 16000`

Original file line number Diff line number Diff line change
@@ -1,44 +1,42 @@
#!usr/bin/python
# Copyright (c) 2018-2022, XMOS Ltd, All rights reserved
# Copyright (c) 2018-2023, XMOS Ltd, All rights reserved

#run this on the raspberry pi to program the DAC
# run this on the raspberry pi to setup the IO expander and program the DAC (DAC setup for non-xvf3800 only)

import argparse
import smbus
import time

def setup_dac(args):
def setup_io_expander(bus, args):
"""
Function to configure DAC of XVF boards
Function to setup the I2C IO expander of XVF boards
Args:
bus - I2C access object
args - command line arguments
Returns:
None
"""

samFreq = 48000
bus = smbus.SMBus(1)

# I2C expander bus address for XVF36XX and XVF3800 with PCAL6408A expander device
I2C_EXPANDER_ADDRESS = 0x20

if "xvf36" in args.hw:
# I2C expander register addresses
I2C_EXPANDER_OUTPUT_PORT_REG = 0x01
I2C_EXPANDER_CONFIGURATION_REG = 0x03
I2C_EXPANDER_INTERRUPT_MASK_REG = 0x45

# I2C expander pin mapping
XVF_RST_N_PIN = 0
INT_N_PIN = 1
DAC_RST_N_PIN = 2
BOOT_SEL_PIN = 3
MCLK_OE_PIN = 4
SPI_OE_PIN = 5
I2S_OE_PIN = 6
MUTE_PIN = 7

# I2C expander register addresses
I2C_EXPANDER_OUTPUT_PORT_REG = 0x01
I2C_EXPANDER_CONFIGURATION_REG = 0x03
I2C_EXPANDER_INTERRUPT_MASK_REG = 0x45

# I2C expander pins
XVF_RST_N_PIN = 0
INT_N_PIN = 1
DAC_RST_N_PIN = 2
BOOT_SEL_PIN = 3
MCLK_OE_PIN = 4
SPI_OE_PIN = 5
I2S_OE_PIN = 6
MUTE_PIN = 7
if "xvf36" in args.hw:

# Set pin values
# set DAC_RST_N to 0 and enable level shifters on the I2C expander
Expand Down Expand Up @@ -79,18 +77,61 @@ def setup_dac(args):
bus.write_byte_data(I2C_EXPANDER_ADDRESS, I2C_EXPANDER_OUTPUT_PORT_REG, OUTPUT_PORT_MASK | (1<<DAC_RST_N_PIN))
time.sleep(0.1)

elif "xvf38" in args.hw:
# Set pin values to 1. Note no DAC reset as this is done by the firmware
# Note pre-load XVF_RST and BOOT_SEL to 1 and preload I2S/MCLK/SPI driving signal from host to xvf
OUTPUT_PORT_MASK= (1<<XVF_RST_N_PIN) | \
(1<<BOOT_SEL_PIN) | \
(1<<MCLK_OE_PIN) | \
(1<<SPI_OE_PIN) | \
(1<<I2S_OE_PIN)

bus.write_byte_data(I2C_EXPANDER_ADDRESS, I2C_EXPANDER_OUTPUT_PORT_REG, OUTPUT_PORT_MASK)
time.sleep(0.1)

# Configure pin directions. Setting to 1 means input, or Hi-Z. So anything not mentioned
# below will be an output. Note reset, int and boot_sel NOT driven because they are set high in the mask
# use DAC_RST_N and level shift OE as driven outputs
CONFIGURATION_MASK = (1<<XVF_RST_N_PIN) | \
(1<<INT_N_PIN) | \
(1<<DAC_RST_N_PIN) | \
(1<<BOOT_SEL_PIN)
#I2S, MCLK and SPI all enabled so we can drive from host to xvf3800

bus.write_byte_data(I2C_EXPANDER_ADDRESS, I2C_EXPANDER_CONFIGURATION_REG, CONFIGURATION_MASK)
time.sleep(0.1)

# Enable the interrupt on INT_N pin
# Interrupts are enabled by setting corresponding mask bits to logic 0
INTERRUPT_MASK = 0xFF & ~(1<<INT_N_PIN)
bus.write_byte_data(I2C_EXPANDER_ADDRESS, I2C_EXPANDER_INTERRUPT_MASK_REG, INTERRUPT_MASK)


else:
# set DAC_RST_N to 0 on the I2C expander (address 0x20)
bus.write_byte_data(I2C_EXPANDER_ADDRESS, 6, 0xff)
time.sleep(0.1)
bus.write_byte_data(I2C_EXPANDER_ADDRESS, 6, 0x7f)
time.sleep(0.1)



def setup_dac(bus):
"""
Function to configure DAC of XVF boards
Args:
bus - I2C access object
Returns:
None
"""

DEVICE_ADDRESS = 0x18
# TLV320DAC3101 Register Addresses
# Page 0
DAC3101_PAGE_CTRL = 0x00 # Register 0 - Page Control
DAC3101_SW_RST = 0x01 # Register 1 - Software Reset
DAC3101_PAGE_CTRL = 0x00 # Register 0 - Page Control
DAC3101_SW_RST = 0x01 # Register 1 - Software Reset
DAC3101_CLK_GEN_MUX = 0x04 # Register 4 - Clock-Gen Muxing
DAC3101_PLL_P_R = 0x05 # Register 5 - PLL P and R Values
DAC3101_PLL_J = 0x06 # Register 6 - PLL J Value
Expand Down Expand Up @@ -250,4 +291,9 @@ def setup_dac(args):
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("hw", help="Hardware type")
setup_dac(parser.parse_args())
args = parser.parse_args()
bus = smbus.SMBus(1)

setup_io_expander(bus, args)
if "xvf36" in args.hw:
setup_dac(bus)
4 changes: 2 additions & 2 deletions resources/clk_dac_setup/setup_mclk_bclk.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2019, XMOS Ltd, All rights reserved
// Copyright (c) 2019-2023, XMOS Ltd, All rights reserved

/*
Trimmed down version of the minimal_clk.c file present
Expand All @@ -11,7 +11,7 @@
*/

/*
Set the general purpose clk GPCLK0 (gpio4) to 24.576 MHz,
Set the general purpose clk GPCLK0 (gpio4) to 12.288 MHz,
and PCM CLK to 3.072 MHz, using PLLD as source.
*/

Expand Down
39 changes: 29 additions & 10 deletions setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ I2S_MODE=
XMOS_DEVICE=
INSTALL_ATTEMPT_NUM_MAX=10
# Valid values for XMOS device
VALID_XMOS_DEVICES="xvf3100 xvf3500 xvf3510-int xvf3510-ua xvf3600-slave xvf3600-master xvf3610-int xvf3610-ua xvf3615-int xvf3615-ua"
VALID_XMOS_DEVICES="xvf3100 xvf3500 xvf3510-int xvf3510-ua xvf3600-slave xvf3600-master xvf3610-int xvf3610-ua xvf3615-int xvf3615-ua xvf3800-intdev xvf3800-inthost"

PACKAGES_TO_INSTALL="python3-matplotlib python3-numpy libatlas-base-dev audacity libreadline-dev libncurses-dev"
PACKAGES_TO_INSTALL_ONLY_FOR_UA="libusb-1.0-0-dev libevdev-dev libudev-dev"
Expand Down Expand Up @@ -65,10 +65,9 @@ case $XMOS_DEVICE in
I2S_MODE=slave
ASOUNDRC_TEMPLATE=$RPI_SETUP_DIR/resources/asoundrc_vf_xvf3510_ua
;;

xvf3510-int|xvf3610-int|xvf3615-int)
I2S_MODE=master
DAC_SETUP=y
IO_EXP_AND_DAC_SETUP=y
ASOUNDRC_TEMPLATE=$RPI_SETUP_DIR/resources/asoundrc_vf_xvf3510_int
;;
xvf3500)
Expand All @@ -81,12 +80,23 @@ case $XMOS_DEVICE in
;;
xvf3600-slave)
I2S_MODE=master
DAC_SETUP=y
IO_EXP_AND_DAC_SETUP=y
ASOUNDRC_TEMPLATE=$RPI_SETUP_DIR/resources/asoundrc_vf
;;
xvf3600-master)
I2S_MODE=slave
DAC_SETUP=y
IO_EXP_AND_DAC_SETUP=y
ASOUNDRC_TEMPLATE=$RPI_SETUP_DIR/resources/asoundrc_vf
;;
# Note DAC is not setup for XVF3800 - the setup script takes an arg which will conditionally do this
xvf3800-intdev)
I2S_MODE=master
IO_EXP_AND_DAC_SETUP=y
ASOUNDRC_TEMPLATE=$RPI_SETUP_DIR/resources/asoundrc_vf
;;
xvf3800-inthost)
I2S_MODE=slave
IO_EXP_AND_DAC_SETUP=y
ASOUNDRC_TEMPLATE=$RPI_SETUP_DIR/resources/asoundrc_vf
;;
*)
Expand Down Expand Up @@ -225,9 +235,18 @@ if [[ -n "$I2S_MODE" ]]; then
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

if [[ "$I2S_MODE" = "master" ]]; then
echo "# Preconfigure i2s clocks to 48kHz" >> $i2s_driver_script
# wait a bit as it doesn't work otherwise, this is probably caused
# by the same process that is deleting .asoundrc
echo "sleep 15" >> $i2s_driver_script
echo "arecord -Dhw:sndrpisimplecar,0 -c2 -fS32_LE -r48000 -s1 /dev/null" >> $i2s_driver_script
echo "sudo $RPI_SETUP_DIR/resources/clk_dac_setup/setup_bclk" >> $i2s_driver_script
fi
fi

if [[ -n "$DAC_SETUP" ]]; then
if [[ -n "$IO_EXP_AND_DAC_SETUP" ]]; then
pushd $RPI_SETUP_DIR/resources/clk_dac_setup/ > /dev/null
make
popd > /dev/null
Expand All @@ -239,11 +258,11 @@ if [[ -n "$DAC_SETUP" ]]; then
echo "sudo $RPI_SETUP_DIR/resources/clk_dac_setup/setup_bclk" >> $dac_and_clks_script
fi
# Note that only the substring xvfXXXX from $XMOS_DEVICE is used in the lines below
echo "python $RPI_SETUP_DIR/resources/clk_dac_setup/setup_dac.py $(echo $XMOS_DEVICE | cut -c1-7)" >> $dac_and_clks_script
echo "python $RPI_SETUP_DIR/resources/clk_dac_setup/setup_io_exp_and_dac.py $(echo $XMOS_DEVICE | cut -c1-7)" >> $dac_and_clks_script
echo "python $RPI_SETUP_DIR/resources/clk_dac_setup/reset_xvf.py $(echo $XMOS_DEVICE | cut -c1-7)" >> $dac_and_clks_script
fi

if [[ -n "$DAC_SETUP" ]]; then
if [[ -n "$IO_EXP_AND_DAC_SETUP" ]]; then
audacity_script=$RPI_SETUP_DIR/resources/run_audacity.sh
rm -f $audacity_script
echo "#!/usr/bin/env bash" >> $audacity_script
Expand All @@ -267,11 +286,11 @@ fi
rm -f $crontab_file

# Setup the crontab to restart I2S at reboot
if [ -n "$I2S_MODE" ] || [ -n "$DAC_SETUP" ]; then
if [ -n "$I2S_MODE" ] || [ -n "$IO_EXP_AND_DAC_SETUP" ]; then
if [[ -n "$I2S_MODE" ]]; then
echo "@reboot sh $i2s_driver_script" >> $crontab_file
fi
if [[ -n "$DAC_SETUP" ]]; then
if [[ -n "$IO_EXP_AND_DAC_SETUP" ]]; then
echo "@reboot sh $dac_and_clks_script" >> $crontab_file
fi
popd > /dev/null
Expand Down

0 comments on commit 85dad33

Please sign in to comment.