@@ -24,6 +24,7 @@ extern void L_queue_toward( int id );
extern void L_queue_metro( int id, int state );
extern void L_queue_in_stream( int id );
extern void L_queue_change( int id, float state );
extern void L_queue_midi( uint8_t* data );

// Callback declarations
extern void L_handle_toward( int id );
@@ -33,3 +34,4 @@ extern void L_handle_change( int id, float state );
extern void L_handle_ii_leadRx( uint8_t address, uint8_t cmd, float data );
extern void L_handle_ii_followRx( uint8_t cmd, int args, float* data );
extern float L_handle_ii_followRxTx( uint8_t cmd, int args, float* data );
extern void L_handle_midi( uint8_t* data );
@@ -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 );
211 ll/midi.c

This file was deleted.

This file was deleted.

@@ -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 );
@@ -29,6 +29,7 @@ local function closelibs()
metro = nil --alias
II = nil
Cal = nil
Midi = nil
end

function _crow.libs( lib )
@@ -42,6 +43,7 @@ function _crow.libs( lib )
metro = Metro --alias
II = dofile('lua/ii.lua')
Cal = dofile('lua/calibrate.lua')
Midi = dofile('lua/midi.lua')
elseif type(lib) == 'table' then
-- load the list
else
@@ -21,6 +21,7 @@ function Input.new( chan )
-- user-customizable events
, stream = function(value) _c.tell('ret_cv',chan,value) end
, change = function(state) _c.tell('change',chan,state) end
, midi = function(data) _c.tell('midi',table.unpack(data)) end
, window = function(ix, direction) get_cv(chan) end
, scale = function(octave, ix) get_cv(chan) end
, quantize = function(octave, ix) get_cv(chan) end
@@ -41,30 +42,30 @@ function Input:set_mode( mode, ... )
if mode == 'stream' then
self.time = args[1] or self.time
set_input_stream( self.channel, self.time )
elseif mode == 'change' then
self.threshold = args[1] or self.threshold
self.hysteresis = args[2] or self.hysteresis
self.direction = args[3] or self.direction
set_input_change( self.channel
, self.threshold
, self.hysteresis
, self.direction
)
elseif mode == 'midi' then
set_input_midi( self.channel )
elseif mode == 'window' then
self.windows = args[1] or self.windows
self.hysteresis = args[2] or self.hysteresis
self.direction = args[3] or self.direction
elseif mode == 'scale' then
self.notes = args[1] or self.notes
elseif mode == 'quantize' then
self.tones = args[1] or self.tones
self.quants = args[2] or self.scale
elseif mode == 'ji' then
self.ratios = args[1]
else
if mode == 'change' then
self.threshold = args[1] or self.threshold
self.hysteresis = args[2] or self.hysteresis
self.direction = args[3] or self.direction
set_input_change( self.channel
, self.threshold
, self.hysteresis
, self.direction
)
elseif mode == 'window' then
self.windows = args[1] or self.windows
self.hysteresis = args[2] or self.hysteresis
self.direction = args[3] or self.direction
elseif mode == 'scale' then
self.notes = args[1] or self.notes
elseif mode == 'quantize' then
self.tones = args[1] or self.tones
self.quants = args[2] or self.scale
elseif mode == 'ji' then
self.ratios = args[1]
else
set_input_none( self.channel )
end
set_input_none( self.channel )
end
self._mode = mode
end
@@ -107,6 +108,7 @@ setmetatable(Input, Input) -- capture the metamethods
-- callback
function stream_handler( chan, val ) Input.inputs[chan].stream( val ) end
function change_handler( chan, val ) Input.inputs[chan].change( val ) end
function midi_handler( ... ) d = {...}; Input.inputs[1].midi(d) end

print 'input loaded'

2 main.c
@@ -13,7 +13,6 @@

#include "ll/debug_usart.h"
#include "ll/debug_pin.h"
#include "ll/midi.h"
#include "ll/random.h"

#include "usbd/usbd_cdc_interface.h"
@@ -41,7 +40,6 @@ int main(void)
events_init();
Metro_Init();
Caw_Init();
MIDI_Init();
II_init( II_CROW );
Random_Init();