Changeset 0529a19 in buchla-emu for emu


Ignore:
Timestamp:
10/26/2017 08:04:09 PM (6 years ago)
Author:
Alexander Heinrich <alex.heinrich@…>
Branches:
master
Children:
5326a5e
Parents:
0d83ce8
Message:

Add basic handling of midi input.

Location:
emu
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • emu/cpu.c

    r0d83ce8 r0529a19  
    9191        { 0x3a4001, 0x3a8001, 0, lcd_init, lcd_quit, lcd_exec, lcd_read, lcd_write },
    9292        { 0x3a8001, 0x3ac001, 5, ser_init, ser_quit, ser_exec, ser_read, ser_write },
    93         { 0x3ac001, 0x3b0001, 0, mid_init, mid_quit, mid_exec, mid_read, mid_write },
     93        { 0x3ac001, 0x3b0001, 5, mid_init, mid_quit, mid_exec, mid_read, mid_write },
    9494        { 0x3b0001, 0x3b4001, 0, fdd_init, fdd_quit, fdd_exec, fdd_read, fdd_write },
    9595        { 0x3b4001, 0x3b8001, 0, snd_init, snd_quit, snd_exec, snd_read, snd_write },
  • emu/mid.c

    r0d83ce8 r0529a19  
    1717
    1818#include <all.h>
     19#include <rtmidi/rtmidi_c.h>
    1920
    2021#define ver(...) _ver(mid_verbose, 0, __VA_ARGS__)
    2122#define ver2(...) _ver(mid_verbose, 1, __VA_ARGS__)
    2223#define ver3(...) _ver(mid_verbose, 2, __VA_ARGS__)
    23 
    24 int32_t mid_verbose = 0;
    2524
    2625#define REG_IER_ISR 0
     
    2928#define REG_TDR_RDR 3
    3029
     30#define BUF_SZ 128
     31
     32typedef struct {
     33        int32_t buf_hd;
     34        int32_t buf_tl;
     35        uint8_t buf[BUF_SZ];
     36        bool irq_r;
     37        bool irq_t;
     38        bool rdr_ok;
     39        uint8_t rdr;
     40} state_t;
     41
     42static state_t state[] = {
     43        { .buf_hd = 0, .buf_tl = 0, .irq_r = false, .irq_t = false, .rdr_ok = false, .rdr = 0x00 },
     44        { .buf_hd = 0, .buf_tl = 0, .irq_r = false, .irq_t = false, .rdr_ok = false, .rdr = 0x00 }
     45};
     46
     47int32_t mid_verbose = 0;
     48
     49struct RtMidiWrapper* midiin;
     50
     51static void xmit(int32_t un)
     52{
     53        int32_t i = state[un].buf_tl;
     54        ver2("mid xmit %d %d", i, state[un].buf_hd);
     55
     56        if (i >= state[un].buf_hd) {
     57                return;
     58        }
     59
     60        uint8_t byte = state[un].buf[i % BUF_SZ];
     61        ver2("mid xmit 0x%02x", byte);
     62
     63        state[un].rdr = byte;
     64        state[un].rdr_ok = true;
     65        state[un].irq_r = true;
     66
     67        state[un].buf_tl = i + 1;
     68
     69        if (state[un].buf_tl >= BUF_SZ) {
     70                state[un].buf_hd -= BUF_SZ;
     71                state[un].buf_tl -= BUF_SZ;
     72                ver2("mid adj %d %d", state[un].buf_tl, state[un].buf_hd);
     73        }
     74}
     75
     76static void out_lk(int32_t un, uint8_t c)
     77{
     78        int32_t i = state[un].buf_hd;
     79        ver2("mid out %d %d 0x%02x", state[un].buf_tl, i, c);
     80
     81        if (i >= state[un].buf_tl + BUF_SZ) {
     82                err("midi port %d losing data", un);
     83                return;
     84        }
     85
     86        state[un].buf[i % BUF_SZ] = c;
     87        state[un].buf_hd = i + 1;
     88
     89        if (!state[un].irq_r && !state[un].rdr_ok) {
     90                xmit(un);
     91        }
     92}
     93
     94static void out(int32_t un, uint8_t c)
     95{
     96        if (SDL_LockMutex(cpu_mutex) < 0) {
     97                fail("SDL_LockMutex() failed: %s", SDL_GetError());
     98        }
     99
     100        out_lk(un, c);
     101
     102        if (SDL_UnlockMutex(cpu_mutex) < 0) {
     103                fail("SDL_UnlockMutex() failed: %s", SDL_GetError());
     104        }
     105}
     106
     107static void midi_callback(double timeStamp, const unsigned char* message, void *userData) {
     108        ver2("Timestamp %f\n", timeStamp);
     109
     110        for (uint8_t i = 0; i < sizeof(message); i++) {
     111                ver2("Message %i %u", i, (uint8_t) message[i]);
     112                out(0, message[i]);
     113        }
     114}
     115
    31116void mid_init(void)
    32117{
    33118        ver("mid init");
     119
     120        midiin = rtmidi_in_create_default();
     121        ver2("%p", midiin->ptr);
     122        // check if null
     123        uint32_t portcount = rtmidi_get_port_count(midiin);
     124        ver2("%d", midiin->ok);
     125
     126        if (portcount == 0) {
     127                midiin = NULL;
     128                ver2("no midi ports\n");
     129                return;
     130        }
     131
     132        for (uint32_t i = 0; i < portcount; i++) {
     133                ver2("Port %d: %s", i, rtmidi_get_port_name(midiin, i));
     134        }
     135
     136        rtmidi_open_port(midiin, 0, rtmidi_get_port_name(midiin, 0));
     137        if(!midiin->ok) {
     138                fail("Failed to open Midi port");
     139        }
     140
     141        rtmidi_in_set_callback(midiin, midi_callback, midiin->data);
     142        if(!midiin->ok) {
     143                fail("Failed to set Midi Callback");
     144        }
    34145}
    35146
    36147void mid_quit(void)
    37148{
     149        if(midiin) {
     150                rtmidi_close_port(midiin);
     151                rtmidi_in_free(midiin);
     152        }
     153
    38154        ver("mid quit");
    39155}
     
    42158{
    43159        ver3("mid exec");
    44         return false;
     160        return state[0].irq_r || state[0].irq_t || state[1].irq_r || state[1].irq_t;
    45161}
    46162
     
    48164{
    49165        ver2("mid rd %u:%d", off, sz * 8);
    50         return 0;
     166
     167        if (sz != 1 || off > 7) {
     168                fail("invalid mid rd %u:%d", off, sz * 8);
     169        }
     170
     171        int32_t rg = (int32_t)(off % 4);
     172        int32_t un = (int32_t)(off / 4);
     173
     174        uint32_t rv;
     175
     176        switch (rg) {
     177        case REG_IER_ISR:
     178                rv = (uint32_t)(0xc0 | (state[un].rdr_ok ? 0x01 : 0x00));
     179                state[un].irq_r = false;
     180                state[un].irq_t = false;
     181                ver2("ISR[%d] 0x%02x", un, rv);
     182                break;
     183
     184        case REG_TDR_RDR:
     185                rv = state[un].rdr;
     186                state[un].rdr_ok = false;
     187                ver2("RDR[%d] 0x%02x", un, rv);
     188                break;
     189
     190        default:
     191                rv = 0x00;
     192                break;
     193        }
     194
     195        if (!state[un].irq_r && !state[un].rdr_ok) {
     196                xmit(un);
     197        }
     198
     199        return rv;
    51200}
    52201
Note: See TracChangeset for help on using the changeset viewer.