Graphical front panel display

Hello,

The following is just an exploration of what might be possible… I do ask some development-related questions at the end.

mpd_oled – for MoOde, Volumio, and Rune – looks to be a compiled program that uses what was originally an Arduino library for driving a graphical display (over I2C or SPI) and an audio-visualizer (C.A.V.A.) originally developed for console use:

https://github.com/antiprism/mpd_oled#readme

Although C.A.V.A. (linked at bottom of that readme page) was originally written for use with ALSA, per its name mpd_oled is principally focused on making use of a FIFO file output from mpd for obtaining the audio info used to drive the display. Thus the focus on the various mpd-based audio distributions.

Per this posting, though,

https://github.com/antiprism/mpd_oled/issues/4#issuecomment-423255641

and comments from the author (on Volumio’s forum), it seems like mpd_oled can still “connect” to ALSA directly.

So, my question is what might be possible with kodi and CoreELEC?

I currently have an Odroid C4 and a semi-retired Odroid C2. I’ve ordered a nice 2.4" 128x64 blue OLED display based on an SSD1309 controller from BuyDisplay. I feel pretty sure that the Odroid C* boards can drive either I2C or SPI. (I ordered the display configured for I2C, which may have been a mistake, but I figure it’s one I can correct.)

As installed, though, I worry that CoreELEC doesn’t provide much of a development environment. Is that impression correct? Would I be better off installing a more complete Raspbian OS, installing kodi under it, to experiment with something like this?

(I’m an ASIC engineer and have used Linux since 1996, so I can handle the basics. Software development is really a whole separate world, though, and I’ve never experimented with cross-compiling. Thus the questions above.)

My goal is to get a spectrum display somewhat mimicking the AudioControl C-101:

Yes, I’m a child of the '80s! Why do you ask? The whole assembly would then go into a “case” like this one (after modifying the display opening as needed):

https://www.thingiverse.com/thing:2890736

Thanks for any suggestions!
Matt


Update

20 Oct 2020

Results of my efforts thus far:

There is a summary post below that lists all of the various “front panel” projects I’ve found, from character LCDs to OLEDs.

Others are starting efforts of their own, so keep reading!

Ok, the Odroid C2 doesn’t seem to have hardware SPI pins – so I2C or bit-banging only for the C2.

That looks to have been rectified with the C4.

This project, service.odroidn2.oled by roidy, looks quite useful!

https://github.com/roidy/service.odroidn2.oled

It doesn’t have the spectrum display, but the info display is quite nice. It’s for an Odroid N2, driving via I2C. I think that should easily port to either a C2 or C4.

Discussed here on this thread:

https://discourse.coreelec.org/t/odroid-n2-oled-i2c-spi-driver/4995

As far as I know the only way to get audio data from Kodi is using a visualisation add-on, have you had a look here:-

and here:-

Hi roidy,

That particular wiki page needs a bit of help (!), but I’ll take a look.

This site also looks useful, although it’s already been updated for Kodi 19:
https://alwinesch.github.io/group__cpp__kodi__addon__visualization.html

I wonder if Kodi would be bothered by a visualization that doesn’t want to render anything to the actual screen. :grin:

When my display eventually arrives, I’m certainly going to start by experimenting with your package! (BTW, I ask some controller and installation questions for you back on your “Odroid N2 OLED I2C” thread.)

Thanks.

Somewhat interestingly, looking at

https://github.com/xbmc/visualization.spectrum/blob/Matrix/src/directx_spectrum.cpp

and CVisualizationSpectrum::AudioData(), it does not make use of the FreqData argument. Bar heights seem to be derived directly from AudioData. I guess I expected that the spectrum display visualization would have requested (via WantsFreq) the FFT data. Live and learn!

I’m really interested in seeing how this develops.

I’m really interested in seeing how this develops.

Me too!

Above I note that the default spectrum visualization build into Kodi doesn’t seem to make use of FreqData to draw its bars. Looks like that was also noted back in 2014 as part of a Kodi discussion!

https://forum.kodi.tv/printthread.php?tid=204991&page=2

(2014-11-26, 06:12)ironic_monkey Wrote: the spectrum viz doesn’t use fft data… there are no vizes in mainline using the fft data.

Wow. No wonder it looks nothing like a spectrum analyser display…
I really think it should be using the fft data (well assuming the fft data is fixed).

So it just uses a random subset of audio samples. That would explain why it looks like random noise.

The Kodi class that invokes the visualization, CGUIVisualisationControl::OnAudioData(), includes code that can optionally invoke a FFT:

