cl-useq – A Common Lisp Library for working with uSEQ

Had a few moments this weekend to put together a library to connect to uSEQ. It uses a standard common-lisp implementation (tested with SBCL) and cl-libserial-port to form a serial connection to the uSEQ device (RP2040 based usb device).

I implemented a basic REPL to have a back and forth with the device. uSEQ ships with a much more full featured library called useqedit that I would recommend most people to use. I wrote this library to fold uSEQ into my native coding environment, which is Emacs and SLIME.

The cl-useq library can be found on my github along with a description and examples.

uSeq

It’s been a loong while since I last posted and I’ve been getting back into coding and music, the intersection of which got me into EE and CompSci way back in the early 2000s.

Common Lisp was the language of CLM and other software synthesis that attracted me at the time with fantasies of studying at Stanford’s CCRMA lab and the LaBRI Institute.

Nowadays there are new options like Incudine and OpusModus, which continue that direction and give me hope that I can continue to experiment with software based composition.

Lately I’ve been spending my days studying and practicing on an old studio piano as well as building a modest Eurorack DIY modular synth setup.

A kit popped up over at Thonk for a “livecoding” module called “uSeq” by Emute Labs, which is connected to the University of Sussex Experimental Music Lab.  It uses a Lisp dialect (uLisp) as a means to program the module using their own DSL called ModuLisp. There is even a published paper written that discusses livecoding with this tool.

The kit as sold by Thonk

The kit comes with everything you need to assemble the module minus a soldering iron, solder, and about 1/2 an hour of time.  There are two SMD switches, but other than it’s all through hole components.  They have a great build guide here and there is also a prebuilt version if you’d prefer to rack it up and go.

Soldered with Kestler no clean 60/40 solder
Installed and testing the blinkenlights.

The soldering went well and everything fired up on first go.  The 10 LEDs lit up in circling sequence and it showed up as a USB device on my Gentoo Linux host running realtime Linux Kernel 6.6.36. Here is the output of dmesg:

[646594.147296] usb 1-3: new full-speed USB device number 6 using xhci_hcd
[646594.295794] usb 1-3: New USB device found, idVendor=2e8a, idProduct=f00a, bcdDevice= 1.00
[646594.295812] usb 1-3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[646594.295820] usb 1-3: Product: RP2040
[646594.295825] usb 1-3: Manufacturer: Generic
[646594.295830] usb 1-3: SerialNumber: E463B013DB56402B
[646594.332211] cdc_acm 1-3:1.0: ttyACM0: USB ACM device
[646594.332284] usbcore: registered new interface driver cdc_acm
[646594.332291] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters

The bolded text “ttyACM0” is the device name for connecting to this new USB connection via the device file /dev/ttyACM0. The issue is that the permissions on that file did not allow my user to open the device:

elliott@deph ~ $ ls -al /dev/ttyACM0
crw-rw---- 1 root dialout 166, 0 Aug 4 04:22 /dev/ttyACM0

The OS is assigning the Rasberry Pi 2040 chip on uSeq as a communications device (like modems) rather than a USB serial device and so it assigns the “dialout” group and root user. If I’d like to connect to the device, I’ll need to either join that group or change permissions. I decided to change the permissions and the best way to do that is by setting up a udev rule. Here is what I added:

elliott@deph ~ $ cat /etc/udev/rules.d/50-useq.rules
SUBSYSTEMS=="usb"
ATTRS{idVendor}=="2e8a"
ATTRS{idProduct}=="f00a"
GROUP="audio"
MODE="0660"

The idVendor and idProduct were from dmesg output above, but also can be found by doing a lsusb -vvv to see all the details of the device. I have the “audio” group setup, my user configured to use it, and I changed the permissions to “0660” to ensure read/write access to that group as well as the root user. The udev rules were reloaded and the cable replugged back in to complete the permissions adjustment.

elliott@deph ~ $ ls -al /dev/ttyACM0
crw-rw---- 1 root audio 166, 0 Aug 4 04:22 /dev/ttyACM0

