• WANTED: Happy members who like to discuss audio and other topics related to our interest. Desire to learn and share knowledge of science required. There are many reviews of audio hardware and expert members to help answer your questions. Click here to have your audio equipment measured for free!

RPi + CamillaDSP Tutorial

Thanks for the response @HenrikEnquist, I added -a 0.0.0.0 to my start commend and all is good now!
 
Have you guys thought of building real VU meters somehow with a pwm signal?
 
Have you guys thought of building real VU meters somehow with a pwm signal?

I think it would be possible. Using a Raspberry Pi Pico, which has WiFi and ADC converter, one could write a small micropython program that supports WebSockets to read camillaDSP values and produce appropriate values into the ADC changes connected to analog VU Meters. PWM would also be an option I guess if ADC does not work for some reason.
 
  • Like
Reactions: MCH
Has anybody managed to get audio from windows PC via Jack over ethernet to CDSP? I am really struggling with that as I am new to Jack as well as linux....
 
Hey Michael,

I am working on making my wireless zigbee knob that I use for volume to control tone (bass/treble) as well in camilladsp. I have used the route that @HenrikEnquist proposed a couple of days ago in a different thread and I have it working!

Now I want to use the oled display to show bass/treble levels while I am changing them, but I see that in your oled script the big 40 pixel fonts for volume contain the “-“ symbol but not the “+”. I think it would be cool to have the “+” as well for positive values of the tone controls, but I have no idea of where to get it to add to the script.

Can you share what was your source for the fonts or just pm me the “+” if you have it handy?

Thanks a lot!
 
Hey Michael,

I am working on making my wireless zigbee knob that I use for volume to control tone (bass/treble) as well in camilladsp. I have used the route that @HenrikEnquist proposed a couple of days ago in a different thread and I have it working!

Now I want to use the oled display to show bass/treble levels while I am changing them, but I see that in your oled script the big 40 pixel fonts for volume contain the “-“ symbol but not the “+”. I think it would be cool to have the “+” as well for positive values of the tone controls, but I have no idea of where to get it to add to the script.

Can you share what was your source for the fonts or just pm me the “+” if you have it handy?

Thanks a lot!

Unfortunately I am away from the computer that has the necessary information for the next month so this post will be lacking in detail.

I used The Dot Factory -> http://www.eran.io/the-dot-factory-an-lcd-font-and-image-generator/ to generate the font tables. The output format from The Dot Factory is pretty close to what I needed but I did need to remove a few instances of "[" and ]" (I've been meaning to write a script to get it in the exact format). I believe I used Nimbus D OT Light for both the 20 pixel tall and 56 pixel tall font but the method of generating them was slightly different.

For the volume font (56 pixel high) I used only a few characters in the font table, I believe I used -012345789 and also dB (which I did not include in oled.py) and a fixed width so that spacing between the characters stays constant. I added the dB as originally I thought I might want a full sized dB AND it gives extra spacing around the numbers so that they do not run in to each other. The fixed width makes it so that the position of the numbers does not "jump around" as you change to numbers of different width. The end result was a fixed 40 pixel width.

Without a computer that has The Dot Factory installed I am flying a bit blind here but I think we should be able to manually create a "+". The volume font table consists of 280 8 bit bytes, each byte defines a column of 1 pixel wide x 8 pixels high. So looking at the case of the "-" entry you can see that the first 40 x 4 = 160 bytes are all 0x00 which means that the first 4 rows of 8 pixel high columns are all blank. Starting in the 5th row we have some entries of 0x3E which translates to 00111110 in binary. This means that the top 2 pixels of that 8 pixel column are blank, the next 5 are filled and the last is blank. End result is a 17 pixel wide x 5 pixel high dash that has 10 blank pixels to the left of the dash and 17 blank pixels below the dash.

To create a similarly proportioned "+" please see tables below.

1674229158283.png

1674234783775.png


The other thing is that because the volume font does not use a full table I do not rely on standard character numbering. As such you also need to modify oled_string_vol to match the "+" to a font table entry. I know you've modified your oled script but see attached for an updated version of oled.py for reference which adds the "+" to the end of the volume font table and has an updated oled_string_vol. Again I can't test it so please let me know if you have any issues.

Michael
 

Attachments

  • oled_01202023.txt
    73.4 KB · Views: 64
Last edited:
  • Like
Reactions: MCH
Unfortunately I am away from the computer that has the necessary information for the next month so this post will be lacking in detail.

I used The Dot Factory -> http://www.eran.io/the-dot-factory-an-lcd-font-and-image-generator/ to generate the font tables. The output format from The Dot Factory is pretty close to what I needed but I did need to remove a few instances of "[" and ]" (I've been meaning to write a script to get it in the exact format). I believe I used Nimbus D OT Light for both the 20 pixel tall and 56 pixel tall font but the method of generating them was slightly different.

