/* Send a buffer full of MIDI data to the DSP
Returns how many actually written or < 0 on error */ staticint write_midi(struct echoaudio *chip, u8 *data, int bytes)
{ if (snd_BUG_ON(bytes <= 0 || bytes >= MIDI_OUT_BUFFER_SIZE)) return -EINVAL;
if (wait_handshake(chip)) return -EIO;
/* HF4 indicates that it is safe to write MIDI output data */ if (! (get_dsp_register(chip, CHI32_STATUS_REG) & CHI32_STATUS_REG_HF4)) return0;
/* Run the state machine for MIDI input data MIDItimecodesyncisn'tsupportedbythiscoderightnow,butyoustillneed thisstatemachinetoparsetheincomingMIDIdatastream.EverytimetheDSP seesa0xF1bytecomein,itaddstheDSPsamplepositiontotheMIDIdata stream.TheDSPsamplepositionisrepresentedasa32bitunsignedvalue, withthehigh16bitsfirst,followedbythelow16bits.Sincethesearen't
real MIDI bytes, the following logic is needed to skip them. */ staticinlineint mtc_process_data(struct echoaudio *chip, short midi_byte)
{ switch (chip->mtc_state) { case MIDI_IN_STATE_NORMAL: if (midi_byte == 0xF1)
chip->mtc_state = MIDI_IN_STATE_TS_HIGH; break; case MIDI_IN_STATE_TS_HIGH:
chip->mtc_state = MIDI_IN_STATE_TS_LOW; return MIDI_IN_SKIP_DATA; break; case MIDI_IN_STATE_TS_LOW:
chip->mtc_state = MIDI_IN_STATE_F1_DATA; return MIDI_IN_SKIP_DATA; break; case MIDI_IN_STATE_F1_DATA:
chip->mtc_state = MIDI_IN_STATE_NORMAL; break;
} return0;
}
/* This function is called from the IRQ handler and it reads the midi data
from the DSP's buffer. It returns the number of bytes received. */ staticint midi_service_irq(struct echoaudio *chip)
{ shortint count, midi_byte, i, received;
/* The count is at index 0, followed by actual data */
count = le16_to_cpu(chip->comm_page->midi_input[0]);
if (snd_BUG_ON(count >= MIDI_IN_BUFFER_SIZE)) return0;
/* Get the MIDI data from the comm page */
received = 0; for (i = 1; i <= count; i++) { /* Get the MIDI byte */
midi_byte = le16_to_cpu(chip->comm_page->midi_input[i]);
/* Parse the incoming MIDI stream. The incoming MIDI data consistsofMIDIbytesandtimestampsfortheMIDItimecode 0xF1bytes.mtc_process_data()isalittlestatemachinethat parsesthestream.IfyougetMIDI_IN_SKIP_DATAback,then thisisatimestampbyte,notaMIDIbyte,sodon'tstoreit
in the MIDI input buffer. */ if (mtc_process_data(chip, midi_byte) == MIDI_IN_SKIP_DATA) continue;
/* No interrupts are involved: we have to check at regular intervals
if the card's output buffer has room for new data. */
sent = 0;
spin_lock_irqsave(&chip->lock, flags);
chip->midi_full = 0; if (!snd_rawmidi_transmit_empty(chip->midi_out)) {
bytes = snd_rawmidi_transmit_peek(chip->midi_out, buf,
MIDI_OUT_BUFFER_SIZE - 1);
dev_dbg(chip->card->dev, "Try to send %d bytes...\n", bytes);
sent = write_midi(chip, buf, bytes); if (sent < 0) {
dev_err(chip->card->dev, "write_midi() error %d\n", sent); /* retry later */
sent = 9000;
chip->midi_full = 1;
} elseif (sent > 0) {
dev_dbg(chip->card->dev, "%d bytes sent\n", sent);
snd_rawmidi_transmit_ack(chip->midi_out, sent);
} else { /* Buffer is full. DSP's internal buffer is 64 (128 ?)
bytes long. Let's wait until half of them are sent */
dev_dbg(chip->card->dev, "Full\n");
sent = 32;
chip->midi_full = 1;
}
}
/* We restart the timer only if there is some data left to send */ if (!snd_rawmidi_transmit_empty(chip->midi_out) && chip->tinuse) { /* The timer will expire slightly after the data has been
sent */
time = (sent << 3) / 25 + 1; /* 8/25=0.32ms to send a byte */
mod_timer(&chip->timer, jiffies + (time * HZ + 999) / 1000);
dev_dbg(chip->card->dev, "Timer armed(%d)\n", ((time * HZ + 999) / 1000));
}
spin_unlock_irqrestore(&chip->lock, flags);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.