Toggle Navigation
TiDAL Hatchery
Eggs
Euclidean Tides
__init__.py
Users
Badges
Login
Register
__init__.py
raw
Content
from app import TextApp from machine import Pin import tidal import vga2_bold_16x32 as font def euclid_rhythm(n,k): if k > n: n,k = k,n seq = [[True] for i in range(k)] + [[False] for j in range(n-k)] popped = True while seq[-1] == seq[-2] and popped: # Are there multiple copies of the same sequence at the end? popped = False last = seq[-1] for item in seq: if item == last: break # Run out of things to tack the sequence on to... else: if seq[-1] == last: item += seq.pop() popped = True else: break # Run out of copies of the sequence. while True: for chunk in seq: yield from chunk class EuclidApp(TextApp): par_names = [ 'chan A 0', 'chan A 1', 'chan A 2', 'chan B 0', 'chan B 1', 'chan B 2', 'tempo' ] tempo = [75, 125, 250, 375, 500] def on_start(self): super().on_start() self.pins = [ Pin(18, Pin.OUT), Pin(17, Pin.OUT), Pin(2, Pin.OUT), Pin(5, Pin.OUT) ] self.buttons.on_press(tidal.JOY_LEFT, self.prev_par) self.buttons.on_press(tidal.JOY_RIGHT, self.next_par) self.buttons.on_press(tidal.JOY_UP, self.par_up) self.buttons.on_press(tidal.JOY_DOWN, self.par_down) self.buttons.on_press(tidal.JOY_CENTRE, self.toggle_pause) self.pars = [[5, 13, 11], [11, 13, 17]] self.seq = [[[], []], [[], []]] self.selected_par = 0 self.selected_tempo = 2 self.paused = False self.init_seq(0) self.init_seq(1) def on_activate(self): super().on_activate() self.pulse = self.periodic(250, self.seq_step) tidal.led_power_on() self.update_display() def on_deactivate(self): super().on_deactivate() self.pulse.cancel() tidal.led_power_off() def init_seq(self, chan): pars_1 = self.pars[chan][0:2] pars_2 = self.pars[chan][1:] if all([par > 0 for par in pars_1 + pars_2]): self.seq[chan][0] = euclid_rhythm(*pars_1) self.seq[chan][1] = euclid_rhythm(*pars_1) def seq_step(self): if not self.paused: p0 = self.seq[0][0].__next__() p1 = self.seq[0][1].__next__() p2 = self.seq[1][0].__next__() p3 = self.seq[1][1].__next__() self.pins[0].value(p0) self.pins[1].value(p1) self.pins[2].value(p2) self.pins[3].value(p3) red = 64 * p0 + 128 * p1 green = 64 * p1 + 128 * p2 blue = 64 * p2 + 128 * p3 tidal.led[0] = (red, green, blue) tidal.led.write() def next_par(self): self.selected_par = (self.selected_par + 1) % 7 self.update_display() def prev_par(self): self.selected_par = (self.selected_par - 1) % 7 self.update_display() def par_up(self): self.par_delta(1) def par_down(self): self.par_delta(-1) def toggle_pause(self): self.paused = not self.paused def par_chan(self): if self.selected_par < 6: if self.selected_par < 3: chan = 0 par = self.selected_par else: chan = 1 par = self.selected_par - 3 return (par, chan) else: return (6, None) def par_delta(self, delta): par, chan = self.par_chan() if not chan is None: self.pars[chan][par] += delta self.init_seq(chan) else: self.selected_tempo = (self.selected_tempo + delta) % 5 self.pulse.cancel() self.pulse = self.periodic(self.tempo[self.selected_tempo], self.seq_step) self.update_display() def update_display(self): tidal.display.fill(tidal.BLACK) tidal.display.text(font, self.par_names[self.selected_par], 0, 20, tidal.WHITE, tidal.BLACK) par, chan = self.par_chan() if not chan is None: tidal.display.text(font, str(self.pars[chan][par]), 0, 50, tidal.WHITE, tidal.BLACK) else: tidal.display.text(font, str(self.tempo[self.selected_tempo])+'ms', 0, 50, tidal.WHITE, tidal.BLACK) main = EuclidApp