For the volume font (56 pixel high) I used only a few characters in the font table, I believe I used -012345789 and also dB (which I did not include in oled.py) and a fixed width so that spacing between the characters stays constant. I added the dB as originally I thought I might want a full sized dB AND it gives extra spacing around the numbers so that they do not run in to each other. The fixed width makes it so that the position of the numbers does not "jump around" as you change to numbers of different width. The end result was a fixed 40 pixel width.

Without a computer that has The Dot Factory installed I am flying a bit blind here but I think we should be able to manually create a "+". The volume font table consists of 320 8 bit bytes, each byte defines a column of 1 pixel wide x 8 pixels high. So looking at the case of the "-" entry you can see that the top 8 x 4 = 32 pixels are all blank. Starting in the 5th row we have some entries of 0x3E which translates to 00111110 in binary. This means that the top 2 pixels of that 8 pixel column are blank, the next 5 are filled at the last is blank. End result is a 17 pixel wide x 5 pixel high dash that has 10 blank pixels to the left of the dash and 17 blank pixels below the dash.

To create a similarly proportioned "+" please see tables below.

View attachment 258560
View attachment 258561

The other thing is that because the volume font does not use a full table I do not rely on standard character numbering. As such you also need to modify oled_string_vol to match the "+" to a font table entry. I know you've modified your oled script but see attached for an updated version of oled.py for reference which adds the "+" to the end of the volume font table and has an updated oled_string_vol. Again I can't test it so please let me know if you have any issues.

Michael
that's awesome, Michael and more than enough for now!
I realize now that the modification will probably need to be deeper than i thought because i will also need the dot, as i am changing the bass/treble level in 0.2 or 0.5 (to be decided yet) db steps, 1 full db would be too coarse. But if i see it gets too difficult for me, i may decide to show only whole db values (without comma) on the display, not a big deal to start with.

With these little mods, i am seeing the possibilities of mqtt combined with pycamilladsp are endless, i recommend you to play a little with it if you haven't yet. So far it has been super reliable and robust too.
thanks again!
 
hey Michael, the + looks a bit more like an old division symbol :D but it works!
i will have to work on the dot anyways so i'll see how i can fix it. Will send it back to you if interested. btw, i would never had found the oled_string_vol modification alone, Thanks a ton!

IMG20230121093226.jpg

edit: found the fail. I just copy/pasted the font from the document you attached and did not pay attention that the central line (the original -) was not modified to include the FF instead of 3E. still looks funky but i will manage to fix it

edit2: fixed and working as intended with dot and decimals, thanks again. Curiously, i got this very symmetric + entering what you posted upside down (F8 row up, 0F down):

IMG_20230121_171149.jpg
 
Last edited:
hey Michael, the + looks a bit more like an old division symbol :D but it works!
i will have to work on the dot anyways so i'll see how i can fix it. Will send it back to you if interested. btw, i would never had found the oled_string_vol modification alone, Thanks a ton!

View attachment 258715
edit: found the fail. I just copy/pasted the font from the document you attached and did not pay attention that the central line (the original -) was not modified to include the FF instead of 3E. still looks funky but i will manage to fix it

Yes, looks like I missed the FFs, sorry about that.

Michael
 
  • Like
Reactions: MCH
Hi

is there any example for switching one of the rpi GPIO if camillaDSP startet running? For powering on some amps.... I found example for external network plug but this is way too much for my need. A simple switched output port would do as soon as CDSP is running.....
Sorry for lacking linux and python skills :facepalm:
 
If your 'amps' can be triggered with 3.3VDC you can use the RPi GPIO pins. You can likely trigger w/5VDC from the Pi also but I haven't tried it.
I used @igfarm SmartPlug as a templet for my trigger on a Hypex NCore amp using GPIO. I also use the same commends when the Pi turns off, to turn avoid the turn off pop of the amp:

import time
import RPi.GPIO as GPIO

TRIG = 26
MUTE = 16
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
GPIO.setup(TRIG, GPIO.OUT)
GPIO.setup(MUTE, GPIO.OUT)

#
# Main loop
#
if __name__ == '__main__':
GPIO. output(MUTE1)
time.sleep(1)
GPIO. output(TRIG,0)
I use GPIO 26 for the trigger and 16 for MUTE. You can flip the bits for turn on. You can change these to your preferred GPIO pin. I'm not sure if the MUTE is doing much, but It doesn't hurt.
 
Last edited:
  • Like
