Nuno Trocado

Lisp and cl-collider in Bela

2023-01-31

I started using a Bela board. It works with a series of programming languages, including SuperCollider. But I’d rather use Lisp through cl-collider, which is unsupported. I spent way more time than I’d like to admit trying to get this to work, but I finally did it! For my reference and for the improbable benefit of anyone else playing with this, here’s how to set things up.

Install Clozure CL in Bela

We need an ARM 32-bit implementation. SBCL has a port, but it doesn’t support threads. Use CCL. Following the instructions for the current release, download both the source code and the bootstrapping binaries for linuxarm, copy them over to Bela, unpack, launch the CCL image and run (rebuild-ccl :full t).

Use a fixed version of osc

To avoid compile errors in CCL use my fork of the osc library. Clone it to local-projects on the host machine.

Bundle cl-collider

On the host machine, create a Quicklisp bundle for cl-collider.

Create a file called bela.lisp with the following contents:

(require "cl-collider")

(in-package :ccl)

(advise ccl::resolve-address (let ((arglist (list* :address-family
                                                   :internet
                                                   arglist)))
                               (:do-it))
        :when :around
        :name :internet)

(in-package :sc)

;;; the following are needed for working with the Trill UGens at https://github.com/jreus/Trill_SC

(defugen (trill-raw "TrillRaw")
    (&key (i2c-bus 1) (i2c-address #x20) (noise-threshold 0) (pre-scaler 2) (reset-baseline 0.0))
  ((:kr (multinew new 'multiout-ugen 11
                  i2c-bus i2c-address noise-threshold pre-scaler reset-baseline))))

(defugen (trill-centroids "TrillCentroids")
    (&key (i2c-bus 1) (i2c-address #x20) (noise-threshold 0) (pre-scaler 2) (reset-baseline 0.0))
  ((:kr (multinew new 'multiout-ugen 11
                  i2c-bus i2c-address noise-threshold pre-scaler reset-baseline))))

(in-package :sc-user)

(setf *s* (make-external-server "bela"
                                :port 5000
                                :server-options (make-server-options :block-size 16)))

(unless (boot-p *s*)
  (loop :initially (server-boot *s*)
        :with start := (get-universal-time)
        :do (sleep 1)
        :until (or (boot-p *s*) (> (get-universal-time) (+ start 10)))))

Copy the bundle and the lisp file to a new directory on Bela

For example: scp /path-to-bundle-and-file/ [email protected]:~/bela-lisp/

Run

armcl --load "bundle" --load "bela" -S 8000000 -Z 8000000

This will hopefully leave you at the repl with the server booted and ready to play.

Run at startup

Create a systemd process (that runs the above command, or alternatively that loads a prebuilt image) and enable it—follow this guide.

Connect to a running instance on Bela - live coding / hot rewire

It’s possible to connect to a scsynth server running on Bela. From the host use the following:

(setf *s* (make-external-server "bela"
                                :port 5000
                                :just-connect-p t))

For a more sophisticated option, it’s also possible to use swank or slynk to connect to the running lisp instance on Bela.