| @@ -0,0 +1,116 @@ | ||
| #include "midi.h" | ||
|
|
||
| #include "../ll/midi_ll.h" | ||
|
|
||
| #include "lualink.h" // L_queue_midi() | ||
|
|
||
| typedef enum{ MIDI_NOTEOFF = 0x80 | ||
| , MIDI_NOTEON = 0x90 | ||
| , MIDI_AFTERTOUCH = 0xA0 | ||
| , MIDI_CC = 0xB0 | ||
| , MIDI_PATCHCHANGE = 0xC0 | ||
| , MIDI_CH_PRESSURE = 0xD0 | ||
| , MIDI_PITCHBEND = 0xE0 | ||
| , MIDI_SYS = 0xF0 | ||
| } MIDI_Cmd_e; | ||
|
|
||
| typedef enum{ MIDI_SYSEX = 0xF0 | ||
| , MIDI_MTC_QUARTER = 0xF1 | ||
| , MIDI_SONG_POS = 0xF2 | ||
| , MIDI_SONG_SEL = 0xF3 | ||
| , MIDI_TUNE = 0xF6 | ||
| , MIDI_SYSEX_END = 0xF7 | ||
| , MIDI_CLOCK = 0xF8 | ||
| , MIDI_START = 0xFA | ||
| , MIDI_CONTINUE = 0xFB | ||
| , MIDI_STOP = 0xFC | ||
| , MIDI_ACTIVE_SENSE = 0xFE | ||
| , MIDI_SYS_RESET = 0xFF | ||
| } MIDI_Sys_e; | ||
|
|
||
|
|
||
| // private declarations | ||
| static uint8_t MIDI_rx_cmd( void ); | ||
| static uint8_t MIDI_rx_data( uint8_t count ); | ||
| static void event_complete( uint8_t* d ); | ||
|
|
||
|
|
||
| // public defns | ||
| void MIDI_Active( int state ) | ||
| { | ||
| static int is_active = 0; | ||
| if( state && !is_active ){ | ||
| MIDI_ll_Init( &MIDI_Handle_LL ); | ||
| if( MIDI_rx_cmd() ){ printf("midi0\n"); } | ||
| is_active = 1; | ||
| } else if( !state && is_active ){ | ||
| MIDI_ll_DeInit(); | ||
| is_active = 0; | ||
| } else if( is_active ){ | ||
| if( MIDI_rx_cmd() ){ printf("retry failed\n"); } | ||
| } // else ignore | ||
| } | ||
|
|
||
| uint8_t receiving_packet = 0; | ||
| static uint8_t MIDI_rx_cmd( void ) | ||
| { | ||
| receiving_packet = 0; | ||
| return MIDI_ll_Rx( 0, 1); | ||
| } | ||
|
|
||
| static uint8_t MIDI_rx_data( uint8_t count ) | ||
| { | ||
| receiving_packet = 1; | ||
| return MIDI_ll_Rx( 1, count); | ||
| } | ||
|
|
||
| int sysex_count = 0; | ||
| void MIDI_Handle_LL( uint8_t* buf ) | ||
| { | ||
| if( !receiving_packet ){ // this is a new midi message | ||
| int count = MIDI_byte_count(buf[0]); | ||
| if( count > 0 ){ | ||
| MIDI_rx_data( count ); | ||
| } else if( count == 0 ){ // sys | ||
| if( buf[0] == MIDI_SYSEX ){ | ||
| receiving_packet = 1; | ||
| MIDI_ll_Rx( ++sysex_count, 1 ); | ||
| } else { // system action | ||
| event_complete(buf); | ||
| } | ||
| } else { // error retry | ||
| if( MIDI_rx_cmd() ){ printf("midi2\n"); } | ||
| } | ||
| } else { // receiving data | ||
| if( buf[0] == MIDI_SYSEX ){ | ||
| if( buf[sysex_count] == MIDI_SYSEX_END ){ | ||
| event_complete(buf); | ||
| } else { | ||
| MIDI_ll_Rx( ++sysex_count, 1 ); | ||
| } | ||
| } else { | ||
| event_complete(buf); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| int MIDI_byte_count( uint8_t cmd_byte ) | ||
| { | ||
| switch(cmd_byte & 0xF0){ | ||
| case MIDI_NOTEOFF: return 2; | ||
| case MIDI_NOTEON: return 2; | ||
| case MIDI_AFTERTOUCH: return 2; | ||
| case MIDI_CC: return 2; | ||
| case MIDI_PATCHCHANGE: return 2; | ||
| case MIDI_CH_PRESSURE: return 1; | ||
| case MIDI_PITCHBEND: return 2; | ||
| case MIDI_SYS: return 0; | ||
| default: return -1; | ||
| } | ||
| } | ||
|
|
||
| static void event_complete( uint8_t* d ) | ||
| { | ||
| L_queue_midi(d); | ||
| if( MIDI_rx_cmd() ){ printf("midi3\n"); } | ||
| } |
| @@ -0,0 +1,7 @@ | ||
| #pragma once | ||
|
|
||
| #include <stdint.h> | ||
|
|
||
| void MIDI_Active( int state ); | ||
| void MIDI_Handle_LL( uint8_t* buf ); | ||
| int MIDI_byte_count( uint8_t cmd_byte ); |
| @@ -0,0 +1,102 @@ | ||
| #include "midi_ll.h" | ||
|
|
||
| UART_HandleTypeDef midiuart; | ||
|
|
||
| void rx_callback_null( uint8_t* buf ); | ||
| void (*rx_callback)(uint8_t*) = rx_callback_null; | ||
| uint8_t rx_buf[8]; // TODO not big enough for sysex! | ||
|
|
||
| // public defns | ||
| void MIDI_ll_Init( void(*rx_handler)(uint8_t*) ) | ||
| { | ||
| midiuart.Instance = MIDIx; | ||
|
|
||
| midiuart.Init.BaudRate = MIDI_baud; | ||
| midiuart.Init.WordLength = UART_WORDLENGTH_8B; | ||
| midiuart.Init.StopBits = UART_STOPBITS_1; | ||
| midiuart.Init.Parity = UART_PARITY_NONE; | ||
| midiuart.Init.Mode = UART_MODE_RX; | ||
| midiuart.Init.OverSampling = UART_OVERSAMPLING_16; // 16 or 8. d=16 | ||
| if( HAL_UART_Init( &midiuart ) ){ printf("!midi_uart_init\n"); } | ||
|
|
||
| while( HAL_UART_GetState( &midiuart ) != HAL_UART_STATE_READY ){} | ||
|
|
||
| rx_callback = rx_handler; | ||
| } | ||
|
|
||
| void MIDI_ll_DeInit(void) | ||
| { | ||
| HAL_UART_DeInit( &midiuart ); | ||
| } | ||
|
|
||
| void HAL_UART_MspInit(UART_HandleTypeDef *hu ) | ||
| { | ||
| MIDIx_FORCE_RESET(); | ||
| MIDIx_RELEASE_RESET(); | ||
|
|
||
| static DMA_HandleTypeDef hdma_rx; | ||
|
|
||
| MIDI_UART_RCC(); | ||
| MIDI_GPIO_RCC(); | ||
| MIDI_DMA_CLK_ENABLE(); | ||
|
|
||
| GPIO_InitTypeDef gpio; | ||
| gpio.Pin = MIDI_RXPIN; | ||
| gpio.Mode = GPIO_MODE_AF_PP; | ||
| gpio.Pull = GPIO_PULLUP; | ||
| gpio.Speed = GPIO_SPEED_FREQ_HIGH; | ||
| gpio.Alternate = MIDI_AF; | ||
| HAL_GPIO_Init( MIDI_GPIO, &gpio ); | ||
|
|
||
| hdma_rx.Instance = MIDIx_RX_DMA_STREAM; | ||
| hdma_rx.Init.Channel = MIDIx_RX_DMA_CHANNEL; | ||
| hdma_rx.Init.Direction = DMA_PERIPH_TO_MEMORY; | ||
| hdma_rx.Init.PeriphInc = DMA_PINC_DISABLE; | ||
| hdma_rx.Init.MemInc = DMA_MINC_ENABLE; | ||
| hdma_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE; | ||
| hdma_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE; | ||
| hdma_rx.Init.Mode = DMA_NORMAL; | ||
| hdma_rx.Init.Priority = DMA_PRIORITY_HIGH; | ||
| if( HAL_DMA_Init( &hdma_rx ) ){ printf("!MIDI_DMA\n"); } | ||
| __HAL_LINKDMA( hu, hdmarx, hdma_rx ); // Associate DMA to UART handle | ||
|
|
||
| HAL_NVIC_SetPriority( MIDIx_DMA_RX_IRQn | ||
| , MIDIx_DMA_IRQPriority | ||
| , MIDIx_DMA_IRQSubPriority | ||
| ); | ||
| HAL_NVIC_EnableIRQ( MIDIx_DMA_RX_IRQn ); | ||
|
|
||
| HAL_NVIC_SetPriority( MIDIx_IRQn | ||
| , MIDIx_IRQPriority | ||
| , MIDIx_IRQSubPriority | ||
| ); | ||
| HAL_NVIC_EnableIRQ( MIDIx_IRQn ); | ||
| } | ||
|
|
||
| void MIDI_ll_DMA_RX_IRQHandler( void ) | ||
| { | ||
| HAL_DMA_IRQHandler( midiuart.hdmarx ); | ||
| } | ||
|
|
||
| int MIDI_ll_Rx( int ix, int count ) | ||
| { | ||
| int err; | ||
| err = HAL_UART_Receive_DMA( &midiuart | ||
| , &(rx_buf[ix]) | ||
| , count | ||
| ); | ||
| if( err ){ printf("MIDI_ll_Rx %i\n", err); } | ||
| return err; | ||
| } | ||
|
|
||
| void HAL_UART_RxCpltCallback( UART_HandleTypeDef *huart ) | ||
| { | ||
| (*rx_callback)(rx_buf); | ||
| } | ||
|
|
||
| void MIDI_ll_IRQHandler( void ) | ||
| { | ||
| HAL_UART_IRQHandler( &midiuart ); | ||
| } | ||
|
|
||
| void rx_callback_null( uint8_t* buf ){} |
| @@ -0,0 +1,41 @@ | ||
| #pragma once | ||
|
|
||
| #include <stm32f7xx.h> | ||
| #include "interrupts.h" // MIDI_IRQPriority | ||
|
|
||
| #define MIDI_GPIO_RCC() __HAL_RCC_GPIOA_CLK_ENABLE() | ||
| #define MIDI_UART_RCC() __HAL_RCC_UART4_CLK_ENABLE() | ||
| #define MIDI_DMA_CLK_ENABLE() __HAL_RCC_DMA1_CLK_ENABLE() | ||
|
|
||
| #define MIDIx_FORCE_RESET() __UART4_FORCE_RESET() | ||
| #define MIDIx_RELEASE_RESET() __UART4_RELEASE_RESET() | ||
|
|
||
|
|
||
| #define MIDI_baud 31250 | ||
| #define MIDIx UART4 | ||
| #define MIDI_AF GPIO_AF8_UART4 | ||
| #define MIDI_GPIO GPIOA | ||
| #define MIDI_RXPIN GPIO_PIN_1 | ||
|
|
||
| #define MIDIx_RX_DMA_STREAM DMA1_Stream2 | ||
| #define MIDIx_RX_DMA_CHANNEL DMA_CHANNEL_4 | ||
|
|
||
| #define MIDIx_DMA_RX_IRQn DMA1_Stream2_IRQn | ||
| #define MIDI_ll_DMA_RX_IRQHandler DMA1_Stream2_IRQHandler | ||
|
|
||
| #define MIDIx_IRQn UART4_IRQn | ||
| #define MIDI_ll_IRQHandler UART4_IRQHandler | ||
| #define MIDIx_IRQPriority MIDI_IRQPriority | ||
| #define MIDIx_IRQSubPriority 0 | ||
| #define MIDIx_DMA_IRQPriority MIDI_IRQPriority | ||
| #define MIDIx_DMA_IRQSubPriority 1 | ||
|
|
||
| #define DBG_UART_TIMEOUT 0x4000 /* a long time */ | ||
|
|
||
| void MIDI_ll_Init( void(*rx_handler)(uint8_t*) ); | ||
| void MIDI_ll_DeInit(void); | ||
|
|
||
| int MIDI_ll_Rx( int ix, int count ); | ||
|
|
||
| void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart); | ||
| void MIDI_ll_IRQHandler( void ); |