#!/usr/bin/env python ########################################################################## # tas5806-init # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. ########################################################################## ''' install: pip3 install smbus2 run: python3 tas5806Test.py ''' from smbus2 import SMBus # Open i2c bus 1 and read one byte from address 80, offset 0 import os import time import subprocess from math import log, exp MAX_VOL = 84 class tasTest: devAddr = 0x2f bus = "" commandReturn = "" def __init__(self): self.bus = SMBus(1) def dumpData(self): #for i in range(0x10): # b = self.bus.read_byte_data(self.devAddr, i) # print("%s: %s" % (hex(i), hex(b)) ) #print("------------------") commandSend = 'i2cdump -y 1 ' +str( self.devAddr) +' W' #os.system(commandSend) self.commandReturn = os.popen(commandSend).read() #print(self.commandReturn) self.checkErrors() ''' Check through error codes in i2cDump ''' def checkErrors(self): # register 0x37 fsMon = self.commandReturn.splitlines()[4][25:27] fsMonBin = "{0:08b}".format(int(fsMon, 16)) fsMonStr = ["FS Error","","","","","","32KHz","","Reserved","48KHz","","96KHz"] #print("FS_MON: %s (0x37)" % (fsMon)) print("FS_MON: %s (reg: 0x37)" % fsMonStr[int(fsMon)] ) # (reg: 0x70) errorString = self.commandReturn.splitlines()[8][4:6] errorStringBin = "{0:08b}".format(int(errorString, 16)) if(errorStringBin[-4] == "1" ): print("Left channel DC fault" ) if(errorStringBin[-3] == "1" ): print("Right channel DC fault" ) if(errorStringBin[-2] == "1" ): print("Left channel over current fault" ) if(errorStringBin[-1] == "1" ): print("Right channel over current fault" ) # (reg: 0x71) errorString = self.commandReturn.splitlines()[8][7:9] errorStringBin = "{0:08b}".format(int(errorString, 16)) if(errorStringBin[-3] == "1" ): print("Clock fault (reg: 0x71)" ) # register 0x68 runStatus = self.commandReturn.splitlines()[7][29:31] runStatusBin = "{0:08b}".format(int(runStatus, 16)) #print(runStatus) runStatusStr = ["Deep sleep","Sleep","HIZ","Play"] print("Run Status: %s (reg: 0x68)" % runStatusStr[int(runStatus)] ) def writeData(self, addr, val, comment = "" ): self.bus.write_byte_data(self.devAddr, addr , val) #print("write: %s: %s - %s" %(hex(addr),hex(val), comment ) ) time.sleep(0.1) def close(self): self.bus.close() ''' Start Sequence for the TAS5806 ''' def startSequence(self): self.writeData(0x01,0x11, "Reset Chip") #reset chip self.writeData(0x78,0x80, "Clear Faults") #clear fault - works self.dumpData() self.writeData(0x01,0x00 , "Remove Reset") #remove reset self.writeData(0x78,0x00 , "Remove Clear Fault") #remove clear fault self.dumpData() #self.writeData(51,3) # 0x33 h set bit rate #self.writeData(118,64) # 0x76 ##self.writeData(0x6A,3 , "") ##self.dumpData() #self.writeData(0x33,0x00, "16-bit") #self.writeData(0x33,0x01, "20-bit") #self.writeData(0x33,0x02, "24-bit") self.writeData(0x33,0x03, "32-bit") self.dumpData() self.setVolume(0x60) self.writeData(0x30,0x01, "SDOUT is the DSP input (pre-processing)") self.writeData(0x03,0x00, "Deep Sleep") #Deep Sleep self.dumpData() #self.writeData(0x03,0x01) #Sleep #self.dumpData() self.writeData(0x03,0x02, "HiZ") #HiZ self.dumpData() self.writeData(0x5C,0x01, "coefficient") #Indicate the first coefficient of a BQ is starting to write self.dumpData() self.writeData(0x03,0x03 , "Play") #Play self.dumpData() def calc_log_y(self, x): """ given x produce y. takes in an int 0-100 returns a log oriented hardware value with larger steps for low volumes and smaller steps for loud volumes """ if x < 0: x = 0 if x > 100: x = 100 x0 = 0 # input range low x1 = 100 # input range hi y0 = MAX_VOL # max hw vol y1 = 210 # min hw val p1 = (x - x0) / (x1 - x0) p2 = log(y0) - log(y1) pval = p1 * p2 + log(y1) return round(exp(pval)) def calc_log_x(self, y): """ given y produce x. takes in an int 30-210 returns a value from 0-100 """ if y < 0: y = MAX_VOL if y > 210: y = 210 x0 = 0 # input range low x1 = 100 # input range hi y0 = MAX_VOL # max hw vol y1 = 210 # min hw val x = x1 - x0 p1 = (log(y) - log(y0)) / (log(y1) - log(y0)) return x * p1 + x0 def setVolume(self, vol=1.0): # vol takes a float from 0.0 - 1.0 # default vol 0.5 = 50% hw_vol = self.calc_log_y(vol * 100.0) setVolStr = "Set Volume %s" %( str (hw_vol) ) self.writeData(0x4c, hw_vol, setVolStr) #Set volume if __name__ == '__main__': tt = tasTest() tt.startSequence() tt.setVolume() tt.close()