   assigned device ID if the identity is correct, or logs an error and
   returns nil if it is not."
   [port-in port-out]
-  (let [ident (controllers/identify port-in port-out)]
-    (if (= (take 5 (drop 4 (:data ident))) '(0 32 41 54 0))
-      (aget (:data ident) 1)
+  (let [ident-msg (controllers/identify port-in port-out)
+        ident (take 5 (drop 4 (:data ident-msg)))]
+    (if (or (= ident '(0 32 41 54 0))   ; Launchpad Mini
+            (= ident '(0 32 41 32 0)))  ; Launchpad S
+      (aget (:data ident-msg) 1)
       (timbre/error "Device does not identify as a Launchpad Mini:" port-in))))
 
 (defn bind-to-show

  (when (not= origin @(:origin controller))
    (reset! (:origin controller) origin)
    (doseq [f @(:move-listeners controller)] (f @(:grid-controller-impl controller) :moved))))

(defn clear-interface
  "Clears all illuminated buttons and pads."

  the main interface update thread, and terminate the task running the
  animation."
  [controller counter task]
  (let [gradient [0x3c 0x3e 0x3f 0x2f 0x1f 0x0f 0x0e 0x0d]]
    (try
      (cond
        (< @counter 8)
        (doseq [y (range 0 (inc @counter))]
          (let [color (gradient (- @counter y))]
            (set-pad-color controller 3 y color)
            (set-pad-color controller 4 y color)))

        (< @counter 12)
        (doseq [x (range 0 (- @counter 7))
                y (range 0 8)]
          (let [color (gradient (- @counter 8 x))]
            (set-pad-color controller (- 3 x) y color)
            (set-pad-color controller (+ 4 x) y color)))

        (= @counter 12)
        (show-round-buttons controller 0x3e)

        (= @counter 20)
        (show-round-buttons controller 0x1f)

        (< @counter 29)
        (doseq [x (range 0 8)]
          (set-pad-color controller x (- 28 @counter) button-off-color))

        :else
        (do
          (start-interface controller)
          (at-at/kill @task)))
      (catch Throwable t
        (warn t "Animation frame failed"))))

  (swap! counter inc))

