LPC55S69 Embedded Graphics : Using LVGL to build a VU Meter

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPC55S69 Embedded Graphics : Using LVGL to build a VU Meter

Eli_H
NXP Pro Support
NXP Pro Support
1 0 3,177

VU.jpg

 

“Embedded” graphics technologies have come a long way since simple character displays. At one time it the not so distant past, microcontrollers were not powerful enough to drive high resolution color LCD displays effectively. The proliferation of low cost 32-bit microcontrollers has made it much easier to use high resolution color displays without needing to resort to high-end applications processors. I like to shop at buydisplay.com as there is great selection of low cost displays directly from Asia. One of the design features of the LPC55S69 Mini-Monkey was the incorporation of a 240x240 IPS display.  The LPC55S69 is a great fit for small, low active power embedded graphics applications. In my previous articles, I used my own embedded graphics library for doing basic image and line drawing. Putting pixels and simple graphics on a memory buffer is straight forward. However, using a library can save time when constructing a more complicated user interface. There is one library that I wanted to demonstrate in this article that can save time in your application development cycle and is well suited to the LPC55S69.

The Light and Versatile Graphics Library (LVGL) has been around for awhile but has been attracting quite a bit of attention lately.   LVGL is open source (MIT licensed) and is well documented making it simple to integrate into your project.   Looking at the GitHub repo,  you can see development is active and quite healthy for an embedded open source effort.     Some notable features that I found important for my personal use cases:

  • A very simple driver interface that cleanly separates the graphics logic from the physical interface to the display.
  • Clean input interfaces for touch controllers, encoders and buttons.  
  • A simulator to run code on PC.

You can find some demonstrations here that run in web browser.  While I certainly like toying around with my own library, LVGL is quite impressive in its documentation and features.   

To kick the proverbial tires, I wanted to put together a simple demonstration using the available I/O on the Mini-Monkey Since the Mini-Monkey has a MEMs microphone, I thought that building a simple audio VU Meter using the LVGL gauge widget would be an effective demonstration.

 

analog-vu.png

Figure 1.  A "Classic" VU Meter

 

Creating a LVGL Port

 

Since I already had code to initialize my IPS display and the microphone on the Mini-Monkey, all I had to do was write a simple driver layer for LVGL.   This task was simplified for me as LVGL is built into MCUXpresso SDK and there is an example for the LPC55S69 using FreeRTOS or a bare metal environment.

lvgl1.png

Figure 2.  LVGL Examples built into the LPC55S69 SDK

I generally prefer to pull in code directly from the GitHub repositories, but using the version from the MCUXpresso SDK was a useful starting point to observe a basic LVGL port.  Once you bring the LVGL source tree into your project,  porting to a new screen is straightforward.      In the MCUXpresso example, a file littlevgl_support.c is provided as an example.

lvgl2.png

Figure 3.  LVGL Port Layer in the MCUXpresso SDK example.

In addition actual driver port, you need to provide some configuration files to enable/disable features in LVGL.  You can pull the templates from the MCUXpresso example.

 

lvgl3.png

Figure 4.  LVGL Configuration File.

Since I was familiar with the interface to the Mini-Monkey IPS display through previous development with my own graphics library, I was able to get the SDK example ported in about 30 minutes.    LVGL provides a “demo widgets” example which shows how to instantiate some common user interface widgets.   I used this as a starting point to verify that I had things ported OK.      The LPC55S69 has plenty of RAM for LVGL’s working buffer.   LVGL recommends a 1/10 screen sized buffer but you could provide a 1:1 sized back-buffer with the large amount of RAM available in the LPC55S69.  

Microphone Signal Processing for the VU Meter

 

To implement my VU meter, I decided to use an envelope detector and map the output to an LVGL gauge.

 

Envelope.png

Figure 5.  Envelope Detector Algorithm (Image Source is from Wikipedia.org)

The are several methods for detecting the envelop of a signal but I chose to use a simple single-pole filter applied to rectified version of the input signal with programmable attack and release times. 

 

 

// attTime and relTime is in seconds

float ga = exp(-1.0f/(sampleRate*attTime));
float gr = exp(-1.0f/(sampleRate*relTime));

float envOut = 0.0f;

for( ... )
{
    // get your data into 'input'

    envIn = fabs(input);

    if( envOut < envIn )
        envOut = envIn + ga * (envOut - envIn);
    else
        envOut = envIn + gr * (envOut - envIn);

    // envOut now contains the envelope
}

 

 

I want to point out a very useful resource for many common audio effects:

https://www.musicdsp.org/en/latest/

You can find code snippets for many common audio effects to use a starting point.  This is where I found a sample envelope detector.  For my purposes, I did not need to convert the detector output to a dBu value.  Instead, I just mapped my envelope detector output to a simple 0 to 100 scale for demonstration purposes.

Setting the a gauge in LVGL is straight forward.

guage_setup.png

 Figure 6.  LVGL Gauge Setup.

Updating the gauge value is a one-liner with LVGL:

 

 

lv_gauge_set_value(gauge1, 0, EnvelopeOut);

 

 

In my demonstration code,  EnvelopeOut is computed on a per sample basis in an IRQ routine.    To keep things simple, I simply ran my main program “open loop” to update the display as fast as I could.   LVGL only updates areas of the screen that have actually changed so animations can be very smooth!   You can find my LPC55S69 LVGL VU meter code here.

So, how did it turn out?   Note that IPS displays are quite difficult to record via a cell phone camera.  If you see some “grittiness” in the video, this is an artifact of the optical sampling of an IPS display with my cell phone camera.    This particular IPS display with LVGL looks *very* good.

 

I was quite impressed with how quickly I could get LVGL up and running on the Mini-Monkey.     If you are looking at implementing embedded graphics on the LPC55S69 or another NXP part, LVGL should be on your short list for evaluation.    In my next article on embedded graphics with the LPC55S69, we are going to look at decoding JPEG images so stay tuned!