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:

Product Brief:

Alongside SaraKIT, we provide a pre-configured audio driver, based on the codec included in the Linux distribution for Raspberry Pi (, enhanced with several useful controls accessible via the Alsa interface from Python or C++. Our extended version of the codec is available at:
You can find the build instructions for the codec here:

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:

# 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
        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 += '#'
            bar += '-'
    sys.stdout.write(f'\r[{bar}] -{100-percent}dBFS')

# print sound card
for card in

#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)")['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

    while True:

        mixin = alsaaudio.Mixer(mixin_name,cardindex=0)
        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
            display_position = None

        display_progress_bar(percentage, max_value=100, bar_length=50, max_position=display_position)

except KeyboardInterrupt:


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.

import alsaaudio
import time
import subprocess

def ReadZL38063(register, firstTime=False):
    if firstTime:
        register &= 0xFFFF
        register = (register << 16) | 0x40000000   ['amixer', '-c0', 'cset', 'name=Registers', str(register)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
    result =['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['amixer', '-c0', 'cset', 'name=Registers', str(register)], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)     
    return 0

#define ZL380xx_SND_LOC_DIR_REG 0x00A0

while True:
    print("Angle: %s°" % ReadZL38063(0xA0))


Audio Volume Example:

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

# 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:


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




 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