Skip to content

Instantly share code, notes, and snippets.

@eparadis
Created January 5, 2022 02:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eparadis/54adcf08573416b4459a57fb1ca28a20 to your computer and use it in GitHub Desktop.
Save eparadis/54adcf08573416b4459a57fb1ca28a20 to your computer and use it in GitHub Desktop.
my Game of Life eurorack module. CircuitPython on an Adafruit QT Py
import random
import time
import board
import simpleio
from adafruit_ht16k33.matrix import Matrix8x8
import pwmio
import analogio
i2c = board.I2C()
matrix = Matrix8x8(i2c, auto_write=False)
pwm3 = pwmio.PWMOut(board.D3, variable_frequency=True)
pwm4 = pwmio.PWMOut(board.D6, variable_frequency=True)
a_out = analogio.AnalogOut(board.A0)
# C5 A4 G4 F4 D4 C4 A3 G3
notes = [ 523, 440, 392, 349, 294, 262, 220, 196 ]
clock = simpleio.DigitalIn(board.D1)
def apply_life_rule(old, new):
width = old.width
height = old.height
for y in range(height):
yyy = y * width
ym1 = ((y + height - 1) % height) * width
yp1 = ((y + 1) % height) * width
xm1 = width - 1
for x in range(width):
xp1 = (x + 1) % width
neighbors = (
old[xm1 + ym1] + old[xm1 + yyy] + old[xm1 + yp1] +
old[x + ym1] + old[x + yp1] +
old[xp1 + ym1] + old[xp1 + yyy] + old[xp1 + yp1])
new[x+yyy] = neighbors == 3 or (neighbors == 2 and old[x+yyy])
xm1 = x
def display(board):
for y in range(board.height):
yyy = y * board.width
for x in range(board.width):
matrix[x,y] = board[x+yyy]
matrix.show()
def randomize(output, fraction=0.33):
for i in range(output.height * output.width):
output[i] = random.random() < fraction
# our two boards/bitmaps
class Board:
def __init__(self):
self.width = 8
self.height = 8
self.data = bytearray(64)
def __getitem__(self, idx):
return self.data[idx]
def __setitem__(self, idx, val):
self.data[idx] = val
def blank(self):
return all(v == 0 for v in self.data)
def population(self):
pop = 0
for c in self.data:
if c:
pop += 1
return pop
def step_thru(board):
global last_beat_at
for beat in range(8):
while not clock.value:
pass
display(board)
high_note = -1
low_note = -1
for y in range(8):
yyy = y * 8
if board[beat+yyy] and high_note == -1:
high_note = y
if board[beat+yyy]:
low_note = y
matrix[beat, y] = not board[beat+yyy]
matrix.show()
elapsed = now() - last_beat_at
#while(elapsed < 2500):
# elapsed = now() - last_beat_at
while clock.value:
pass
last_beat_at = now()
if low_note != -1: # and low_note > 3:
play_low_note(low_note)
else:
quiet_low_note()
if high_note != -1: # and high_note <= 3:
play_high_note(high_note)
else:
quiet_high_note()
def now():
return int(time.monotonic()*10000)
def play_high_note(note):
pwm3.frequency = notes[note]
pwm3.duty_cycle = 0x1000
def play_low_note(note):
pwm4.frequency = notes[note]
pwm4.duty_cycle = 0x8000
def quiet_high_note():
pwm3.duty_cycle = 0x0
def quiet_low_note():
pwm4.duty_cycle = 0x0
matrix.brightness = 0.1
b1 = Board()
b2 = Board()
randomize(b1)
last_beat_at = now()
stag_count = 0
max_pop = 0
while True:
step_thru(b1)
apply_life_rule(b1,b2)
step_thru(b2)
apply_life_rule(b2, b1)
b1p = b1.population()
b2p = b2.population()
clamped = b1p
if clamped > 33:
clamped = 33
scaled = (float(clamped) * 65535.0) / 33.0
a_out.value = int(scaled)
max_pop = max(b1p, max_pop)
print("population: ", b1p, " historical max: ", max_pop, " a_out: ", scaled)
if b1p == b2p: #and b1p < 5:
stag_count += 1
print("small pop stagnent: ", b1.population(), " for ", stag_count)
if stag_count == 4:
print("repopulating!")
randomize(b1)
stag_count = 0
else:
stag_count = 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment