Updated iap stuff

This commit is contained in:
Ross Owen
2012-03-02 17:25:24 +00:00
parent ddd6e6523c
commit 017ef915bb
3 changed files with 263 additions and 218 deletions

View File

@@ -889,6 +889,14 @@ int AudioClassRequests_2(XUD_ep ep0_out, XUD_ep ep0_in, SetupPacket &sp, chanend
storeFreq(buffer, i, 192000); storeFreq(buffer, i, 192000);
num_freqs++; num_freqs++;
#endif #endif
#if MAX_FREQ >= 352800
storeFreq(buffer, i, 352800);
num_freqs++;
#endif
#if MAX_FREQ >= 384000
storeFreq(buffer, i, 384000);
num_freqs++;
#endif
storeShort(buffer, 0, num_freqs); storeShort(buffer, 0, num_freqs);
// break; // break;
//} //}

View File

@@ -15,7 +15,7 @@
* \param cable_number the cable number of the MIDI implementation. * \param cable_number the cable number of the MIDI implementation.
* This should be set to 0. * This should be set to 0.
**/ **/
void usb_midi(in port ?p_midi_in, out port ?p_midi_out, void usb_midi(port ?p_midi_in, port ?p_midi_out,
clock ?clk_midi, clock ?clk_midi,
chanend c_midi, chanend c_midi,
unsigned cable_number, unsigned cable_number,
@@ -61,5 +61,7 @@ INLINE void midi_send_ack(chanend c) {
outuchar(c, 0); outuchar(c, 0);
outuchar(c, 0); outuchar(c, 0);
} }
#define MIDI_RATE (31250)
#define MIDI_BITTIME (XS1_TIMER_MHZ * 1000000 / MIDI_RATE)
#define MIDI_BITTIME_2 (MIDI_BITTIME>>1)
#endif // __usb_midi_h__ #endif // __usb_midi_h__

View File

@@ -6,13 +6,14 @@
#include "midiinparse.h" #include "midiinparse.h"
#include "midioutparse.h" #include "midioutparse.h"
#include "queue.h" #include "queue.h"
//#include "port32A.h"
#ifdef IAP #ifdef IAP
#include "iAP.h" #include "iAP.h"
#include "iapuser.h"
#endif #endif
//#define MIDI_LOOPBACK 1 //#define MIDI_LOOPBACK 1
static unsigned makeSymbol(unsigned data) { static unsigned makeSymbol(unsigned data)
{
// Start and stop bits to the data packet // Start and stop bits to the data packet
// like 10'b1dddddddd0 // like 10'b1dddddddd0
return (data << 1) | 0x200; return (data << 1) | 0x200;
@@ -31,27 +32,31 @@ int th_count = 0; // MIDI sent (To Host)
static inline void handle_byte_from_uart(chanend c_midi, struct midi_in_parse_state &mips, int cable_number, static inline void handle_byte_from_uart(chanend c_midi, struct midi_in_parse_state &mips, int cable_number,
int &got_next_event, int &next_event, int &waiting_for_ack, int byte) int &got_next_event, int &next_event, int &waiting_for_ack, int byte)
{ {
int valid; int valid;
unsigned event; unsigned event;
{valid, event} = midi_in_parse(mips, cable_number, byte); {valid, event} = midi_in_parse(mips, cable_number, byte);
if (valid && !got_next_event) { if (valid && !got_next_event)
// data to send to host {
if (!waiting_for_ack) { // data to send to host
// send data if (!waiting_for_ack)
event = byterev(event); {
outuint(c_midi, event); // send data
th_count++; event = byterev(event);
waiting_for_ack = 1; outuint(c_midi, event);
th_count++;
waiting_for_ack = 1;
}
else
{
event = byterev(event);
next_event = event;
got_next_event = 1;
}
} }
else { else if (valid)
event = byterev(event); {
next_event = event; // printstr("g\n");
got_next_event = 1;
} }
}
else if (valid) {
// printstr("g\n");
}
} }
#endif #endif
@@ -68,27 +73,11 @@ unsigned authenticating = 0;
// state for auto-selecting dock or USB B // state for auto-selecting dock or USB B
extern unsigned polltime; extern unsigned polltime;
#ifdef IO_EXPANSION #ifdef IAP
extern port p_i2c_scl;
extern port p_i2c_sda;
#define p_midi_out p_i2c_scl
#define p_midi_in p_i2c_sda
#else
//extern out port p_midi_tx;
//extern port p_midi_rx;
#define p_midi_out p_midi_tx
#define p_midi_in p_midi_rx
#endif
//#ifdef IO_EXPANSION
#if 0
extern timer i2ctimer;
#define iAPTimer i2ctimer
#else
timer iAPTimer; timer iAPTimer;
#endif #endif
void usb_midi(in port ?p_midi_in, out port ?p_midi_out, void usb_midi(port ?p_midi_in, port ?p_midi_out,
clock ?clk_midi, clock ?clk_midi,
chanend c_midi, chanend c_midi,
unsigned cable_number, unsigned cable_number,
@@ -142,204 +131,250 @@ void usb_midi(in port ?p_midi_in, out port ?p_midi_out,
#ifndef MIDI_LOOPBACK #ifndef MIDI_LOOPBACK
#ifdef IAP #ifdef IAP
#ifdef IO_EXPANSION CoProcessorDisable();
port32A_unset(P32A_I2C_NOTMIDI);
#endif
#endif #endif
p_midi_out <: 1; // Start with high bit. p_midi_out <: 1; // Start with high bit.
#ifdef IAP #ifdef IAP
#ifdef IO_EXPANSION CoProcessorEnable();
port32A_set(P32A_I2C_NOTMIDI);
#endif
#endif #endif
#endif #endif
#ifdef IAP #ifdef IAP
init_iAP(c_i2c, p_scl, p_sda); // uses timer for i2c initialisation pause.. /* Check for special case where MIDI and i2c ports are shared... */
if(isnull(c_i2c) && isnull(p_scl) && isnull(p_sda))
{
init_iAP(c_i2c, p_midi_out, p_midi_in); // uses timer for i2c initialisation pause..
}
else
{
init_iAP(c_i2c, p_scl, p_sda); // uses timer for i2c initialisation pause..
}
#endif #endif
{ {
#ifdef IAP #ifdef IAP
iAPTimer :> polltime; iAPTimer :> polltime;
polltime + XS1_TIMER_HZ / 2; polltime += XS1_TIMER_HZ / 2;
#endif #endif
while (1) { while (1)
int is_ack; {
int is_reset; int is_ack;
unsigned int datum; int is_reset;
select { unsigned int datum;
// Input to read the start bit select
{
// Input to read the start bit
#ifndef MIDI_LOOPBACK #ifndef MIDI_LOOPBACK
#ifdef MIDI_IN_4BIT_PORT case (!authenticating && !isRX) => p_midi_in when pinseq(0) :> void @ rxPT:
case (!authenticating && !isRX) => p_midi_in when pinseq(0xE) :> void @ rxPT: isRX = 1;
#else t2 :> rxT;
case (!authenticating && !isRX) => p_midi_in when pinseq(0) :> void @ rxPT: rxT += (bit_time + bit_time_2);
#endif rxPT += (bit_time + bit_time_2); // absorb start bit and set to halfway through the next bit
isRX = 1; rxI = 0;
t2 :> rxT; asm("setc res[%0],1"::"r"(p_midi_in));
rxT += (bit_time + bit_time_2); asm("setpt res[%0],%1"::"r"(p_midi_in),"r"(rxPT));
rxPT += (bit_time + bit_time_2); // absorb start bit and set to halfway through the next bit break;
rxI = 0;
asm("setc res[%0],1"::"r"(p_midi_in)); // Input to read the remaining bits
asm("setpt res[%0],%1"::"r"(p_midi_in),"r"(rxPT)); case (!authenticating && isRX) => t2 when timerafter(rxT) :> int _ :
break; {
// Input to read the remaining bits unsigned bit;
case (!authenticating && isRX) => t2 when timerafter(rxT) :> int _ : p_midi_in :> bit;
{ if (rxI++ < 8)
unsigned bit; {
p_midi_in :> bit; // shift in bits into the high end of a word
if (rxI++ < 8) { rxByte = (bit << 31) | (rxByte >> 1);
// shift in bits into the high end of a word rxT += bit_time;
rxByte = (bit << 31) | (rxByte >> 1); rxPT += bit_time;
rxT += bit_time; asm("setpt res[%0],%1"::"r"(p_midi_in),"r"(rxPT));
rxPT += bit_time; }
asm("setpt res[%0],%1"::"r"(p_midi_in),"r"(rxPT)); else
} else { {
// rcv and check stop bit // rcv and check stop bit
if ((bit & 0x1) == 1) { if ((bit & 0x1) == 1)
unsigned valid = 0; {
unsigned event = 0; unsigned valid = 0;
uin_count++; unsigned event = 0;
rxByte >>= 24; uin_count++;
// if (rxByte != outputted_symbol) { rxByte >>= 24;
// // Loopback check // if (rxByte != outputted_symbol) {
// printhexln(rxByte); // // Loopback check
// printhexln(outputted_symbol); // printhexln(rxByte);
// } // printhexln(outputted_symbol);
// }
{valid, event} = midi_in_parse(mips, cable_number, rxByte); {valid, event} = midi_in_parse(mips, cable_number, rxByte);
if (valid && isempty(midi_to_host_fifo)) { if (valid && isempty(midi_to_host_fifo))
event = byterev(event); {
// data to send to host - add to fifo event = byterev(event);
if (!waiting_for_ack) { // data to send to host - add to fifo
// send data if (!waiting_for_ack)
// printstr("uart->decouple: "); {
outuint(c_midi, event); // send data
waiting_for_ack = 1; // printstr("uart->decouple: ");
th_count++; outuint(c_midi, event);
} else { waiting_for_ack = 1;
enqueue(midi_to_host_fifo, event); th_count++;
} }
} else if (valid) { else
// printstr("g"); {
enqueue(midi_to_host_fifo, event);
}
}
else if (valid)
{
// printstr("g");
}
}
isRX = 0;
}
break;
}
// Output
// If isTX then feed the bits out one at a time
// until symbol is zero expect pattern like 10'b1dddddddd0
// This code will leave the output high afterwards due to the stop bit added with makeSymbol
case (!authenticating && isTX) => t when timerafter(txT) :> int _:
if (symbol == 0)
{
// Got something to output but not mid-symbol.
// Start sending symbol.
// This case is reached when a symbol has been received from the host but not started AND
// When it has just finished sending a symbol
// Take from FIFO
outputting_symbol = dequeue(symbol_fifo);
symbol = makeSymbol(outputting_symbol);
if (space(symbol_fifo) > 3 && midi_from_host_overflow)
{
midi_from_host_overflow = 0;
midi_send_ack(c_midi);
}
p_midi_out <: 1 @ txPT;
// printstr("mout1\n");
t :> txT;
txT += bit_time;
txPT += bit_time;
isTX = 1;
}
else
{
// Mid-symbol
txT += bit_time; // Should this be after the output otherwise be double the length of the high before the start bit
txPT += bit_time;
p_midi_out @ txPT <: (symbol & 1);
// printstr("mout2\n");
symbol >>= 1;
if (symbol == 0)
{
// Finished sending byte
uout_count++;
outputted_symbol = outputting_symbol;
if (isempty(symbol_fifo))
{ // FIFO empty
isTX = 0;
}
} }
} }
isRX = 0; break;
}
break;
}
// Output
// If isTX then feed the bits out one at a time
// until symbol is zero expect pattern like 10'b1dddddddd0
// This code will leave the output high afterwards due to the stop bit added with makeSymbol
case (!authenticating && isTX) => t when timerafter(txT) :> int _:
if (symbol == 0) {
// Got something to output but not mid-symbol.
// Start sending symbol.
// This case is reached when a symbol has been received from the host but not started AND
// When it has just finished sending a symbol
// Take from FIFO
outputting_symbol = dequeue(symbol_fifo);
symbol = makeSymbol(outputting_symbol);
if (space(symbol_fifo) > 3 && midi_from_host_overflow) {
midi_from_host_overflow = 0;
midi_send_ack(c_midi);
}
p_midi_out <: 1 @ txPT;
// printstr("mout1\n");
t :> txT;
txT += bit_time;
txPT += bit_time;
isTX = 1;
} else {
// Mid-symbol
txT += bit_time; // Should this be after the output otherwise be double the length of the high before the start bit
txPT += bit_time;
p_midi_out @ txPT <: (symbol & 1);
// printstr("mout2\n");
symbol >>= 1;
if (symbol == 0) {
// Finished sending byte
uout_count++;
outputted_symbol = outputting_symbol;
if (isempty(symbol_fifo)) { // FIFO empty
isTX = 0;
}
}
}
break;
#endif #endif
case !authenticating => midi_get_ack_or_data(c_midi, is_ack, datum): case !authenticating => midi_get_ack_or_data(c_midi, is_ack, datum):
if (is_ack) {
// have we got more data to send
//printstr("ack\n");
if (!isempty(midi_to_host_fifo)) {
//printstr("uart->decouple\n");
outuint(c_midi, dequeue(midi_to_host_fifo));
th_count++;
} else {
waiting_for_ack = 0;
}
} else {
unsigned midi[3];
unsigned size;
// received data from host
int event = byterev(datum);
mr_count++;
#ifdef MIDI_LOOPBACK
if (isempty(midi_to_host_fifo)) {
// data to send to host
if (!waiting_for_ack) {
// send data
event = byterev(event);
outuint(c_midi, event);
th_count++;
waiting_for_ack = 1;
} else {
event = byterev(event);
enqueue(midi_to_host_fifo, event);
}
}
#else
{midi[0], midi[1], midi[2], size} = midi_out_parse(event);
for (int i = 0; i != size; i++) {
// add symbol to fifo
enqueue(symbol_fifo, midi[i]);
}
if (space(symbol_fifo) > 3) { if (is_ack)
midi_send_ack(c_midi);
} else {
midi_from_host_overflow = 1;
}
// Drop through to the isTX guarded case
if (!isTX) {
t :> txT; // Should be enough to trigger the other case
isTX = 1;
}
#endif
}
break;
#ifdef IAP
case !(isTX || isRX) => iap_get_ack_or_reset_or_data(c_iap, is_ack, is_reset, datum):
handle_iap_case(is_ack, is_reset, datum, c_iap, c_i2c, p_scl, p_sda);
if (!authenticating)
{ {
// printstrln("Completed authentication"); // have we got more data to send
p_midi_in :> void; // Change port around to input again after authenticating (unique to midi+iAP case) //printstr("ack\n");
if (!isempty(midi_to_host_fifo))
{
//printstr("uart->decouple\n");
outuint(c_midi, dequeue(midi_to_host_fifo));
th_count++;
}
else
{
waiting_for_ack = 0;
}
}
else
{
unsigned midi[3];
unsigned size;
// received data from host
int event = byterev(datum);
mr_count++;
#ifdef MIDI_LOOPBACK
if (isempty(midi_to_host_fifo))
{
// data to send to host
if (!waiting_for_ack)
{
// send data
event = byterev(event);
outuint(c_midi, event);
th_count++;
waiting_for_ack = 1;
}
else
{
event = byterev(event);
enqueue(midi_to_host_fifo, event);
}
}
#else
{midi[0], midi[1], midi[2], size} = midi_out_parse(event);
for (int i = 0; i != size; i++)
{
// add symbol to fifo
enqueue(symbol_fifo, midi[i]);
}
if (space(symbol_fifo) > 3)
{
midi_send_ack(c_midi);
}
else
{
midi_from_host_overflow = 1;
}
// Drop through to the isTX guarded case
if (!isTX)
{
t :> txT; // Should be enough to trigger the other case
isTX = 1;
}
#endif
} }
break; break;
case iAPTimer when timerafter(polltime) :> void: #ifdef IAP
handle_poll_dev_det(iAPTimer); case !(isTX || isRX) => iap_get_ack_or_reset_or_data(c_iap, is_ack, is_reset, datum):
break;
/* Check for special case where MIDI ports are shared with i2c ports */
if(isnull(c_i2c) && isnull(p_scl) && isnull(p_sda))
{
handle_iap_case(is_ack, is_reset, datum, c_iap, c_i2c, p_midi_out, p_midi_in);
}
else
{
handle_iap_case(is_ack, is_reset, datum, c_iap, c_i2c, p_scl, p_sda);
}
if (!authenticating)
{
// printstrln("Completed authentication");
p_midi_in :> void; // Change port around to input again after authenticating (unique to midi+iAP case)
}
break;
/* Slow timer looking for IDevice plug/unplug event */
case iAPTimer when timerafter(polltime) :> void:
handle_poll_dev_det(iAPTimer);
break;
#endif #endif
} }
} }
} }
} }