Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create MIDI "root complex" abstraction. #3157

Draft
wants to merge 10 commits into
base: community
Choose a base branch
from
8 changes: 3 additions & 5 deletions src/RZA1/usb/r_usb_basic/src/driver/r_usb_hlibusbip.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@
#include "RZA1/usb/userdef/r_usb_hmidi_config.h"

#include "definitions.h"
#include "deluge/io/midi/midi_device_manager.h"

#include "deluge/drivers/uart/uart.h"
#include "deluge/io/midi/midi_device_manager.h"
#include "deluge/io/midi/midi_engine.h"
#include "deluge/io/usb/usb_state.h"

#if ((USB_CFG_DTC == USB_CFG_ENABLE) || (USB_CFG_DMA == USB_CFG_ENABLE))
#include "drivers/usb/r_usb_basic/src/hw/inc/r_usb_dmac.h"
Expand Down Expand Up @@ -954,7 +954,7 @@ void usb_hstd_receive_start(usb_utr_t* ptr, uint16_t pipe)
// I now just call the PSTD one instead of this - it does the same.
/***********************************************************************************************************************
Function Name : usb_hstd_read_data
Description : Request to read data from USB FIFO, and manage the size of
Description : Request to read data from USB FIFO, and manage the size of
: the data read.
Arguments : usb_utr_t *ptr : Pointer to usb_utr_t structure.
: uint16_t pipe : Pipe number.
Expand Down Expand Up @@ -1186,8 +1186,6 @@ void usb_hstd_data_end(usb_utr_t* ptr, uint16_t pipe, uint16_t status)
}
} /* End of function usb_hstd_data_end() */

extern usb_utr_t g_usb_midi_recv_utr[][MAX_NUM_USB_MIDI_DEVICES];