// Fourier transform the data if the vis wants it...
if (!m_transform)
  m_transform.reset(new RFFT(AUDIO_BUFFER_SIZE/2, false)); // half due to stereo

m_transform->calc(psAudioData, m_freq);

but that’s not involved in the current spectrum. Perhaps invoking the FFT was deemed too expensive?

For the purpose of a front panel display, it seems like there are two options:

  • Write a visualization plugin (in C++), and move all of rest of the OLED driving code into that plugin as well.

  • Write a visualization plugin (one that uses GetInfo() to set wantsFreq) that provides a path for exporting the frequency data externally, presumably in a form that’s easy for Python to consume. This is along the lines of the named FIFO approach that mpd_oled pursues to get data from MPD and was the subject of this now-old Kodi thread that I recently bumped:
    https://forum.kodi.tv/showthread.php?tid=223983

For the moment, I’m sufficiently entertained with the service addon from @roidy that I want to figure it out a bit more. What, if anything, actually makes it specific to an Odroid N2? Would it work as-is on a Raspberry Pi, for instance?

Once I get that figured out and, well, get a display, I can pursue the spectrum display further.

A visualization plugin that just dumps the AudioData (and FreqData) for external use seems like it could be generically useful. I worry, though, whether using it would then preclude things like fetching Artist images (since Kodi would think a visualization is active). That either-or choice might restrict interest in it.

Lots to experiment with, at least!

  • Write a visualization plugin (one that uses GetInfo() to set wantsFreq) that provides a path for exporting the frequency data externally, presumably in a form that’s easy for Python to consume.

Hmmm, I wonder if the JSON-RPC available in Kodi would be a means of implementing such communication:

https://codedocs.xyz/xbmc/xbmc/group__jsonrpc.html

Presumably, the FreqData arriving via AudioData() updates wouldn’t be all that large. (It should be far smaller than the actual audio data itself.) Would it suffice for the C++ visualization addon to just maintain the last-received frequency values and provide them to any “caller” via JSON-RPC?

The alternative to some form of within-Kodi communication would be some OS-level alternative – files, named pipes, and the like. That seems like a bit of overhead for what should be a fairly small number of frequency amplitude values. (How many bars can one display, after all?)

Perhaps someone with more Kodi experience will notice this topic and pipe up with a useful opinion.

I got a little side-tracked with the above details, so perhaps I should clarify one of my questions…

What’s the suggested development environment for CoreELEC? Does a normal installation provide the header files and compilation tools necessary to make “tweaks” or try small-ish changes, or is there an easy way to pull in everything needed for that? I’ll go look to see if there’s a developer’s guide.

The service addon from roidy is all Python, but playing with the visualization plugin will require a bit more infrastructure.

Perhaps a weird range of questions, but everyone starts into this with differing levels of experience.

Thanks!
Matt

For the moment, I’m sufficiently entertained with the service addon from @roidy that I want to figure it out a bit more. What, if anything, actually makes it specific to an Odroid N2? Would it work as-is on a Raspberry Pi, for instance?

There is nothing that really makes it specific to the Odroid N2, other than in SPI mode the GPIO pins are hardcoded for the N2 and the SPI /dev/spidev32766.0 path is probably unique to the N2.

I know people have used the add-on on the Vim3 board in I2C mode by just changing the I2C bus number.

There is nothing that really makes it specific to the Odroid N2, other than in SPI mode the GPIO pins are hardcoded for the N2 and the SPI /dev/spidev32766.0 path is probably unique to the N2.

Great. After reading that, at least for modern versions of Raspian on the RPi, /dev/i2c* and /dev/spidev* device files exist, I became hopeful that your addon was essentially platform independent. Sounds like it almost is!

Above I write:

I’ll go look to see if there’s a developer’s guide.

FWIW, looks like the Kodi team has put quite a bit of effort into updating and restructuring their build documentation, which now resides in github alongside the code. The Linux build guide starts here:

https://github.com/xbmc/xbmc/blob/master/docs/README.Linux.md

Seems like binary addons can be compiled outside of the Kodi tree. So, playing with just a visualization addon doesn’t have to be a very heavy lift.

I’ve not yet found anything CoreELEC-specific. LibreELEC’s guide is this document:
https://libreelec.wiki/compile

My (likely too) naive hope is that a CoreELEC installation either includes or provides a route for installing development packages that would allow the “light lift” approach… provide the headers needed for out-of-tree binary addon compilation, as well as the tool chain of course. I’ll go look this weekend (work is a bit too all-consuming).

1 Like

I received a 20x4 LCD character display in the mail yesterday and verified that it was alive (via a spare Raspberry Pi and one of the numerous python-using tutorials online). Since the OLED display has yet to arrive, I’ll likely take a detour investigating this character display.

