If you only need to use one display, then maybe it's best to use the UART, as it provides a UART input as well. See instructions here https://learn.bela.io/using-bela/technical-explainers/device-tree-overlays/#image-v034-or-above to enable UART4 on Bela (the Tx pin, once enabled, is P9.13), or use config-pin P2.07 uart
on BelaMini and use P2.07 as the Tx pin.
Then you can use our Serial library to send messages to the display. The current example for the Serial
library (Communication/Serial
) only receives text via UART. I modified it so that it should work with your display, see below. This should send a waiting pattern .___
_.__
__._
___.
to the display. If you were to connect the RX pin as well to something that can send a k
or s
then you'd get printed "hich" or "5nar" respectively. Anyhow, looking at it you should be able to figure out how to setup and write to the display. This was implemented based on the datasheet, but of course I haven't tested it.
/*
____ _____ _ _
| __ )| ____| | / \
| _ \| _| | | / _ \
| |_) | |___| |___ / ___ \
|____/|_____|_____/_/ \_\
http://bela.io
*/
/**
\example Communication/Serial/render.cpp
Serial communication
------------
This example demonstrates how to receive and transmit serial data from Bela.
When a 'k' or 's' are received on the specified serial port, a kick or snare
sound, respectively, are generated.
Serial data is received in a lower-priority thread (an AuxiliaryTask). From
there, relevant data is passed to the audio thread via a Pipe. The
AuxiliaryTask is also writing to the serial port.
If the `useDisplay` variable is set to `true`, the code will assume that the
output of the UART is connected to a Sparkfun Serial 7-Segment Display
(https://www.sparkfun.com/datasheets/Components/LED/7-Segment/SFE-0012-DS-7segmentSerial-v41.pdf)
and write messages that are compatible with it.
The sound generator is very simple and "retro". It uses a decaying noise
burst for the snare sound and a decaying sine sweep for the kick
*/
#include <Bela.h>
#include <libraries/Pipe/Pipe.h>
#include <libraries/Serial/Serial.h>
#include <cmath>
Serial gSerial;
Pipe gPipe;
unsigned int gSnareDuration;
int gSnareTime = 0;
unsigned int gKickDuration;
int gKickTime = 0;
float gKickPhase = 0;
bool useDisplay = true; // whether to use the Sparkfun Serial 7-Segment Display
void serialIo(void* arg) {
while(!Bela_stopRequested())
{
unsigned int maxLen = 128;
char serialBuffer[maxLen];
// read from the serial port with a timeout of 300ms
int ret = gSerial.read(serialBuffer, maxLen, 300);
if (ret > 0) {
printf("Received: %.*s\n", ret, serialBuffer);
for(int n = 0; n < ret; ++n)
{
// when some relevant data is received
// send a notification to the audio thread via
// the pipe
// and send a reply on the serial port
if('k' == serialBuffer[n])
{
gPipe.writeNonRt('k');
if(useDisplay)
{
// the display does not support all
// characters so we have to be a bit
// creative about which ones we use.
// When writing data, we manually
// specify the size because the display
// requires that exactly 4 bytes are
// written at a time.
const char buf[] = "hich";
gSerial.write(buf, 4);
} else
gSerial.write("kick!\n\r");
} else if('s' == serialBuffer[n])
{
gPipe.writeNonRt('s');
if(useDisplay){
const char buf[] = "5NAR";
gSerial.write(buf, 4);
} else {
gSerial.write("snare!\n\r");
}
}
}
} else {
if(useDisplay)
{
// if nothing came in, show a waiting pattern
char buf[] = "----";
static int dot = 0;
buf[dot] = '.';
dot++;
if(dot >= 4)
dot = 0;
gSerial.write(buf, 4);
}
}
}
}
bool setup(BelaContext *context, void *userData) {
gSerial.setup ("/dev/ttyS4", 9600);
AuxiliaryTask serialCommsTask = Bela_createAuxiliaryTask(serialIo, 0, "serial-thread", NULL);
Bela_scheduleAuxiliaryTask(serialCommsTask);
gPipe.setup("serialpipe", 1024);
gKickDuration = 0.2 * context->audioSampleRate;
gSnareDuration = 0.2 * context->audioSampleRate;
return true;
}
void render(BelaContext *context, void *userData) {
char c;
// check if the serial thread has received any message and sent a notification
while(gPipe.readRt(c) > 0)
{
// if there is, trigger the start of the respective sound
if('s' == c)
gSnareTime = gSnareDuration;
if('k' == c)
gKickTime = gKickDuration;
}
for(unsigned int n = 0; n < context->audioFrames; ++n)
{
// synthesize the snare and kick
float snareOut = 0;
float kickOut = 0;
if(gSnareTime)
{
// just a burst of white noise with a decaying envelope
float noise = 2.f * (rand() / (float)RAND_MAX) - 1.f;
float env = gSnareTime / (float)gSnareDuration;
snareOut = 0.4f * noise * env;
--gSnareTime;
}
if(gKickTime)
{
// a descending sinewave
float frequency = map(gKickTime, gKickDuration, 0, 150, 20);
float env = gKickTime / (float)gKickDuration;
gKickPhase += 2.f * (float)M_PI * frequency / context->audioSampleRate;
if(gKickPhase > M_PI)
gKickPhase -= 2.f * (float)M_PI;
kickOut = env * sinf(gKickPhase);
--gKickTime;
}
float out = snareOut + kickOut;
for(unsigned int ch = 0; ch < context->audioOutChannels; ++ch)
{
audioWrite(context, n, ch, out);
}
}
}
void cleanup(BelaContext *context, void *userData) {}