LFO patch
This commit is contained in:
22
MCP3008.py
Normal file
22
MCP3008.py
Normal 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
120
main.py
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user