2016-09-02 06:52 AM
Hey all!
I am trying to see if I can eliminate the serial port version of MIDI and switch over to using USB MIDI controllers/keyboards instead. Searching on this forum (and Google as well), I see many attempts at creating this, mostly poorly documented and or proprietary (i.e. - MIOS), and other open source code that doesn't seem to survive the transition from GCC to KEIL, and the rest of what is available is written for SPL only. Is there an example of a USB MIDI ''Class-Compliant'' code that can be used on the USB-OTG port of STM32 Nucleo boards? Can an existing piece of code (like the USB Flash Drive FatFS 3rd-party examples in the v1.4.0 firmware) be modified to connect to USB ''Class-Compliant'' devices such as controllers or keyboards? Does it seem like a feasible task, or is it just too much work to get this to work on HAL? Does anybody have suggestions or ideas or comments about this subject? Thanks!! Christopher #usb-midi-class #usb-midi-host-nucleo-144 #class-compliant-hal-midi Note: this post was migrated and contained many threaded conversations, some content may be missing.Solved! Go to Solution.
2017-02-06 03:13 PM
Whery interesting project,
Christopher! Is it possible to see its demo?
Now I'm coding my hybrid paraphonic synthesizer too. It's close to Korg Mono/Poly in architecture and consist of quad DCOs and dual Polyvosk state variable VCF. And I am looking for how to implement two virtual MIDI ports one for MIDI data from DAW and other for Control Face App.
First, needs to modify the descriptor by adding two additional MIDI Jack for input and output. But what to do next is not clear, because I still can't fully understand exactly how the library works
It's work on my STM32F407 Discovery board. I just modify string
&sharpinclude
'stm32f0xx_hal.h' to 'stm32f4xx_hal.h' where the compiler point.Then I removed all code not directly related to data exchange.
usbd_midi_if.c
&sharpinclude
'usbd_midi_if.h'&sharpinclude
'stm32f4xx_hal.h'static
uint16_t MIDI_DataRx(uint8_t *msg, uint16_t length);static
uint16_t MIDI_DataTx(uint8_t *msg, uint16_t length);USBD_MIDI_ItfTypeDef USBD_Interface_fops_FS =
{
MIDI_DataRx,
MIDI_DataTx
};
static
uint16_t MIDI_DataRx(uint8_t *msg, uint16_t length){
uint8_t chan = msg[
1
] &0xf
;uint8_t msgtype = msg[
1
] &0xf0
;uint8_t b1 =
msg[
2
];uint8_t b2 =
msg[
3
];uint16_t b = ((b2 &
0x7f
) <<7
) | (b1 &0x7f
);
switch
(msgtype) {
case
0x80
:HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_13); //blink LED
break
;
case
0x90
:HAL_GPIO_TogglePin(GPIOD,GPIO_PIN_13);
//blink LED
break
;
case
0xB0
:
break
;
case
0xC0
:
break
;
case
0xD0
:
break
;
case
0xE0
:
break
;default
:
break
;}
return
0
;
}
static
uint16_t MIDI_DataTx(uint8_t *msg, uint16_t length){
uint32_t i =
0
;
while
(i < length) {APP_Rx_Buffer[APP_Rx_ptr_in] = *(msg + i);
APP_Rx_ptr_in++;
i++;
if
(APP_Rx_ptr_in == APP_RX_DATA_SIZE) {APP_Rx_ptr_in =
0
;}
}
return
USBD_OK;}
Even when I switched the compiler in C++, I got the following errors:
Error[Pe167]: argument of type 'char const *' is incompatible with parameter of type 'uint8_t *'
Error[Pe167]: argument of type 'void *' is incompatible with parameter of type 'USBD_HandleTypeDef *'
I did an explicit conversion of types where needed, putting (uint8_t*) and (
USBD_HandleTypeDef*).
2017-02-07 09:12 PM
It's done! I modified the descriptorand now it showsas two separate MIDI ports(cables).
usbd_midi.c
___________________________
***
__ALIGN_BEGIN uint8_t USBD_MIDI_CfgDesc[USB_MIDI_CONFIG_DESC_SIZ] __ALIGN_END =
{
// configuration descriptor
0x09
,0x02
, DESC_SIZ_LOBYTE, DESC_SIZ_HIBYTE,0x02
,0x01
,0x00
,0x80
,0x31
,//
USB_MIDI_CONFIG_DESC_SIZ = 133,
DESC_SIZ_LOBYTE =133,
DESC_SIZ_HIBYTE = 0
// The Audio Interface Collection
0x09
,
0x04
,
0x00
,
0x00
,
0x00
,
0x01
,
0x01
,
0x00
,
0x02
,
// Standard AC Interface Descriptor0x09
,
0x24
,
0x01
,
0x00
,
0x01
,
0x09
,
0x00
,
0x01
,
0x01
,
// Class-specific AC Interface Descriptor0x09
,
0x04
,
0x01
,
0x00
,
0x02
,
0x01
,
0x03
,
0x00
,
0x02
,
// MIDIStreaming Interface Descriptors0x07
,
0x24
,
0x01
,
0x00
,
0x01
,
0x41
,
0x00
,
// Class-Specific MS Interface Header Descriptor// MIDI IN JACKS
0x06
,
0x24,
0x02,
0x01,
0x01,
0x00,
0x06
,
0x24,
0x02,
0x02,
0x02,
0x00,
// MIDI OUT JACKS
0x09
,
0x24,
0x03,
0x01,
0x03,
0x01,
0x02,
0x01,
0x00,
0x09
,
0x24,
0x03,
0x02,
0x04,
0x01,
0x01,
0x01,
0x00,
// MIDI IN JACKS
0x06
,
0x24,
0x02,
0x01,
0x05,
0x00,
0x06
,
0x24,
0x02,
0x02,
0x06,
0x00,
// MIDI OUT JACKS
0x09
,
0x24,
0x03,
0x01,
0x07,
0x01,
0x06,
0x01,
0x00,
0x09
,
0x24,
0x03,
0x02,
0x08,
0x01,
0x05,
0x01,
0x00,
// OUT endpoint descriptor
0x09
,
0x05, MIDI_OUT_EP,
0x02,
0x40,
0x00,
0x00,
0x00,
0x00,
0x06
,
0x25,
0x01,
0x02,
0x01,
0x05,
// IN endpoint descriptor
0x09
,
0x05, MIDI_IN_EP,
0x02,
0x40,
0x00,
0x00,
0x00,
0x00,
0x06
,
0x25,
0x01,
0x02,
0x03,
0x07,
};
***
_________________
usbd_midi_if.c
_________________
***
static
uint16_t MIDI_DataRx(uint8_t *msg, uint16_t length){
uint8_t chan = msg[
1
] &0xf
;uint8_t msgtype = msg[
1
] &0xf0
;uint8_t b1 = msg[
2
];uint8_t b2 = msg[
3
];uint16_t b = ((b2 &
0x7f
) <<7
) | (b1 &0x7f
);switch
(msgtype) {case
0x80
:if
( (msg[0
]>>4
) ==0
) HAL_GPIO_WritePin(GPIOD,GPIO_PIN_13, GPIO_PIN_RESET);if
( (msg[0
]>>4
) ==1
) HAL_GPIO_WritePin(GPIOD,GPIO_PIN_15, GPIO_PIN_RESET);if
(length>4
) /* if more then two events came at the same time */{
//
if
( (msg[4
]>>4
) ==0
) HAL_GPIO_WritePin(GPIOD,GPIO_PIN_12, GPIO_PIN_RESET);if
( (msg[4
]>>4
) ==1
) HAL_GPIO_WritePin(GPIOD,GPIO_PIN_14, GPIO_PIN_RESET);}
break
;case
0x90
:if
( (msg[0
]>>4
) ==0
) HAL_GPIO_WritePin(GPIOD,GPIO_PIN_13, GPIO_PIN_SET);if
( (msg[0
]>>4
) ==1
) HAL_GPIO_WritePin(GPIOD,GPIO_PIN_15, GPIO_PIN_SET);if
(length>4
)/* if more then two events came at the same time */
{
//
if
( (msg[4
]>>4
) ==0
) HAL_GPIO_WritePin(GPIOD,GPIO_PIN_12, GPIO_PIN_SET);if
( (msg[4
]>>4
) ==1
) HAL_GPIO_WritePin(GPIOD,GPIO_PIN_14, GPIO_PIN_SET);}
break
;***
2017-02-09 05:00 PM
Hey Chris - over in the other thread
https://community.st.com/0D50X00009XkYz2SAF
Chinzai Tsuneo suggested that the usbh_MIDI implementation fromDekrispator was flawed with some incorrect assumptions about control flow in the USB Host. He gave a number of suggestions for correcting that and you came back with a short reply that you had it working.
I've tried the same path you took and I'm having the same problem - the device appears to connect but I never get data from it no matter how hard I mash the keys . Do you have any notes on how you got the MIDI host class to work?
Eric
2017-02-09 05:47 PM
Hey Eric,
I did not have to modify the HAL hcd code at all, but as a result, I had to modify MIDI_Application.h and
MIDI_Application.c to add another state to the process.
2017-02-09 11:28 PM
Thanks Chris - makes sense in light of what was discussed in the other thread. I've been able to use this to get my code working.
Something that I noticed - your switch statement in the packet decoder relies on the event0 byte having a low nybble of 0 (ie MIDI channel 0) so it won't catch messages on other channels. My controller is outputting on channel 1 so no data from it was captured. I did a logical AND with 0xF0 in the parameter of the switch statement to make the decoder more promiscuous.
PS - nice to see someone else working on synth stuff. F7 is great for that.
2017-02-10 07:12 PM
Your welcome, Eric.
Yes, I just default to MIDI channel 0, that's why I didn't mask off the channel bits.
The F7 has a balanced mix of speed and peripherals, and the Nucleo-144 boards (at $23 a piece) are perfectly priced for Flash-It/Snap-It/Embed-It projects.
2017-09-21 04:43 AM
For those of you who want to experiment with a VA Synthesizer, check out my
project.2017-10-16 03:36 AM
Hello, Alexander!
With your and
Pappas.Chris
helpful posts, I have a working MIDI device with my STM32F429 discovery board. My device is receiving incoming MIDI packets from host. Please, describe me, how I should use aMIDI_DataTx routineto send MIDI packets to host. Thank you in advance.
2017-10-30 04:54 PM
Hello Alexander,
I'm trying to modify a CDC USB code from cubeMX to transform it to midi device. Then your post look very interesting for me. Then I download mimuz tuch project and copy the two files (c and h) in my project replacing the original ones for CDC.
I get a stm32 virtual com midi device on MIDI OX but i didn't see any data from my nulceo 64 board (l053) .
I suspect the malloc found on usbd_conf.c 'void *USBD_static_malloc(uint32_t size)
{ static uint32_t mem[(sizeof(USBD_HandleTypeDef)/4)+1];/* On 32-bit boundary */ return mem;}'I try to replace the original value : USBD_CDC_HandleTypeDef by only USBD_HandleTypeDef (and in the mimuz project is set to 512).
Can you give me more details on how you modify your cube mx original CDC project to get working midi device ?
Regards
2017-12-08 03:12 PM
Sorry it took so long to respond, bro. I have not included a subscription to the topic.
I pulled the whole driver package from HAL in a separate folder, which can be used without CubeMX
Just add all the files from the USB directory and subdirectories to a project and add some lines from the README file in the corresponding files.
If you have any questions, here is my email:
mailto:eternalengineemi@gmail.com
It have some problems in OsX 9 and later, that i haven't fix yet.
________________ Attachments : STM_32_HAL_USB_MIDI.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006HyGJ&d=%2Fa%2F0X0000000b5B%2F6suQdVjsOjc18HBLImLnJ9Bc.pWiadRKpF9JEpi9vPA&asPdf=false