LFO patch

This commit is contained in:
Mikayla Dobson
2023-04-12 17:01:07 -05:00
parent 4c91814545
commit 338b0756c8
2 changed files with 92 additions and 50 deletions

22
MCP3008.py Normal file
View File

@@ -0,0 +1,22 @@
import machine
# adapted from MCCP3008 class by @romilly, which was adapted from Adafruit CircuitPython driver
# source: https://github.com/romilly/pico-code/blob/master/src/pico_code/pico/mcp3008/mcp3008.py
class MCP3008:
def __init__(self, spi: machine.SPI, chip_select: machine.Pin, ref_voltage=3.3):
self.chip_select = chip_select
self.chip_select.value(1)
self._spi = spi
self._out_buffer = bytearray(3)
self._out_buffer[0] = 0x01
self._in_buffer = bytearray(3)
self._ref_voltage = ref_voltage
def get_voltage(self):
return self._ref_voltage
def read(self, pin):
self.chip_select.value(0)
self._out_buffer[1] = pin << 4
self._spi

120
main.py
View File

@@ -1,21 +1,8 @@
# PICOSYNTH from machine import Pin, ADC, PWM, SPI
# open source semi-modular synthesizer model
# developer: Mikayla Dobson
# github: github.com/innocuous-symmetry
""" " " " " " " " " " " " " " " " " " " " " " "
IMPORTS
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ """
from machine import Pin, ADC, PWM
from random import randint from random import randint
from math import floor, ceil from math import floor, ceil
from time import sleep from time import sleep
""" " " " " " " " " " " " " " " " " " " " " " "
CONSTANTS
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ """
__SYSTEM_PWM_FREQUENCY__ = 1000 __SYSTEM_PWM_FREQUENCY__ = 1000
HIGH = 65535 HIGH = 65535
@@ -93,9 +80,6 @@ SYNTH_CONFIG = {
} }
} }
""" " " " " " " " " " " " " " " " " " " " " " "
INDEPENDENT FUNCTIONS FOR TESTING, COMMON USE CASES
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ """
def blink(controller: type[ADC], target=Pin(25, Pin.OUT), sleep_duration = 1000): def blink(controller: type[ADC], target=Pin(25, Pin.OUT), sleep_duration = 1000):
if not controller: pass if not controller: pass
@@ -112,9 +96,17 @@ def blink(controller: type[ADC], target=Pin(25, Pin.OUT), sleep_duration = 1000)
target.value(0) target.value(0)
sleep(modulated_sleep) sleep(modulated_sleep)
# convert input from -1 to 1 range, to u16
def polar_to_u16(input: float) -> int:
return floor((input + 1) * 32767.5)
# convert input from u16 to -1 to 1 range
def u16_to_polar(input: int) -> float:
return (input / 32767.5) - 1
""" " " " " " " " " " " " " " " " " " " " " " " """ " " " " " " " " " " " " " " " " " " " " " "
" CLASS DEFINITIONS FOR BASIC HARDWARE BEHAVIORS " BEGIN CLASS DEFINITIONS FOR BASIC HARDWARE BEHAVIORS
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ """ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ """
# for representing and interacting with waveform data # for representing and interacting with waveform data
@@ -172,29 +164,48 @@ class DigitalOut:
def read(self): def read(self):
return self.PIN.value() return self.PIN.value()
"""
DEFINITIONS FOR HARDWARE PERIPHERALS
"""
# adapted from MCCP3008 class by @romilly, which was adapted from Adafruit CircuitPython driver
# source: https://github.com/romilly/pico-code/blob/master/src/pico_code/pico/mcp3008/mcp3008.py
class MCP3008:
def __init__(self, spi: SPI, chip_select: Pin, ref_voltage=3.3):
self.chip_select = chip_select
self.chip_select.value(1)
self._spi = spi
self._out_buffer = bytearray(3)
self._out_buffer[0] = 0x01
self._in_buffer = bytearray(3)
self._ref_voltage = ref_voltage
def get_voltage(self):
return self._ref_voltage
def read(self, pin):
self.chip_select.value(0)
self._out_buffer[1] = pin << 4
self._spi.write_readinto(self._out_buffer, self._in_buffer)
self.chip_select.value(1) # turn off
return ((self._in_buffer[1] & 0x03) << 8) | self._in_buffer[2]
class Oscillator: class Oscillator:
def __init__(self, waveform = 'sine', tick_interval_ms: int = 35, current_tick: int = 0) -> None: def __init__(self, waveform = 'sine', downsampling: int = 0, current_tick: int = 0) -> None:
self.tick_interval_ms = ceil(tick_interval_ms)
self.waveform = waveform if waveform in WAVEFORMS else None self.waveform = waveform if waveform in WAVEFORMS else None
self.downsampling = downsampling
self.current_tick = current_tick self.current_tick = current_tick
self.value = 0 self.value = 0
def step(self): def out(self):
current_step = SINE_WAVE[self.current_tick]
self.current_tick = self.current_tick + 1 if self.current_tick + 1 < len(SINE_WAVE) else 0
sleep(self.tick_interval_ms / 1000)
return current_step
def out(self, cb):
if (self.waveform is 'square'): if (self.waveform is 'square'):
self.value = not self.value self.value = not self.value
pass
else: else:
current_step = SINE_WAVE[self.current_tick] current_step = SINE_WAVE[floor(self.current_tick)]
self.current_tick = current_step + 1 if current_step + 1 < len(SINE_WAVE) else 0 interval = self.downsampling if self.downsampling > 0 else 1
self.current_tick = self.current_tick + interval if self.current_tick + interval < len(SINE_WAVE) else 0
sleep(self.tick_interval_ms / 1000) return current_step
return self.out(cb)
class Synthesizer: class Synthesizer:
# PIN CONFIGURATION # PIN CONFIGURATION
@@ -243,26 +254,35 @@ class Synthesizer:
def __init__(self, config): def __init__(self, config):
self.config = config self.config = config
""" " " " " " " " " " " " " " " " " " " " " " "
SYNTHESIZER DEFINITION AND PIN/COMPONENT ASSIGNMENTS
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ """
gate_out = PWMOutput(15, 0) gate_out = PWMOutput(15, 0)
voct_out = PWMOutput(16, 0) voct_out = PWMOutput(16, 0)
# spi = SPI(0, sck=Pin(2), mosi=Pin(3), miso=Pin(4), baudrate=100_000)
# chip_select = Pin(22, Pin.OUT)
# chip_select.value(1)
""" " " " " " " " " " " " " " " " " " " " " " " # square = Pin(21, Pin.OUT)
START # mcp = MCP3008(spi, chip_select)
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ """
while True: cv_one = PWMOutput(16)
random_value = VOCT_PITCH_VALUES[randint(0, len(VOCT_PITCH_VALUES) - 1)] * 65535 led_one = PWMOutput(17)
print(int(random_value))
print('go')
gate_out.set_duty(65535) pot = Potentiometer(0)
voct_out.set_duty(int(random_value))
sleep(0.25) osc = Oscillator('sine', 32)
gate_out.set_duty(0)
sleep(1.5) timer = 1
sleep_interval = 0.01
try:
while True:
current_step = polar_to_u16(osc.out())
led_one.set_duty(current_step)
cv_one.set_duty(current_step)
sleep(0.001 + (pot.read_polar() / 32))
except KeyboardInterrupt:
print("Exiting program...")
led_one.set_duty(0)
cv_one.set_duty(0)