SaraKIT features the advanced ZL38063 audio processor from Microsemi's Timberwolf family, enhancing Automatic Speech Recognition (ASR) across extended distances with barge-in capabilities and optimized for voice command detection.
The ZL38063, powered by Microsemi's AcuEdge™ Technology, is tailored for use in televisions, set-top boxes, and smart speakers, and is equally effective in other smart home applications. This device supports voice control and two-way full-duplex audio, incorporating voice enhancements like Acoustic Echo Cancellation (AEC) and Noise Reduction (NR) to improve voice clarity and quality in challenging acoustic environments.
Full DataSheet is available here:
https://www.microsemi.com/document-portal/doc_view/136798-zl38063-datasheet
Product Brief:
https://www.microsemi.com/document-portal/doc_view/136797-zl38063-product-brief
Alongside SaraKIT, we provide a pre-configured audio driver, based on the codec included in the Linux distribution for Raspberry Pi (https://elixir.bootlin.com/linux/v6.1.74/source/sound/soc/codecs/zl38060.c, enhanced with several useful controls accessible via the Alsa interface from Python or C++. Our extended version of the codec is available at: https://github.com/SaraEye/SaraKIT-ZL38063-Audio-Codec/blob/main/zl38060.c
You can find the build instructions for the codec here: https://github.com/SaraEye/SaraKIT-ZL38063-Audio-Codec
To the standard controls for adjusting volume (MasterA and MasterB) and microphone gain (Dig MIC), we've added two controls: "Power Meter" and "Registers." Before detailing the controls, let's look at the current configuration.
See the connection diagram:
In most of our development projects, the sound originates from three microphones, processed through Sin Gain->Equalizer->AEC (Acoustic Echo Canceller)->Beamformer->Noise Reduction->Expander->Compressor->Limiter, then sent as a two-channel (Stereo) audio path. The left channel delivers processed voice, and the right channel provides the voice without processing.
Thus, MasterA and MasterB controls adjust the volume of the left and right channels for music listening, but for microphone voice analysis, they adjust the volume of processed voice in MasterA and unprocessed voice in MasterB as described above.
The "Power Meter" control displays the audio processor's internal signal levels in decibels, essential for adjusting signal gains under various conditions. Here's an example Python code demonstrating this control's functionality:
https://github.com/SaraEye/SaraKIT-Python-Examples/blob/main/SaraKIT-Audio/ShowPowerMeter.py
# sudo apt install python3-alsaaudio
import alsaaudio
import time
import math
import sys
import subprocess
def scale_dBov_to_percentage(power_value, min_dBov=-90, max_dBov=0):
if power_value==0:
return 0
dBov = 10 * math.log10(power_value) - 10 * math.log10(2**30)
if dBov < min_dBov:
return 0
elif dBov > max_dBov:
return 100
else:
return (dBov - min_dBov) / (max_dBov - min_dBov) * 100
def display_progress_bar(value, max_value=100, bar_length=50, max_position=None):
percent = int((value / max_value) * 100)
fill_length = int(percent * bar_length // 100)
bar = ''
for i in range(bar_length):
if i == max_position:
bar += '\033[91m|\033[0m'
elif i < fill_length:
bar += '#'
else:
bar += '-'
sys.stdout.write(f'\r[{bar}] -{100-percent}dBFS')
sys.stdout.flush()
# print sound card
for card in alsaaudio.cards():
print(card)
#Tap-off Points:
# ----- 0x0000 Silence (measurement off)
# SIN_A 0x0005 Sin1 input
# AEC_IN_A 0x0006 Input to AEC 1
# AEC_OUT_A 0x0008 Output of AEC 1
# SIN_B 0x0009 Sin2 input
# AEC_IN_B 0x000A Input to AEC 2
# AEC_OUT_B 0x000C Output of AEC 2
# SIN_C 0x000D Sin3 input
# AEC_IN_C 0x000E Input to AEC 3
# AEC_OUT_C 0x0010 Output of AEC 3
# SOUT2 0x0016 Sout2 after Beamformer output
# SOUT1 0x0017 Sout1 before the master bypass point
# RIN_LEFT/RIN_RIGHT 0x0018 Rin_Left/Rin_Right after the Receive High
#AEC_IN_A = 6 (from Mic1)
print("Sin1 input (Mic1)")
subprocess.run(['amixer', '-c0', 'cset', 'name=Power Meter', '6'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
mixin_name = 'Power Meter'
max_value_seen = 0
max_value_time = time.time()
max_position = None
try:
while True:
mixin = alsaaudio.Mixer(mixin_name,cardindex=0)
vol=mixin.getvolume()
power_value = vol[0]
percentage = scale_dBov_to_percentage(power_value)
if percentage > max_value_seen or time.time() - max_value_time > 2:
max_value_seen = percentage
max_value_time = time.time()
max_position = int((max_value_seen / 100) * 50)
if time.time() - max_value_time <= 2: #1 second
display_position = max_position
else:
display_position = None
display_progress_bar(percentage, max_value=100, bar_length=50, max_position=display_position)
time.sleep(0.1)
except KeyboardInterrupt:
print("\nEnd.")
The "Registers" control offers a unique interface to access every ZL38063 register, allowing full control and customization of the audio processor's capabilities. The following example reads the direction of incoming sound. Easy access to registers opens up endless possibilities.
https://github.com/SaraEye/SaraKIT-Python-Examples/blob/main/SaraKIT-Audio/SoundLocator.py
import alsaaudio
import time
import subprocess
def ReadZL38063(register, firstTime=False):
if firstTime:
register &= 0xFFFF
register = (register << 16) | 0x40000000
subprocess.run(['amixer', '-c0', 'cset', 'name=Registers', str(register)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
result = subprocess.run(['amixer', '-c0', 'cget', 'name=Registers'], capture_output=True, text=True)
output = result.stdout
last_line = output.strip().split('\n')[-1]
value = last_line.split('=')[-1] if last_line else None
return value
def WriteZL38063(register,value):
register &= 0xFFFF
value &= 0xFFFF
register = (register << 16) | value | 0x20000000
subprocess.run(['amixer', '-c0', 'cset', 'name=Registers', str(register)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
return 0
#define ZL380xx_SND_LOC_DIR_REG 0x00A0
ReadZL38063(0x00A0,True)
while True:
print("Angle: %s°" % ReadZL38063(0xA0))
time.sleep(0.1)
Audio Volume Example:
https://github.com/SaraEye/SaraKIT-Python-Examples/blob/main/SaraKIT-Audio/AudioVolume.py
import alsaaudio
import time
mixinA_name = 'MasterA'
mixinB_name = 'MasterB'
mixinA = alsaaudio.Mixer(mixinA_name, cardindex=0)
mixinB = alsaaudio.Mixer(mixinB_name, cardindex=0)
# Set new volume value (in percent)
new_volume = 24 # Set the value between 0 and 100
# Apply the new volume value
mixinA.setvolume(new_volume)
mixinB.setvolume(new_volume)
# Read and display the new volume value to confirm the change
current_volume = mixinA.getvolume()
print(f"New volume: {current_volume[0]}%")
============= for Geeks:
You can find the build instructions for the codec here: https://github.com/SaraEye/SaraKIT-ZL38063-Audio-Codec
============= for Geeks (Old Microsemi Driver for MiTuner):
Audio setup
You can use prepared by us prebuild driver installing by script described above or build manually as described below.
You can find audio driver in our repository ZL38063 driver
Install rpi-soure
Build linux kernel(on raspberrypi it can take about 4hrs)
cd ~/linux
make oldconfig && make prepare && make -j4
go to vproc_sdk in ZL38063_driver and build build all neceseary things
make hbilnx
all modules and overlays will be stored in libs directory
from vproc_sdk/libs install overlays(dtbo) in /boot/overlays
sudo install -m 0755 ./*.dtbo /boot/overlays
from vproc_sdk/libs install modules replace kernel version if necesseary
sudo mkdir /lib/modules/5.15.32-v8+/sarakit
sudo install -m 0755 ./*.ko /lib/modules/5.15.32-v8+/sarakit
sudo install -m 0755 ./*.dtbo /boot/overlays
sudo depmod
modify /boot/config.txt
uncomment:
dtparam=i2c_arm=on
dtparam=i2s=on
dtparam=spi=on
comment:
#dtparam=audio=on
add:
dtoverlay=spi0-2cs
dtoverlay=microsemi-spi-overlay
dtoverlay=microsemi-dac-overlay
after reboot aplay should be able to list devices
aplay -l
for testing
aplay -f S16_LE -r 16000 -c2 -Dplug:dmix song.wav
arecord -d5 -f S16_LE -r 16000 -Dplug:dsnoop -c2 record.wav