Your comments reveal I need to better clarify what this does. The linked code are some modifications to the Atmel AT90 code that runs in the Adafruit USB backpack to make it more suitable for audio use -- particularly the audio level meter function. You communicate to the character display through a serial port (or USB serial), for example /dev/ttyACM0
.
giuliomoro I had a quick look at the the code above the other day but I did not see any actual example, perhaps I missed it?
The code referenced makes the Adafruit USB LCD backpack "Bela-ready". Now all the BBB needs to do is send something out the serial port every 50ms or so to keep the bars bouncing.
giuliomoro Sounds great, how do you interface this with Bela though?
UART (USB or serial pins) I'm working on the software interface part. At the moment I am using a random number generator to create bouncing levels to emulate audio and writing text on the unused lines as proof-of-concept. No code worth pushing to github yet.
giuliomoro Also, out of curiosity, how early in the boot can you start this?
As early as you can get a tty up and get a process running to talk to it. As for the audio level metering, obviously you need a process running that can get audio or ADC inputs. This probably makes more sense when you realize the display interface is just a tty port.
My plan is for an auto-started Bela project to initiate communication with this, so it will be blank until the system is go. It will be an indication it's booted and running.
Here is a very basic sketch of how it will be used to monitor levels on Bela.
//
// Note: This is not "copy and paste" code
// Read this like "pseudocode". Only for purpose of illustrating the
// intended method of application to Bela
//
AuxiliaryTask SerialLcdFuncs;
unsigned int gLcdTimer;
unsigned char gLevel;
unsigned char gChannel;
float gMax0, gMax1;
.
.
.
void SerialLCD_BG_Task(void*)
{
float tmpLevel = 20.0 + 20.0*log10(gMax0); //This will register any levels from -20 dBFS up to 0 dBFS
//Assumes a 20x4 display
unsigned char uLev = (unsigned char) (0xFF & lrintf(tmpLevel));
//Assume there is some object called Serial that was initialized, and is configured to talk to the
//serial port to which the USB LCD backpack is connected. (for example /dev/ttyACM0)
Serial.Write(0xFE); //command mode
Serial.Write(0xD6); //Audio Level Meter command
Serial.Write(0x02); //Audio level meter channel (second row, top bar)
Serial.Write(uLev); //Audio Level Meter Level field
gMax0 = 0.0; //This might be a little dangerous, but this serves as "pseudo-code" for the general idea
//Repeat calculation for channel 2, only change third line to adapt:
//Serial.Write(0xFE); //command mode
//Serial.Write(0xD6); //Audio Level Meter command
Serial.Write(0x03); //Audio level meter channel (second row, bottom bar)
//Serial.Write(uLev); //Audio Level Meter Level field
//Read serial port for button press messages (extra I/O)
//Send text if there is stuff to send
}
.
.
.
bool setup(BelaContext *context, void *userData)
{
SerialLcdFuncs= Bela_createAuxiliaryTask(&SerialLCD_BG_Task, 50, "bela-serial-lcd", arg);
gChannel = 0;
gLevel = 0;
gLcdTimer = 0;
gMax0 = 0.0;
gMax1 = 0.0;
}
void render(BelaContext *context, void *userData)
{
float ch0 = 0.0;
float ch1 = 0.0;
float tmp = 0.0;
for(unsigned int n = 0; n < context->audioFrames; n++) {
ch0 = audioRead(context, n, 0);
ch1 = audioRead(context, n, 1);
tmp = fabs(ch0);
if(tmp > gMax0)
gMax0 = tmp;
tmp = fabs(ch1);
if(tmp > gMax1)
gMax1 = tmp;
if(++gLcdTimer >= LCD_WRITE_INTERVAL)
{
gLcdTimer = 0;
Bela_scheduleAuxiliaryTask(SerialLcdFuncs);
}
}
}