FTDI transmit, add partial packet output

This commit is contained in:
PaulStoffregen 2017-10-15 04:28:07 -07:00
parent b58d4c7191
commit 5575f9fcae
3 changed files with 98 additions and 28 deletions

View File

@ -391,6 +391,7 @@ public:
USBDriverTimer(USBDriver *d) : driver(d) { }
void init(USBDriver *d) { driver = d; };
void start(uint32_t microseconds);
void stop();
void *pointer;
uint32_t integer;
uint32_t started_micros; // testing only
@ -747,7 +748,7 @@ private:
class USBSerial: public USBDriver, public Stream {
public:
enum { BUFFER_SIZE = 390 }; // must hold at least 6 max size packets, plus 2 extra bytes
USBSerial(USBHost &host) { init(); }
USBSerial(USBHost &host) : txtimer(this) { init(); }
void begin(uint32_t baud, uint32_t format=0);
void end(void);
virtual int available(void);
@ -760,6 +761,7 @@ protected:
virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len);
virtual void control(const Transfer_t *transfer);
virtual void disconnect();
virtual void timer_event(USBDriverTimer *whichTimer);
private:
static void rx_callback(const Transfer_t *transfer);
static void tx_callback(const Transfer_t *transfer);
@ -772,6 +774,7 @@ private:
private:
Pipe_t mypipes[3] __attribute__ ((aligned(32)));
Transfer_t mytransfers[7] __attribute__ ((aligned(32)));
USBDriverTimer txtimer;
uint32_t bigbuffer[(BUFFER_SIZE+3)/4];
setup_t setup;
uint8_t setupdata[8];

View File

@ -457,6 +457,39 @@ void USBDriverTimer::start(uint32_t microseconds)
list->next = this;
}
void USBDriverTimer::stop()
{
__disable_irq();
if (active_timers) {
if (active_timers == this) {
USBHS_GPTIMER1CTL = 0;
if (next) {
uint32_t usec_til_next = USBHS_GPTIMER1CTL & 0xFFFFFF;
usec_til_next += next->usec;
next->usec = usec_til_next;
USBHS_GPTIMER1LD = usec_til_next;
USBHS_GPTIMER1CTL = USBHS_GPTIMERCTL_RST | USBHS_GPTIMERCTL_RUN;
next->prev = NULL;
active_timers = next;
} else {
active_timers = NULL;
}
} else {
for (USBDriverTimer *t = active_timers->next; t; t = t->next) {
if (t == this) {
t->prev->next = t->next;
if (t->next) {
t->next->usec += t->usec;
t->next->prev = t->prev;
}
break;
}
}
}
}
__enable_irq();
}
static uint32_t QH_capabilities1(uint32_t nak_count_reload, uint32_t control_endpoint_flag,
uint32_t max_packet_length, uint32_t head_of_list, uint32_t data_toggle_control,

View File

@ -28,6 +28,11 @@
#define print USBHost::print
#define println USBHost::println
/************************************************************/
// Initialization and claiming of devices & interfaces
/************************************************************/
void USBSerial::init()
{
contribute_Pipes(mypipes, sizeof(mypipes)/sizeof(Pipe_t));
@ -135,6 +140,9 @@ void USBSerial::disconnect()
}
/************************************************************/
// Control Transfer For Configuration
/************************************************************/
void USBSerial::control(const Transfer_t *transfer)
@ -177,6 +185,11 @@ void USBSerial::control(const Transfer_t *transfer)
}
}
/************************************************************/
// Interrupt-based Data Movement
/************************************************************/
void USBSerial::rx_callback(const Transfer_t *transfer)
{
if (!transfer->driver) return;
@ -281,14 +294,54 @@ void USBSerial::tx_data(const Transfer_t *transfer)
println("tx2:");
txstate &= 0xFD;
}
// TODO: anything need to be done with latency timeout?
}
void USBSerial::timer_event(USBDriverTimer *whichTimer)
{
println("txtimer");
uint32_t count;
uint32_t head = txhead;
uint32_t tail = txtail;
if (head == tail) {
return; // nothing to transmit
} else if (head > tail) {
count = head - tail;
} else {
count = txsize + head - tail;
}
uint8_t *p;
if ((txstate & 0x01) == 0) {
p = tx1;
txstate |= 0x01;
} else if ((txstate & 0x02) == 0) {
p = tx2;
txstate |= 0x02;
} else {
txtimer.start(1200);
return; // no outgoing buffers available, try again later
}
if (++tail >= txsize) tail = 0;
uint32_t n = txsize - tail;
if (n > count) n = count;
memcpy(p, txbuf + tail, n);
if (n >= count) {
tail += n - 1;
if (tail >= txsize) tail = 0;
} else {
uint32_t len = count - n;
memcpy(p + n, txbuf, len);
tail = len - 1;
}
txtail = tail;
queue_Data_Transfer(txpipe, p, count, this);
}
/************************************************************/
// User Functions - must disable USBHQ IRQ for EHCI access
/************************************************************/
void USBSerial::begin(uint32_t baud, uint32_t format)
{
@ -301,6 +354,7 @@ void USBSerial::begin(uint32_t baud, uint32_t format)
void USBSerial::end(void)
{
// TODO: lower DTR
}
int USBSerial::available(void)
@ -407,32 +461,12 @@ size_t USBSerial::write(uint8_t c)
return 1;
}
}
// TODO: otherwise set a latency timer to transmit partial packet
// otherwise, set a latency timer to later transmit partial packet
txtimer.stop();
txtimer.start(3500);
NVIC_ENABLE_IRQ(IRQ_USBHS);
return 1;
}