Better LEDs through DMA

While regular Hackaday readers already know how to blink a LED with a microcontroller and have moved onto slightly more challenging projects such as solving the Navier-Stokes equations in 6502 assembly, that doesn’t mean there’s not space for newbies. [Rik] has published a great tutorial on abusing DMA for blinkier glowy things. Why would anyone want to learn about DMA techniques? For blinkier glowy things, of course.

This tutorial assumes knowledge of LED multiplexing and LED matrices, or basically a bunch of LEDs connected together on an XY grid. The naive way to drive an 8×8 grid of LEDs is attaching eight cathodes to GPIO pins on a microcontroller, attaching the eight anodes to another set of GPIO pins, and sourcing and sinking current as required. The pin count can be reduced with shift registers, and LED dimming can be implemented with PWM. This concludes our intensive eight-week Arduino course.

Thanks to microcontrollers that aren’t trapped in the 1980s, new techniques can be used to drive these LED matrices. Most of the more powerful ARM microcontrollers come with DMA, a peripheral for direct memory access. Instead of having the CPU do all the work, the DMA controller can simply shuffle around bits between memory and pins. This means blinker projects and glowier LEDs.

[Rik]’s method for DMAing LEDs includes setting up a big ‘ol array in the code, correctly initializing the DMA peripheral, and wiring up the LED matrix to a few of the pins. This technique can be expanded to animations with 64 levels of brightness, something that would take an incredible amount of processing power (for a microcontroller, at least) if it weren’t for the DMA controller.

The setup used in these experiments is an STM32F103 Nucleo board along with the OpenSTM32 IDE. [Rik] has released all the code over on GitHub, and you are, of course, encouraged to play around.

Understanding DMA

In the world of computers, the central processing unit (CPU) is–well–central. Your first computer course probably explained it like the brain of the computer. However, sometimes you can overload that brain and CPU designers are always trying to improve both speed and throughput using a variety of techniques. One of those methods is DMA or direct memory access.

As the name implies, DMA is the ability for an I/O device to transfer data directly to or from memory. In some cases, it might actually transfer data to another device, but not all DMA systems support that. Sounds simple, but the devil is in the details. There’s a lot of information in this introduction to DMA by [Andrei Chichak]. It covers different types of DMA and the tradeoffs involved in each one.

Continue reading “Understanding DMA”

High Speed SSD1306 Library

[Lewin] wrote in to tell us about a high speed library for Arduino Due that he helped develop which allows interfacing OLED displays that use the SSD1306 display controller, using DMA routines for faster display refresh time.

Typically, displays such as the Monochrome 1.3″ 128×64 OLED graphic display , are interfaced with an Arduino board via the SPI or I2C bus. The Adafruit_SSD1306 library written by [Limor Fried] makes it simple to use these displays with a variety of Arduinos, using either software or hardware SPI. With standard settings using hardware SPI, calls to display() take about 2ms on the Due.

[Lewin] wanted to make it faster, and the SAM3X8E on the Due seemed like it could deliver. He first did a search to find out if this was already done, but came up blank. He did find [Marek Buriak]’s library for ILI9341-based TFT screens. [Marek] used code from [William Greiman], who developed SD card libraries for the Arduino. [William] had taken advantage of the SAM3X8E’s DMA capabilities to enable faster SD card transfers, and [Marek] then adapted this code to allow faster writes to ILI9341-based screens. All [Lewin] had to do was to find the code that sent a buffer out over SPI using DMA in Marek’s code, and adapt that to the Adafruit library for the SSD1306.

There is a caveat though: using this library will likely cause trouble if you are also using SPI to interface to other hardware, since the regular SPI.h library will no longer work in tandem with [Lewin]’s library. He offers some tips on how to overcome these issues, and would welcome any feedback or testing to help improve the code. The speed improvement is substantial. Up to 4 times quicker using standard SPI clock, or 8 times if you increase SPI clock speed. The code is available on his Github repo.