As demonstrated in the video, the primary method of interacting with the sequencer is through the NeoTrellis array. After much refinement, I settled on allowing the user to do a very basic 8-step sequence without needing to interact with anything except the array itself.
There is a potentiometer that is used to change the velocity of a selected note, which is indicated by the note blinking.
There are 4 buttons to the left of that that act as a "directional pad" for the array, which allows "banking" up and down to access all 16 tracks, and "scrolling" left to right to access up to 32 steps, since the arrays are costly to build a 16x32 array. However, after workshopping the sequencer with some testers, I realized that the "banking" and "scrolling" is not a very approachable UX. Therefore, the default sequence length is 8 steps so it fits on one array, the user does not need to deal with any banking/scrolling right away.
To the left of that, you will find two buttons that increment and decrement the tempo by 5bpm. The default project tempo is 120bpm, to follow the standard set by most midi sequencers.
The leftmost pushbutton allows the user to change the project length. Upon pressing the button, the trellis will light up a pixel for each step in the project, and the user can use the left or down button to decrease project length by 1 step down to 2 steps, and use the right or up button to increase project length by 1 step up to 32 steps.
All the way to the left is an audio jack, which can be used for audio output of the sequencer using the Teensy Audio Library drum synthesizer. However, at the moment I have not gotten around to programming all the values, so all the drums mostly sound the same.
Some things I learned along the way:
Memory Management: Don't bother getting fancy with the data structures on a Teensy, even with my massive project I only use about 3% of the runtime memory on the Teensy 3.5. However, optimize, optimize, optimize.
Analog Ground: My audio output was extremely noisy when I first connected it, and the noise would change as the NeoTrellis changed its display. However, when Professor Litt connected the audio output ground to analog ground instead of my regular ground, that completely solved the issue. When doing the lab with Teensy Audio Libraries, we did not experience noise from the typical Teensy ground.
Some drawbacks:
Processing Power: I programmed all of my dream features into the device, and then immediately got decimated by the limited processing power of the Teensy. For example, I had a system to sync the unit to an incoming MIDI signal from a DAW, however, this system only operated properly when I disabled almost every other feature of the device, as MIDI sends 24 clock pulses per beat, and at 120BPM that becomes 48 clock signals per second, which the Teensy cannot process gracefully while simultaneously generating audio and MIDI for a sequencer and drawing the Trellis every step.
EEPROM: I'm not sure if it is just my Teensy, but the EEPROM is noisy. I ran some stress tests where I wrote 4096 values to the EEPROM and then read them out after a complete power cycle, and on nearly every test there would be inaccurate values. Errors within my usage were limited, as it would only disturb only a few "notes". However, errors that change the tempo or project length values are typically fatal for the proper operation of the sequencer, so they have been disabled for now. I have a tentative future plan to write the saved information multiple times (I think 3) and using the extra copies of the saved information for error-correction. The Teensy 3.5 has 4096 bytes, I need 514 bytes to save the information to restore the users "project".
The Hardware:
The hardware side of this project is fairly simple: A 4x8 NeoTrellis array that connects over I2C. The NeoTrellis was great to work with, as it includes event handlers for all of its buttons which greatly simplified programming. For the other buttons, I used my own ShaneButton button handling class- I did not implement event handlers in that class and instead just used a boolean value representing ifthe button is currently pushed, which allowed me to change the function of the buttons depending on where I am in the program control.
There is a small handful of pushbuttons and a potentiometer on the breadboard that allow the user to interact with some other settings.
There is also a headphone jack for audio output.
The Software:
If you're interested in the software that powers this thing, the 706-line source is available on my GitHub.
I tried to write the software as flexible as possible, and be moderately conscious of memory usage. After the first 68 lines of variable definitions, there are very very very few hardcoded values. This way, a change to a default value or pin location, or even the size of the NeoTrellis being used can be adjusted in the constants and the program will function without changing any other code.