• Disclaimer: This Vendor's Forum is a paid-for commercial area. Unlike the rest of diyAudio, the Vendor has complete control of what may or may not be posted in this forum. If you wish to discuss technical matters outside the bounds of what is permitted by the Vendor, please use the non-commercial areas of diyAudio to do so.

Control of BBB-based audio appliances

Status
This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.
Member
Joined 2007
Paid Member
Hmm - you could have some DC on your mains - an isolation transformer can help for that. Otherwise you might just need better shielding. Large ground bounces can wreak havoc on your gear.

Also - you can detect when a reset occurs and then respond by re-initializing to your desired state.

Been away traveling but now back on this issue. Two things:

1. I added (what I hope is) a decent multi-stage power filter to the BBB/DAC plus the switching power supply for the external chassis fans. I also put the amps on a better surge suppressor. Still gathering data. I don't claim to know everything that could go wrong.

2. I've been studying my Python, and have now modified the control program for the system so that it runs in multiprocessing mode. This allowed me to add a 'police' function that checks one register in each of the 9028s at fixed time intervals (trying 0.3 seconds). The question is, what is the best register to monitor in this situation? The ultimate problem is DC going to the speakers. I don't really know if that has been caused by a full DAC reset or just some registers being disturbed. For various reasons I suspect the latter. Otherwise, why would only one of two tweeters fry? So I'm wondering if there is one register in particular to blame, because that would be the one to monitor. My guess would be register 15 somehow being knocked out of 'stereo mode'. It might be feasible to monitor two registers - I haven't tried. Any and all thoughts on this question would be appreciated. Pure speculation welcome! ;)

Cheers,

Frank
 
Member
Joined 2007
Paid Member
The question is, what is the best register to monitor in this situation?

Reflecting further on this, I would like to know the mapping of the 9028's 8 channels by Buffalo. Specifically, to the plus and minus sides of each differential output. I saw problems when I tried to tweak the relative volume of the left vs. the right channel using registers 16-23. If that were done incorrectly, could it 'unbalance' the output of a channel? :confused:
 
Member
Joined 2007
Paid Member
Sporadic work on the problem of 9028 register stability is yielding some progress.

Unintended alterations of 9028 registers is still occurring. How? Still no clue. The 3 DAC boards are housed together in a rack chassis and the BBB is housed in a smaller chassis - the two are attached by a multi-function cable with 2X5v power and I2C connections. All the chassis casing is shielded to the same ground, with the 4 ft. power cable being completely surrounded by copper braid. I2S signals travel through separate cat6 cables via teleporters. I placed a power conditioner on the power plugs to the DAC chassis - 10A Two Outlet Power Conditioner | Furman Power | Purifying power for over 40 years. That made an improvement - now it seems that the main source of interference is the power switches to the 6 amp channels. They have large power supplies, and they are protected by their own separate surge suppressor - 6 Outlet, 2x3 Pro Surge Suppressor Strip | Furman Power | Purifying power for over 40 years.

I have been tweaking the Python program that controls the system's core functions. To prevent damage to the drivers, I've been monitoring register 15 of each 9028 three times per second to assure stereo mode is maintained. If that register becomes corrupted I reset all of the important registers. It worked pretty well until once the I2C function quit and then some heat damage occurred - but not to expensive drivers. Now I also monitor for proper I2C function, and if that is lost then the BBB immediately kills the process running whatever player is producing I2S. So far, so good... However, amps must be turned off before hard resetting the DACs to prevent major thumps!

We're getting there... Next step is to incorporate diagnostic logging into the Python control program. Then data can be collected without real-time monitoring from the command line. That will allow me to gain sufficient confidence before risking damage to 'good drivers'. But even with the temporary setup, the sound is SO GOOD! It will be truly worth the effort to overcome these thorny issues.

Ideas, thoughts, comments? Please speak up. Especially any of you engineers! :)

Frank
 
Member
Joined 2007
Paid Member
Hi Twluke and those interested in control of the es9028/38 via I2C:

I placed some example code on GitHub HERE. It is NOT ready to run - unfortunately I can't take the time to test it now and it needs to be changed to initialize the DAC in the way twluke prefers. After that is done it should be OK to try running it from the command line of a BBB; simply type 'python DACserver.py' from the source directory in which the code is located.

