ws-ldn-12 icon indicating copy to clipboard operation
ws-ldn-12 copied to clipboard

ARM / STM32F7 DIY synth workshop

  • thi.ng/ws-ldn-12 ARM / STM32F7 DIY synth workshop (STM32F746-DISCO)

[[./assets/ws-ldn-12-minigorille.jpg]]

Photo by Lysandre Follet

[[https://soundcloud.com/forthcharlie/sets/stm32f4][Check out demo tracks on Soundcloud]]

** Project setup

This repo contains 8 sub-projects, all described below and each compilable as standalone application. The repo also includes various support libraries of the thi.ng collection as Git submodules, located in the [[./ext][/ext]] folder:

  • [[http://thi.ng/ct-gui][ct-gui]] - tiny GUI library
  • [[http://thi.ng/ct-head][ct-head]] - common headers, macros & utils
  • [[http://thi.ng/synstack][ct-synstack]] - softsynth / DSP engine

#+BEGIN_SRC shell

clone with submodules

git clone https://github.com/thi-ng/ws-ldn-12 --recursive #+END_SRC

*** Other 3rd party dependecies

  • [[http://www.st.com/web/en/catalog/tools/PF261909][STM32 CubeF7 SDK]]
  • [[https://launchpad.net/gcc-arm-embedded][GCC ARM toolchain]]
  • [[https://github.com/texane/stlink][ST-Link]]
  • [[https://gnuarmeclipse.github.io/openocd/releases/][OpenOCD]] (optional, using dev version w/ STM32F746 support) ** Building

This repo uses a flexible =Makefile= to build all included projects - no IDE required! The setup features:

  • easily customizable device config & linker scripts
  • no requirement to manually copy STM Cube SDK sources
  • catalog file(s) to selectively exclude various SDK source files (see [[./make/sources.txt][/make/sources.txt]], can be overridden per project)
  • config flags to include USBH & FatFs middlewares
  • support for multiple sub-projects (with & without shared sources)
  • individual module (sub-project) configs (e.g. [[./make/modules/ex08.make][/make/modules/ex08.make]])
  • separate build & target folders for each module

Currently only the STM32F746-DISCO board is supported, but additional board configurations can be easily added (see [[./make/devices/][/make/devices/]] for reference).

IMPORTANT: The =Makefile= requires the env var =STM_CUBE_HOME= to be set to the root of your STM SDK directory, e.g. =~/dev/arm/STM32Cube_FW_F7_V1.4.0=.

#+BEGIN_SRC shell export STM_CUBE_HOME=~/dev/arm/STM32Cube_FW_F7_V1.4.0

make module=ex01 clean make module=ex01 -j4

flash device (0x800000 is ROM start address)

st-flash --reset write bin/ex01/app.bin 0x8000000

combine for improved usability in terminal

make module=ex01 -j4 && st-flash --reset write bin/ex01/app.bin 0x8000000 #+END_SRC

** Examples *** ex01 - blinky

[[./src/ex01/main.c][Source]]

Simple Hello World LED blink example & demo of using EXTI interrupt to react to user button. Stops/starts blinking each time button is pressed.

*** ex02 - LCD, touchscreen & GUI basics

[[./src/ex02/main.c][Source]]

Basic demonstration of working with BSP LCD & touchscreen modules, as well as intro to working w/ external libraries (here [[http://thi.ng/ct-gui][thi.ng/ct-gui]]).

Edit the source file to [[./src/ex02/main.c#L28][uncomment different demo modes]]:

  • =demoWelcome()= - simple text rendering & random dots, non-interactive
  • =demoScribble()= - 5 point multi-touch drawing
  • =demoGUI()= - basic GUI usage example (dials control nothing)

*** ex03 - Timers

[[./src/ex03/main.c][Source]]

Basic timer setup & multi-tasking example. Timer runs @ 10kHz and controls simple LED blinking task. Task can be suspended interactively by pressing user button.

*** ex04 - Oscillators

[[./src/ex04/main.c][Source]]

Simple oscillator & frequency modulation experiment. The following oscillator types are supported for both main osc & modulator:

| ID | Type | |------+-------------------------------| | 0 | Sine | | 1 | Saw | | 2 | Square | | 3 | Triangle | | 4 | Saw + Sin | | 5 | Noise (uses [[http://xoroshiro.di.unimi.it/][Xorshift128]] PRNG) |

Important: The =mod_amp= field of the =Oscillator= struct is the modulation amplitude, but since the modulator is acting in the frequency domain, this amplitude too is in Hz.

*** ex05 - USB stick WAV file streaming playback

[[./src/ex05/main.c][Source]]

This example uses the STM USB Host library & FatFS to access a USB memory stick connected to the board. Once USB handshake is complete, the app will then attempt to read the file =sound.wav= located in the root of the USB filesystem and start streaming to the headphone audio output (looping playback).

Important:

  • The WAV file MUST be in 44.1kHz, 16bit stereo format
  • The example is currently configured to use the USB FS (fullspeed) port (not HS (highspeed)). This can be changed via the =ex05/usbh_conf.h= file.

*** ex06 - thi.ng/synstack basics

[[./src/ex06/main.c][Source]] | [[https://soundcloud.com/forthcharlie/stm32f7-synstack-ex06-ws-ldn-12][Soundcloud]]

First example using [[http://thi.ng/synstack][thi.ng/synstack]] to implement polyphonic synth with fully configurable node based DSP graph (1 graph per voice). The graph implemented is shown below.

We also define a musical scale to play a randomized, but always harmonic sequence and show how to dynamically modify parameters of the DSP node.

Note: The graph doesn't show global LFOs, which are used for various modulation purposes (env mod, freq etc.).

#+BEGIN_SRC dot :file assets/ex06-dag.png :exports results digraph g { rankdir=LR; node[color="black",style="filled",fontname="Inconsolata",fontcolor="white",fontsize=11]; edge[fontname="Inconsolata",fontsize=9];

env[label="AD(S)R"]; osc1[label="osc #1\n(spiral)"]; osc2[label="osc #2\n(saw-sin)"]; mul1[shape="circle",label=""]; mul2[shape="circle",label=""]; sum[shape="circle",label="+"]; filter[label="biquad LPF\n(randomized)"]; pan[label="stereo pan"]; delay[label="delay"]; env -> mul1; env -> mul2; osc1 -> mul1 -> sum; osc2 -> mul2 -> sum; sum -> filter -> pan -> delay; } #+END_SRC

#+RESULTS: [[file:assets/ex06-dag.png]]

*** ex07 - thi.ng/synstack & custom SDRAM delay

[[./src/ex07/main.c][Source]] | [[https://soundcloud.com/forthcharlie/stm32f7-synstack-3-osc-fb-sdramdelay][Soundcloud]]

Similar setup to ex06 above, however to enable much longer delay times and not be limited by the <320KB of available on-chip RAM of the STM32F746-DISCO board, this example uses the 8MB "external" SDRAM (still on-board, just not in-chip), a [[./src/common/sdram_alloc.c][custom memory allocator]] (targetting SDRAM) and shows how to easily extend Synstack with custom DSP nodes - in this case a [[./src/synth_extras/osc_noise.c][noise oscillator]] and a [[./src/synth_extras/sdram_delay.c][new delay node]], which stores its long delay line in SDRAM, but then has to work with small, windowed sections in main RAM and mirror them back & forth.

We also updated the DSP node graph to add the new oscillator, foldback distortion and replace the old delay with the new one...

#+BEGIN_SRC dot :file assets/ex07-dag.png :exports results digraph g { rankdir=LR; node[color="black",style="filled",fontname="Inconsolata",fontcolor="white",fontsize=11]; edge[fontname="Inconsolata",fontsize=9];

env[label="AD(S)R"]; osc1[label="osc #1\n(spiral)"]; osc2[label="osc #2\n(saw-sin)"]; osc3[label="osc #3\n(noise)", color="red"]; mul1[shape="circle",label=""]; mul2[shape="circle",label=""]; mul3[shape="circle",label="*"]; sum[shape="circle",label="+"]; sum2[shape="circle",label="+"]; fb[label="foldback\ndistortion", color="red"]; filter[label="biquad LPF\n(randomized)"]; pan[label="stereo pan"]; delay[label="SDRAM delay", color="red"]; env -> mul1; env -> mul2; osc1 -> mul1 -> sum -> sum2; osc2 -> mul2 -> sum; osc3 -> mul3 -> sum2; sum2 -> fb -> filter -> pan -> delay; } #+END_SRC

#+RESULTS: [[file:assets/ex07-dag.png]]

*** ex08 - Synstack & MIDI

[[./src/ex08/main.c][Source]]

Based on ex07 synth setup, but with USB MIDI support to turn synth into actual instrument (4 voice polyphonic). Via the optional =LOG_MIDI= flag (defined in [[./make/modules/ex08.make][ex08.make]]), received MIDI message can be logged to the board's LCD screen.

Note: Currently the synth only accepts MIDI Note On messages and ignores MIDI Note Off's, since all voices only use an ADR envelope, without "sustain" phase. This will be added later... ** Resources

  • http://asm.thi.ng/ - links to all required SDK & build tools, references, learning resources...

** Contributors

| Name | Role | Website | | [[mailto:[email protected]][Karsten Schmidt]] | initiator & principal developer | [[http://thi.ng][thi.ng]] |

** License

This project is open source and licensed under the [[http://www.apache.org/licenses/LICENSE-2.0][Apache Software License 2.0]].