Friday, October 29, 2021

Arduino sketch for TFT display rendering using serial commands

I've been using a Seeed Studio Wio Terminal as an external display for a Raspberry Pi. I initially wrote an Arduino sketch that took high level, application-specific commands over serial and rendered appropriate display elements. This has the disadvantage that adding UI features required updating the Arduino code, which is more of a pain and slower to iterate on.

Instead, I'm now planning on sending rendering commands over the serial interface - turning the microcontroller into a general purpose rendering device.

I've thrown my initial code up on GitHub here:

It currently only supports a small set of commands for rendering rectangles and text. I'll be adding more features as I need them.

Sunday, October 17, 2021

Speeding up Arduino TFT (TFT_eSPI) writes

 I've been recently playing around with "Arduino" microcontroller stuff - specifically a Seeed Studio Wio Terminal.

Playing around with the TFT display, I noticed that drawing to it was pretty slow. After doing some research, I found out that direct TFT writes are indeed quite slow. But there is an easy way around it.

The TFT_eSPI graphics library, a modified version of which is used by the Wio Terminal, provides a Sprite class that can be used to do quick TFT writes. If you have enough memory (which the Wio Terminal *just* barely does), you can create a full screen-sized sprite.

The Sprite class supports the same drawing API as the main TFT class, so it is pretty easy to convert code that is writing directly to the TFT to use a Sprite instead.

To initialize it, do this:

TFT_eSPI tft = TFT_eSPI();
TFT_eSprite screen = TFT_eSprite(&tft);

In your setup(), after initializing the TFT, do this:

screen.createSprite(tft.width(), tft.height());

Then, use "screen" instead of "tft" for all of your drawing calls. When you want to update the TFT with the current state of your sprite, do this:

 screen.pushSprite(0, 0);

That's it! The result is a display that will update *much* faster.

One caveat is that this method uses up the vast majority of the Wio Terminal's RAM. It works fine for me, since my application is not otherwise particularly memory hungry. More complicated applications (using WiFi, for example) may run into problems. If that happens, a good (if more complicated) solution would be to use a smaller screen area sprite and do targeted writes to sub-areas of the screen.

Monday, October 4, 2021

Fixing Hotone Jogg ASIO "No devices connected" issue

I recently ordered a Hotone Jogg guitar audio interface pedal and had trouble getting the Windows 10 ASIO drivers to work. Turns out that ASIO support was added with a firmware update, and the pedal I got had the old firmware.

If you are having this problem, you need to get the updated firmware from here:

Scroll down until you see "Jogg firmware with Hotone ASIO driver support" and click on the link to download the firmware.

Follow the included instructions (you have to open up the unit to flip a dip switch, which is not very user friendly) and you should soon be good to go.

Hotone Jogg audio interface pedal works in Linux

 After posting a number of previous posts about guitar audio interfaces that did not work out of the box, I am pleased to report that the Hotone Jogg works right out of the box in Linux. Pleasant surprise!

I couldn't find any information on using this device with Linux, so I thought I'd do this brief post for any future people that may be looking.

Wednesday, January 20, 2021

NUX MG-300 Guitar Processor under Linux and Android


I picked up a NUX MG-300 guitar effects unit with high hopes that it would work under Linux, since it is supposed to be a class-compliant USB audio device.

Unfortunately, it did not work out of the box. After some back and forth with the maintainer of the Linux kernel sound subsystem, we managed to get audio capture working, but never managed to get playback working. Everything seems to be operating correctly, but the device produces no audio output over USB.

I have admitted defeat and will be returning the device.

The discussion on the alsa-devel mailing list can be found here:

It at least resulted in a kernel patch to enable audio capture.

I also had no success getting it to work with Android - even with some of the apps that have their own custom USB audio implementation.

If anyone has more luck with this interface down the road, please let me know.

Update: As a last ditch effort, I gave the interface a try with the aforementioned kernel patch on my Raspberry Pi 4, which was running about a year old kernel version. And it worked. Sort of. It initially worked perfectly, but I found after more testing that it is sporadic. Sometimes it worked fine, sometimes only playback worked, and sometimes only capture worked. Not sure what needs to be done to get the interface working reliably.

Tuesday, November 3, 2020

Guitar amplifier and pedal simulation

I've been spending a lot of time lately playing guitar, and working on my own software for simulating guitar amplifiers and pedals. It is coming along nicely, and I have most of the important stuff covered.

I run it as a VST under Windows, but I also have a Linux version that I run on a Raspberry Pi 4. Coupled with a USB audio interface, a PA speaker, and a remote control app on my phone, it makes for a nice little portable rig.

Here is a little video of it in action (running as a VST in Reaper):

Saturday, August 22, 2020

Starting JACK automatically when a USB audio device is connected

I have a Raspberry Pi that I'm using headless for audio, and I wanted to automatically start jackd when I connected my USB audio device.

There are a lot of ways to try to do this - after a few false starts, I ended up with this method. It took me long enough to sort out the details that I figured I'd write up a little how-to.

This solution is composed of two parts: 1) set up jackd as a systemd service, and 2) use a udev rule to start the service when the sound card is connected.

First the service. Create a file called '/etc/systemd/system/jackd.service' with the following:

Description=JACK audio

ExecStart=/usr/bin/jackd <your jack commandline arguments here>


Now (or at least after you reboot, or do 'sudo systemctl daemon-reload', you can start and stop jackd with 'sudo systemctl start jackd.service' and 'sudo systemctl stop jackd.service'. I'm running the service as root - if you want to use a different user, change the "User=" line.

We want this to happen automatically, though, so it is time to use udev - the system for managing Linux device events.

First, you need to know some information about your USB audio device. Plug it in, and run 'lsusb'. You should see something like this:

Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 003: ID 0582:01d6 Roland Corp.
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

Look for your sound card device in the list (mine is showing as "Roland Corp."), and note the two hex numbers after ID. They are the USB Vender and Product IDs for your device.

Create a file called something like '/etc/udev/rules.d/80-local.rules' with the following in it:

ACTION=="add", ATTR{idVendor}=="0582", ATTR{idProduct}=="01d6", TAG+="systemd", ENV{SYSTEMD_WANTS}="jackd.service"

Where the values for 'ATTR{idVendor}' and 'ATTR{idProduct}' are the Vendor and Product IDs you got from lsusb.

After your next reboot, or after running 'sudo udevadm control --reload', you new rule should be ready. When you plug in your sound card, the udev rule will fire and request your service, which will then start jackd.