The first thing that will happen is various helper programs for Python will be loaded.
Second, the DAC will be initialized.
Third, a server program will be started to listen for text commands. You can enter them via a second ssh window using netcat - something like 'nc localhost 8192' where 8192 represents the port number. Then you can type control text followed by 'enter', which is anything the python server function can recognize. In this case, it can listen for: "set it to XXX" where the x's represent volume; "mute" and "unmute"; plus 6 different functions that, as written, change the type of filter used for 8x FIR interpolation. These are just simple examples. I am also using this text-based server function to initiate or kill BBB programs, change indicator LEDs, and route input signals using TPA's Otto board.
Finally, the code includes a (disabled) 'police' function that will examine register 15 to be sure it is in stereo mode. That can be used to cause a soft-reset or kill a BBB process (like a music renderer) if something goes wrong with I2C functioning.

Take a look and ask any questions at all...

Best,

Frank
 
Last edited:
Member
Joined 2007
Paid Member
Another way to use netcat in a separate ssh login window is:

echo 'your text here' | netcat localhost 8192

Note that Python lines 177-179 are comments here, but in my case I use 4 ports rather than just 8192. Then my various controllers that are running NetIO do not conflict with one another.
 
Member
Joined 2007
Paid Member
mini update: The DAC configuration script (over on GitHub) is working correctly to configure one of my B3Pros as suggested. Unfortunately, the server function to control the options is not responding correctly. Apparently I chopped something out that I need to restore. ...working on it as time permits.
 
-snip-
After that is done it should be OK to try running it from the command line of a BBB; simply type 'python DACserver.py' from the source directory in which the code is located.
Hi Frank, thank you for guiding me to this thread. Well, on BBB I tried this command line but I got errors like below:
Code:
root@arm:~# python ./DACserver.py
Traceback (most recent call last):
  File "./DACserver.py", line 31, in <module>
    dacregister()
  File "./DACserver.py", line 16, in dacregister
    bus.write_byte_data(0x48, 0x07, mutebus)  # mute
NameError: global name 'bus' is not defined
Am I missing something? TIA
 
Member
Joined 2007
Paid Member
Hi Twluke,

Change line 16 to: bus.write_byte_data(0x48, 0x07, mute) # mute

Again in the GitHub version of DACserver.py, the DAC initialization seems to be working but the server function to change settings on the fly is not working - though it does work in my own system. Mine is far more complex, and not worth your time to investigate: 3 B3Pros, BBB control of inputs, outputs, and player software in addition to I2C. So, it could be a while before I find the problem and get it corrected. ... probably a couple of days minimum, with my current schedule. :)
 
Hi Twluke,
Change line 16 to: bus.write_byte_data(0x48, 0x07, mute) # mute
Thanks for this info but, sorry to say, it didn't work.
Code:
root@arm:~# python ./DACserver.py
Traceback (most recent call last):
  File "./DACserver.py", line 31, in <module>
    dacregister()
  File "./DACserver.py", line 16, in dacregister
    bus.write_byte_data(0x48, 0x07, mute)  # mute
NameError: global name 'bus' is not defined
So, it could be a while before I find the problem and get it corrected. ... probably a couple of days minimum, with my current schedule. :)
It's quite okay. I'm not in hurry. Thank you.
 
Thanks for this info but, sorry to say, it didn't work.
Code:
root@arm:~# python ./DACserver.py
Traceback (most recent call last):
  File "./DACserver.py", line 31, in <module>
    dacregister()
  File "./DACserver.py", line 16, in dacregister
    bus.write_byte_data(0x48, 0x07, mute)  # mute
 NameError: global name 'bus' is not defined
Well I modified part of the script like below:

Code:
import smbus
 [COLOR=Red]bus = smbus.SMBus(1)[/COLOR]
import os
mutebus = 0x61  # default mute setting
FIR = 0x60  # unmute plus default filter shape
# The following routines run once to initialize the DAC
# setup I2C volume, DPLL bandwidth, other es9028 parameters
def dacregister(): # enter desired register values for initialization - these are mine
   [COLOR=red]bus.write_byte_data(0x48, 0x07, 0x61)  # mute[/COLOR]
Execution of this command returned successful answer:
Code:
root@arm:~# python ./DACserver.py
DAC ready
This is my current status. Will continue. After sending this, I got the same answer from you. Thank you!
 
Last edited:
Member
Joined 2007
Paid Member
Good - you can now confirm that your registers are correct using i2cget.