In case it’s useful to anyone, here’s a summary of what I’ve learned thus far regarding possible quick “routes” for displays. Several viable ones exist… so long as you’re not hankering for a spectrum display.


LCDproc

An overloaded name, referring both to a C-based client/server program for driving LCD or OLED displays and a Python addon to Kodi that acts as another form of client for that C-based server. (There was also an older LCDproc that was part of the original XBMC core. The Python addon is intended to replace that. The longevity of both projects means one can find a lot of hits when searching for them. To me, that makes it hard to find what’s up-to-date.)

As of 2020, both are still getting commits. The webpage for the C-based lcdproc doesn’t seem to have been updated for several years, though. The C client/server has support for a wide range of displays, including HD44780-based character LCDs and apparently some graphical displays as well.

Communication from the addon to the server is sockets based, making use of Python’s telnetlib.

Client/server program: source, webpage
Kodi addon: source

OpenVFD

Python-based service addon for Kodi, by Arthur Liberman, that communicates to displays using C drivers. Configs for the Odroid C2 support HD44780 LCDs and SSD130[69], SH1106 OLEDs. A form of graphical support for the HD44780 displays exists, at least in the form of “big digits”. Based on the name, I originally thought that this addon only supported a very-specific type of display, which was an error.

At least for the HD44780, the actual format of data displayed is handled by the C driver, making local customization not particularly easy.

Kodi addon: source, config files
C drivers: source

This addon has several CoreELEC and LibreELEC forum threads:

Odroid N2 OLED Driver

Python-based service addon for Kodi from @roidy, distinct from OpenVFD. Supports SSD130[69] and SH1106-based OLED graphical displays. (SSD1309 support is SPI-only as of this writing, but I2C should be possible.)

Kodi addon: source

Discussion thread:

KodiDisplayInfo

A completely separate Python program (i.e., not an addon) that queries Kodi (via JSON-RPC) for what’s playing, apparently including artwork, and throws it up on a TFT LCD display. Display duties are handled vi pygame, which in turn depends upon the C-based Simple DirectMedia Layer (libsdl).

The web page unfortunately suggests that the music view with cover thumbnail is a work-in-progress. The most recent commit, as of this writing, is dated June 2017. Still, the KODI_WEBSERVER class may be an interesting starting point; it doesn’t seem like the artwork retrieval was ever implemented.

Python program: source, webpage

Kodisplay

A Python-based Kodi service addon also making use of pygame (and SDL) for displaying to a TFT LCD. Looks like the idea was to have the layout of the displayed controlled via a layout.xml file. Since it’s an addon, details from Kodi are retrieved via InfoLabels. The music section of the example includes this:

		<image path="$INFO[Player.Art(thumb)]">

As of this writing, the last commit is dated Dec 2016.

Kodi addon: source



The not Kodi-related section…

mpd_oled

Focused on the MPD audio distributions moOde, Volume, and RuneAudio. Separate C-based program by Adrian Rossiter that supports SSD130[69] and S[S]H1106-based OLED displays. Depends upon MPD integration to know music-player state and track information, and uses a named pipe (FIFO) to obtain a copy of audio data out of MPD for its spectrum display.

Each of those MPD-based distributions has a forum thread for this program.

The audio spectrum was originally leveraged from C.A.V.A., which obtained audio data from ALSA. That approach is evidently temperamental, though, and the mpd_oled author doesn’t directly support it.

C program: source

pydPiper

Standalone python program, using luma.core and luma.oled, for displaying track information from MPD in moOde, Volumio, and RuneAudio. As of late 2020, supports HD44780 LCDs, SSD1306 panels (I2C only), and two Winstar display types. Looks to have a fairly impressive approach to font support and, more interestingly, page files for the customization of display info.

Audiophonics (the French audio company) made a fork of pydPiper for the displays in their RASPDAC products.

Python program: source

3.5" Touchscreen on Volumio

Instructions on how to enable a 3.5" Waveshare display within Volumio. From what I can tell, both Volumio and moOde Audio have the option of driving a local display – supported by running a web browser within X.

Volumio forum: thread

PyAudioTFT

… and another one. Looks like a pygame-based Python script to present info from MPD. Hasn’t been updated since early 2016, but the screen layout is nicely designed.

Python program: source



UPDATES:

  • Realized there was a C component to OpenVFD.
  • Added pydPiper
  • Added KodiDisplayInfo
  • Added Kodisplay

Here’s what I’ve found thus far regarding the topic of inter-process communication for Kodi. The links are to forum.kodi.tv threads.

