# The Technocolour Dreamcoat, phone-free Burning Man 2023 edition!

**URL:** <https://forum.electromage.com/t/the-technocolour-dreamcoat-phone-free-burning-man-2023-edition/3115>\
**Category:** Show and Tell\
**Created:** [August 15, 2023, 2:42pm UTC](https://forum.electromage.com/t/the-technocolour-dreamcoat-phone-free-burning-man-2023-edition/3115 "2023-08-15T14:42:59Z")\
**Posts on this page:** 1\
**Showing post:** 3

<div class="post-metadata">

**Author:** ![ratkins](https://forum.electromage.com/user_avatar/forum.electromage.com/ratkins/32/3035_2.png) [@ratkins](https://forum.electromage.com/u/ratkins)\
**Post date:** [August 15, 2023, 4:08pm UTC](https://forum.electromage.com/t/the-technocolour-dreamcoat-phone-free-burning-man-2023-edition/3115/3 "2023-08-15T16:08:47Z")

</div>

Well, sure. Here’s the code:

```auto
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:

 ![tempImageyX8mGl](https://forum.electromage.com/uploads/default/original/2X/7/7ffba378822ccb91864a9a3b55f69d3b55bc35fa.jpeg)  
 ![tempImageP6nSqh](https://forum.electromage.com/uploads/default/original/2X/b/b62c6fbf904e43534e646129af7762595ba83916.jpeg)  
 ![tempImage1T2t8O](https://forum.electromage.com/uploads/default/original/2X/4/4f43b8dc2f265fb9381dfe2931bf5fe18e0c4c01.jpeg)

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 :).

---

_[View the full topic](https://forum.electromage.com/t/the-technocolour-dreamcoat-phone-free-burning-man-2023-edition/3115)._
