/** ****************************************************************************** * @file : usbd_midi_if.c * @brief : ****************************************************************************** (CC at)2016 by D.F.Mac. @TripArts Music ****************************************************************************** Modified by keshikan (www.keshikan.net) 2018 The license is (CC BY 4.0), and takes over from original usbd_midi_if.h/c. See also original source code page. https://github.com/mimuz/mimuz-tuch/blob/master/STM32/ ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "usbd_midi_if.h" #include "stm32f0xx_hal.h" // basic midi rx/tx functions static uint16_t MIDI_DataRx(uint8_t *msg, uint16_t length); static uint16_t MIDI_DataTx(uint8_t *msg, uint16_t length); // for Cure Series #define MIDI_BUFFER_SIZ (512)//FIFO buffer byte size for midi message buffer RingBufferU8 rbuf_usb_rx[MIDI_OUT_JACK_NUM]; //for input from USB RingBufferU8 rbuf_jack_rx[MIDI_IN_JACK_NUM]; //for input from MIDI-IN jack //for receiving midi data from jack MidiAnalysisStatus analyzed_status[MIDI_IN_JACK_NUM]; MIDIEvent midi_event[MIDI_IN_JACK_NUM]; //received midi data uint8_t rx_midi_msg[MIDI_IN_JACK_NUM]; FUNC_STATUS midiInit() { uint32_t i,j; for(i=0; i> 4; uint8_t code_idx_num = msg[0 + 4*cnt_msgs] & 0x0F; switch (code_idx_num) { //not defined case 0x0: case 0x1: midi_size = 0; break; //1byte message case 0x5: case 0xF: midi_size = 1; break; //2byte message case 0x2: case 0x6: case 0xC: case 0xD: midi_size = 2; break; //3byte message case 0x3: case 0x4: case 0x7: case 0x8: case 0x9: case 0xA: case 0xB: case 0xE: midi_size = 3; break; default: midi_size = 0; break; } for(cnt = 0;cnt < midi_size;cnt ++){ u8b = *(msg + 4*cnt_msgs + cnt + 1); cureRingBufferU8Enqueue(&rbuf_usb_rx[cable_num], &u8b); } } return 0; } void sendMidiMessage(uint8_t *msg, uint16_t size){ if(size == 4){ // APP_Rx_Buffer[0] = msg[0]; // APP_Rx_Buffer[1] = msg[1]; // APP_Rx_Buffer[2] = msg[2]; // APP_Rx_Buffer[3] = msg[3]; // USBD_MIDI_SendData(&hUsbDeviceFS, APP_Rx_Buffer, size); MIDI_DataTx(msg, size); } } 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; } bool midiEventIsGenerated(uint8_t cable_num) { uint8_t upper_half_byte= (rx_midi_msg[cable_num]) & 0xF0; if( upper_half_byte & 0x80 ){//0x80-0xFF:status byte switch(upper_half_byte){ case 0xF0://0xF0-0xFF:system message switch(rx_midi_msg[cable_num]){ case 0xF0://SysEx Start analyzed_status[cable_num].data_idx = 0; midi_event[cable_num].midi_byte[ analyzed_status[cable_num].data_idx++ ] = rx_midi_msg[cable_num]; analyzed_status[cable_num].type = MSG_SYSEX; analyzed_status[cable_num].stat = WAIT_SYSTEM_DATA; break; case 0xF7://SysEx End midi_event[cable_num].midi_byte[ analyzed_status[cable_num].data_idx++ ] = rx_midi_msg[cable_num]; midi_event[cable_num].length = analyzed_status[cable_num].data_idx; analyzed_status[cable_num].stat = END_ANALYSIS; break; case 0xF2://Song Position midi_event[cable_num].midi_byte[0] = rx_midi_msg[cable_num]; analyzed_status[cable_num].type = MSG_THREE_BYTE; analyzed_status[cable_num].stat = WAIT_DATA1; break; case 0xF1://Time Code case 0xF3://Song Select midi_event[cable_num].midi_byte[0] = rx_midi_msg[cable_num]; analyzed_status[cable_num].type = MSG_TWO_BYTE; analyzed_status[cable_num].stat = WAIT_DATA1; break; case 0xF4://Undefined case 0xF5://Undefined case 0xF6://Tune request case 0xF8://Timing clock case 0xF9://Undefined case 0xFA://Start case 0xFB://Continue case 0xFC://Stop case 0xFD://Undefined case 0xFE://Active Sensing case 0xFF://Reset midi_event[cable_num].midi_byte[0] = rx_midi_msg[cable_num]; midi_event[cable_num].length = 1; analyzed_status[cable_num].type = MSG_ONE_BYTE; analyzed_status[cable_num].stat = END_ANALYSIS; break; } analyzed_status[cable_num].is_system_common = true; break; case 0x80://Note Off case 0x90://Note On case 0xA0://Polyphonic key-pressure case 0xB0://ControlChange case 0xE0://PitchBend midi_event[cable_num].midi_byte[0] = rx_midi_msg[cable_num]; analyzed_status[cable_num].type = MSG_THREE_BYTE; analyzed_status[cable_num].stat = WAIT_DATA1; analyzed_status[cable_num].is_system_common = false; break; case 0xC0://Program Change case 0xD0://Channel pressure midi_event[cable_num].midi_byte[0] = rx_midi_msg[cable_num]; analyzed_status[cable_num].type = MSG_TWO_BYTE; analyzed_status[cable_num].stat = WAIT_DATA1; analyzed_status[cable_num].is_system_common = false; break; default: analyzed_status[cable_num].type = MSG_NOTHING; analyzed_status[cable_num].stat = START_ANALYSIS; analyzed_status[cable_num].is_system_common = false; break; } }else{//0x00-0x7F:data byte switch(analyzed_status[cable_num].stat){ case WAIT_DATA1: midi_event[cable_num].midi_byte[1] = rx_midi_msg[cable_num]; if(MSG_THREE_BYTE == analyzed_status[cable_num].type ){ analyzed_status[cable_num].stat = WAIT_DATA2; }else if( MSG_TWO_BYTE == analyzed_status[cable_num].type ){ midi_event[cable_num].length = 2; analyzed_status[cable_num].stat = END_ANALYSIS; }else{ analyzed_status[cable_num].stat = START_ANALYSIS; } break; case WAIT_DATA2: if(MSG_THREE_BYTE == analyzed_status[cable_num].type ){ midi_event[cable_num].midi_byte[2] = rx_midi_msg[cable_num]; midi_event[cable_num].length = 3; analyzed_status[cable_num].stat = END_ANALYSIS; }else{ analyzed_status[cable_num].stat = START_ANALYSIS; } break; case WAIT_SYSTEM_DATA: midi_event[cable_num].midi_byte[ analyzed_status[cable_num].data_idx++ ] = rx_midi_msg[cable_num]; if(analyzed_status[cable_num].data_idx > (MIDI_SENDDATA_MAX - 1) ){ analyzed_status[cable_num].stat = END_ANALYSIS; } break; case END_ANALYSIS://running status:When status byte is omitted. midi_event[cable_num].midi_byte[1] = rx_midi_msg[cable_num]; if(MSG_THREE_BYTE == analyzed_status[cable_num].type){ analyzed_status[cable_num].stat = WAIT_DATA2; }else if(MSG_TWO_BYTE == analyzed_status[cable_num].type){ midi_event[cable_num].length = 2; analyzed_status[cable_num].stat = END_ANALYSIS; } break; case START_ANALYSIS: break; default: break; } } if(END_ANALYSIS == analyzed_status[cable_num].stat){ return true; }else{ return false; } } void midiGenerateUsbPacket(uint8_t cable_num) { uint8_t msg_buf[4] = {0x00,0x00,0x00,0x00}; uint32_t cnt_remain=0, cnt_length; switch(analyzed_status[cable_num].type){ case MSG_ONE_BYTE: //byte 0: cable number + code index number msg_buf[0] = (cable_num << 4) + ((midi_event[cable_num].midi_byte[0] & 0xF0) >> 4); sendMidiMessage(msg_buf,4); break; case MSG_TWO_BYTE: case MSG_THREE_BYTE: //byte 0: cable number + code index number if(analyzed_status[cable_num].is_system_common){ msg_buf[0] = (cable_num << 4) + midi_event[cable_num].length; }else{ msg_buf[0] = (cable_num << 4) + ((midi_event[cable_num].midi_byte[0] & 0xF0) >> 4); } //byte 1-3 for(uint32_t i=0; i=3){ cnt_remain = 0; } } break; default: break; } USBD_MIDI_SendPacket(); } void midiProcess(){ for(uint32_t cable_num=0; cable_num