Now that we have a device and it’s attached, we can connect to it via a serial console emulator app. Luckily Emacs has built in methods and it was quick to load serial-term mode and connect to the device with an “9600 baud 8N1” connection rate using line-mode.

All this went flawlessly and I was soon issuing ModuLisp commands to the uSeq module to get reoccurring patterns on the analog outputs. Looking at the code it’s apparent that there is a python interface (useqedit) and I believe a SuperCollider interface here. The easiest method of connecting with uSeq is the webbased interface and it works well.

Over the next few weeks I’d like to go over the current state of the development environment, commands, and other aspects about using this module towards doing some livecoded audio.

quicklisp and clsql-fluid

This is a tech post and the intended audience is the few people who will bash their heads against a piece of software until it gets installed. I’ve just gone through one of these “sessions”, so I thought I’d document it here for the next person.

Zach Beane created quicklisp, which is a great way to load up common lisp libraries without a headache.

To give an example of this, to load my favorite web programming framework, all I need to do is type the following: (ql:quickload 'weblocks)

It loads everything I need and I can instantly get started working. Very cool! Now after a bit of programming I find that I’d like to customise the storage layer to use a mysql database, but that’s when it gets hairy…

First of all, weblocks’ clsql interface depends on clsql-fluid, which as a project doesn’t package anything… so this doesn’t give quicklisp an opportunity to distribute it. I guess someone could make a package, but I assume Zach would like to have the project maintainers do this instead of himself.

Secondly quicklisp already had installed the clsql library for me and I couldn’t find a command to remove it. So after looking through the documentation and the source I went and deleted things under my quicklisp directory (and ~/.cache) to remove quicklisp’s version of clsql. A remove command in quicklisp would be a nice touch. It would also be nice to get some like functionality for quicklisp in managing software beyond installing & searching. Maybe Zach already has plans for these for when the code goes out of beta…

Thirdly, I fetched clsql-fluid as described on the website and linked it in and loaded it up… but got errors:

"The name NIL does not designate any package."

What is happening here is that clsql-uffi tests that it’s properly loaded by looking for a defined symbol (atol64) to have an associated function. If that function doesn’t exist then we havn’t loaded the foreign libraries and therefore haven’t successfully loaded. The problem with this is that the clsql-uffi package doesn’t exist yet, so we get the error when the test code tries to (find-package #:clsql-uffi).

Since this test is a predicate of sorts I decided that instead of erroring it should just return nil, so I wrapped those probing statements in an: (ignore-errors ...) statement. Once I’d done this it allowed me to get to the next level of errors :)

Fourthly, the syntax used in the uffi calls seems different than what the uffi installed via quicklisp expects. After getting beyond the “nil package” problem above, I encountered this error:

caught ERROR:
; (in macroexpansion of (UFFI:CONVERT-FROM-FOREIGN-STRING CHAR-PTR
:LOCALE ...))
; (hint: For more precise location, try *BREAK-ON-SIGNALS*.)
; error while parsing arguments to DEFMACRO CONVERT-FROM-FOREIGN-STRING:
; unknown keyword: :LOCALE; expected one of :NULL-TERMINATED-P,
:LENGTH

After looking around a bit I got the tip that cffi-uffi-compat might be more compatible than quicklisp’s version of uffi, so I edited clsq.asd, clsql-mysql.asd, clsql-uffi.asd, and uffi/clsql-uffi-package.lisp and edited them to use the uffi compatibility layer from cffi. After all that was done I did another (ql:quickload 'clsql-mysql) and the clsql-fluid version loaded. whew

I hope this helps others stuck in a similar situation and here is the result of a git diff in the root of the clsql-fluid source:

diff --git a/clsql-mysql.asd b/clsql-mysql.asd
index a176f85..1263457 100644
--- a/clsql-mysql.asd
+++ b/clsql-mysql.asd
@@ -20,8 +20,8 @@
 (in-package #:clsql-mysql-system)
 
 (eval-when (:compile-toplevel :load-toplevel :execute)
-  (unless (find-package 'uffi)
-    (asdf:operate 'asdf:load-op 'uffi)))
+  (unless (find-package 'cffi-uffi-compat)
+    (asdf:operate 'asdf:load-op 'cffi-uffi-compat)))
 
 (defvar *library-file-dir* (append (pathname-directory *load-truename*)
                                   (list "db-mysql")))
@@ -48,8 +48,8 @@
   t)
 
 (defmethod operation-done-p ((o load-op) (c clsql-mysql-source-file))
-  (and (symbol-function (intern (symbol-name '#:mysql-get-client-info)
-                               (find-package '#:mysql)))
+  (and (ignore-errors (symbol-function (intern (symbol-name '#:mysql-get-client-info)
+                                              (find-package '#:mysql))))
        t)) 
 
 (defmethod perform ((o compile-op) (c clsql-mysql-source-file))
@@ -80,7 +80,7 @@
   :description "Common Lisp SQL MySQL Driver"
   :long-description "cl-sql-mysql package provides a database driver to the MySQL database system."
 
-  :depends-on (uffi clsql clsql-uffi)
+  :depends-on (cffi-uffi-compat clsql clsql-uffi)
   :components
diff --git a/clsql-mysql.asd b/clsql-mysql.asd
index a176f85..1263457 100644
--- a/clsql-mysql.asd
+++ b/clsql-mysql.asd
@@ -20,8 +20,8 @@
 (in-package #:clsql-mysql-system)
 
 (eval-when (:compile-toplevel :load-toplevel :execute)
-  (unless (find-package 'uffi)
-    (asdf:operate 'asdf:load-op 'uffi)))
+  (unless (find-package 'cffi-uffi-compat)
+    (asdf:operate 'asdf:load-op 'cffi-uffi-compat)))
 
 (defvar *library-file-dir* (append (pathname-directory *load-truename*)
                                   (list "db-mysql")))
@@ -48,8 +48,8 @@
   t)
 
 (defmethod operation-done-p ((o load-op) (c clsql-mysql-source-file))
-  (and (symbol-function (intern (symbol-name '#:mysql-get-client-info)
-                               (find-package '#:mysql)))
+  (and (ignore-errors (symbol-function (intern (symbol-name '#:mysql-get-client-info)
+                                              (find-package '#:mysql))))
        t)) 
 
 (defmethod perform ((o compile-op) (c clsql-mysql-source-file))
@@ -80,7 +80,7 @@
   :description "Common Lisp SQL MySQL Driver"
   :long-description "cl-sql-mysql package provides a database driver to the MySQL database system."
 
-  :depends-on (uffi clsql clsql-uffi)
+  :depends-on (cffi-uffi-compat clsql clsql-uffi)
   :components
   ((:module :db-mysql
            :components
diff --git a/clsql-uffi.asd b/clsql-uffi.asd
index e5a75f6..e78f09e 100644
--- a/clsql-uffi.asd
+++ b/clsql-uffi.asd
@@ -50,8 +50,8 @@
   nil) ;;; library will be loaded by a loader file
 
 (defmethod operation-done-p ((o load-op) (c clsql-uffi-source-file))
-  (and (symbol-function (intern (symbol-name '#:atol64)
-                               (find-package '#:clsql-uffi)))
+  (and (ignore-errors (symbol-function (intern (symbol-name '#:atol64)
+                                              (find-package '#:clsql-uffi))))
        t))
 
 (defmethod perform ((o compile-op) (c clsql-uffi-source-file))
@@ -79,7 +79,7 @@
   :description "Common UFFI Helper functions for Common Lisp SQL Interface Library"
   :long-description "cl-sql-uffi package provides common helper functions using the UFFI for the CLSQL package."
 
-  :depends-on (uffi clsql)
+  :depends-on (cffi-uffi-compat clsql)
 
   :components
   ((:module :uffi
diff --git a/clsql.asd b/clsql.asd
index 35e172a..51da309 100644
--- a/clsql.asd
+++ b/clsql.asd
@@ -26,8 +26,8 @@
 
 ;; need to load uffi for below perform :after method
 (eval-when (:compile-toplevel :load-toplevel :execute)
-  (unless (find-package 'uffi)
-    (asdf:operate 'asdf:load-op 'uffi)))
+  (unless (find-package 'cffi-uffi-compat)
+    (asdf:operate 'asdf:load-op 'cffi-uffi-compat)))
 
 (defsystem clsql
     :name "CLSQL"
diff --git a/uffi/clsql-uffi-package.lisp b/uffi/clsql-uffi-package.lisp
index be5abf5..153ca1f 100644
--- a/uffi/clsql-uffi-package.lisp
+++ b/uffi/clsql-uffi-package.lisp
@@ -19,7 +19,7 @@
 (in-package #:cl-user)
 
 (defpackage #:clsql-uffi
-  (:use #:cl #:uffi)
+  (:use #:cl #:cffi-uffi-compat)
   (:export
    #:find-and-load-foreign-library
    #:canonicalize-type-list

Stopping to look at the scenery

In working with old VW’s you end up looking at a lot of… old VW stuff. I assume this is true of most things you do, you end up looking at historical info to get an idea where to take the next step.

Sometimes this leads you to the most boring series of endless searches that yield nothing, but sometimes you luck out and find what your looking for and can even be pleasantly surprised along the way:


471155
stare

right

Interestingly enough I arrived at the reason why I was looking in these old brochures in the first place… the hose layout for my 1963 :)


left
right

It’s nice when you can get period correct info from a sources that are so inspiring. You can check out more at thesamba.com

American vs European Consumer Protection.

I subscribe to the bicycle frame builders mailing list and like most good mailing lists threads can go on forever and get mired in details or tangents. Occasionally things jump out at you as important and this post by Elliott McFadden did and I thought I’d pass it along:

I listened to a product liability attorney talk about the difference
between the American and European systems of consumer protection. In
America, we keep regulations relatively light and underfund enforcement
then let lawsuits do the real heavy lifting. In Europe, regulation is
higher and enforcement well staffed and financed while large lawsuits are
relatively rare.

As a citizen and a business owner, I’d rather have the European model. It
seems more predictable and less expensive in the long run. Plus
governments are usually the only ones with the resources and time to
regularly take on real abusers with deep pockets.

bus updates

It’s only fitting to give an update on today 9/20/10, which happens to be my bus’ 48th birthday.

To celebrate, I worked a bit on the headlight buckets.  This is the driver side bucket, which has some rust in a few areas due to the elements.  The rubber seals were very brittle and may have never been changed.  Now 48 years later it’ll get it’s “eyes” cleaned up and converted back to 6v sealed beams.  I’ll be painting tomorrow after work.

Updates can be followed on my photo stream on flickr.

Twisted spoke patterns

It is totally structurally unsound to do so, but man it looks cool:

I’ve thought of doing a few myself, but for a later time when I’m a more experienced wheel builder and I’d like some wall hangers.  Currently my most unorthodox builds have been a three leading / three trailing pattern on Mehran’s bike and a crow foot pattern on my Rebolledo track bike.

Franz mentioned on Dr Dobbs site

A lot of people ask about my day job at Franz and I usually have a rehearsed answer that goes something like this:

We work on a version of a programming language called Common Lisp and we have built tools on top of it. One of these tools is a database useful for studying complex data sets.

It would be cool to say something like “twitter” or “vimeo” and have instant recognition of my area of work, but with Franz you get a puzzled look and usually 10 minutes of back and forth to properly describe what we do.

With that confusion in mind I jumped to read this Dr. Dobbs interview with our CEO, Jans. I think to the technical people out there, some of this will make sense:

Dr. Dobbs interview with Jans Aasman of Franz Inc