Browse Source

FTDI serial config & receive (still work in progress)

main
PaulStoffregen 7 years ago
parent
commit
2b8ca63069
2 changed files with 117 additions and 22 deletions
  1. +13
    -6
      USBHost_t36.h
  2. +104
    -16
      serial.cpp

+ 13
- 6
USBHost_t36.h View File

virtual int available(void); virtual int available(void);
virtual int peek(void); virtual int peek(void);
virtual int read(void); virtual int read(void);
virtual int availableForWrite();
virtual size_t write(uint8_t c); virtual size_t write(uint8_t c);
protected: protected:
virtual bool claim(Device_t *device, int type, const uint8_t *descriptors, uint32_t len); 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 disconnect();
private: private:
static void rx_callback(const Transfer_t *transfer); static void rx_callback(const Transfer_t *transfer);
Pipe_t mypipes[3] __attribute__ ((aligned(32))); Pipe_t mypipes[3] __attribute__ ((aligned(32)));
Transfer_t mytransfers[7] __attribute__ ((aligned(32))); Transfer_t mytransfers[7] __attribute__ ((aligned(32)));
uint32_t bigbuffer[(BUFFER_SIZE+3)/4]; uint32_t bigbuffer[(BUFFER_SIZE+3)/4];
setup_t setup;
uint8_t setupdata[8];
uint32_t baudrate;
Pipe_t *rxpipe; Pipe_t *rxpipe;
Pipe_t *txpipe; Pipe_t *txpipe;
uint8_t *rx1; // location for first incoming packet uint8_t *rx1; // location for first incoming packet
uint8_t *rx2; // location for second incoming packet uint8_t *rx2; // location for second incoming packet
uint8_t *rxbuf; // receive circular buffer uint8_t *rxbuf; // receive circular buffer
uint16_t rxhead;// receive head
uint16_t rxtail;// receive tail
uint8_t *tx1; // location for first outgoing packet uint8_t *tx1; // location for first outgoing packet
uint8_t *tx2; // location for second outgoing packet uint8_t *tx2; // location for second outgoing packet
uint8_t *txbuf; uint8_t *txbuf;
uint16_t txhead;
uint16_t txtail;
volatile uint16_t rxhead;// receive head
volatile uint16_t rxtail;// receive tail
volatile uint16_t txhead;
volatile uint16_t txtail;
uint16_t rxsize;// size of receive circular buffer uint16_t rxsize;// size of receive circular buffer
uint16_t txsize;// size of transmit circular buffer uint16_t txsize;// size of transmit circular buffer
uint8_t rxstate;// bitmask: which receive packets are queued
bool ignore_first_two_bytes;
volatile uint8_t rxstate;// bitmask: which receive packets are queued
volatile uint8_t txstate;
uint8_t pending_control;
enum { CDCACM, FTDI, PL2303, CH341 } sertype;
}; };





+ 104
- 16
serial.cpp View File

// TODO: free rxpipe // TODO: free rxpipe
return false; return false;
} }
ignore_first_two_bytes = true;
sertype = FTDI;
rxpipe->callback_function = rx_callback; rxpipe->callback_function = rx_callback;
queue_Data_Transfer(rxpipe, rx1, 64, this); queue_Data_Transfer(rxpipe, rx1, 64, this);
rxstate = 1; rxstate = 1;
rxstate = 3; rxstate = 3;
} }
txpipe->callback_function = tx_callback; txpipe->callback_function = tx_callback;
baudrate = 115200;
pending_control = 0x0F;
mk_setup(setup, 0x40, 0, 0, 0, 0); // reset port
queue_Control_Transfer(dev, &setup, NULL, this);
return true; return true;
} }
} }
return true; return true;
} }


void USBSerial::disconnect()
{
}








void USBSerial::control(const Transfer_t *transfer)
{
println("control callback (serial)");

// set data format
if (pending_control & 1) {
pending_control &= ~1;
mk_setup(setup, 0x40, 4, 8, 0, 0); // data format 8N1
queue_Control_Transfer(device, &setup, NULL, this);
return;
}
// set baud rate
if (pending_control & 2) {
pending_control &= ~2;
uint32_t baudval = 3000000 / baudrate;
mk_setup(setup, 0x40, 3, baudval, 0, 0);
queue_Control_Transfer(device, &setup, NULL, this);
return;
}
// configure flow control
if (pending_control & 4) {
pending_control &= ~4;
mk_setup(setup, 0x40, 2, 0, 0, 0);
queue_Control_Transfer(device, &setup, NULL, this);
return;
}
// set DTR
if (pending_control & 8) {
pending_control &= ~8;
mk_setup(setup, 0x40, 1, 0x0101, 0, 0);
queue_Control_Transfer(device, &setup, NULL, this);
return;
}


}


