Isolating USB MIDI device/host code from Ksoloti (STM32F429 + ChibiOS)

Hi,

I’m working on a hardware sequencer based on STM32F429 + ChibiOS to be used with the Ksoloti. I already have a minimal USB MIDI device running (it enumerates and can send notes), but I’d like to make it more robust and add USB MIDI host support too.

Since Ksoloti already implements both device and host on the same platform, I was thinking it could be a good reference. I’m still quite new to ChibiOS, so I might be missing some obvious details here. Sorry if this is a bit off-topic — my project isn’t directly Ksoloti, but I thought the technical overlap might make it relevant.

  • What would be the recommended way to isolate only the USB MIDI device/host parts of Ksoloti, without pulling in all the other project dependencies?
  • Do I just need to look at usbcfg.c/h, or are there other key files that are important for a clean, standalone USB MIDI implementation?

Any tips on pitfalls when extracting just the USB stack from a larger ChibiOS-based codebase would also be really helpful.

Thanks a lot for your time!

Hi, sounds like an exciting project! Will you be offering kits or PCBs for it?

As far as I know, the USB MIDI device/host code (mostly?) consists of:

firmware/STM32_USB_Host_Library this is based on some older version of ST’s “STM32Cube USB host library” I believe.

./firmware/bulk_usb.c
./firmware/bulk_usb.h
./firmware/midi_usb.c
./firmware/midi_usb.h
./firmware/usbcfg.c
./firmware/usbcfg.h
./firmware/usbh_conf.c
./firmware/usbh_conf.h
./firmware/usbh_midi_core.c
./firmware/usbh_midi_core.h
./firmware/usbh_vendor.c

These are responsible for all the USB MIDI stuff and more I guess! To be honest I have not spent much time on the USB MIDI code because I am really bad at USB, and as long as it works I don’t want to verschlimmbesser anything.

@AndyCap is far more familiar with the USB since he implemented USB audio! Any thoughts?

1 Like

Thanks for your reply!

About your first question — I’d love to eventually, but right now I’m still very much at an amateur stage. For example, my custom PCB for this sequencer is basically a copy/paste of the Ksoloti PCB, so thanks also for making that available, it’s been a huge help.

And about the USB code — I totally get that, haha. I’ve been poking at it for a week and it’s already been painful enough. Thanks again for pointing me to the right files.

One last thing — I was also wondering about alternative ways to communicate with Ksoloti beyond MIDI, like using a UART protocole for faster data transfer (for things like Elektron-style parameter locks, or loading/saving presets). Would you prefer that I open a separate thread for that, or is it fine to ask here?

Thanks again for your time and help!

1 Like

I think basically what you want are:

${FIRMWARE}/STM32_USB_Host_Library/Core/Src/usbh_core.c \
${FIRMWARE}/STM32_USB_Host_Library/Core/Src/usbh_ctlreq.c \
${FIRMWARE}/STM32_USB_Host_Library/Core/Src/usbh_ioreq.c \
${FIRMWARE}/STM32_USB_Host_Library/Core/Src/usbh_pipes.c \
${FIRMWARE}/usbh_midi_core.c \
${FIRMWARE}/usbh_conf.c \

to bring up the host:

  USBH_Init(&hUSBHost, USBH_UserProcess, 0);
  USBH_RegisterClass(&hUSBHost, USBH_MIDI_CLASS);

  USBH_Start(&hUSBHost);

  usbh_midi_init();

USBH_UserProcess() doesn’t do much:

static void USBH_UserProcess(USBH_HandleTypeDef *pHost, uint8_t vId) {
  switch (vId) {
  case HOST_USER_SELECT_CONFIGURATION:
    break;

  case HOST_USER_DISCONNECTION:
    break;

  case HOST_USER_CLASS_ACTIVE:
    break;

  case HOST_USER_CONNECTION:
    break;

  default:
    break;
  }
}

For receiving look at usb_conf.c:


void MIDI_CB(uint8_t a,uint8_t b,uint8_t c,uint8_t d){
    USBH_DbgLog("M %x - %x %x %x\r\n",a,b,c,d);
    //  a= pkt header 0xF0 = cable number 0x0F=CIN
    MidiInMsgHandler(MIDI_DEVICE_USB_HOST, ((a & 0xF0) >> 4)+ 1 ,b,c,d);
}

That MIDI_CB() is called by the midi host stuff, you can call your midi in handler here, the above code is for the ksoloti/axoloti where MidiInMsgHandler is defined elsewhere.

2 Likes

As you already have the device stuff going I would stick with that and just try to shoehorn in the host stuff.

Any of the above could be (and probably is) wrong, any issues just post here and we can try to help…

One thing I’ve always felt can interface well with other devices is SPIlink. You would flash the Ksoloti in SPILink firmware mode and its SPI3 becomes a master sending and receiving stuff with a 10 MHz clock.

palSetPadMode(GPIOB, 3, PAL_MODE_ALTERNATE(6)); /* SCK */
palSetPadMode(GPIOB, 4, PAL_MODE_ALTERNATE(6)); /* MISO */
palSetPadMode(GPIOD, 5, PAL_MODE_ALTERNATE(5)); /* NSS */
palSetPadMode(GPIOD, 6, PAL_MODE_ALTERNATE(5)); /* MOSI */

You’d already have the relevant ksoloti/spilink/ objects for sending and receiving values in your patch so the “only” work would be to set up a SPI target (“slave”) and implement the protocol.

I don’t remember all of the details right not but in essence the protocol has a header that keeps bits in sync and a body that sends/receives a whole bunch of int32’s so you could basically transfer anything with it at high speed.

I am saying this because I always meant to try just hooking up an Arduino and making a template so it would interface with a SPILink-ing Ksoloti.

If this sounds interesting to you, check out

spidb.c/h
spilink.c/h
spilink_lld.h

If you want fewer pins, there is always UART but I guess you would have to write some sort of protocol for it as well. Then there is MIDI via a free UART (has been done on Axoloti before) but slow… and you’d probably be limited by the way Ksoloti/your future MIDI code processes MIDI, 3 bytes at a time…

1 Like

Hi!
Thanks a lot for the detailed replies! I started working on the host implementation, but along the way I noticed I was having issues with my device, especially with program change. So I decided to switch to the Ksoloti device code in the hope of saving myself some sleepless nights. However, I’m now running into quite a few problems due to version differences in ChibiOS. I did see the migration_v16.h file, but I haven’t been able to integrate it cleanly, so I’m wondering what the best strategy would be to port these files to the latest version of ChibiOS.

What exact chibios version are you using?

I’m on ChibiOS 21.11.x. From what I can tell, some things like InputQueue and OutputQueue don’t seem to exist anymore, so I guess that might be the reason I’m getting so many errors. But I’m not entirely sure

1 Like

The code in the stm32h743_andy branch here might help: GitHub - AndrewCapon/ksoloti at stm32h743_andy

That has been converted to 21.11.3

I think all the file names should still be the same, let me know if anything is different and I will take a look. I haven’t looked at it all for a while!

1 Like