Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .vscode/c_cpp_properties.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,16 @@
"${workspaceRoot}/tests/googletest/googletest/include",
"${workspaceRoot}/src/sys",
"${workspaceRoot}/src/usbd",
"${workspaceRoot}/src/usbh",
"${workspaceRoot}/Drivers/CMSIS_5/CMSIS/Core/Include",
"${workspaceRoot}/Drivers/CMSIS-Device/ST/STM32H7xx/Include",
"${workspaceRoot}/Drivers/STM32H7xx_HAL_Driver/Inc",
"${workspaceRoot}/Drivers/STM32H7xx_HAL_Driver/Inc/Legacy",
"${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Core/Inc",
"${workspaceRoot}/Middlewares/ST/STM32_USB_Device_Library/Class/CDC/Inc",
"${workspaceRoot}/Middlewares/ST/STM32_USB_Host_Library/Core/Inc",
"${workspaceRoot}/Middlewares/ST/STM32_USB_Host_Library/Class/MIDI/Inc",
"${workspaceRoot}/Middlewares/ST/STM32_USB_Host_Library/Class/MSC/Inc",
"${workspaceRoot}/Middlewares/Third_Party/FatFs/src"
],
"defines": [
Expand Down
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ add_library(daisy STATIC
${MODULE_DIR}/daisy_pod.cpp
${MODULE_DIR}/daisy_seed.cpp
${MODULE_DIR}/daisy_versio.cpp
${MODULE_DIR}/desktop_devkit.cpp
${MODULE_DIR}/eurorack_devkit.cpp
${MODULE_DIR}/pedal_devkit.cpp
${MODULE_DIR}/dev/codec_ak4556.cpp
${MODULE_DIR}/dev/codec_pcm3060.cpp
${MODULE_DIR}/dev/codec_wm8731.cpp
Expand Down Expand Up @@ -130,15 +133,13 @@ target_compile_options(daisy PRIVATE
$<$<CXX_COMPILER_ID:GNU>:-Wno-missing-attributes>
)


set_target_properties(daisy PROPERTIES
CXX_STANDARD 14
CXX_STANDARD_REQUIRED
C_STANDARD 11
C_STANDARD_REQUIRED
)


# Don't add examples if we're being included in another project
if(PROJECT_IS_TOP_LEVEL)
add_subdirectory(examples EXCLUDE_FROM_ALL)
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ daisy_field \
daisy_versio \
daisy_legio \
daisy_patch_sm \
desktop_devkit \
eurorack_devkit \
pedal_devkit \
sys/fatfs \
sys/system \
dev/sr_595 \
Expand Down
33 changes: 33 additions & 0 deletions examples/devkits/Desktop-DevKit-UI-Template/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Project Name
TARGET = Desktop-DevKit-UI-Template

# Configure for debugging
# common configurations:
# use DEBUG = 1 and OPT = -Og for debugging
# or DEBUG = 0 and OPT = -O3 for performance
DEBUG = 1
OPT = -Og

# (optional) use bootloader
APP_TYPE=BOOT_SRAM

# Sources
CPP_SOURCES = src/main.cpp

LIBDAISY_DIR = ../../../

# (optional) Add DaisySP
# DAISYSP_DIR = ../path/to/DaisySP
# USE_DAISYSP_LGPL=1

# (optional) Includes FatFS source files within project.
USE_FATFS = 1

# Core location, and generic Makefile.
SYSTEM_FILES_DIR = $(LIBDAISY_DIR)/core

# Use the bootloader variant that allows programming DFU over the
# external USB port (used to power the devkit).
BOOT_BIN=$(SYSTEM_FILES_DIR)/dsy_bootloader_v6_4-extdfu-2000ms.bin

include $(SYSTEM_FILES_DIR)/Makefile
38 changes: 38 additions & 0 deletions examples/devkits/Desktop-DevKit-UI-Template/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Desktop Devkit UI Template

This example is a bit more complex than the other examples in the repo.

All inputs for the Desktop DevKit are read, and printed when changed to Serial over the external USB port, also used to power the DevKit.

The 16 buttons, 8 pots, and LEDs are all managed using libDaisy's UI class from `main_page.h`.

As usual inputs are read in the AudioCallback. UI Events are then created for the relevant pieces of the interface.
Inside the Low-priority Callback, the events are handled, and the LED UI is redrawn.
The Low-priority Callback is used so that things like SD Card Disk I/O, QSPI saving, etc. that may block the main while() loop do not cause the UI to become unresponsive, or appear stuck.

## Flashing to the Daisy

This is designed to use the external USB version of the bootloader.

This version of the bootloader can be flashed to the daisy via the built-in USB port by running `make program-boot` from this directory, or by selecting the "v6.x (external)" variant from the [web programmer](https://flash.daisy.audio/).

Once the bootloader has been flashed to the Daisy, you can power connect the USB-C cable from your computer to the Desktop Devkit's USB-C port (located above the Seed3).

With the device connected, press RESET and then BOOT on the Seed.
You should see the USR LED on the Daisy blink quickly and then start slowly pulsing.

While in this state you can run: `make program-dfu`, or upload the `Desktop-DevKit-UI-Template.bin` file to the [web programmer](https://flash.daisy.audio/) to program the example to the Seed.

Once bootloader is programmed onto the Seed it does not need to be reprogrammed unless you need to install a different variant of the bootloader, or program an app to the Seed's internal flash.

## Connecting to the Program

Once the program has been flashed to the Daisy, you'll see that the Seed's USR LED is blinking at a steady rate.
You can push each of the tactile switches to see the corresponding LED illuminate.

The CV outputs will be generating slow ramp and saw waveforms respectively, MIDI note messages to the MIDI Input will emit from the MIDI output, and audio sent to the audio inputs will be copied to the outputs.

You can connect to the program using a serial monitor, and see print statements that occur whenever any input is changed.

Within the source code you'll see that many of these print statements are set within on change callbacks in the `main_page.h`.
Other inputs are checked in the Audio Callback, and messages are generated to be sent from the main `while()` loop.
230 changes: 230 additions & 0 deletions examples/devkits/Desktop-DevKit-UI-Template/src/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
/** Desktop DevKit UI Template
*
* UI template program for the Desktop DevKit
*
* This program uses the libDaisy UI framework to generate events from the input
* that can be handled within UI pages.
* This is a bit more complex than the simpler approach to handling UI in other examples,
* but provides a lot of flexibility for more involved applications.
*
* Since the Desktop DevKit is USB powered via the port on the devkit, this build uses the
* external variant of the bootloader so that the seed on the devkit can be reprogrammed
* while connected to the single USB port on the desktop devkit.
*
* This program:
* - initializes the Desktop DevKit hardware
* - starts an audio callback to do pass through, update the controls, and generate UI events
* - starts a low-priority callback to process the UI events
* - prints input data from the `main_page.h` event hooks over USB serial
*/
#include "desktop_devkit.h"
#include "userinterface.h"

using namespace daisy;
using namespace daisy::desktop_devkit;

/** Naive hysteresis filter for printing CV input changes
*
* Only update the value if the input has changed by enough to print.
*/
struct CvChangeFilter
{
float prev_val;
bool changed;

/** simple constructor */
CvChangeFilter() : prev_val(0.f), changed(false) {}

/** compares the input to the last value output, and updates it if it exceeds a threshold of 0.1 */
inline float Process(const float in)
{
changed = false;
if(std::abs(in - prev_val) > 0.01f)
{
prev_val = in;
changed = true;
}
return prev_val;
}

/** returns true the value changed last time `Process` was called */
inline bool Changed() const { return changed; }
};

/** Global Hardware object */
Hardware hw;

/** Global UI object */
Ui ui;

/** FIFO of strings that we can use to move messages from the Audio callback
* to be printed in the main while() loop.
*/
FIFO<FixedCapStr<32>, 16> msg_fifo;

/** state of 3-way toggle for output when changed */
int prev_toggle_pos = 0;

/** Simple filters for CV inputs to only output values when they have changed */
CvChangeFilter cv_change_filt[2];

void AudioCallback(AudioHandle::InputBuffer in,
AudioHandle::OutputBuffer out,
size_t size)
{
hw.UpdateAllControls();
ui.GenerateEvents();

// Here we'll send some strings based on events not covered in the UI.
//
// Certain things (e.g. gate inputs, CV inputs, etc.) often make more sense to
// handle within the audio callback so that there is a new value once per callback,
// syncronized with the block of audio it was read in.
//
// A few of these (e.g. toggles) could be handled in the UI pages.

// Gate Inputs
if(hw.gate_in[0].Trig())
msg_fifo.PushBack("Gate In 1: Trig!");
if(hw.gate_in[1].Trig())
msg_fifo.PushBack("Gate In 2: Trig!");

// Input detection changes
if(hw.sd_detect.FallingEdge())
msg_fifo.PushBack("SD card removed");
else if(hw.sd_detect.RisingEdge())
msg_fifo.PushBack("SD card inserted");

if(hw.left_detect.FallingEdge())
msg_fifo.PushBack("Left input removed");
else if(hw.left_detect.RisingEdge())
msg_fifo.PushBack("Left input inserted");

if(hw.right_detect.FallingEdge())
msg_fifo.PushBack("Right input removed");
else if(hw.right_detect.RisingEdge())
msg_fifo.PushBack("Right input inserted");

// 2-way Toggle
if(hw.tog_sw17.FallingEdge())
msg_fifo.PushBack("SW17: Down");
else if(hw.tog_sw17.RisingEdge())
msg_fifo.PushBack("SW17: Up");

// 3-way Toggle
auto new_tog_pos = hw.tog_sw18.Read();
if(prev_toggle_pos != new_tog_pos)
{
switch(new_tog_pos)
{
case Switch3::POS_CENTER: msg_fifo.PushBack("SW18: Center"); break;
case Switch3::POS_UP: msg_fifo.PushBack("SW18: Up"); break;
case Switch3::POS_DOWN: msg_fifo.PushBack("SW18: Down"); break;
default: break;
}
prev_toggle_pos = new_tog_pos;
}

// CV Inputs
auto cv1 = cv_change_filt[0].Process(hw.cv[0].Value());
if(cv_change_filt[0].Changed())
{
FixedCapStr<32> msg("CV1: ");
msg.AppendFloat(cv1);
msg_fifo.PushBack(msg);
}
auto cv2 = cv_change_filt[1].Process(hw.cv[1].Value());
if(cv_change_filt[1].Changed())
{
FixedCapStr<32> msg("CV2: ");
msg.AppendFloat(cv2);
msg_fifo.PushBack(msg);
}

// Audio pass through
for(size_t i = 0; i < size; i++)
{
out[0][i] = in[0][i];
out[1][i] = in[1][i];
}
}


/** This callback happens every 4ms (250Hz) and can be interrupted by
* everything except for the SysTick interrupt.
* The frequency of this callback is set in the `Hardware::StartLowPriorityCallback`
* parameters.
*
* Handling the UI events here means that anything we do in the main while()
* loop that may take an indeterminate time (file system I/O, QSPI Saving, etc.)
* won't cause the UI to stall during those processes
*/
void LowPriorityCallback(void *data)
{
// Handles events, and redraws the current UI pages
ui.DoEvents();
}

int main(void)
{
hw.Init();
System::Delay(50);
Logger<LOGGER_EXTERNAL>::StartLog(false);
ui.Init(&hw);

hw.StartLowPriorityCallback(LowPriorityCallback, 250);
hw.seed.StartAudio(AudioCallback);

auto last_dac_write = System::GetNow();
uint16_t dac_value = 0;

while(true)
{
auto now = System::GetNow();

/** Handle MIDI events */
while(hw.midi.HasEvents())
{
auto msg = hw.midi.PopEvent();
switch(msg.type)
{
case NoteOn:
// Echo note on messages to the MIDI out
{
uint8_t bytes[3] = {0x90, 0x00, 0x00};
bytes[1] = msg.data[0];
bytes[2] = msg.data[1];
hw.midi.SendMessage(bytes, 3);
}
break;
default: break;
}
}

/** Write a ramp (cv out 1) and saw (cv out 2) waveform to the DAC outputs
* Approx. 2.5s period for waveform (0.005s * (4096 / 8)) = 2.56s
*/
if(now - last_dac_write > 5)
{
dac_value += 8;
if(dac_value > 4095)
{
dac_value = 0;
}
hw.SetDacOut(DacHandle::Channel::ONE, dac_value);
hw.SetDacOut(DacHandle::Channel::TWO, 4095 - dac_value);
last_dac_write = now;
}

/** Print messages from the audio callback */
while(!msg_fifo.IsEmpty())
{
auto msg = msg_fifo.PopFront();
Logger<LOGGER_EXTERNAL>::PrintLine(msg.Cstr());
}

System::Delay(1);
}

return 0;
}
Loading
Loading