void USBSerial::rx_callback(const Transfer_t *transfer) void USBSerial::rx_callback(const Transfer_t *transfer)
{ {
void USBSerial::rx_data(const Transfer_t *transfer) void USBSerial::rx_data(const Transfer_t *transfer)
{ {
uint32_t len = transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF); uint32_t len = transfer->length - ((transfer->qtd.token >> 16) & 0x7FFF);
print("rx: ");
print_hexbytes(transfer->buffer, len);


// first update rxstate bitmask
// first update rxstate bitmask, since buffer is no longer queued
if (transfer->buffer == rx1) { if (transfer->buffer == rx1) {
rxstate &= 0xFE; rxstate &= 0xFE;
} else if (transfer->buffer == rx2) { } else if (transfer->buffer == rx2) {
} }
// get start of data and actual length // get start of data and actual length
const uint8_t *p = (const uint8_t *)transfer->buffer; const uint8_t *p = (const uint8_t *)transfer->buffer;
if (ignore_first_two_bytes) {
if (sertype == FTDI) {
if (len >= 2) { if (len >= 2) {
p += 2; p += 2;
len -= 2; len -= 2;
len = 0; len = 0;
} }
} }
// copy data from packet buffer to circular buffer
if (len > 0) { if (len > 0) {
// TODO: copy to buffer
print("rx: ");
print_hexbytes(p, len);
} }
// re-queue packet buffer(s) if possible
uint32_t avail;
// Copy data from packet buffer to circular buffer.
// Assume the buffer will always have space, since we
// check before queuing the buffers
uint32_t head = rxhead; uint32_t head = rxhead;
uint32_t tail = rxtail; uint32_t tail = rxtail;
uint32_t avail;
if (len > 0) {
avail = rxsize - head;
if (avail > len) avail = len;
memcpy(rxbuf + head, p, avail);
if (len <= avail) {
head += avail;
if (head >= rxsize) head = 0;
} else {
head = len - avail;
memcpy(rxbuf, p + avail, head);
}
rxhead = head;
}
// re-queue packet buffer(s) if possible
if (head >= tail) { if (head >= tail) {
avail = rxsize - 1 + (tail - head);
avail = rxsize - 1 - head + tail;
} else { } else {
avail = (tail - head) - 1;
avail = tail - head - 1;
} }
uint32_t packetsize = rx2 - rx1; uint32_t packetsize = rx2 - rx1;
if (avail >= packetsize) { if (avail >= packetsize) {


int USBSerial::available(void) int USBSerial::available(void)
{ {
if (!device) return 0;
uint32_t head = rxhead;
uint32_t tail = rxtail;
if (head >= tail) return head - tail;
return 0; return 0;
} }


int USBSerial::peek(void) int USBSerial::peek(void)
{ {
return -1;
if (!device) return -1;
uint32_t head = rxhead;
uint32_t tail = rxtail;
if (head == tail) return -1;
if (++tail >= rxsize) tail = 0;
return rxbuf[tail];
} }


int USBSerial::read(void) int USBSerial::read(void)
{ {
return -1;
if (!device) return -1;
uint32_t head = rxhead;
uint32_t tail = rxtail;
if (head == tail) return -1;
if (++tail >= rxsize) tail = 0;
int c = rxbuf[tail];
rxtail = tail;
// TODO: if rx packet not queued, and buffer now can fit a full packet, queue it
return c;
}

int USBSerial::availableForWrite()
{
if (!device) return 0;
uint32_t head = txhead;
uint32_t tail = txtail;
if (head >= tail) return txsize - 1 - head + tail;
return tail - head - 1;
} }


size_t USBSerial::write(uint8_t c) size_t USBSerial::write(uint8_t c)
{ {
if (!device) return 0;
uint32_t head = txhead;
if (++head >= txsize) head = 0;
while (txtail == head) {
// wait...
}
txbuf[head] = c;
txhead = head;
// TODO: if full packet in buffer and tx packet ready, queue it
// TODO: otherwise set a latency timer to transmit partial packet
return 1; return 1;
} }








void USBSerial::disconnect()
{
}





Loading…
Cancel
Save