I'm definitely making progress here but must quit for now. However, the touchscreen slider interface that i'm using for volume control is difficult to 'hack' without the 'NetIO' interface from my iOS devices. One question is whether you would like to have such a mobile interface for your system? If not, then a 'louder' and 'softer' routine can be written and accessed using netcat. The touchscreen sliders, though, are nice! :) If you are curious, below is a shot of my iPad controller screen that runs using NetIO. So if you wanted such a controller, I can leave the NetIO code intact. Again, all of the switching and routing and I2C is managed by the python program, which can execute system commands and kill processes as needed from within the script.

Information on NetIO is HERE. Documentation is not great but I have solved most of the issues by trial-and-error.
 

Attachments

  • Image-1.jpg
    Image-1.jpg
    239.5 KB · Views: 191
Member
Joined 2007
Paid Member
OK twluke - I hope your objectives will be met by the updated python program named DACserver.py that I placed on the GitHub page we have been using.

This program initializes your 9028/9038 DAC according to the register settings we have discussed. Then it continues to run and allows you to change certain registers. The code is most certainly NOT optimized because it is derived from a much more complicated program. For example, there are definitions with only one line. Also, the asyncore server and client are more complex than necessary. But importantly, they work on my system. I can't run sound with your settings, but I've confirmed all of the register manipulations. These manipulations are defined in the section: 'def handle_command'. The syntax of these brief commands is simple and you will have no trouble adding or deleting to suit your needs. To access these commands you need only open a second ssh socket and then use netcat to send text to the program. Example:

Code:
echo 'set volume 110' | nc -q .1 10.0.1.5 8193

in the above example, 10.0.1.5 is the IP of my BBB, and 8193 is the port I selected from the range 8192-8195. Best if each TCP source uses a different port. After running the echo command, the volume register should be at 0x6e:

Code:
root@beaglebone:/usr/script# echo 'set volume 110' | nc -q .1 10.0.1.5 8193
root@beaglebone:/usr/script# i2cget -y 1 0x48 0x1b
0x6e

Here are the commands to which DACserver.py will respond:

'set volume XXX' - where XXX is from 0-127 (0 is very quiet but not mute; 127 is no attenuation)
'+' - increases volume by 10dB
'-' - decreases volume by 10dB
'freq' - reports the frequency of PCM
'apodize' - sets register 7 to apodizing, fast roll-off, linear phase filter with IIR @ 50K (0x82)
'slow-min' - sets register 7 to slow roll-off, minimum phase filter (0x62)
'fast-min' - sets register 7 to fast roll-off, minimum phase filter (0x42)
'slow-linear' - sets register 7 to slow roll-off, linear phase filter (0x22)
'fast-linear' - sets register 7 to fast roll-off, linear phase filter (0x02)
'brick' - sets register 7 to brick wall filter (0xe2)

Again, all register 7 settings use the 50k IIR setting. Of course one could modify IIR independently using an additional variable to remember the desired FIR filter.

You will see that there is a 'def police()' line followed by various commands. This is something that you may not need, but I suggest that you use it at least at first. This routine checks that the DAC is in stereo mode, and if for any reason it has been knocked out of stereo mode it will restore ALL of the initialization register settings. This is done every 0.3 seconds. For systems that use balanced amps, this can help prevent accidents. There may be a better register to monitor than number 15, and that can be easily changed. For my system, I monitor register 15. The 'police()' function also can catch any disruption in I2C serial communication. That is usually not the worst thing in the world, but requires a cold re-boot. However, I automatically kill whatever source program is running on the BBB, so that when the DAC comes back online after re-boot it doesn't get any input until all registers are ready. Those lines are commented-out, but are there for your modification if you wish.

Finally, even for non-programmers like myself, Python is easy enough to work in so that the BBB's GPIO and command-line functions can be manipulated, and 'handle commands' can be customized for different uses. I gave you an (inactive) example of how you can select the output of a player - I used Squeezelite - in order to secondarily manipulate the PCM in ALSA. ALSA LADSPA filters can create a crossover, an EQ, etc. by placement in unique pathways between the rendering program and the output pins. So I have made specialized ALSA pathways using custom plugs for each mode of system operation, and can switch among them using simple commands like 'os.system(command-line function)'. [hint: sometimes os.system commands are a bit slow and need to be followed by a brief sleep command.]

