more class definitions
This commit is contained in:
111
MCP3008.py
111
MCP3008.py
@@ -1,22 +1,105 @@
|
|||||||
|
"""
|
||||||
|
MicroPython Library for MCP3008 8-channel ADC with SPI
|
||||||
|
|
||||||
|
Datasheet for the MCP3008: https://www.microchip.com/datasheet/MCP3008
|
||||||
|
|
||||||
|
This code makes much use of Adafruit's CircuitPython code at
|
||||||
|
https://github.com/adafruit/Adafruit_CircuitPython_MCP3xxx
|
||||||
|
adapted for MicroPython.
|
||||||
|
|
||||||
|
Tested on the Raspberry Pi Pico.
|
||||||
|
|
||||||
|
Thanks, @Raspberry_Pi and @Adafruit, for all you've given us!
|
||||||
|
"""
|
||||||
|
|
||||||
import machine
|
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)
|
|
||||||
|
|
||||||
|
class MCP3008:
|
||||||
|
|
||||||
|
def __init__(self, spi, cs, ref_voltage=3.3):
|
||||||
|
"""
|
||||||
|
Create MCP3008 instance
|
||||||
|
|
||||||
|
Args:
|
||||||
|
spi: configured SPI bus
|
||||||
|
cs: pin to use for chip select
|
||||||
|
ref_voltage: r
|
||||||
|
"""
|
||||||
|
self.cs = cs
|
||||||
|
self.cs.value(1) # ncs on
|
||||||
self._spi = spi
|
self._spi = spi
|
||||||
self._out_buffer = bytearray(3)
|
self._out_buf = bytearray(3)
|
||||||
self._out_buffer[0] = 0x01
|
self._out_buf[0] = 0x01
|
||||||
self._in_buffer = bytearray(3)
|
self._in_buf = bytearray(3)
|
||||||
self._ref_voltage = ref_voltage
|
self._ref_voltage = ref_voltage
|
||||||
|
|
||||||
def get_voltage(self):
|
def reference_voltage(self) -> float:
|
||||||
|
"""Returns the MCP3xxx's reference voltage as a float."""
|
||||||
return self._ref_voltage
|
return self._ref_voltage
|
||||||
|
|
||||||
def read(self, pin):
|
def read(self, pin, is_differential=False):
|
||||||
self.chip_select.value(0)
|
"""
|
||||||
self._out_buffer[1] = pin << 4
|
read a voltage or voltage difference using the MCP3008.
|
||||||
self._spi
|
|
||||||
|
Args:
|
||||||
|
pin: the pin to use
|
||||||
|
is_differential: if true, return the potential difference between two pins,
|
||||||
|
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
voltage in range [0, 1023] where 1023 = VREF (3V3)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.cs.value(0) # select
|
||||||
|
self._out_buf[1] = ((not is_differential) << 7) | (pin << 4)
|
||||||
|
self._spi.write_readinto(self._out_buf, self._in_buf)
|
||||||
|
self.cs.value(1) # turn off
|
||||||
|
return ((self._in_buf[1] & 0x03) << 8) | self._in_buf[2]
|
||||||
|
|
||||||
|
# And here's the code for the loop-back test.
|
||||||
|
from machine import Pin, SPI
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
spi = SPI(0, sck=Pin(2),mosi=Pin(3),miso=Pin(4), baudrate=100000)
|
||||||
|
cs = Pin(22, Pin.OUT)
|
||||||
|
cs.value(1) # disable chip at start
|
||||||
|
|
||||||
|
chip = MCP3008(spi, cs)
|
||||||
|
|
||||||
|
def loop():
|
||||||
|
cv_one = chip.read(0)
|
||||||
|
cv_two = chip.read(1)
|
||||||
|
cv_three = chip.read(2)
|
||||||
|
|
||||||
|
print(f"input one: {cv_one}, input two: {cv_two}, input three: {cv_three}")
|
||||||
|
|
||||||
|
sleep(0.01)
|
||||||
|
|
||||||
|
cv_one = chip.read(0)
|
||||||
|
cv_two = chip.read(1)
|
||||||
|
cv_three = chip.read(2)
|
||||||
|
|
||||||
|
print(f"input one: {cv_one}, input two: {cv_two}, input three: {cv_three}")
|
||||||
|
|
||||||
|
sleep(0.01)
|
||||||
|
|
||||||
|
|
||||||
|
class Module(MCP3008):
|
||||||
|
def __init__(self, module_function, spi, cs, ref_voltage=3.3):
|
||||||
|
super().__init__(spi, cs, ref_voltage)
|
||||||
|
self.module_function = module_function
|
||||||
|
|
||||||
|
def read_all(self):
|
||||||
|
return {
|
||||||
|
'pot_one': self.read(0),
|
||||||
|
'pot_two': self.read(1),
|
||||||
|
'pot_three': self.read(2),
|
||||||
|
'pot_four': self.read(3),
|
||||||
|
'cv_in_one': self.read(4),
|
||||||
|
'cv_in_two': self.read(5),
|
||||||
|
'cv_in_three': self.read(6),
|
||||||
|
'cv_in_four': self.read(7)
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
229
main.py
229
main.py
@@ -1,7 +1,7 @@
|
|||||||
from machine import Pin, ADC, PWM, SPI
|
from machine import Pin, ADC, PWM, SPI
|
||||||
|
from utime import sleep
|
||||||
from random import randint
|
from random import randint
|
||||||
from math import floor, ceil
|
from math import floor, ceil
|
||||||
from time import sleep
|
|
||||||
|
|
||||||
__SYSTEM_PWM_FREQUENCY__ = 1000
|
__SYSTEM_PWM_FREQUENCY__ = 1000
|
||||||
|
|
||||||
@@ -118,6 +118,25 @@ class Hertz:
|
|||||||
self.tick_freq = self.ONE_HERTZ * hz
|
self.tick_freq = self.ONE_HERTZ * hz
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
class Oscillator:
|
||||||
|
def __init__(self, waveform = 'sine', downsampling: int = 0, current_tick: int = 0) -> None:
|
||||||
|
self.waveform = waveform if waveform in WAVEFORMS else None
|
||||||
|
self.downsampling = downsampling
|
||||||
|
self.current_tick = current_tick
|
||||||
|
self.value = 0
|
||||||
|
|
||||||
|
def out(self):
|
||||||
|
if (self.waveform is 'square'):
|
||||||
|
self.value = not self.value
|
||||||
|
else:
|
||||||
|
current_step = SINE_WAVE[floor(self.current_tick)]
|
||||||
|
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
|
||||||
|
return current_step
|
||||||
|
|
||||||
|
def out_u16(self):
|
||||||
|
return polar_to_u16(self.out())
|
||||||
|
|
||||||
# basic set of analog input behaviors
|
# basic set of analog input behaviors
|
||||||
class AnalogInput:
|
class AnalogInput:
|
||||||
def __init__(self, ADC_PIN):
|
def __init__(self, ADC_PIN):
|
||||||
@@ -168,121 +187,145 @@ class DigitalOut:
|
|||||||
DEFINITIONS FOR HARDWARE PERIPHERALS
|
DEFINITIONS FOR HARDWARE PERIPHERALS
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# adapted from MCCP3008 class by @romilly, which was adapted from Adafruit CircuitPython driver
|
# 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
|
# source: https://github.com/romilly/pico-code/blob/master/src/pico_code/pico/mcp3008/mcp3008.py
|
||||||
class MCP3008:
|
class MCP3008:
|
||||||
def __init__(self, spi: SPI, chip_select: Pin, ref_voltage=3.3):
|
def __init__(self, spi, cs, ref_voltage=3.3):
|
||||||
self.chip_select = chip_select
|
"""
|
||||||
self.chip_select.value(1)
|
Create MCP3008 instance
|
||||||
|
|
||||||
|
Args:
|
||||||
|
spi: configured SPI bus
|
||||||
|
cs: pin to use for chip select
|
||||||
|
ref_voltage: r
|
||||||
|
"""
|
||||||
|
self.cs = cs
|
||||||
|
self.cs.value(1) # ncs on
|
||||||
self._spi = spi
|
self._spi = spi
|
||||||
self._out_buffer = bytearray(3)
|
self._out_buf = bytearray(3)
|
||||||
self._out_buffer[0] = 0x01
|
self._out_buf[0] = 0x01
|
||||||
self._in_buffer = bytearray(3)
|
self._in_buf = bytearray(3)
|
||||||
self._ref_voltage = ref_voltage
|
self._ref_voltage = ref_voltage
|
||||||
|
|
||||||
def get_voltage(self):
|
def reference_voltage(self) -> float:
|
||||||
|
"""Returns the MCP3xxx's reference voltage as a float."""
|
||||||
return self._ref_voltage
|
return self._ref_voltage
|
||||||
|
|
||||||
def read(self, pin):
|
def read(self, pin, is_differential=False):
|
||||||
self.chip_select.value(0)
|
"""
|
||||||
self._out_buffer[1] = pin << 4
|
read a voltage or voltage difference using the MCP3008.
|
||||||
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:
|
Args:
|
||||||
def __init__(self, waveform = 'sine', downsampling: int = 0, current_tick: int = 0) -> None:
|
pin: the pin to use
|
||||||
self.waveform = waveform if waveform in WAVEFORMS else None
|
is_differential: if true, return the potential difference between two pins,
|
||||||
self.downsampling = downsampling
|
|
||||||
self.current_tick = current_tick
|
|
||||||
self.value = 0
|
|
||||||
|
|
||||||
def out(self):
|
|
||||||
if (self.waveform is 'square'):
|
Returns:
|
||||||
self.value = not self.value
|
voltage in range [0, 1023] where 1023 = VREF (3V3)
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
self.cs.value(0) # select
|
||||||
|
self._out_buf[1] = ((not is_differential) << 7) | (pin << 4)
|
||||||
|
self._spi.write_readinto(self._out_buf, self._in_buf)
|
||||||
|
self.cs.value(1) # turn off
|
||||||
|
return ((self._in_buf[1] & 0x03) << 8) | self._in_buf[2]
|
||||||
|
|
||||||
|
|
||||||
|
class Module:
|
||||||
|
def __init__(self, mcp3008: MCP3008, out_one: int, out_two: int):
|
||||||
|
self.chip = mcp3008
|
||||||
|
self.cv_out_one = PWMOutput(out_one)
|
||||||
|
self.cv_out_two = PWMOutput(out_two)
|
||||||
|
|
||||||
|
def cleanup(self):
|
||||||
|
self.cv_out_one.set_duty(0)
|
||||||
|
self.cv_out_two.set_duty(0)
|
||||||
|
|
||||||
|
def read_one(self, pin: int):
|
||||||
|
return self.chip.read(pin)
|
||||||
|
|
||||||
|
def read_all(self):
|
||||||
|
return {
|
||||||
|
'pot_one': chip.read(0),
|
||||||
|
'pot_two': chip.read(1),
|
||||||
|
'pot_three': chip.read(2),
|
||||||
|
'pot_four': chip.read(3),
|
||||||
|
'cv_in_one': chip.read(4),
|
||||||
|
'cv_in_two': chip.read(5),
|
||||||
|
'cv_in_three': chip.read(6),
|
||||||
|
'cv_in_four': chip.read(7)
|
||||||
|
}
|
||||||
|
|
||||||
|
def loop(self, sleep_interval=0.01, function=None):
|
||||||
|
if function:
|
||||||
|
function()
|
||||||
else:
|
else:
|
||||||
current_step = SINE_WAVE[floor(self.current_tick)]
|
print()
|
||||||
interval = self.downsampling if self.downsampling > 0 else 1
|
# convert to u16
|
||||||
self.current_tick = self.current_tick + interval if self.current_tick + interval < len(SINE_WAVE) else 0
|
# cv_in_value = self.chip.read(4) * 64
|
||||||
return current_step
|
# print(cv_in_value)
|
||||||
|
# self.cv_out_one.set_duty(cv_in_value)
|
||||||
|
|
||||||
class Synthesizer:
|
|
||||||
# PIN CONFIGURATION
|
|
||||||
|
|
||||||
p1 = None # GP0
|
sleep(sleep_interval)
|
||||||
p2 = None # GP1
|
|
||||||
# p3 = GND
|
|
||||||
p4 = None # GP2
|
|
||||||
p5 = None # GP3
|
|
||||||
p6 = None # GP4
|
|
||||||
p7 = None # GP5
|
|
||||||
# p8 = GND
|
|
||||||
p9 = None # GP6
|
|
||||||
p10 = None
|
|
||||||
p11 = None
|
|
||||||
p12 = None
|
|
||||||
# p13 = GND
|
|
||||||
p14 = None # GP10
|
|
||||||
p15 = None
|
|
||||||
p16 = None
|
|
||||||
p17 = None
|
|
||||||
# p18 = GND
|
|
||||||
p19 = None # GP14
|
|
||||||
p20 = None
|
|
||||||
p21 = None
|
|
||||||
p22 = None
|
|
||||||
# p23 = GND
|
|
||||||
p24 = None # GP18
|
|
||||||
p25 = None
|
|
||||||
p26 = None
|
|
||||||
p27 = None
|
|
||||||
# p28 = GND
|
|
||||||
p29 = None # GP22
|
|
||||||
# p30 = RUN
|
|
||||||
p31 = None # GP26, ADC0
|
|
||||||
p32 = None # GP27, ADC1
|
|
||||||
# p33 = GND, AGND
|
|
||||||
p34 = None # GP28, ADC2
|
|
||||||
p35 = None # ADC_VREF
|
|
||||||
# p36 = 3v3(out)
|
|
||||||
# p37 = 3V3_EN
|
|
||||||
# p38 = GND
|
|
||||||
# p39 = VSYS
|
|
||||||
# p40 = VBUS
|
|
||||||
|
|
||||||
def __init__(self, config):
|
|
||||||
self.config = config
|
|
||||||
|
|
||||||
gate_out = PWMOutput(15, 0)
|
class ADSR(Module):
|
||||||
voct_out = PWMOutput(16, 0)
|
def __init__(self, mcp3008: MCP3008, out_one: int, out_two: int):
|
||||||
|
super().__init__(mcp3008, out_one, out_two)
|
||||||
|
|
||||||
# spi = SPI(0, sck=Pin(2), mosi=Pin(3), miso=Pin(4), baudrate=100_000)
|
def loop(self, time_interval=0.01):
|
||||||
# chip_select = Pin(22, Pin.OUT)
|
if time_interval < 0:
|
||||||
# chip_select.value(1)
|
raise Exception("Time interval may not be less than 0")
|
||||||
|
elif time_interval > 1:
|
||||||
|
raise Exception("Time interval may not be greater than 1")
|
||||||
|
|
||||||
# square = Pin(21, Pin.OUT)
|
# only move on to envelope generation when a gate is detected
|
||||||
# mcp = MCP3008(spi, chip_select)
|
if self.chip.read(4) is not 0:
|
||||||
|
# get data and convert to polar
|
||||||
|
attack = (self.chip.read(0) / 1024)
|
||||||
|
decay = (self.chip.read(1) / 1024)
|
||||||
|
sustain = self.chip.read(2) / 1024
|
||||||
|
release = (self.chip.read(3) / 1024)
|
||||||
|
|
||||||
cv_one = PWMOutput(16)
|
counter = 0
|
||||||
led_one = PWMOutput(17)
|
value = 0
|
||||||
|
|
||||||
pot = Potentiometer(0)
|
print(self.chip.read(4))
|
||||||
|
|
||||||
osc = Oscillator('sine', 32)
|
attack_steps = floor(attack / time_interval)
|
||||||
|
while counter < attack_steps:
|
||||||
|
value = value + time_interval
|
||||||
|
counter = counter + 1
|
||||||
|
print(value)
|
||||||
|
self.cv_out_one.set_duty(floor(value))
|
||||||
|
|
||||||
timer = 1
|
decay_steps = floor(decay / time_interval)
|
||||||
sleep_interval = 0.01
|
while counter < attack_steps + decay_steps:
|
||||||
|
value = value - time_interval
|
||||||
|
counter = counter + 1
|
||||||
|
print(value)
|
||||||
|
self.cv_out_one.set_duty(floor(value))
|
||||||
|
|
||||||
|
sleep(time_interval)
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
variable initialization and prep for loop
|
||||||
|
"""
|
||||||
|
spi = SPI(0, sck=Pin(2),mosi=Pin(3),miso=Pin(4), baudrate=100000)
|
||||||
|
cs = Pin(22, Pin.OUT)
|
||||||
|
cs.value(1) # disable chip at start
|
||||||
|
|
||||||
|
chip = MCP3008(spi, cs)
|
||||||
|
module = Module(chip, out_one=14, out_two=15)
|
||||||
|
adsr = ADSR(chip, out_one=14, out_two=15)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
while True:
|
while True:
|
||||||
current_step = polar_to_u16(osc.out())
|
adsr.loop()
|
||||||
|
|
||||||
led_one.set_duty(current_step)
|
|
||||||
cv_one.set_duty(current_step)
|
|
||||||
|
|
||||||
sleep(0.001 + (pot.read_polar() / 32))
|
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
module.cleanup()
|
||||||
print("Exiting program...")
|
print("Exiting program...")
|
||||||
led_one.set_duty(0)
|
|
||||||
cv_one.set_duty(0)
|
|
||||||
|
|||||||
18
sandbox.py
Normal file
18
sandbox.py
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
def envelope_generator(start=1, target=10, slew_rate=512):
|
||||||
|
"""
|
||||||
|
Creates a generator function returning the absolute value differece between
|
||||||
|
the start and target voltages over the given duration in ms.
|
||||||
|
"""
|
||||||
|
cv_diff = abs(target - start)
|
||||||
|
cur = min(start, target)
|
||||||
|
_target = max(start, target)
|
||||||
|
slew_rate = max(slew_rate, 1) # avoid div by zero
|
||||||
|
|
||||||
|
env_progress = 1
|
||||||
|
|
||||||
|
while cur < _target:
|
||||||
|
cur = env_progress * cv_diff
|
||||||
|
yield cur
|
||||||
|
|
||||||
|
result = envelope_generator()
|
||||||
|
print(result)
|
||||||
Reference in New Issue
Block a user