This communication topic definitely pops up from time to time. I’ll keep poking around. So far, I haven’t found anything definitive regarding addon (C++ or Python) extensibility of Kodi’s JSON-RPC.

Of course, I also haven’t found anyone with Kodi experience willing to reply. :slight_smile:

1 Like

Two of the three displays on order arrived. I thought it prudent to make sure they’re both alive before moving on… Plus I’m not that experienced with soldering, so always good to make sure I didn’t ruin anything!

20x4 I2C LCD

128x64 SPI OLED

In case anyone is following along, I realized this evening that there is a non-trivial C component to OpenVFD. I updated the description above.

The OLED display I have on-hand uses SPI, and the C2 did not implement a HW-based SPI interface. The HardKernel wiki describes loading modules to get a bit-bang / SW version going. CoreELEC must do something of the sort for the C2, since there is a /dev/spidev* file present.

I couldn’t find any description of what pin assignments get made for the C2’s spi-gpio, though. So, I decided to get get the odroidn2.oled service running on the RPi.

With very little coding changes, it worked!

spi_OLED_RPi

Earlier, @roidy wrote:

There is nothing that really makes it specific to the Odroid N2, other than in SPI mode the GPIO pins are hardcoded for the N2 and the SPI /dev/spidev32766.0 path is probably unique to the N2.

That was indeed the case. I only ended up editing lib/oled.py and lib/gpio.py. Many thanks!

Change to lib/oled.py

diff --git a/lib/oled.py b/lib/oled.py
index a3aadcb..beea936 100644
--- a/lib/oled.py
+++ b/lib/oled.py
@@ -52,7 +52,7 @@ class Oled:
             except IOError:
                 xbmcgui.Dialog().notification("OLED IO Error", "Please check your I2C address and controller type.", xbmcgui.NOTIFICATION_ERROR, 5000)
         else:
-            self.spi= spi.SPI("/dev/spidev32766.0")
+            self.spi= spi.SPI("/dev/spidev0.0")
             self.spi.mode = spi.SPI.MODE_0
             self.spi.bits_per_word = 8
             self.spi.speed = 5000000

New lib/gpio.py

import RPi.GPIO as GPIO
import time

dc_select = 24
spi_reset = 25

def initGPIO():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(dc_select, GPIO.OUT)
    GPIO.setup(spi_reset, GPIO.OUT)

def gpioWriteDC(val):
    GPIO.output(dc_select, val)    

def gpioWriteReset(val):
    GPIO.output(spi_reset, val)

def gpioDoReset():
    gpioWriteReset(1)
    time.sleep(0.1)
    gpioWriteReset(0)
    time.sleep(0.1)
    gpioWriteReset(1)
    time.sleep(0.1)

Note that the code above doesn’t have the try/except blocks, as I was trying to debug matters and appreciated kodi complaining when I messed things up.


My next big question is whether I want the time (elapsed) display during music playback or track information instead (name, album name, artist/composer). True, one likely cannot read it from across the living room, but the same is true for the info tags which I do like.

2 Likes
dc_select = 24
spi_reset = 25

Those particular pin assignments (for data/code and reset signals on the RPi) came from luma.oled, which I what I used to first test out the display.

https://luma-oled.readthedocs.io/en/latest/

GPIO24 and GPIO25 correspond to RPi GPIO Header pins 18 and 20. Connectivity, and numbering, on the Odroid boards is different of course.

Onward to the Odroid C4 next!

In further web searches, I stumbled across the Python-only pydPiper, which displays (text) track information for the MPD distributions (moOde, Volumio, Rune).

I added it to the growing summary above.

Playing with possible approaches to showing audio information, I have this attempt:

audio_info_display

After filling out the 5x7 font to have the full set of ASCII-printable characters, I moved the track number up to become an info “tag” and am trying to show track name, album name, and artist name rather than a time value.

Readability across the room likely isn’t too great. I still also need to figure out

  • unicode display (e.g., what if the artist’s name has accented characters) and
  • truncation of the string at an appropriate length (either that or figure out horizontal scrolling).

Oh, and one of the audio codecs isn’t showing up as a tag appropriately. Still, it’s a potential start and definitely shows how convenient it is to have an all-Python addon.

Display of the audio spectrum is going to take a bit of work. I did get a Feature Request posted, hopefully even in the right spot, on Kodi Forums. I recently found out that one of the available info labels in Kodi is MusicPlayer.cover. I don’t know if that just returns a Kodi-URL for the album art or the art itself. I’m starting to wonder about some of the slightly larger 18-bit color SPI-connected TFT LCDs! :grin:

Anyone have thoughts on alternative info arrangements?