2021年3月30日火曜日

Tiny USB のMIDIクラスの受信ルーチン

先日見つけた Tiny USB のサンプルコードは送信しかしていなかったので受信はどうするのかなと色々見てたのですが特にドキュメントも用意されていない様子。まぁこれぐらいのことはソースコードを読んで理解しろということなのかもしれません。

とりあえずサンプルコードで送信している関数tudi_midi_write24()をgrepしてみるとこれはmidi_device.hというヘッダーファイルにインライン関数として定義されていました。
同列に用意されているAPIは以下の通り。

//--------------------------------------------------------------------+
// Application API (Single Interface)
//--------------------------------------------------------------------+
static inline bool     tud_midi_mounted    (void);
static inline uint32_t tud_midi_available  (void);
static inline uint32_t tud_midi_read       (voidbufferuint32_t bufsize);
static inline void     tud_midi_read_flush (void);
static inline uint32_t tud_midi_write      (uint8_t jack_iduint8_t constbufferuint32_t bufsize);
static inline uint32_t tudi_midi_write24   (uint8_t jack_iduint8_t b1uint8_t b2uint8_t b3);
static inline bool     tud_midi_receive    (uint8_t packet[4]);
static inline bool     tud_midi_send       (uint8_t const packet[4]);

3バイトメッセージの送信関数はあるのに2バイトメッセージの送信関数は無いんだなという中途半端感はありますが、問題はそこではなく受信関数でした。この中で受信に関係ありそうなのはtud_midi_read()とtud_midi_read_flush()。ソースコードを確認してみたところtud_midi_available()も受信用APIでした。

static inline uint32_t tud_midi_available(void);
受信FIFOにあるデータ数を返す。

static inline uint32_t tud_midi_read(void* buffer, uint32_t bufsize);
受信FIFOにあるデータを指定されたバッファにコピーする。

static inline void     tud_midi_read_flush(void);
受信FIFOをクリアする。

ということらしいのでtud_midi_available()でデータを受信しているか確認してデータがあればtud_midi_read()で読み込むというのが正しそうです。

実際のコードにするとこんな感じ

void MIDI_ReadTaskvoid )
{
    uint8_t buff[RX_BUFFSIZE];
    
    uint32_t read_size = tud_midi_available();
    if ( read_size > 0 )
    {
        int32_t i;
        read_size = tud_midi_readbuffRX_BUFFSIZE );

        for ( i=0i<read_sizei++ )
        {
            printf"0x%02X "buff[i] );
        }
        puts(" ");
    }
}

試しにMIDI-OXからノートメッセージを送信してみるとコンソールに正しく表示されました。この関数をメインループの中からポーリングしても良いですがtud_midi_rx_cb()というコールバックの仕組みも用意されているのでこちらから呼ぶのがスマートですね。
RTOSが使えるようになったらここでタスクを起床してMIDI処理をさせる流れです。

void tud_midi_rx_cb(uint8_t itf)
{
    MIDI_ReadTask();
}



0 件のコメント:

コメントを投稿