|
|
|
|
|
|
|
|
#endif |
|
|
#endif |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// Maximum number of transmit packets to queue so we don't starve other endpoints for memory |
|
|
|
|
|
//#define TX_PACKET_LIMIT 8 |
|
|
|
|
|
|
|
|
|
|
|
// When the PC isn't listening, how long do we wait before discarding data? If this is |
|
|
// When the PC isn't listening, how long do we wait before discarding data? If this is |
|
|
// too short, we risk losing data during the stalls that are common with ordinary desktop |
|
|
// too short, we risk losing data during the stalls that are common with ordinary desktop |
|
|
// software. If it's too long, we stall the user's program when no software is running. |
|
|
// software. If it's too long, we stall the user's program when no software is running. |
|
|
#define TX_TIMEOUT_MSEC 70 |
|
|
|
|
|
|
|
|
|
|
|
/*#if F_CPU == 240000000 |
|
|
|
|
|
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1600) |
|
|
|
|
|
#elif F_CPU == 216000000 |
|
|
|
|
|
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1440) |
|
|
|
|
|
#elif F_CPU == 192000000 |
|
|
|
|
|
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1280) |
|
|
|
|
|
#elif F_CPU == 180000000 |
|
|
|
|
|
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1200) |
|
|
|
|
|
#elif F_CPU == 168000000 |
|
|
|
|
|
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 1100) |
|
|
|
|
|
#elif F_CPU == 144000000 |
|
|
|
|
|
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 932) |
|
|
|
|
|
#elif F_CPU == 120000000 |
|
|
|
|
|
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 764) |
|
|
|
|
|
#elif F_CPU == 96000000 |
|
|
|
|
|
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 596) |
|
|
|
|
|
#elif F_CPU == 72000000 |
|
|
|
|
|
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 512) |
|
|
|
|
|
#elif F_CPU == 48000000 |
|
|
|
|
|
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 428) |
|
|
|
|
|
#elif F_CPU == 24000000 |
|
|
|
|
|
#define TX_TIMEOUT (TX_TIMEOUT_MSEC * 262) |
|
|
|
|
|
#endif */ |
|
|
|
|
|
|
|
|
#define TX_TIMEOUT_MSEC 120 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// When we've suffered the transmit timeout, don't wait again until the computer |
|
|
// When we've suffered the transmit timeout, don't wait again until the computer |
|
|
// begins accepting data. If no software is running to receive, we'll just discard |
|
|
// begins accepting data. If no software is running to receive, we'll just discard |
|
|
// data as rapidly as Serial.print() can generate it, until there's something to |
|
|
// data as rapidly as Serial.print() can generate it, until there's something to |
|
|
// actually receive it. |
|
|
// actually receive it. |
|
|
//static uint8_t transmit_previous_timeout=0; |
|
|
|
|
|
|
|
|
static uint8_t transmit_previous_timeout=0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// transmit a character. 0 returned on success, -1 on error |
|
|
// transmit a character. 0 returned on success, -1 on error |
|
|
|
|
|
|
|
|
if (!usb_configuration) return 0; |
|
|
if (!usb_configuration) return 0; |
|
|
while (size > 0) { |
|
|
while (size > 0) { |
|
|
transfer_t *xfer = tx_transfer + tx_head; |
|
|
transfer_t *xfer = tx_transfer + tx_head; |
|
|
//int waiting=0; |
|
|
|
|
|
//uint32_t wait_begin_at=0; |
|
|
|
|
|
|
|
|
int waiting=0; |
|
|
|
|
|
uint32_t wait_begin_at=0; |
|
|
while (!tx_available) { |
|
|
while (!tx_available) { |
|
|
//digitalWriteFast(3, HIGH); |
|
|
//digitalWriteFast(3, HIGH); |
|
|
uint32_t status = usb_transfer_status(xfer); |
|
|
uint32_t status = usb_transfer_status(xfer); |
|
|
if (status & 0x7F) { |
|
|
|
|
|
printf("ERROR status = %x, i=%d, ms=%u\n", status, tx_head, systick_millis_count); |
|
|
|
|
|
} |
|
|
|
|
|
if (!(status & 0x80)) { |
|
|
if (!(status & 0x80)) { |
|
|
// TODO: what if status has errors??? |
|
|
|
|
|
|
|
|
if (status & 0x68) { |
|
|
|
|
|
// TODO: what if status has errors??? |
|
|
|
|
|
printf("ERROR status = %x, i=%d, ms=%u\n", |
|
|
|
|
|
status, tx_head, systick_millis_count); |
|
|
|
|
|
} |
|
|
tx_available = TX_SIZE; |
|
|
tx_available = TX_SIZE; |
|
|
|
|
|
transmit_previous_timeout = 0; |
|
|
break; |
|
|
break; |
|
|
}/* else { |
|
|
|
|
|
if (!waiting) { |
|
|
|
|
|
wait_begin_at = systick_millis_count; |
|
|
|
|
|
waiting = 1; |
|
|
|
|
|
} else { |
|
|
|
|
|
if (systick_millis_count - wait_begin_at > 250) { |
|
|
|
|
|
printf("\nstop, waited too long\n"); |
|
|
|
|
|
printf("status = %x\n", status); |
|
|
|
|
|
printf("tx head=%d\n", tx_head); |
|
|
|
|
|
printf("TXFILLTUNING=%08lX\n", USB1_TXFILLTUNING); |
|
|
|
|
|
usb_print_transfer_log(); |
|
|
|
|
|
while (1) ; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
} */ |
|
|
|
|
|
// TODO: proper timout? |
|
|
|
|
|
// TODO: check for USB offline |
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
if (!waiting) { |
|
|
|
|
|
wait_begin_at = systick_millis_count; |
|
|
|
|
|
waiting = 1; |
|
|
|
|
|
} |
|
|
|
|
|
if (transmit_previous_timeout) return sent; |
|
|
|
|
|
if (systick_millis_count - wait_begin_at > TX_TIMEOUT_MSEC) { |
|
|
|
|
|
// waited too long, assume the USB host isn't listening |
|
|
|
|
|
transmit_previous_timeout = 1; |
|
|
|
|
|
return sent; |
|
|
|
|
|
//printf("\nstop, waited too long\n"); |
|
|
|
|
|
//printf("status = %x\n", status); |
|
|
|
|
|
//printf("tx head=%d\n", tx_head); |
|
|
|
|
|
//printf("TXFILLTUNING=%08lX\n", USB1_TXFILLTUNING); |
|
|
|
|
|
//usb_print_transfer_log(); |
|
|
|
|
|
//while (1) ; |
|
|
|
|
|
} |
|
|
|
|
|
if (!usb_configuration) return sent; |
|
|
|
|
|
yield(); |
|
|
} |
|
|
} |
|
|
//digitalWriteFast(3, LOW); |
|
|
//digitalWriteFast(3, LOW); |
|
|
|
|
|
|
|
|
uint8_t *txdata = txbuffer + (tx_head * TX_SIZE) + (TX_SIZE - tx_available); |
|
|
uint8_t *txdata = txbuffer + (tx_head * TX_SIZE) + (TX_SIZE - tx_available); |
|
|
|
|
|
|
|
|
if (size >= tx_available) { |
|
|
if (size >= tx_available) { |
|
|
memcpy(txdata, data, tx_available); |
|
|
memcpy(txdata, data, tx_available); |
|
|
//*(txbuffer + (tx_head * TX_SIZE)) = 'A' + tx_head; // to see which buffer |
|
|
//*(txbuffer + (tx_head * TX_SIZE)) = 'A' + tx_head; // to see which buffer |