Skip to content

Commit

Permalink
lichen-community-systemsgh-22: Adds support for different types of bu…
Browse files Browse the repository at this point in the history
…ffered analog outputs,

and for scaling outputs to accommodate situations like the DPT's
offset internal DAC outputs.
  • Loading branch information
colinbdclark committed Jul 5, 2024
1 parent 6d9a679 commit bc31c26
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 22 deletions.
30 changes: 30 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,36 @@
"svdFile": "${workspaceRoot}/.vscode/STM32H750x.svd",
"type": "cortex-debug"
},
{
"name": "Remote DPT triangles",
"configFiles": [
"interface/stlink.cfg",
"target/stm32h7x.cfg"
],
"cwd": "${workspaceFolder}/hosts/daisy/examples/dpt/triangles",
"debuggerArgs": [
"-d",
"${workspaceRoot}/hosts/daisy/examples/dpt/triangles"
],
"executable": "${workspaceRoot}/hosts/daisy/examples/dpt/triangles/build/signaletic-dpt-triangles.elf",
"interface": "swd",
"openOCDLaunchCommands": [
"init",
"reset init"
],
"preLaunchTask": "Debug Build DPT Examples",
"preRestartCommands": [
"load",
"enable breakpoint",
"monitor reset"
],
"request": "launch",
"runToEntryPoint": "main",
"servertype": "openocd",
"showDevDebugOutput": "parsed",
"svdFile": "${workspaceRoot}/.vscode/STM32H750x.svd",
"type": "cortex-debug"
},
{
"name": "Remote DPT lfos",
"configFiles": [
Expand Down
21 changes: 21 additions & 0 deletions hosts/daisy/examples/dpt/triangles/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Project Name
TARGET ?= signaletic-dpt-triangles

DEBUG = 1
OPT = -O0

# Sources
C_SOURCES += ../../../../../libsignaletic/vendor/tlsf/tlsf.c ../../../../../libsignaletic/src/libsignaletic.c ../../../src/signaletic-host.c
C_INCLUDES += -I../../../../../libsignaletic/vendor/tlsf -I../../../../../libsignaletic/include

CPP_INCLUDES += -I../vendor/lib -I../../../vendor/lib/dev -I../../../include
CPP_SOURCES = ../../../vendor/dpt/lib/dev/DAC7554.cpp ../../../src/signaletic-daisy-host.cpp ../../../src/sig-daisy-patch-sm.cpp src/${TARGET}.cpp

USE_FATFS = 0

# Library Locations
LIBDAISY_DIR = ../../../vendor/libDaisy

# Core location, and generic Makefile.
SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core
include $(SYSTEM_FILES_DIR)/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
#include "../../../../include/dspcoffee-dpt-device.hpp"

#define SAMPLERATE 96000
#define HEAP_SIZE 1024 * 256 // 256KB
#define MAX_NUM_SIGNALS 128

uint8_t memory[HEAP_SIZE];
struct sig_AllocatorHeap heap = {
.length = HEAP_SIZE,
.memory = (void*) memory
};

struct sig_Allocator allocator = {
.impl = &sig_TLSFAllocatorImpl,
.heap = &heap
};

DaisyHost<dspcoffee::dpt::DPTDevice> host;

struct sig_dsp_Signal* listStorage[MAX_NUM_SIGNALS];
struct sig_List signals = {
.items = (void**) &listStorage,
.capacity = MAX_NUM_SIGNALS,
.length = 0
};

struct sig_dsp_SignalListEvaluator* evaluator;
struct sig_host_CVIn* frequency;
struct sig_host_CVIn* triangleGain;
struct sig_dsp_Oscillator* triangle;
struct sig_dsp_BinaryOp* scaledTriangle;
struct sig_host_CVOut* cv1Out;
struct sig_host_CVOut* cv3Out;
float cv1Value;
float cv2Value;

void buildSignalGraph(struct sig_SignalContext* context,
struct sig_Status* status) {
frequency = sig_host_CVIn_new(&allocator, context);
frequency->hardware = &host.device.hardware;
sig_List_append(&signals, frequency, status);
frequency->parameters.control = sig_host_CV_IN_1;
frequency->parameters.scale = 110.0f;

triangle = sig_dsp_LFTriangle_new(&allocator, context);
sig_List_append(&signals, triangle, status);
triangle->inputs.freq = frequency->outputs.main;

triangleGain =sig_host_CVIn_new(&allocator, context); triangleGain->hardware = &host.device.hardware;
sig_List_append(&signals, triangleGain, status);
triangleGain->parameters.control = sig_host_CV_IN_2;

scaledTriangle= sig_dsp_Mul_new(&allocator, context);
sig_List_append(&signals, scaledTriangle, status);
scaledTriangle->inputs.left = triangle->outputs.main;
scaledTriangle->inputs.right = triangleGain->outputs.main;

cv1Out = sig_host_CVOut_new(&allocator, context);
cv1Out->hardware = &host.device.hardware;
sig_List_append(&signals, cv1Out, status);
cv1Out->inputs.source = scaledTriangle->outputs.main;
cv1Out->parameters.control = sig_host_CV_OUT_1;

cv3Out = sig_host_CVOut_new(&allocator, context);
cv3Out->hardware = &host.device.hardware;
sig_List_append(&signals, cv3Out, status);
cv3Out->inputs.source = scaledTriangle->outputs.main;
cv3Out->parameters.control = sig_host_CV_OUT_3;
}

int main(void) {
allocator.impl->init(&allocator);

struct sig_AudioSettings audioSettings = {
.sampleRate = SAMPLERATE,
.numChannels = 2,
.blockSize = 1
};

struct sig_Status status;
sig_Status_init(&status);
sig_List_init(&signals, (void**) &listStorage, MAX_NUM_SIGNALS);

evaluator = sig_dsp_SignalListEvaluator_new(&allocator, &signals);
host.Init(&audioSettings, (struct sig_dsp_SignalEvaluator*) evaluator);

struct sig_SignalContext* context = sig_SignalContext_new(
&allocator, &audioSettings);
buildSignalGraph(context, &status);
host.Start();

while (1) {}
}
23 changes: 11 additions & 12 deletions hosts/daisy/include/dspcoffee-dpt-device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@

using namespace sig::libdaisy;

struct Normalization DPT_INTERNAL_DAC_NORMALIZATION = {
.scale = 0.651f,
.offset = -0.348f
};

enum {
sig_host_CV_IN_1 = 0,
sig_host_CV_IN_2,
Expand Down Expand Up @@ -95,8 +100,9 @@ namespace dpt {
InputBank<GateInput, NUM_GATES> gateInputBank;
GPIOOutput gateOutputs[NUM_GATES];
OutputBank<GPIOOutput, NUM_GATES> gateOutputBank;
DMAAnalogOutput dacChannels[NUM_DAC_CHANNELS];
OutputBank<DMAAnalogOutput, NUM_DAC_CHANNELS> dacOutputBank;
BipolarInvertedBufferedAnalogOutput dacChannels[NUM_DAC_CHANNELS];
OutputBank<BipolarInvertedBufferedAnalogOutput, NUM_DAC_CHANNELS>
dacOutputBank;
struct sig_host_HardwareInterface hardware;

static void onEvaluateSignals(size_t size,
Expand Down Expand Up @@ -177,14 +183,6 @@ namespace dpt {
}

void InitADCController() {
// TODO: Scale DPT CV outputs so that they're all in
// a normalized range (e.g. -4V to +4V).
// Currently, I think, they're outputting -4.67V to 7.96V)
//static constexpr struct Normalization DPT_TO_8VPP = {
// .scale = ??f,
// .offset = ??f
// };

adcController.Init(&board.adc, ADC_CHANNEL_SPECS);
}

Expand All @@ -193,12 +191,13 @@ namespace dpt {
// here. A better architecture would allow for
// multiple DAC (and ADC) instances.
for (size_t i = 0; i < NUM_INTERNAL_DAC_CHANNELS; i++) {
dacChannels[i].Init(board.dacOutputValues, i);
dacChannels[i].Init(board.dacOutputValues, i,
DPT_INTERNAL_DAC_NORMALIZATION);
}

for (size_t i = 0; i < NUM_EXTERNAL_DAC_CHANNELS; i++) {
size_t j = NUM_INTERNAL_DAC_CHANNELS + i;
dacChannels[j].Init(externalDACBuffer, i);
dacChannels[j].Init(externalDACBuffer, i, NO_NORMALIZATION);
}

dacOutputBank.outputs = dacChannels;
Expand Down
4 changes: 2 additions & 2 deletions hosts/daisy/include/lichen-bifocals-device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ namespace bifocals {
ADCController<AnalogInput, NUM_ADC_CHANNELS> adcController;
Toggle buttons[NUM_BUTTONS];
InputBank<Toggle, NUM_BUTTONS> buttonBank;
DMAAnalogOutput dacChannels[NUM_DAC_CHANNELS];
OutputBank<DMAAnalogOutput, NUM_DAC_CHANNELS> dacOutputBank;
BufferedAnalogOutput dacChannels[NUM_DAC_CHANNELS];
OutputBank<BufferedAnalogOutput, NUM_DAC_CHANNELS> dacOutputBank;
struct sig_host_HardwareInterface hardware;

static void onEvaluateSignals(size_t size,
Expand Down
4 changes: 2 additions & 2 deletions hosts/daisy/include/lichen-medium-device.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,8 @@ namespace medium {
InputBank<TriSwitch, NUM_TRISWITCHES> switchBank;
Toggle buttons[NUM_BUTTONS];
InputBank<Toggle, NUM_BUTTONS> buttonBank;
DMAAnalogOutput dacChannels[NUM_DAC_CHANNELS];
OutputBank<DMAAnalogOutput, NUM_DAC_CHANNELS> dacOutputBank;
BufferedAnalogOutput dacChannels[NUM_DAC_CHANNELS];
OutputBank<BufferedAnalogOutput, NUM_DAC_CHANNELS> dacOutputBank;
struct sig_host_HardwareInterface hardware;

static void onEvaluateSignals(size_t size,
Expand Down
37 changes: 31 additions & 6 deletions hosts/daisy/include/signaletic-daisy-host.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,33 +161,58 @@ template<typename T, size_t numChannels> class ADCController {
}
};

class DMAAnalogOutput {
class BaseAnalogOutput {
public:
float scale = 1.0f;
float offset = 0.0f;
};

class BufferedAnalogOutput : public BaseAnalogOutput{
public:
uint16_t* dacOutputs;
size_t channel;

void Init(uint16_t* inDACOutputs, size_t inChannel) {
void Init(uint16_t* inDACOutputs, size_t inChannel,
struct Normalization normalization = NO_NORMALIZATION) {
dacOutputs = inDACOutputs;
channel = inChannel;
scale = normalization.scale;
offset = normalization.offset;
}

inline void Write(float value) {
dacOutputs[channel] = sig_unipolarToUint12(value);
float normalizedValue = value * scale + offset;
dacOutputs[channel] = sig_unipolarToUint12(normalizedValue);
}
};

// TODO: Probably worth parameterizing the write strategy,
// though it will make for quite long templated definitions,
// e.g. OutputBank<AnalogOutput<BipolarInvertedWriter>> dacOutputBank;
class BipolarInvertedBufferedAnalogOutput : public BufferedAnalogOutput{
public:
inline void Write(float value) {
float normalizedValue = value * scale + offset;
dacOutputs[channel] = sig_bipolarToInvUint12(normalizedValue);
}
};

class PollingAnalogOutput {
class PollingAnalogOutput : public BaseAnalogOutput {
public:
daisy::DacHandle* dac;
size_t channel;

void Init(daisy::DacHandle* inDAC, size_t inChannel) {
void Init(daisy::DacHandle* inDAC, size_t inChannel,
struct Normalization normalization = NO_NORMALIZATION) {
dac = inDAC;
channel = inChannel;
scale = normalization.scale;
offset = normalization.offset;
}

inline void Write(float value) {
uint16_t convertedValue = sig_unipolarToUint12(value);
float normalizedValue = value * scale + offset;
uint16_t convertedValue = sig_unipolarToUint12(normalizedValue);
dac->WriteValue(static_cast<daisy::DacHandle::Channel>(channel),
convertedValue);
}
Expand Down

0 comments on commit bc31c26

Please sign in to comment.