How to create a Launchpad Mini digital clock using Node.js
Tags: node, typescript, raspberrypi
Published: 2023-03-04 20:32:44

The Launchpad Mini is a MIDI controller with 8x8 buttons that can be used to trigger clips, play notes, and control various software applications. One fun project you can do with the Launchpad Mini is to turn it into a digital clock. This project uses NodeJS and the [midi-stream npm package](https://www.npmjs.com/package/midi-stream) to communicate with the device.

In this blog post, I will outline the steps I took and problems I encountered.



![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s74c9wamdxodoe14hz8d.jpg)

## Test the clock for yourself

Before we get started, make sure you have the following:

- A Launchpad Mini device
- NodeJS installed on your computer

### Step 1: Setting up the project

- Clone the [Launchpad Clock repo](https://github.com/digglp/LaunchpadClock)
- Install the project with `npm install`

### Step 2: Execute the program

- Execute the project with `npx ts-node src/application/console.ts`


![Select a port (running on Raspberry Pi)](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/tvz1s8u2b8rn6e3ida6a.png)


## Building the clock

To start, I began by setting up a series of tests to ensure that I could successfully illuminate the individual buttons. From there, I developed a basic JavaScript application to explore concepts such as colour mapping and data mapping from the launchpad to a grid.

	var MidiStream = require("midi-stream");
	//https://www.youtube.com/watch?v=JatNuVsbsEQ
	
	var duplex = MidiStream("Launchpad Mini");
	
	duplex.write([176, 0, 0]); //clear all
	//duplex.pipe(duplex);
	duplex.on("data", function (data) {
	  console.log(data);
	  //console.log(mapToGrid(data[1]));
	
	  //buttons across top 104 - 111
	  //botton down right 8,24,40,56,72,88,104,120
	
	  play(mapToGrid(data[1]).row, mapToGrid(data[1]).col, randomVelocity());
	});
	
	const play = (row, col, velocity, delay) => {
	  var note = mapToMidi(row, col);
	
	  setTimeout(() => {
	    duplex.write([144, note, velocity]);
	  }, delay || 0);
	};
	
	const mapToGrid = (data) => {
	  const row = Math.floor(data / 16);
	  const col = data % 8;
	  return { row, col };
	};
	const mapToMidi = (row, col) => {
	  return row * 16 + col;
	};
	const randomVelocity = () => {
	  return Math.floor(Math.random() * 100);
	};

When configuring a button on the MIDI interface, an array of values is sent to specify the desired behavior. For instance, `stream.write([176,0,0])` may be used to turn a button off, while `stream.write([144,0,3])` would turn it on. The first value in the array indicates the desired state, with 176 indicating "switch off" and 144 indicating "switch on." The second value corresponds to the specific button being configured, and while it took a bit of experimentation to fully grasp the mapping between numbers and buttons, I eventually got the hang of it. Finally, the third value specifies the colour of the button, and again, some testing was necessary to understand the relationship between values and colours.


![Grid Layout](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8ymhtyvdevb33siq3b0t.png)

The codebase was loosely designed with the hexagonal architecture in mind, featuring three primary components:

Application - This component is responsible for starting the clock application.
Domain - Here, the domain objects manage the bulk of the application's functionality.
Infrastructure - Finally, the infrastructure component handles external entities, such as the low-level code for the Launchpad Mini.
Of all the unit tests, the GridManager tests were the most vital. These tests validated that the grid correctly maps to the MIDI call, ensuring proper operation of the clock.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eydknty0q4nmc4orkvov.PNG)

In summary, this project was an enjoyable endeavour that allowed me to breathe new life into an old device. I've even gone so far as to install the application on a Raspberry Pi, where it runs 24/7 and serves as a stylish and functional decoration for my desk.