Lesson: Noise Generator on Archean Synthesizer with Lisp

Introduction

Lisp is one of the very first programming languages ever created. It appeared in the late 1950s and has remained unique: a functional language built on parentheses and simple rules. Lisp is often described as aesthetic. Its form is elegant, and for artists, engineers, and musicians it can be not only a tool but also an inspiration.

In this workshop we will use Lisp to program the Archean synthesizer. We will run Lisp inside the synth thanks to a special interpreter called uLisp.

Our goals are simple and concrete:
1. To learn how uLisp works as an interpreter on Teensy.
2. To send Lisp code directly into the synthesizer through the Serial Monitor.
3. To create a noise generator — turning random numbers into sound.

The result: your first step into programming sound with Lisp, and the first noise textures from Archean.

Prerequisites

- Archean synthesizer — the instrument already contains a Teensy 4.0
- Computer — Windows, macOS, or Linux.
- Arduino IDE — installed on your system.
- Headphones or speakers — connected to Archean’s audio output, so you can hear the noise we generate.

Getting Started

Before you can program Archean with Lisp, you need to install the uLisp interpreter on the Teensy 4.0 inside your synth. This interpreter turns your Teensy into a small Lisp machine, accessible through the Serial Monitor in Arduino IDE.

Installing uLisp

- Go to the uLisp GitHub repository (https://github.com/technoblogy/ulisp-arm).
- Download the ZIP archive.
- Open the Arduino IDE, load the ulisp-arm.ino sketch, and upload it to the Teensy.
- Upload it to the Teensy.

After installation

- Open the Serial Monitor.
- Set the correct baud rate (usually 9600 or 115200).
- You should see the uLisp prompt: >

Lisp Basics

Before diving into the code, here are some Lisp basics you need to know:

1. Everything in parentheses

Lisp code is made of expressions inside parentheses. The first item in the parentheses is usually the function name or operator.The following items are arguments to that function.
Example:

(+ 2 3)

Here + is the function, 2 and 3 are arguments. The result is 5.

2. Defining functions

(defun name (args...) body)

defun defines a new function.
- name – the function’s name
- args – a list of arguments
- body – code executed when the function is called

3. Progn

(progn ...)

lets you execute multiple expressions in sequence, returning the result of the last one.

4. Let

(let ((var1 val1) (var2 val2) ...) …)

Creates local variables for a block of code.

5. Loop

(loop ...)

repeats code endlessly (or until explicitly broken).
The Code
Below is the complete Lisp program.
Type each line or whole code into the Serial Monitor.
(pinmode 1 t)

(defun delay-loop (n)
  (dotimes (i n)
    (+ i 0))) 

(defun noise ()
  (progn
    (with-spi (s 1)
      (loop
        (let ((val (logior #x7000 (random 4096))))
          (delay-loop 200)
          (digitalwrite 1 nil)
          (write-byte (ash val -8) s)
          (write-byte (logand val #xFF) s)
          (digitalwrite 1 t))))))

(noise)
Line-by-Line:
(pinmode 1 t)
Sets pin 1 of the Teensy as output (t - true). This pin controls Chip Select (CS) for the MCP4921 DAC.
(defun delay-loop (n)
  (dotimes (i n)
    (+ i 0)))
Defines a function delay-loop that runs a simple loop n times.
- This is used to slow down the updates to the DAC.
- dotimes loops a given number of times.
- (+ i 0) does nothing meaningful; it just prevents the loop from being empty.
(defun noise ()
  (progn
    (with-spi (s 1)
      (loop
        (let ((val (logior #x7000 (random 4096))))
          (delay-loop 200)
          (digitalwrite 1 nil)
          (write-byte (ash val -8) s)
          (write-byte (logand val #xFF) s)
          (digitalwrite 1 t))))))
Defines the noise function.
Step by step inside noise:
- (with-spi (s 1) ...) – opens SPI communication with the DAC.
- (loop ...) – runs indefinitely.
- (let ((val ...))) – generates a 12-bit random value and adds DAC control bits (#x7000).
- (delay-loop 200) – slows down the output.
- (digitalwrite 1 nil) – lowers CS pin to start DAC transfer.
- (write-byte (ash val -8) s) – sends the high byte of val to DAC.
- (write-byte (logand val #xFF) s) – sends the low byte of val to DAC.
- (digitalwrite 1 t) – raises CS pin, latching the value in DAC.
(noise)
Calls the function noise to start the generator. It will run until you interrupt it in the Serial Monitor.
Conclusion

You have just written your first sound generator in Archean. With only a few lines of Lisp, you controlled a DAC directly and transformed random numbers into analog audio noise.

Archean is not only a synthesizer, it is a way of thinking about sound. Continue by writing new functions, experimenting with randomness, and creating your own living textures.

Troubleshooting / Notes

- If uLisp doesn’t compile: make sure there is only one .ino file in the sketch folder (ulisp-arm.ino). Extra .ino files cause errors.
- If Serial Monitor shows nothing: select the correct port and baud rate (usually 9600 or 115200), then reset the Teensy.