Skip to content

Commit

Permalink
Merge pull request #54 from ed-xmos/feature/xvf3800_support
Browse files Browse the repository at this point in the history
XVF3800 support
  • Loading branch information
ed-xmos authored Jan 3, 2023
2 parents ea5b95a + dd5938b commit 34dc994
Show file tree
Hide file tree
Showing 5 changed files with 119 additions and 42 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## 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
Expand Down
26 changes: 22 additions & 4 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,15 @@ 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.
Expand All @@ -119,5 +137,5 @@ write it's own value to the clocks and the MCLK will no longer be phase locked.
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`
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
30 changes: 20 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 @@ -236,7 +246,7 @@ if [[ -n "$I2S_MODE" ]]; then
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 @@ -248,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 @@ -276,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 34dc994

Please sign in to comment.