Reactions: MCH
Ok thanks. Will look at that. Inwould just switch an ssr so 3v3 are ok...
 
Has anybody managed to get audio from windows PC via Jack over ethernet to CDSP? I am really struggling with that as I am new to Jack as well as linux....
If you're struggling with audio rerouting — you should probably use qpwgraph as well as pipewire with wireplumber. Pipewire is way easier and faster than pulseaudio.
 
Hi kysa,

had basically no time in recent days. Now found some more HowTo and guides so I am quite sure that I will be able to manage Jack from Windows to CDSP. My complete system solution is still changing a bit and not fixed 100%. So sometimes I need some information to keep the progress alive :) . With CDSP so many new possibilities popped up that needs to be sorted out :) . Thanks for the hint withqpwgraph I will also have a look into that!
 
When I was playing with jack2 on windows (several years have passed, true), it was not a production-level experience back then. Maybe it has changed.
 
answering to @Dave Bullet : Last time i ordered a pi i ordered one of the new pico w together with it, that is still there waiting to be used. I will try to find out something, i think it should be easy. I honestly think that in most cases it doesn't make sense to turn it off at all, but i have my Motu M4 plugged to it and as a result always on and i start to think i prefer it to be powered off the 20 hours a day it is not in use...

by the way, what strange hack did you do to your post that it is not possible to quote it??
Hi team, finally received the parts and managed to properly switch off and on the rpi-camilladsp and cards with the power button of the remote control. It is a bit long for a post here but if there is interest i can write it down here or in a different thread.
 
This is such a cool project I've used it to replace my Rotel RC-1590 preamp as the controller for my system. Since it allows my phone to stream to it using Airplay I could even eliminate the AppleTV from the setup.

mdsimon2 has done a really great job documenting this project and turning it into a tutorial!

This is the first time I've really seen or worked with Python code but I've been playing with it to see what all can be done. I wanted to have a bouncing ball animation for the idle-screen so it would match my MOTU Ultralite MkV when its idling but I found that the lgpio/Python combination only updates the screen approximately 1-2 times per second and would use a fair amount of CPU doing it. You can kind of see this when changing the volume that the redraw isn't all that fast. I tried different libraries and the simplest way I found to update the refresh rate is by using RPi.GPIO in place of lgpio. It my testing I think I was able to get around 20+ updates per second at max CPU usage.

Evidently C is able to manipulate the IO pins much faster than Python. I'm not much of a C/C++ coder but I made a quick test program and could get around 100 updates per second. This is enough to do some really interesting things with the display! The exciting thing about this is that if you want to update the display at a more reasonable 10 frames per second you can do so with CPU usage lower than 30%. Combined with the multi-core nature of the RPi this allows reasonable screen updates at the same time as running FIR filters for the DSP.

I decided I wanted fancy VU meters.

That means I had to figure out how to draw graphics to the display as well as figure out how to calculate what graphics to draw. I was researching how to calculate proper diagonal lines and how to draw them on a bitmap display and came across a C library called libssd1306 from Stealthy Labs. This library not only has the algorithms to draw diagonal lines but also allows text drawing with OpenType and TrueType fonts using Freetype. In addition it uses a framebuffer so you can setup what you want the screen to look like in memory and then write it to the display with a single call. This also allows you to have separate framebuffers in memory and switch between them easily. The downside is that the 1306 handles writing quite a bit differently than the 1322 chip that runs the display used for this project. I was able to do a (rough) port to get it to work with this display, at least in 1 bit per pixel mode.

The other remaining piece to the puzzle is getting the information from CamillaDSP using C instead of Python. Fortunately the pyCamillaDSP library is relatively simple and porting the needed functions for VU meters and status display to C was much simpler than the display code up above. That partian port can be found here.

Once all of that framework is in place you can draw a picture of what you want the background of the VU meters to look like and then load that into the framebuffer. From there you can procedurally draw the needles/meter bars into the framebuffer in the appropriate positions and write this out to the display.

I can now write the status text to the display using a fonts of my choosing and then after a few seconds switch to either a screensaver if the system is paused or VU meters if the system is running.

2b.gif
4b.gif


I also added a motorized volume potentiometer as well as a button on the front panel to switch CamillaDSP configuration files. This allows pretty much anyone in the family to walk up to the stereo and, for instance, switch between Phono/Wifi/Aux etc. inputs and control the volume without needing to open a web browser and load the UI or use an IR remote.

I'm still working on getting that code uploaded. None of this stuff is really what I would consider ready for primetime but at least on my own system I've been able to make it work. This just underscores what a great job mdsimon2 did making his code something that is usable and workable for average computer users as opposed to just something that only software developers can make work.

