Well, sure. Here’s the code:
export function beforeRender(delta) {
// ...
// enable next/forward buttons
debounceNext(delta)
debouncePrev(delta)
}
export var analogInputs
var DEBOUNCE_TIME = 40;
var nextBtnState;
var nextBtnTimer;
function debounceNext(delta) {
var newState = analogInputs[2] > 0.5;
if (newState == nextBtnState) {
nextBtnTimer = 0;
} else {
nextBtnTimer += delta;
}
if (nextBtnTimer > DEBOUNCE_TIME) {
nextBtnState = newState;
if (nextBtnState) {
sequencerNext();
}
}
}
var prevBtnState;
var prevBtnTimer;
function debouncePrev(delta) {
var newState = analogInputs[1] > 0.5;
if (newState == prevBtnState) {
prevBtnTimer = 0;
} else {
prevBtnTimer += delta;
}
if (prevBtnTimer > DEBOUNCE_TIME) {
prevBtnState = newState;
if (prevBtnState) {
sequencerPrev();
}
}
}
export function sequencerPrev() {
var p = playlistGetPosition() - 1;
p = mod(p, playlistGetLength());
playlistSetPosition(p);
}
(But note in the other thread I could clean up this duplication a bit by putting the state/timer/action variables in arrays.)
This is what the control box hardware looks like:
I’ve basically got a little board with the buttons mounted on it, plugged in to the analogue inputs of the sensor expansion board with a bodged-up connector made out of a right-angle header socket. The board has resistors that pull the button outputs down to ground (er, not in that picture though, that’s pre-fixing them to pull the correct pins down.) The pot is connected to another analogue input.
I read the button state and call the prev/next functions as per the code above and I’ve had to modify every pattern to multiply the brightness by analogInputs[0] (to which the pot’s wiper is connected.) Either rgb(r * analogInputs[0], g * analogInputs[0], b * analogInputs[0]); or hsv(h, s, v * analogInputs[0]).
And that’s about it! I’m planning on doing a bigger post on my blog about the build, but that’s going to have to wait until I’m back from the Burn :).


