diff --git a/src/sound/snd_mpu401.c b/src/sound/snd_mpu401.c index 33fbe16b4..5b4d2635b 100644 --- a/src/sound/snd_mpu401.c +++ b/src/sound/snd_mpu401.c @@ -80,58 +80,63 @@ mpu401_log(const char *fmt, ...) static void MPU401_ReCalcClock(mpu_t *mpu) { - int32_t maxtempo = 240, mintempo = 16; - - if (mpu->clock.timebase >= 168) - maxtempo = 179; - if (mpu->clock.timebase == 144) - maxtempo = 208; - if (mpu->clock.timebase >= 120) - maxtempo = 8; - - mpu->clock.freq = ((uint32_t)(mpu->clock.tempo * 2 * mpu->clock.tempo_rel)) >> 6; - mpu->clock.freq = mpu->clock.timebase * (mpu->clock.freq < (mintempo * 2) ? mintempo : - ((mpu->clock.freq / 2) < maxtempo ? (mpu->clock.freq / 2) : maxtempo)); + int32_t maxtempo = 240, mintempo = 16; + int32_t freq; - if (mpu->state.sync_in) { - int32_t freq = (int32_t)((float)(mpu->clock.freq) * mpu->clock.freq_mod); + if (mpu->clock.timebase >= 168) + maxtempo = 179; + if (mpu->clock.timebase == 144) + maxtempo = 208; + if (mpu->clock.timebase >= 120) + maxtempo = 8; + + mpu->clock.freq = ((uint32_t)(mpu->clock.tempo * 2 * mpu->clock.tempo_rel)) >> 6; + mpu->clock.freq = mpu->clock.timebase * (mpu->clock.freq < (mintempo * 2) ? mintempo : + ((mpu->clock.freq / 2) < maxtempo ? (mpu->clock.freq / 2) : maxtempo)); + + if (mpu->state.sync_in) { + freq = (int32_t)((float)(mpu->clock.freq) * mpu->clock.freq_mod); if ((freq > (mpu->clock.timebase * mintempo)) && (freq < (mpu->clock.timebase * maxtempo))) - mpu->clock.freq = freq; - } + mpu->clock.freq = freq; + } } + static void MPU401_StartClock(mpu_t *mpu) { - if (mpu->clock.active) - return; - if (!(mpu->state.clock_to_host || mpu->state.playing || (mpu->state.rec == M_RECON))) - return; - - mpu->clock.active = 1; - timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); + if (mpu->clock.active) + return; + if (!(mpu->state.clock_to_host || mpu->state.playing || (mpu->state.rec == M_RECON))) + return; + + mpu->clock.active = 1; + timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); } + static void MPU401_StopClock(mpu_t *mpu) { - if (mpu->state.clock_to_host || mpu->state.playing || (mpu->state.rec == M_RECON)) - return; - mpu->clock.active = 0; - timer_disable(&mpu->mpu401_event_callback); + if (mpu->state.clock_to_host || mpu->state.playing || (mpu->state.rec == M_RECON)) + return; + mpu->clock.active = 0; + timer_disable(&mpu->mpu401_event_callback); } + static void MPU401_RunClock(mpu_t *mpu) { - if (!mpu->clock.active) { - timer_disable(&mpu->mpu401_event_callback); - return; - } - timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); - mpu401_log("Next event after %i us (time constant: %i)\n", (uint64_t) ((MPU401_TIMECONSTANT/mpu->clock.freq) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT); + if (!mpu->clock.active) { + timer_disable(&mpu->mpu401_event_callback); + return; + } + timer_set_delay_u64(&mpu->mpu401_event_callback, (MPU401_TIMECONSTANT / mpu->clock.freq) * 1000 * TIMER_USEC); + mpu401_log("Next event after %i us (time constant: %i)\n", (uint64_t) ((MPU401_TIMECONSTANT/mpu->clock.freq) * 1000 * TIMER_USEC), (int) MPU401_TIMECONSTANT); } + static void MPU401_QueueByte(mpu_t *mpu, uint8_t data) { @@ -139,11 +144,12 @@ MPU401_QueueByte(mpu_t *mpu, uint8_t data) mpu->state.block_ack = 0; return; } - - if ((mpu->queue_used == 0) && (mpu->mode == M_INTELLIGENT)) { + + if (mpu->queue_used == 0) { mpu->state.irq_pending = 1; picint(1 << mpu->irq); } + if (mpu->queue_used < MPU401_QUEUE) { int pos = mpu->queue_used+mpu->queue_pos; @@ -157,33 +163,35 @@ MPU401_QueueByte(mpu_t *mpu, uint8_t data) } } + static void MPU401_RecQueueBuffer(mpu_t *mpu, uint8_t *buf, uint32_t len, int block) { - uint32_t cnt; + uint32_t cnt = 0; + int pos; - cnt = 0; - while (cnt < len) { + while (cnt < len) { if (mpu->rec_queue_used < MPU401_INPUT_QUEUE) { - int pos = mpu->rec_queue_used + mpu->rec_queue_pos; - if (pos >= MPU401_INPUT_QUEUE) - pos -= MPU401_INPUT_QUEUE; - mpu->rec_queue[pos] = buf[cnt]; - mpu->rec_queue_used++; - if ((!mpu->state.sysex_in_finished) && (buf[cnt] == MSG_EOX)) { /*finish sysex*/ - mpu->state.sysex_in_finished = 1; - break; + pos = mpu->rec_queue_used + mpu->rec_queue_pos; + if (pos >= MPU401_INPUT_QUEUE) + pos -= MPU401_INPUT_QUEUE; + mpu->rec_queue[pos] = buf[cnt]; + mpu->rec_queue_used++; + if ((!mpu->state.sysex_in_finished) && (buf[cnt] == MSG_EOX)) { + /* finish sysex */ + mpu->state.sysex_in_finished = 1; + break; + } + cnt++; } - cnt++; - } - } - - if (mpu->queue_used == 0) { + } + + if (mpu->queue_used == 0) { if (mpu->state.rec_copy || mpu->state.irq_pending) { if (mpu->state.irq_pending) { - picintc(1 << mpu->irq); - mpu->state.irq_pending = 0; - } + picintc(1 << mpu->irq); + mpu->state.irq_pending = 0; + } return; } mpu->state.rec_copy = 1; @@ -192,18 +200,19 @@ MPU401_RecQueueBuffer(mpu_t *mpu, uint8_t *buf, uint32_t len, int block) MPU401_QueueByte(mpu, mpu->rec_queue[mpu->rec_queue_pos]); mpu->rec_queue_used--; mpu->rec_queue_pos++; - } + } } + static void MPU401_ClrQueue(mpu_t *mpu) { mpu->queue_used = 0; mpu->queue_pos = 0; - mpu->rec_queue_used = 0; - mpu->rec_queue_pos = 0; - mpu->state.sysex_in_finished = 1; - mpu->state.irq_pending = 0; + mpu->rec_queue_used = 0; + mpu->rec_queue_pos = 0; + mpu->state.sysex_in_finished = 1; + mpu->state.irq_pending = 0; } @@ -218,8 +227,8 @@ MPU401_Reset(mpu_t *mpu) } mpu->mode = M_INTELLIGENT; - mpu->midi_thru = 0; - mpu->state.rec = M_RECOFF; + mpu->midi_thru = 0; + mpu->state.rec = M_RECOFF; mpu->state.eoi_scheduled = 0; mpu->state.wsd = 0; mpu->state.wsm = 0; @@ -236,38 +245,38 @@ MPU401_Reset(mpu_t *mpu) mpu->clock.tempo = mpu->clock.old_tempo = 100; mpu->clock.timebase = mpu->clock.old_timebase = 120; mpu->clock.tempo_rel = mpu->clock.old_tempo_rel = 0x40; - mpu->clock.freq_mod = 1.0; + mpu->clock.freq_mod = 1.0; mpu->clock.tempo_grad = 0; - MPU401_StopClock(mpu); - MPU401_ReCalcClock(mpu); - - for (i = 0; i < 4; i++) - mpu->clock.cth_rate[i] = 60; - - mpu->clock.cth_counter = 0; - mpu->clock.midimetro = 12; - mpu->clock.metromeas = 8; - mpu->filter.rec_measure_end = 1; - mpu->filter.rt_out = 1; - mpu->filter.rt_affection = 1; - mpu->filter.allnotesoff_out = 1; - mpu->filter.all_thru = 1; - mpu->filter.midi_thru = 1; - mpu->filter.commonmsgs_thru = 1; + MPU401_StopClock(mpu); + MPU401_ReCalcClock(mpu); - /*reset channel reference and input tables*/ - for (i = 0; i < 4; i++) { + for (i = 0; i < 4; i++) + mpu->clock.cth_rate[i] = 60; + + mpu->clock.cth_counter = 0; + mpu->clock.midimetro = 12; + mpu->clock.metromeas = 8; + mpu->filter.rec_measure_end = 1; + mpu->filter.rt_out = 1; + mpu->filter.rt_affection = 1; + mpu->filter.allnotesoff_out = 1; + mpu->filter.all_thru = 1; + mpu->filter.midi_thru = 1; + mpu->filter.commonmsgs_thru = 1; + + /* Reset channel reference and input tables. */ + for (i = 0; i < 4; i++) { mpu->chanref[i].on = 1; mpu->chanref[i].chan = i; mpu->ch_toref[i] = i; - } - - for (i = 0; i < 16; i++) { + } + + for (i = 0; i < 16; i++) { mpu->inputref[i].on = 1; mpu->inputref[i].chan = i; if (i > 3) - mpu->ch_toref[i] = 4;/*dummy reftable*/ - } + mpu->ch_toref[i] = 4; /* Dummy reftable. */ + } MPU401_ClrQueue(mpu); mpu->state.data_onoff = -1; @@ -276,19 +285,19 @@ MPU401_Reset(mpu_t *mpu) mpu->condbuf.counter = 0; mpu->condbuf.type = T_OVERFLOW; - for (i=0;i<8;i++) { + for (i = 0; i < 8; i++) { mpu->playbuf[i].type = T_OVERFLOW; mpu->playbuf[i].counter = 0; } - - /*clear MIDI buffers, terminate notes*/ - midi_clear_buffer(); - - for (i = 0xb0; i <= 0xbf; i++) { - midi_raw_out_byte(i); - midi_raw_out_byte(0x7b); - midi_raw_out_byte(0); - } + + /* Clear MIDI buffers, terminate notes. */ + midi_clear_buffer(); + + for (i = 0xb0; i <= 0xbf; i++) { + midi_raw_out_byte(i); + midi_raw_out_byte(0x7b); + midi_raw_out_byte(0); + } } @@ -313,16 +322,21 @@ MPU401_ResetDone(void *priv) static void MPU401_WriteCommand(mpu_t *mpu, uint8_t val) { - uint8_t i, j, was_uart; + uint8_t i, j, was_uart, recmsg[3]; if (mpu->state.reset) mpu->state.cmd_pending = val + 1; - if ((val != 0x3f) && (val != 0xff) && !mpu->intelligent) - return; + /* The only command recognized in UART mode is 0xFF: Reset and return to Intelligent mode. */ + if ((val != 0xff) && (mpu->mode == M_UART)) + return; - /*hack:enable midi through after the first mpu401 command is written*/ - mpu->midi_thru = 1; + /* In Intelligent mode, UART-only variants of the MPU-401 only support commands 0x3F and 0xFF. */ + if ((val != 0x3f) && (val != 0xff) && !mpu->intelligent) + return; + + /* Hack: Enable midi through after the first mpu401 command is written. */ + mpu->midi_thru = 1; if (val <= 0x2f) { /* Sequencer state */ int send_prchg = 0; @@ -383,16 +397,17 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) return; case 0x20: /* Start */ if (!(mpu->state.rec == M_RECON)) { - mpu->clock.rec_counter = 0; - mpu->state.rec = M_RECSTB; + mpu->clock.rec_counter = 0; + mpu->state.rec = M_RECSTB; } if ((mpu->state.last_rtcmd == 0xfa) || (mpu->state.last_rtcmd == 0xfb)) { - mpu->clock.rec_counter = 0; - mpu->state.rec = M_RECON; - if (mpu->filter.prchg_mask) - send_prchg = 1; - MPU401_StartClock(mpu); + mpu->clock.rec_counter = 0; + mpu->state.rec = M_RECON; + if (mpu->filter.prchg_mask) + send_prchg = 1; + MPU401_StartClock(mpu); } + break; } } MPU401_QueueByte(mpu, MSG_MPU_ACK); @@ -401,21 +416,26 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) if (((val == 0x20) || (val == 0x26)) && (mpu->state.rec == M_RECON)) MPU401_RecQueueBuffer(mpu, &rec_cnt, 1, 0); - if (send_prchg) for (i = 0; i < 16; i++) - if (mpu->filter.prchg_mask & (1 << i)) { - uint8_t recmsg[3] = {mpu->clock.rec_counter, 0xc0 | i, mpu->filter.prchg_buf[i]}; - MPU401_RecQueueBuffer(mpu, recmsg, 3, 0); - mpu->filter.prchg_mask &= ~(1 << i); + if (send_prchg) { + for (i = 0; i < 16; i++) { + if (mpu->filter.prchg_mask & (1 << i)) { + recmsg[0] = mpu->clock.rec_counter; + recmsg[1] = 0xc0 | i; + recmsg[2] = mpu->filter.prchg_buf[i]; + MPU401_RecQueueBuffer(mpu, recmsg, 3, 0); + mpu->filter.prchg_mask &= ~(1 << i); + } + } } - } else if ((val >= 0xa0) && (val <= 0xa7)) { /* Request play counter */ + } else if ((val >= 0xa0) && (val <= 0xa7)) /* Request play counter */ MPU401_QueueByte(mpu, mpu->playbuf[val & 7].counter); - } else if ((val >= 0xd0) && (val <= 0xd7)) { /* Send data */ + else if ((val >= 0xd0) && (val <= 0xd7)) { /* Send data */ mpu->state.old_track = mpu->state.track; mpu->state.track= val & 7; mpu->state.wsd = 1; mpu->state.wsm = 0; mpu->state.wsd_start = 1; - } else if ((val < 0x80) && (val >= 0x40)) { /* Set reference table channel */ + } else if ((val < 0x80) && (val >= 0x40)) { /* Set reference table channel */ mpu->chanref[(val >> 4) - 4].on = 1; mpu->chanref[(val >> 4) - 4].chan = val & 0x0f; mpu->chanref[(val >> 4) - 4].trmask = 0; @@ -438,9 +458,9 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) mpu->filter.commonmsgs_thru = 0; mpu->filter.midi_thru = 0; for (i = 0; i < 16; i++) { - mpu->inputref[i].on = 0; - for (j = 0; i < 4; j++) - mpu->inputref[i].key[j] = 0; + mpu->inputref[i].on = 0; + for (j = 0; i < 4; j++) + mpu->inputref[i].key[j] = 0; } break; case 0x34: @@ -459,7 +479,7 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) mpu->filter.rt_in = 1; break; case 0x3f: /* UART mode */ - mpu401_log("MPU-401:Set UART mode %X\n",val); + mpu401_log("MPU-401: Set UART mode %X\n",val); MPU401_QueueByte(mpu, MSG_MPU_ACK); mpu->mode = M_UART; return; @@ -481,11 +501,11 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) case 0x88: case 0x89: /* MIDI through */ mpu->filter.midi_thru = !!(val & 1); for (i = 0; i < 16; i++) { - mpu->inputref[i].on = mpu->filter.midi_thru; - if (!(val & 1)) { - for (j = 0; j < 4; j++) - mpu->inputref[i].key[j] = 0; - } + mpu->inputref[i].on = mpu->filter.midi_thru; + if (!(val & 1)) { + for (j = 0; j < 4; j++) + mpu->inputref[i].key[j] = 0; + } } break; case 0x8a: case 0x8b: /* Data in stop */ @@ -581,7 +601,7 @@ MPU401_WriteCommand(mpu_t *mpu, uint8_t val) mpu->state.command_byte = val; break; case 0xff: /* Reset MPU-401 */ - mpu401_log("MPU-401:Reset %X\n",val); + mpu401_log("MPU-401: Reset %X\n", val); timer_set_delay_u64(&mpu->mpu401_reset_callback, MPU401_RESETBUSY * 33LL * TIMER_USEC); mpu->state.reset = 1; was_uart = (mpu->mode == M_UART); @@ -1028,6 +1048,21 @@ imf_write(uint16_t addr, uint8_t val, void *priv) } +void +MPU401_ReadRaiseIRQ(mpu_t *mpu) +{ + /* Clear IRQ. */ + picintc(1 << mpu->irq); + mpu->state.irq_pending = 0; + + if (mpu->queue_used) { + /* Bytes remaining in queue, raise IRQ again. */ + mpu->state.irq_pending = 1; + picint(1 << mpu->irq); + } +} + + uint8_t MPU401_ReadData(mpu_t *mpu) { @@ -1045,35 +1080,28 @@ MPU401_ReadData(mpu_t *mpu) /* Shouldn't this check mpu->mode? */ if (mpu->mode == M_UART) { - if (mpu->state.irq_pending) { - picintc(1 << mpu->irq); - mpu->state.irq_pending = 0; - } - + MPU401_ReadRaiseIRQ(mpu); return ret; } - if (mpu->state.rec_copy && !mpu->rec_queue_used) { + if (mpu->state.rec_copy && !mpu->rec_queue_used) { mpu->state.rec_copy = 0; MPU401_EOIHandler(mpu); return ret; - } + } - /*copy from recording buffer*/ - if (!mpu->queue_used && mpu->rec_queue_used) { + /* Copy from recording buffer. */ + if (!mpu->queue_used && mpu->rec_queue_used) { mpu->state.rec_copy = 1; if (mpu->rec_queue_pos >= MPU401_INPUT_QUEUE) mpu->rec_queue_pos -= MPU401_INPUT_QUEUE; MPU401_QueueByte(mpu, mpu->rec_queue[mpu->rec_queue_pos]); mpu->rec_queue_pos++; mpu->rec_queue_used--; - } - - if (mpu->queue_used == 0) { - picintc(1 << mpu->irq); - mpu->state.irq_pending = 0; } + MPU401_ReadRaiseIRQ(mpu); + if ((ret >= 0xf0) && (ret <= 0xf7)) { /* MIDI data request */ mpu->state.track = ret & 7; @@ -1094,11 +1122,10 @@ MPU401_ReadData(mpu_t *mpu) } } - if ((ret == MSG_MPU_END) || (ret == MSG_MPU_CLOCK) || (ret == MSG_MPU_ACK) || (ret == MSG_MPU_OVERFLOW)) { + if ((ret == MSG_MPU_END) || (ret == MSG_MPU_CLOCK) || (ret == MSG_MPU_ACK) || (ret == MSG_MPU_OVERFLOW)) MPU401_EOIHandlerDispatch(mpu); - } - return(ret); + return ret; } @@ -1135,8 +1162,10 @@ mpu401_read(uint16_t addr, void *priv) break; case 1: /* Read Status */ - if (mpu->state.cmd_pending) ret=STATUS_OUTPUT_NOT_READY; - if (!mpu->queue_used) ret=STATUS_INPUT_NOT_READY; + if (mpu->state.cmd_pending) + ret = STATUS_OUTPUT_NOT_READY; + if (!mpu->queue_used) + ret = STATUS_INPUT_NOT_READY; ret |= 0x3f; mpu401_log("Read Status (0x331) %x\n", ret); @@ -1153,6 +1182,7 @@ MPU401_Event(void *priv) { mpu_t *mpu = (mpu_t *)priv; uint8_t i; + int max_meascnt; mpu401_log("MPU-401 event callback\n"); @@ -1163,22 +1193,24 @@ MPU401_Event(void *priv) if (mpu->state.irq_pending) goto next_event; - if (mpu->state.playing) { - for (i = 0; i < 8; i++) { /* Decrease counters */ - if (mpu->state.amask & (1 << i)) { - mpu->playbuf[i].counter--; - if (mpu->playbuf[i].counter <= 0) UpdateTrack(mpu, i); - } - } + if (mpu->state.playing) { + for (i = 0; i < 8; i++) { + /* Decrease counters. */ + if (mpu->state.amask & (1 << i)) { + mpu->playbuf[i].counter--; + if (mpu->playbuf[i].counter <= 0) + UpdateTrack(mpu, i); + } + } - if (mpu->state.conductor) { - mpu->condbuf.counter--; - if (mpu->condbuf.counter <= 0) { - mpu->condbuf.counter = 0xf0; - mpu->state.req_mask |= (1 << 9); + if (mpu->state.conductor) { + mpu->condbuf.counter--; + if (mpu->condbuf.counter <= 0) { + mpu->condbuf.counter = 0xf0; + mpu->state.req_mask |= (1 << 9); + } } } - } if (mpu->state.clock_to_host) { mpu->clock.cth_counter++; @@ -1189,108 +1221,108 @@ MPU401_Event(void *priv) } } - if (mpu->state.rec==M_RECON) { /* recording */ - mpu->clock.rec_counter++; - if (mpu->clock.rec_counter>=240) { - mpu->clock.rec_counter=0; - mpu->state.req_mask|=(1<<8); - } + if (mpu->state.rec == M_RECON) { + /* Recording. */ + mpu->clock.rec_counter++; + if (mpu->clock.rec_counter>=240) { + mpu->clock.rec_counter=0; + mpu->state.req_mask|=(1<<8); } + } - if (mpu->state.playing || (mpu->state.rec == M_RECON)) { - int max_meascnt = (mpu->clock.timebase * mpu->clock.midimetro * mpu->clock.metromeas) / 24; - if (max_meascnt != 0) { /* measure end */ - if (++mpu->clock.measure_counter >= max_meascnt) { - if (mpu->filter.rt_out) - midi_raw_out_rt_byte(0xf8); - mpu->clock.measure_counter = 0; - if (mpu->filter.rec_measure_end && (mpu->state.rec == M_RECON)) - mpu->state.req_mask |= (1 << 12); - } + if (mpu->state.playing || (mpu->state.rec == M_RECON)) { + max_meascnt = (mpu->clock.timebase * mpu->clock.midimetro * mpu->clock.metromeas) / 24; + if (max_meascnt != 0) { + /* Measure end. */ + if (++mpu->clock.measure_counter >= max_meascnt) { + if (mpu->filter.rt_out) + midi_raw_out_rt_byte(0xf8); + mpu->clock.measure_counter = 0; + if (mpu->filter.rec_measure_end && (mpu->state.rec == M_RECON)) + mpu->state.req_mask |= (1 << 12); } } - if (!mpu->state.irq_pending && mpu->state.req_mask) { + } + if (!mpu->state.irq_pending && mpu->state.req_mask) MPU401_EOIHandler(mpu); - } next_event: - MPU401_RunClock(mpu); - if (mpu->state.sync_in) - mpu->clock.ticks_in++; + MPU401_RunClock(mpu); + if (mpu->state.sync_in) + mpu->clock.ticks_in++; } + static void MPU401_NotesOff(mpu_t *mpu, int i) { - int j; - uint8_t key; - - if (mpu->filter.allnotesoff_out && !(mpu->inputref[i].on && - (mpu->inputref[i].key[0]|mpu->inputref[i].key[1]| - mpu->inputref[i].key[2]|mpu->inputref[i].key[3]))) { - for (j=0;j<4;j++) - mpu->chanref[mpu->ch_toref[i]].key[j]=0; - midi_raw_out_byte(0xb0|i); - midi_raw_out_byte(123); - midi_raw_out_byte(0); - } else if (mpu->chanref[mpu->ch_toref[i]].on) { - for (key=0;key<128;key++) { - if ((mpu->chanref[mpu->ch_toref[i]].M_GETKEY) && - !(mpu->inputref[i].on && (mpu->inputref[i].M_GETKEY))) { - midi_raw_out_byte(0x80|i); - midi_raw_out_byte(key); - midi_raw_out_byte(0); - } - mpu->chanref[mpu->ch_toref[i]].M_DELKEY; + int j; + uint8_t key; + + if (mpu->filter.allnotesoff_out && !(mpu->inputref[i].on && + (mpu->inputref[i].key[0] | mpu->inputref[i].key[1] | + mpu->inputref[i].key[2] | mpu->inputref[i].key[3]))) { + for (j=0;j<4;j++) + mpu->chanref[mpu->ch_toref[i]].key[j]=0; + midi_raw_out_byte(0xb0 | i); + midi_raw_out_byte(123); + midi_raw_out_byte(0); + } else if (mpu->chanref[mpu->ch_toref[i]].on) { + for (key = 0; key < 128; key++) { + if ((mpu->chanref[mpu->ch_toref[i]].M_GETKEY) && + !(mpu->inputref[i].on && (mpu->inputref[i].M_GETKEY))) { + midi_raw_out_byte(0x80|i); + midi_raw_out_byte(key); + midi_raw_out_byte(0); } + mpu->chanref[mpu->ch_toref[i]].M_DELKEY; } + } } + /*Input handler for SysEx */ static int MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort) { - mpu_t *mpu = (mpu_t *)p; - - mpu401_log("MPU401 Input Sysex\n"); - - int i; - - if (mpu->filter.sysex_in) { - if (abort) { - mpu->state.sysex_in_finished=1; - mpu->rec_queue_used=0;/*reset also the input queue*/ - return 0; - } - if (mpu->state.sysex_in_finished) { - if (mpu->rec_queue_used>=MPU401_INPUT_QUEUE) - return len; - uint8_t val_ff=0xff; - MPU401_RecQueueBuffer(mpu,&val_ff,1,1); - mpu->state.sysex_in_finished=0; - mpu->clock.rec_counter=0; - } + mpu_t *mpu = (mpu_t *)p; + int i; + uint8_t val_ff = 0xff; + + mpu401_log("MPU401 Input Sysex\n"); + + if (mpu->filter.sysex_in) { + if (abort) { + mpu->state.sysex_in_finished=1; + mpu->rec_queue_used=0;/*reset also the input queue*/ + return 0; + } + if (mpu->state.sysex_in_finished) { if (mpu->rec_queue_used>=MPU401_INPUT_QUEUE) return len; - int available=MPU401_INPUT_QUEUE-mpu->rec_queue_used; + MPU401_RecQueueBuffer(mpu, &val_ff, 1, 1); + mpu->state.sysex_in_finished=0; + mpu->clock.rec_counter=0; + } + if (mpu->rec_queue_used>=MPU401_INPUT_QUEUE) + return len; + int available = MPU401_INPUT_QUEUE - mpu->rec_queue_used; - if (available>=len) { - MPU401_RecQueueBuffer(mpu,buffer,len,1); + if (available >= len) { + MPU401_RecQueueBuffer(mpu, buffer, len, 1); + return 0; + } else { + MPU401_RecQueueBuffer(mpu,buffer, available, 1); + if (mpu->state.sysex_in_finished) return 0; - } - else { - MPU401_RecQueueBuffer(mpu,buffer,available,1); - if (mpu->state.sysex_in_finished) - return 0; - return (len-available); - } + return (len - available); } - else if (mpu->filter.sysex_thru && mpu->midi_thru) { - midi_raw_out_byte(0xf0); - for (i=0;ifilter.sysex_thru && mpu->midi_thru) { + midi_raw_out_byte(0xf0); + for (i = 0; i < len; i++) + midi_raw_out_byte(*(buffer+i)); + } + return 0; } @@ -1298,203 +1330,222 @@ MPU401_InputSysex(void *p, uint8_t *buffer, uint32_t len, int abort) static void MPU401_InputMsg(void *p, uint8_t *msg) { - mpu_t *mpu = (mpu_t *)p; + mpu_t *mpu = (mpu_t *)p; + int i, tick; + static uint8_t old_msg = 0; + uint8_t len = msg[3], key; + uint8_t recdata[2], recmsg[4]; + int send = 1, send_thru = 0; + int retrigger_thru = 0, midistatus = 0, chan, chrefnum; - /*abort if sysex transfer is in progress*/ - if (!mpu->state.sysex_in_finished) { - mpu401_log("SYSEX in progress\n"); - return; + /* Abort if sysex transfer is in progress. */ + if (!mpu->state.sysex_in_finished) { + mpu401_log("SYSEX in progress\n"); + return; + } + + mpu401_log("MPU401 Input Msg\n"); + + if (mpu->mode == M_INTELLIGENT) { + if (msg[0] < 0x80) { + /* Expand running status */ + midistatus = 1; + msg[2] = msg[1]; + msg[1] = msg[0]; + msg[0] = old_msg; } - - mpu401_log("MPU401 Input Msg\n"); - - int i; - static uint8_t old_msg=0; - uint8_t len=msg[3]; - int send=1; - int send_thru=0; - int retrigger_thru=0; - int midistatus=0; - if (mpu->mode==M_INTELLIGENT) { - if (msg[0]<0x80) { /* Expand running status */ - midistatus=1; - msg[2]=msg[1];msg[1]=msg[0];msg[0]=old_msg; - } - old_msg=msg[0]; - int chan=msg[0]&0xf; - int chrefnum=mpu->ch_toref[chan]; - uint8_t key=msg[1]&0x7f; - if (msg[0]<0xf0) { //if non-system msg - if (!(mpu->state.midi_mask&(1<filter.all_thru) - send_thru=1; - else if (mpu->filter.midi_thru) - send_thru=1; - switch (msg[0]&0xf0) { - case 0x80: /*note off*/ - if (send_thru) { - if (mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY)) - send_thru=0; - if (!mpu->filter.midi_thru) - break; - if (!(mpu->inputref[chan].M_GETKEY)) - send_thru=0; - mpu->inputref[chan].M_DELKEY; - } - break; - case 0x90: /*note on*/ - if (send_thru) { - if (mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY)) - retrigger_thru=1; - if (!mpu->filter.midi_thru) - break; - if (mpu->inputref[chan].M_GETKEY) - retrigger_thru=1; - mpu->inputref[chan].M_SETKEY; - } - break; - case 0xb0: - if (msg[1]>=120) { - send_thru=0; - if (msg[1]==123) { /* All notes off */ - for (key=0;key<128;key++) { - if (!(mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY))) - if (mpu->inputref[chan].on && mpu->inputref[chan].M_GETKEY) { - midi_raw_out_byte(0x80|chan); - midi_raw_out_byte(key); - midi_raw_out_byte(0); - } + old_msg = msg[0]; + chan = msg[0] & 0xf; + chrefnum = mpu->ch_toref[chan]; + key = msg[1] & 0x7f; + if (msg[0] < 0xf0) { + /* If non-system msg. */ + if (!(mpu->state.midi_mask & (1 << chan)) && mpu->filter.all_thru) + send_thru = 1; + else if (mpu->filter.midi_thru) + send_thru = 1; + switch (msg[0] & 0xf0) { + case 0x80: /* Note off. */ + if (send_thru) { + if (mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY)) + send_thru = 0; + if (!mpu->filter.midi_thru) + break; + if (!(mpu->inputref[chan].M_GETKEY)) + send_thru = 0; + mpu->inputref[chan].M_DELKEY; + } + break; + case 0x90: /* Note on. */ + if (send_thru) { + if (mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY)) + retrigger_thru = 1; + if (!mpu->filter.midi_thru) + break; + if (mpu->inputref[chan].M_GETKEY) + retrigger_thru = 1; + mpu->inputref[chan].M_SETKEY; + } + break; + case 0xb0: + if (msg[1] >= 120) { + send_thru = 0; + if (msg[1] == 123) { + /* All notes off. */ + for (key = 0; key < 128; key++) { + if (!(mpu->chanref[chrefnum].on && (mpu->chanref[chrefnum].M_GETKEY))) + if (mpu->inputref[chan].on && mpu->inputref[chan].M_GETKEY) { + midi_raw_out_byte(0x80 | chan); + midi_raw_out_byte(key); + midi_raw_out_byte(0); + } mpu->inputref[chan].M_DELKEY; } } } break; - } + } } - if (msg[0]>=0xf0 || (mpu->state.midi_mask&(1<filter.bender_in) - send=0; - break; - case 0xb0: /*control change*/ - if (!mpu->filter.bender_in && msg[1]<64) - send=0; - if (msg[1]>=120) { - if (mpu->filter.modemsgs_in) - send=1; - } - break; - case 0xc0: /*program change*/ - if ((mpu->state.rec!=M_RECON) && !mpu->filter.data_in_stop) { - mpu->filter.prchg_buf[chan]=msg[1]; - mpu->filter.prchg_mask|=1<filter.bender_in) - send=0; - break; - case 0xf0: //system message - if (msg[0]==0xf8) { - send=0; - if (mpu->clock.active && mpu->state.sync_in) { - send = 0;/*don't pass to host in this mode?*/ - int tick=mpu->clock.timebase/24; - if (mpu->clock.ticks_in!=tick) { - if (!mpu->clock.ticks_in || (mpu->clock.ticks_in>tick*2)) - mpu->clock.freq_mod*=2.0; - else { - if (ABS(mpu->clock.ticks_in-tick)==1) - mpu->clock.freq_mod/=mpu->clock.ticks_in/(float)(tick*2); - else - mpu->clock.freq_mod/=mpu->clock.ticks_in/(float)(tick); - } - MPU401_ReCalcClock(mpu); + } + if ((msg[0] >= 0xf0) || (mpu->state.midi_mask & (1 << chan))) { + switch (msg[0] & 0xf0) { + case 0xa0: /* Aftertouch. */ + if (!mpu->filter.bender_in) + send = 0; + break; + case 0xb0: /* Control change. */ + if (!mpu->filter.bender_in && (msg[1] < 64)) + send = 0; + if (msg[1] >= 120) { + if (mpu->filter.modemsgs_in) + send = 1; + } + break; + case 0xc0: /* Program change. */ + if ((mpu->state.rec != M_RECON) && !mpu->filter.data_in_stop) { + mpu->filter.prchg_buf[chan] = msg[1]; + mpu->filter.prchg_mask |= 1 << chan; + } + break; + case 0xd0: /* Ch pressure. */ + case 0xe0: /* Pitch wheel. */ + if (!mpu->filter.bender_in) + send = 0; + break; + case 0xf0: /* System message. */ + if (msg[0] == 0xf8) { + send = 0; + if (mpu->clock.active && mpu->state.sync_in) { + send = 0; /* Don't pass to host in this mode? */ + tick = mpu->clock.timebase / 24; + if (mpu->clock.ticks_in != tick) { + if (!mpu->clock.ticks_in || (mpu->clock.ticks_in > (tick * 2))) + mpu->clock.freq_mod *= 2.0; + else { + if (ABS(mpu->clock.ticks_in-tick) == 1) + mpu->clock.freq_mod /= mpu->clock.ticks_in / (float) (tick * 2); + else + mpu->clock.freq_mod /= mpu->clock.ticks_in / (float) (tick); } - mpu->clock.ticks_in=0; + MPU401_ReCalcClock(mpu); } + mpu->clock.ticks_in = 0; } - else if (msg[0]>0xf8) { /*realtime*/ - if (!(mpu->filter.rt_in && msg[0]<=0xfc && msg[0]>=0xfa)) { - uint8_t recdata[2]={0xff,msg[0]}; - MPU401_RecQueueBuffer(mpu,recdata,2,1); - send=0; - } + } else if (msg[0] > 0xf8) { /* Realtime. */ + if (!(mpu->filter.rt_in && (msg[0] <= 0xfc) && (msg[0] >= 0xfa))) { + recdata[0] = 0xff; + recdata[1] = msg[0]; + MPU401_RecQueueBuffer(mpu, recdata, 2, 1); + send = 0; } - else { /*common or system*/ - send=0; - if (msg[0]==0xf2 || msg[0]==0xf3 || msg[0]==0xf6) { - if (mpu->filter.commonmsgs_in) - send=1; - if (mpu->filter.commonmsgs_thru) - for (i=0;ifilter.commonmsgs_in) + send = 1; + if (mpu->filter.commonmsgs_thru) + for (i = 0; i < len; i++) + midi_raw_out_byte(msg[i]); } - if (send) { - uint8_t recmsg[4]={0xff,msg[0],msg[1],msg[2]}; - MPU401_RecQueueBuffer(mpu,recmsg,len+1,1); - } - if (mpu->filter.rt_affection) switch(msg[0]) { - case 0xf2:case 0xf3: - mpu->state.block_ack=1; - MPU401_WriteCommand(mpu,0xb8);/*clear play counters*/ + } + if (send) { + recmsg[0] = 0xff; + recmsg[1] = msg[0]; + recmsg[2] = msg[1]; + recmsg[3] = msg[2]; + MPU401_RecQueueBuffer(mpu, recmsg, len + 1, 1); + } + if (mpu->filter.rt_affection) { + switch(msg[0]) { + case 0xf2: case 0xf3: + mpu->state.block_ack = 1; + MPU401_WriteCommand(mpu, 0xb8); /* Clear play counters. */ break; case 0xfa: - mpu->state.block_ack=1; - MPU401_WriteCommand(mpu,0xa);/*start,play*/ + mpu->state.block_ack = 1; + MPU401_WriteCommand(mpu, 0xa); /* Start, play. */ if (mpu->filter.rt_out) midi_raw_out_rt_byte(msg[0]); break; case 0xfb: - mpu->state.block_ack=1; - MPU401_WriteCommand(mpu,0xb);/*continue,play*/ + mpu->state.block_ack = 1; + MPU401_WriteCommand(mpu, 0xb); /* Continue, play. */ if (mpu->filter.rt_out) midi_raw_out_rt_byte(msg[0]); break; case 0xfc: - mpu->state.block_ack=1; - MPU401_WriteCommand(mpu,0xd);/*stop: play,rec,midi*/ + mpu->state.block_ack = 1; + MPU401_WriteCommand(mpu, 0xd) ;/* Stop: Play, rec, midi */ if (mpu->filter.rt_out) midi_raw_out_rt_byte(msg[0]); break; } return; - } - if (send_thru && mpu->midi_thru) { - if (retrigger_thru) { - midi_raw_out_byte(0x80|(msg[0]&0xf)); - midi_raw_out_byte(msg[1]); - midi_raw_out_byte(msg[2]); - } - for (i=0/*((midistatus && !retrigger_thru)? 1:0)*/;istate.rec==M_RECON) { - uint8_t recmsg[4]={mpu->clock.rec_counter,msg[0],msg[1],msg[2]}; - MPU401_RecQueueBuffer(mpu,recmsg,len+1,1); - mpu->clock.rec_counter=0; - } - else if (mpu->filter.data_in_stop) { - if (mpu->filter.timing_in_stop) { - uint8_t recmsg[4]={0,msg[0],msg[1],msg[2]}; - MPU401_RecQueueBuffer(mpu,recmsg,len+1,1); - } - else { - uint8_t recmsg[4]={msg[0],msg[1],msg[2],0}; - MPU401_RecQueueBuffer(mpu,recmsg,len,1); - } + } + if (send_thru && mpu->midi_thru) { + if (retrigger_thru) { + midi_raw_out_byte(0x80 | (msg[0] & 0xf)); + midi_raw_out_byte(msg[1]); + midi_raw_out_byte(msg[2]); + } + for (i = 0; i < len; i++) + midi_raw_out_byte(msg[i]); + } + if (send) { + if (mpu->state.rec == M_RECON) { + recmsg[0] = mpu->clock.rec_counter; + recmsg[1] = msg[0]; + recmsg[2] = msg[1]; + recmsg[3] = msg[2]; + MPU401_RecQueueBuffer(mpu, recmsg, len + 1, 1); + mpu->clock.rec_counter = 0; + } + else if (mpu->filter.data_in_stop) { + if (mpu->filter.timing_in_stop) { + recmsg[0] = 0; + recmsg[1] = msg[0]; + recmsg[2] = msg[1]; + recmsg[3] = msg[2]; + MPU401_RecQueueBuffer(mpu, recmsg, len + 1, 1); + } else { + recmsg[0] = msg[0]; + recmsg[1] = msg[1]; + recmsg[2] = msg[2]; + recmsg[3] = 0; + MPU401_RecQueueBuffer(mpu, recmsg, len, 1); } } - return; - } - /*UART mode input*/ - for (i=0;iirq); } + return; + } + + /* UART mode input. */ + for (i = 0; i < len; i++) { + MPU401_QueueByte(mpu, msg[i]); + picint(1 << mpu->irq); + } } @@ -1530,7 +1581,8 @@ mpu401_init(mpu_t *mpu, uint16_t addr, int irq, int mode) void mpu401_device_add(void) { - if (!mpu401_standalone_enable) return; + if (!mpu401_standalone_enable) + return; if (machines[machine].flags & MACHINE_MCA) device_add(&mpu401_mca_device);