Da sich der HIFI-Turm um Komponenten von Dual erweitert kam die Idee auf, auch den Volumio Pi mit der ESS9038 Pro Karte in ein entsprechendes Gehäuse zu verfrachten.

Auf bekanntem Wege wurde ein defekter Verstärker (DUAL CV 1450) ersteigert. Ziel war es auch die bestehenden Anzeigen und Schalter einzubinden.

Noch im original Zustand

Für die LED Anzeige musste eine Spannung von +/-15V DC erzeugt werden. Entsprechende IC Module finden sich im Netz. Der Transformator für die Stromversorgung des Pi’s hatte noch eine AC End übrig, sodass dies zunächst mit einem AC/DC Konverter (XL2596S) auf notwendig +11V DC umgewandelt wurde und nachgeschaltet über einen XL6007E1 (Stepper) in +/-15V DC.

Der Aufbau: links der Transformator für den Pi sowie die LED Anzeige. Oben der AC/DC Konverter für den Pi. Links unten zuerst der AC/DC Wandler sowie nachgeschalter der DC +/- Wandler. Ebenfalls links unten die Steuerplatine der LED-Anzeige (im Original). Rechts oben die ESS 9038 Pro Platine mit dem Raspberry Pi unterhalb. Die Potentiometer wurden gegen Drehencoder ersetzt. Die Chinchbuchsen wurden mit dem ES9038Pro Ausgang verbunden.

Software

Als Grundlage dient wie immer Volumio. Die Drehencoder können einfach mit dem Rotary Encoder II Plugin eingebunden werden. Für die LED Meter Anzeige wird das Plugin PeppyMeter verwendet, welches mittels PWM auch ein Analogsignal erzeugen kann. Die Installation erfordert etwas Geschick: https://github.com/balbuze/volumio-plugins/tree/alsa_modular/plugins/miscellanea/peppyMeter

ESS 9038 PRO I2C Ansteuerung

Die Audiosignal Übertragung an den ESS9038 Pro Chip erfolgt mittels SPI. Die Registersteuerung über einen I2C Bus. Die Dokumentation hierzu ist proprietär, kann aber in Netz gefunden werden. Die Initialisierung erfolgt mit einem kleinen Python Skript, welches beim Start des Pi’s ausgeführt wird.

Ein Auszug mit den wichtigsten Befehlen und Einstellungen:

from smbus2 import SMBus
import RPi.GPIO as GPIO
import logging
import sys
import time

I2CAddress = 0x48
i2cbus = SMBus(1)
mute = 0

def Mute():
    global mute
    if mute:
        changeBit(0x07, 0, 0)
        mute = 0
    else:
        changeBit(0x07, 0, 1)
        mute = 1

def startDAC():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(17, GPIO.OUT)
    GPIO.output(17, GPIO.HIGH)
    checki2c()

    try:
        changeBit(0x00, 0, 1,read=False)
    except:
         e = sys.exc_info()[0]
         print(e)
    try:
         changeBit(0x00, 0, 0,read=False)
    except:
          e = sys.exc_info()[0]
          print(e)

    #Mute()
    changeBit(0x09, 7, 0)  #Setup GPIO4
    changeBit(0x09, 6, 1)  #Setup GPIO4
    changeBit(0x09, 5, 0)  #Setup GPIO4
    changeBit(0x09, 4, 0)  #Setup GPIO4
    changeBit(0x0F, 2, 1)  #Set DAC up for Stereo Mode
    changeBit(0x04, 2, 1)  #Automute
    changeBit(0x36, 7, 0)  #Enable DoP support

    changeBit(0x02, 7, 1) #//Automute 1
    changeBit(0x02, 6, 1) #//Automute 2 2’b11: perform a mute and then ramp all channels to ground
                           #//when an automute condition is asserted
    changeBit(0x07, 7, 1)
    changeBit(0x07, 6, 1)
    changeBit(0x07, 5, 1)

    writeRegister(0x1C, 0x08)
    changeBit(0x0D, 7, 0) #enable Dithering
    changeBit(0x06, 6, 0) #Deemphasing enabled
    changeBit(0x06, 7, 1) #Auto Deemphasing


def set_bit(value, bit):
    return value | (1<<bit)

def clear_bit(value, bit):
    return value & ~(1<<bit)

def changeBit(regHex,bit,value,read=False):
    registerValue = readRegister(regHex)
    print()
    if value == 1:
        newRegValue = set_bit(registerValue, bit)
    else:
        newRegValue = clear_bit(registerValue, bit)

    writeRegister(regHex,newRegValue)

    readedRegisterValue = 0x00
    if read:
        readedRegisterValue = readRegister(regHex)

    print("Reg:"+str(regHex)+":"+format(registerValue, '08b')+"->"+format(readedRegisterValue, '08b'))
    time.sleep(0.1)

def readRegister(regHex):
    result = i2cbus.read_byte_data(0x48, regHex)
    print(str(regHex)+":"+format(result, '08b')+":"+str(result))
    return result

def writeRegister(regHex,byte):
    i2cbus.write_byte_data(0x48, regHex, byte)


def checki2c():
    devices = list()
    for device in range(128):
          try:
             i2cbus.read_byte(device)
             devices.append(hex(device))
          except: # exception if read_byte fails
             pass

    if hex(0x048) not in devices:
        logging.info("ESS9038Pro not found")
    else:
        print("ES9038 Pro Found")
        logging.info("i2c devices found: "+str(devices))


def bitAtGivenPosSetOrUnset(n, k):
    new_num = n >> (k - 1)
    return (new_num & 1)

def getlockStatus():
    ret = readRegister(0x40)
    if ret&1 != 0:
        lock = readRegister(0x64)

        if bitAtGivenPosSetOrUnset(lock,4):
            return "DOP"
        elif bitAtGivenPosSetOrUnset(lock,3):
            return "SPDIF"
        elif bitAtGivenPosSetOrUnset(lock,2):
            return "I2S"
        elif bitAtGivenPosSetOrUnset(lock,1):
            return "DSD"
    else:
        return "NOLOCK"

Leave A Comment

Deine E-Mail-Adresse wird nicht veröffentlicht.