// For when data has been received, as host. Hub stuff is on PIPE9
void usb_hstd_brdy_pipe_process_rohan_midi_and_hub(usb_utr_t* ptr, uint16_t bitsts)
{
Expand Down
1 change: 1 addition & 0 deletions src/RZA1/usb/r_usb_basic/src/driver/r_usb_plibusbip.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
#include "deluge/drivers/usb/userdef/r_usb_pmidi_config.h"
#include "deluge/io/midi/midi_device_manager.h"
#include "deluge/io/midi/midi_engine.h"
#include "deluge/io/usb/usb_state.h"

#if ((USB_CFG_DTC == USB_CFG_ENABLE) || (USB_CFG_DMA == USB_CFG_ENABLE))
#include "RZA1/usb/r_usb_basic/src/hw/inc/r_usb_dmac.h"
Expand Down
3 changes: 1 addition & 2 deletions src/RZA1/usb/r_usb_hmidi/src/r_usb_hmidi_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@

#include "deluge/deluge.h"
#include "deluge/drivers/uart/uart.h"
#include "deluge/io/usb/usb_state.h"

/******************************************************************************
Exported global variables
Expand All @@ -61,8 +62,6 @@ static void usb_hmidi_check_result(usb_utr_t* ptr, uint16_t unused, uint16_t sta
static usb_er_t usb_hhid_data_trans(usb_utr_t* ptr, uint16_t pipe, uint32_t size, uint8_t* table, usb_cb_t complete);
static void usb_hmidi_enumeration_sequence(usb_utr_t* mess);

extern uint8_t currentDeviceNumWithSendPipe[];

/******************************************************************************
Exported global variables (to be accessed by other files)
******************************************************************************/
Expand Down
2 changes: 2 additions & 0 deletions src/definitions_cxx.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -489,6 +489,8 @@ enum class Error {
INSUFFICIENT_RAM_FOR_FOLDER_CONTENTS_SIZE,
SD_CARD_NOT_PRESENT,
SD_CARD_NO_FILESYSTEM,
OUT_OF_BUFFER_SPACE,
INVALID_SYSEX_FORMAT,
};

enum class SampleRepeatMode {
Expand Down
45 changes: 22 additions & 23 deletions src/deluge/deluge.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "RZA1/sdhi/inc/sdif.h"
#include "definitions_cxx.hpp"
#include "deluge/io/usb//usb_state.h"
#include "drivers/pic/pic.h"
#include "gui/ui/audio_recorder.h"
#include "gui/ui/browser/browser.h"
Expand Down Expand Up @@ -48,6 +49,8 @@
#include "io/midi/midi_device_manager.h"
#include "io/midi/midi_engine.h"
#include "io/midi/midi_follow.h"
#include "io/midi/root_complex/usb_hosted.h"
#include "io/midi/root_complex/usb_peripheral.h"
#include "lib/printf.h" // IWYU pragma: keep this over rides printf with a non allocating version
#include "memory/general_memory_allocator.h"
#include "model/clip/instrument_clip.h"
Expand Down Expand Up @@ -242,14 +245,6 @@ bool readButtonsAndPads() {
usbInitializationPeriodComplete = 1;
}

/*
if (!inSDRoutine && !closedPeripheral && !anythingInitiallyAttachedAsUSBHost && AudioEngine::audioSampleTimer >=
(44100 << 1)) { D_PRINTLN("closing peripheral"); closeUSBPeripheral(); D_PRINTLN("switching back to host");
openUSBHost();
closedPeripheral = true;
}
*/

if (waitingForSDRoutineToEnd) {
if (sdRoutineLock) {
return false;
Expand Down Expand Up @@ -549,8 +544,6 @@ void setupOLED() {
extern "C" void usb_pstd_pcd_task(void);
extern "C" void usb_cstd_usb_task(void);

extern "C" volatile uint32_t usbLock;

extern "C" void usb_main_host(void);

void registerTasks() {
Expand Down Expand Up @@ -843,20 +836,26 @@ extern "C" int32_t deluge_main(void) {
deluge::hid::display::swapDisplayType();
}

usbLock = 1;
openUSBHost();

// If nothing was plugged in to us as host, we'll go peripheral
// Ideally I'd like to repeatedly switch between host and peripheral mode anytime there's no USB connection.
// To do that, I'd really need to know at any point in time whether the user had just made a connection, just then,
// that hadn't fully initialized yet. I think I sorta have that for host, but not for peripheral yet.
if (!anythingInitiallyAttachedAsUSBHost) {
D_PRINTLN("switching from host to peripheral");
closeUSBHost();
openUSBPeripheral();
}
{
deluge::io::usb::USBAutoLock lock;
openUSBHost();

usbLock = 0;
if (anythingInitiallyAttachedAsUSBHost) {
MIDIDeviceManager::setUSBRoot(new MIDIRootComplexUSBHosted());
}
else {
// If nothing was plugged in to us as host, we'll go peripheral
// Ideally I'd like to repeatedly switch between host and peripheral mode anytime there's no USB connection.
// To do that, I'd really need to know at any point in time whether the user had just made a connection,
// just then, that hadn't fully initialized yet. I think I sorta have that for host, but not for peripheral
// yet.
D_PRINTLN("switching from host to peripheral");
closeUSBHost();
openUSBPeripheral();

// configuredAsPeripheral will set the root complex.
}
}

// Hopefully we can read these files now
runtimeFeatureSettings.readSettingsFromFile();
Expand Down
58 changes: 38 additions & 20 deletions src/deluge/gui/menu_item/midi/devices.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
#include "io/midi/cable_types/usb_hosted.h"
#include "io/midi/midi_device.h"
#include "io/midi/midi_device_manager.h"
#include "io/midi/midi_root_complex.h"
#include "io/midi/root_complex/usb_hosted.h"
#include "io/midi/root_complex/usb_peripheral.h"
#include "util/container/static_vector.hpp"
#include <string_view>

Expand All @@ -37,7 +40,12 @@ static constexpr int32_t lowestDeviceNum = -3;
void Devices::beginSession(MenuItem* navigatedBackwardFrom) {
bool found = false;
if (navigatedBackwardFrom != nullptr) {
for (int32_t idx = lowestDeviceNum; idx < MIDIDeviceManager::hostedMIDIDevices.getNumElements(); idx++) {
// This will technically do the wrong thing when we're in peripheral mode (it'll set the max index to 2 instead
// of 0, which would be accurate) but it should be harmless -- `Devices::getCable` should just return nullptr in
// that case which we handle fine already anyway.
auto maxIndex =
(MIDIDeviceManager::rootUSB != nullptr) ? MIDIDeviceManager::rootUSB->getNumCables() : lowestDeviceNum + 1;
for (int32_t idx = lowestDeviceNum; idx < maxIndex; idx++) {
if (getCable(idx) == soundEditor.currentMIDICable) {
found = true;
this->setValue(idx);
Expand All @@ -62,10 +70,12 @@ void Devices::beginSession(MenuItem* navigatedBackwardFrom) {
void Devices::selectEncoderAction(int32_t offset) {
offset = std::clamp<int32_t>(offset, -1, 1);

auto maxIndex = (MIDIDeviceManager::rootUSB == nullptr) ? 0 : MIDIDeviceManager::rootUSB->getNumCables();

do {
int32_t newValue = this->getValue() + offset;

if (newValue >= MIDIDeviceManager::hostedMIDIDevices.getNumElements()) {
if (newValue >= maxIndex) {
if (display->haveOLED()) {
return;
}
Expand All @@ -75,14 +85,14 @@ void Devices::selectEncoderAction(int32_t offset) {
if (display->haveOLED()) {
return;
}
newValue = MIDIDeviceManager::hostedMIDIDevices.getNumElements() - 1;
newValue = maxIndex - 1;
}

this->setValue(newValue);

soundEditor.currentMIDICable = getCable(this->getValue());

} while (!soundEditor.currentMIDICable->connectionFlags);
} while (soundEditor.currentMIDICable == nullptr && soundEditor.currentMIDICable->connectionFlags == 0);
// Don't show devices which aren't connected. Sometimes we won't even have a name to display for them.

if (display->haveOLED()) {
Expand Down Expand Up @@ -115,24 +125,31 @@ void Devices::selectEncoderAction(int32_t offset) {
}

MIDICable* Devices::getCable(int32_t deviceIndex) {
if (deviceIndex < lowestDeviceNum || deviceIndex >= MIDIDeviceManager::hostedMIDIDevices.getNumElements()) {
if (deviceIndex < lowestDeviceNum) {
D_PRINTLN("impossible device request");
return nullptr;
}
switch (deviceIndex) {
case -3: {
return &MIDIDeviceManager::dinMIDIPorts;
}
case -2: {
return &MIDIDeviceManager::upstreamUSBMIDICable1;
}
case -1: {
return &MIDIDeviceManager::upstreamUSBMIDICable2;
}
default: {
return static_cast<MIDICable*>(MIDIDeviceManager::hostedMIDIDevices.getElement(deviceIndex));

if (deviceIndex == -3) {
return &MIDIDeviceManager::rootDin.cable;
}

if (MIDIDeviceManager::rootUSB != nullptr) {
auto& rootUSB = *MIDIDeviceManager::rootUSB;
if (deviceIndex < 0) {
if (rootUSB.getType() == RootComplexType::RC_USB_PERIPHERAL && deviceIndex >= -2) {
return rootUSB.getCable(deviceIndex + 2);
}
return nullptr;
}

if (rootUSB.getType() == RootComplexType::RC_USB_HOST) {
auto& usb = static_cast<MIDIRootComplexUSBHosted&>(rootUSB);
return usb.getCable(deviceIndex);
}
}

return nullptr;
}

void Devices::drawValue() {
Expand All @@ -154,11 +171,12 @@ void Devices::drawPixelsForOled() {

int32_t selectedRow = -1;

int32_t device_idx = currentScroll;
auto device_idx = currentScroll;
size_t row = 0;
while (row < kOLEDMenuNumOptionsVisible && device_idx < MIDIDeviceManager::hostedMIDIDevices.getNumElements()) {
auto max_index = (MIDIDeviceManager::rootUSB == nullptr) ? 0 : MIDIDeviceManager::rootUSB->getNumCables();
while (row < kOLEDMenuNumOptionsVisible && device_idx < static_cast<ptrdiff_t>(max_index)) {
MIDICable* cable = getCable(device_idx);
if (cable && cable->connectionFlags != 0u) {
if (cable != nullptr && cable->connectionFlags != 0u) {
itemNames.push_back(cable->getDisplayName());
if (device_idx == this->getValue()) {
selectedRow = static_cast<int32_t>(row);
Expand Down
2 changes: 1 addition & 1 deletion src/deluge/gui/menu_item/midi/devices.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class Devices final : public Value<int32_t> {
void drawPixelsForOled();

private:
size_t currentScroll;
ptrdiff_t currentScroll;
};

extern Devices devicesMenu;
Expand Down
4 changes: 2 additions & 2 deletions src/deluge/gui/views/arranger_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1905,7 +1905,7 @@ void ArrangerView::transitionToClipView(ClipInstance* clipInstance) {
PadLEDs::sendOutSidebarColours(); // They'll have been cleared by the first explode render

// Hook point for specificMidiDevice
iterateAndCallSpecificDeviceHook(MIDIDeviceUSBHosted::Hook::HOOK_ON_TRANSITION_TO_CLIP_VIEW);
iterateAndCallSpecificDeviceHook(MIDICableUSBHosted::Hook::HOOK_ON_TRANSITION_TO_CLIP_VIEW);
}

// Returns false if error
Expand Down Expand Up @@ -2009,7 +2009,7 @@ bool ArrangerView::transitionToArrangementEditor() {
doingAutoScrollNow = false; // May get changed back at new scroll pos soon

// Hook point for specificMidiDevice
iterateAndCallSpecificDeviceHook(MIDIDeviceUSBHosted::Hook::HOOK_ON_TRANSITION_TO_ARRANGER_VIEW);
iterateAndCallSpecificDeviceHook(MIDICableUSBHosted::Hook::HOOK_ON_TRANSITION_TO_ARRANGER_VIEW);

return true;
}
Expand Down
14 changes: 7 additions & 7 deletions src/deluge/gui/views/instrument_clip_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ ActionResult InstrumentClipView::commandLearnUserScale() {
recalculateColours();
uiNeedsRendering(this);
// Hook point for specificMidiDevice
iterateAndCallSpecificDeviceHook(MIDIDeviceUSBHosted::Hook::HOOK_ON_CHANGE_SCALE);
iterateAndCallSpecificDeviceHook(MIDICableUSBHosted::Hook::HOOK_ON_CHANGE_SCALE);
display->popupTextTemporary("USER");
return ActionResult::DEALT_WITH;
}
Expand All @@ -205,7 +205,7 @@ ActionResult InstrumentClipView::commandCycleThroughScales() {
recalculateColours();
uiNeedsRendering(this);
// Hook point for specificMidiDevice
iterateAndCallSpecificDeviceHook(MIDIDeviceUSBHosted::Hook::HOOK_ON_CHANGE_SCALE);
iterateAndCallSpecificDeviceHook(MIDICableUSBHosted::Hook::HOOK_ON_CHANGE_SCALE);
return ActionResult::DEALT_WITH;
}

Expand All @@ -215,7 +215,7 @@ ActionResult InstrumentClipView::commandFlashRootNote() {
flashDefaultRootNoteOn = false;
flashDefaultRootNote();
// Hook point for specificMidiDevice
iterateAndCallSpecificDeviceHook(MIDIDeviceUSBHosted::Hook::HOOK_ON_CHANGE_SCALE);
iterateAndCallSpecificDeviceHook(MIDICableUSBHosted::Hook::HOOK_ON_CHANGE_SCALE);
return ActionResult::DEALT_WITH;
}

Expand All @@ -239,7 +239,7 @@ ActionResult InstrumentClipView::commandChangeRootNote(uint8_t yDisplay) {
uiNeedsRendering(this);

// Hook point for specificMidiDevice
iterateAndCallSpecificDeviceHook(MIDIDeviceUSBHosted::Hook::HOOK_ON_CHANGE_ROOT_NOTE);
iterateAndCallSpecificDeviceHook(MIDICableUSBHosted::Hook::HOOK_ON_CHANGE_ROOT_NOTE);

return ActionResult::DEALT_WITH;
}
Expand Down Expand Up @@ -3766,7 +3766,7 @@ void InstrumentClipView::recalculateColour(uint8_t yDisplay) {
rowBlurColour[yDisplay] = rowColour[yDisplay].forBlur();

// Hook point for specificMidiDevice
iterateAndCallSpecificDeviceHook(MIDIDeviceUSBHosted::Hook::HOOK_ON_RECALCULATE_COLOUR);
iterateAndCallSpecificDeviceHook(MIDICableUSBHosted::Hook::HOOK_ON_RECALCULATE_COLOUR);
}

ActionResult InstrumentClipView::scrollVertical(int32_t scrollAmount, bool inCardRoutine, bool draggingNoteRow) {
Expand Down Expand Up @@ -5258,7 +5258,7 @@ void InstrumentClipView::enterScaleMode(uint8_t yDisplay) {
}

// Hook point for specificMidiDevice
iterateAndCallSpecificDeviceHook(MIDIDeviceUSBHosted::Hook::HOOK_ON_ENTER_SCALE_MODE);
iterateAndCallSpecificDeviceHook(MIDICableUSBHosted::Hook::HOOK_ON_ENTER_SCALE_MODE);
}

int32_t InstrumentClipView::setupForExitingScaleMode() {
Expand Down Expand Up @@ -5349,7 +5349,7 @@ void InstrumentClipView::exitScaleMode() {
}

// Hook point for specificMidiDevice
iterateAndCallSpecificDeviceHook(MIDIDeviceUSBHosted::Hook::HOOK_ON_EXIT_SCALE_MODE);
iterateAndCallSpecificDeviceHook(MIDICableUSBHosted::Hook::HOOK_ON_EXIT_SCALE_MODE);
}

// If called from KeyboardScreen, the newRootNote won't correspond to the yDisplay, and that's ok
Expand Down
10 changes: 5 additions & 5 deletions src/deluge/gui/views/session_view.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2744,7 +2744,7 @@ void SessionView::transitionToViewForClip(Clip* clip) {

if (clip->type == ClipType::INSTRUMENT) {
// Hook point for specificMidiDevice
iterateAndCallSpecificDeviceHook(MIDIDeviceUSBHosted::Hook::HOOK_ON_TRANSITION_TO_SESSION_VIEW);
iterateAndCallSpecificDeviceHook(MIDICableUSBHosted::Hook::HOOK_ON_TRANSITION_TO_SESSION_VIEW);
}
}

Expand Down Expand Up @@ -2788,7 +2788,7 @@ void SessionView::transitionToViewForClip(Clip* clip) {
PadLEDs::renderClipExpandOrCollapse();

// Hook point for specificMidiDevice
iterateAndCallSpecificDeviceHook(MIDIDeviceUSBHosted::Hook::HOOK_ON_TRANSITION_TO_SESSION_VIEW);
iterateAndCallSpecificDeviceHook(MIDICableUSBHosted::Hook::HOOK_ON_TRANSITION_TO_SESSION_VIEW);
}

// AudioClips
Expand Down Expand Up @@ -2898,7 +2898,7 @@ void SessionView::transitionToSessionView() {
}

// Hook point for specificMidiDevice
iterateAndCallSpecificDeviceHook(MIDIDeviceUSBHosted::Hook::HOOK_ON_TRANSITION_TO_SESSION_VIEW);
iterateAndCallSpecificDeviceHook(MIDICableUSBHosted::Hook::HOOK_ON_TRANSITION_TO_SESSION_VIEW);
}

// Might be called during card routine! So renders might fail. Not too likely
Expand Down Expand Up @@ -4393,7 +4393,7 @@ void SessionView::gridTransitionToSessionView() {
uiTimerManager.setTimer(TimerName::MATRIX_DRIVER, 35);

// Hook point for specificMidiDevice
iterateAndCallSpecificDeviceHook(MIDIDeviceUSBHosted::Hook::HOOK_ON_TRANSITION_TO_SESSION_VIEW);
iterateAndCallSpecificDeviceHook(MIDICableUSBHosted::Hook::HOOK_ON_TRANSITION_TO_SESSION_VIEW);
}

void SessionView::gridTransitionToViewForClip(Clip* clip) {
Expand Down Expand Up @@ -4477,7 +4477,7 @@ void SessionView::gridTransitionToViewForClip(Clip* clip) {
PadLEDs::sendOutSidebarColours(); // They'll have been cleared by the first explode render

// Hook point for specificMidiDevice
iterateAndCallSpecificDeviceHook(MIDIDeviceUSBHosted::Hook::HOOK_ON_TRANSITION_TO_CLIP_VIEW);
iterateAndCallSpecificDeviceHook(MIDICableUSBHosted::Hook::HOOK_ON_TRANSITION_TO_CLIP_VIEW);
}

const uint32_t SessionView::gridTrackCount() {
Expand Down
Loading
Loading