With his permission I can at least upload the modifications to the oled.py file that gives the faster screen redrawing for simple things like volume changes and basic screensavers.
 
This is such a cool project I've used it to replace my Rotel RC-1590 preamp as the controller for my system. Since it allows my phone to stream to it using Airplay I could even eliminate the AppleTV from the setup.

mdsimon2 has done a really great job documenting this project and turning it into a tutorial!

This is the first time I've really seen or worked with Python code but I've been playing with it to see what all can be done. I wanted to have a bouncing ball animation for the idle-screen so it would match my MOTU Ultralite MkV when its idling but I found that the lgpio/Python combination only updates the screen approximately 1-2 times per second and would use a fair amount of CPU doing it. You can kind of see this when changing the volume that the redraw isn't all that fast. I tried different libraries and the simplest way I found to update the refresh rate is by using RPi.GPIO in place of lgpio. It my testing I think I was able to get around 20+ updates per second at max CPU usage.

Evidently C is able to manipulate the IO pins much faster than Python. I'm not much of a C/C++ coder but I made a quick test program and could get around 100 updates per second. This is enough to do some really interesting things with the display! The exciting thing about this is that if you want to update the display at a more reasonable 10 frames per second you can do so with CPU usage lower than 30%. Combined with the multi-core nature of the RPi this allows reasonable screen updates at the same time as running FIR filters for the DSP.

I decided I wanted fancy VU meters.

That means I had to figure out how to draw graphics to the display as well as figure out how to calculate what graphics to draw. I was researching how to calculate proper diagonal lines and how to draw them on a bitmap display and came across a C library called libssd1306 from Stealthy Labs. This library not only has the algorithms to draw diagonal lines but also allows text drawing with OpenType and TrueType fonts using Freetype. In addition it uses a framebuffer so you can setup what you want the screen to look like in memory and then write it to the display with a single call. This also allows you to have separate framebuffers in memory and switch between them easily. The downside is that the 1306 handles writing quite a bit differently than the 1322 chip that runs the display used for this project. I was able to do a (rough) port to get it to work with this display, at least in 1 bit per pixel mode.

The other remaining piece to the puzzle is getting the information from CamillaDSP using C instead of Python. Fortunately the pyCamillaDSP library is relatively simple and porting the needed functions for VU meters and status display to C was much simpler than the display code up above. That partian port can be found here.

Once all of that framework is in place you can draw a picture of what you want the background of the VU meters to look like and then load that into the framebuffer. From there you can procedurally draw the needles/meter bars into the framebuffer in the appropriate positions and write this out to the display.

I can now write the status text to the display using a fonts of my choosing and then after a few seconds switch to either a screensaver if the system is paused or VU meters if the system is running.

View attachment 261905 View attachment 261906

I also added a motorized volume potentiometer as well as a button on the front panel to switch CamillaDSP configuration files. This allows pretty much anyone in the family to walk up to the stereo and, for instance, switch between Phono/Wifi/Aux etc. inputs and control the volume without needing to open a web browser and load the UI or use an IR remote.

I'm still working on getting that code uploaded. None of this stuff is really what I would consider ready for primetime but at least on my own system I've been able to make it work. This just underscores what a great job mdsimon2 did making his code something that is usable and workable for average computer users as opposed to just something that only software developers can make work.

With his permission I can at least upload the modifications to the oled.py file that gives the faster screen redrawing for simple things like volume changes and basic screensavers.

Wow, wow, wow! Very excited that you were able to dig in to this and come up with some great improvements.

As you note I've always been a bit annoyed by the lag in the display, especially compared to the OLED display in my Okto dac8 pro which is instantaneous. I have hoped for a long time that some with more knowledge would find a way to improve it, either by modifying the python code or moving to a more efficient lower level language and it sounds like you have done both!

Please feel free to share any modifications to oled.py. Unfortunately I am out of town for the next month so I won't get to try it out for a bit but I am very excited.

Also, are you using Ubuntu? The reason I went with lgpio initially is that I had read that RPi.GPIO was unavailable on kernels newer than 5.11 -> https://ubuntu.com//blog/raspberry-pi-gpio-support-in-ubuntu but maybe this is no longer the case? Actually looking at this further it seems like RPi.GPIO may still be on the way out -> https://waldorf.waveform.org.uk/2022/the-one-where-dave-breaks-stuff.html.

Michael
 
Last edited:
Hi team, finally received the parts and managed to properly switch off and on the rpi-camilladsp and cards with the power button of the remote control. It is a bit long for a post here but if there is interest i can write it down here or in a different thread.
Marcos , is this with the 5 volt relay from this post ?

I am interested in a brief explanation.
 
Back
Top Bottom