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.
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"