197 lines
5.9 KiB
Python
Executable File
197 lines
5.9 KiB
Python
Executable File
#!/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()
|
|
|