I hope it will be easy for you to refine and customize the 'handle commands'. Any questions or comments, please let me know! And if you decide to use NetIO with a mobile device as a controller (Android or iOS), I can help you there too... Another possibility might be something like an SSH tunnel from your mac, but I have no experience with that. Perhaps keyboard macros incorporating SSH to the BBB could simplify things.

Cheers,

Frank
 
Member
Joined 2007
Paid Member
One more thing:

Please be VERY CAREFUL introducing this software to your system! Remember, your settings won't work for me so they haven't been verified. First, test all register manipulations with the amps off. Then, if you have analog volume control, test digital volume controls, the police function, etc. with analog volume limiting output. To test the 'police()' routine, simply use 'i2cset to change register 0x0f. Good luck! :)

F.
 
Last edited:
OK twluke - I hope your objectives will be met by the updated python program named DACserver.py that I placed on the GitHub page we have been using.
-snip-

Cheers,

Frank
Hi Frank, thank you for this updated script. It worked well without any glitch!, though only tried volume control. This weekend, I'll get more insight into this script.

Appreciated your courtesy in depth, thank you very much.
 
Hi Frank,

Along with revising my shell scripts for I2C control of B3SEpros, I'm slowly customizing the python script written by you and recently I added some lines to your original like below:
Code:
     .......... snip .........
     bus.write_byte_data(0x48, 0x0a, 0x10) # 128fs enabled 00010000
 [COLOR=Red]    bus.write_byte_data(0x48, 0x0b, 0x30) # using DATA3 for SPDIF input 00110000q[/COLOR]
     bus.write_byte_data(0x48, 0x0c, 0x00) # DPLL off 00000000
    .......... snip .........
    def handle_command(self, line):
        global volume
        global mute
        global FIR
        global rate
        global state  
        [COLOR=red]global serial
        global spdif[/COLOR]
        global kill
        def mute():
            bus.write_byte_data(0x48, 0x07, mute)
            # print "mute ran"
        def unmute():
            bus.write_byte_data(0x48, 0x07, FIR)
        def conFIR():
            bus.write_byte_data(0x48, 0x07, FIR)
       [COLOR=red] if  line.startswith("serial"):
            bus.write_byte_data(0x48, 0x01, 0x04)
        if  line.startswith("spdif"):
            bus.write_byte_data(0x48, 0x01, 0xe1)[/COLOR]
        if  line.startswith("set volume"):
            volume = int(line[11:14])
#            print (line)
    .......... snip .........
I'm not sure if this is grammatically correct but, with this modification, I confirmed the command lines below to work well without problems, making easy switching between spdif and serial connection.
Code:
root@arm:~# echo 'spdif' | nc -q .1 192.168.0.56 8192
root@arm:~# echo 'serial' | nc -q .1 192.168.0.56 8192
Please let me know if I'm on the right track. Also, would you mind my copying this particular script and moving to my GitHub repository?

Thank you.
 
Member
Joined 2007
Paid Member
Hi twluke!

Yes, you are certainly on the right track!

Suggestions:

1. delete the new 'global ...' lines. Those specify variables and you are not using any new variables.
2. I suggest that the first option in the 'handle_command' use 'if' (as you have it) but that the others use 'elif'. I see that my GitHub code wasn't that way but now I changed it.
3. I suggest that the logic statements be changed from 'line.startswith' to 'line =='. Only the 'set volume' option needs 'startswith'.
4. By all means transfer the code to your GitHub page!

As you gain comfort with the modifications, please begin thinking about what will be your favorite way to control the DAC. For example, try the 'echo' commands FROM YOUR MAC!
They work, right? Do you ever use the OS X 'Automator' program? You can program your Mac keyboard to execute a shell script. So, you could change volume on the DAC simply by pressing certain keys on the Mac. That's just one possible way of creating a TCP connection to the BBB...

Best,

Frank
 
Member
Joined 2007
Paid Member
Clarification: Try the 'echo' commands from your Mac's terminal application, without logging into the BBB...

Any TCP connection via ports 8192-8195 can control the DAC merely by sending text strings (the 'line' variable) to trigger an action. You simply match what you send to the string in the 'elif' lines. This begins the following indented code lines with whatever you want the BBB and the DAC to do. It can be a single I2C write, or it can be many lines of configuration changes for anything the BBB can control: player programs, GPIO, ALSA, etc.
 
Status
This old topic is closed. If you want to reopen this topic, contact a moderator using the "Report Post" button.