Minor update: I've cleaned up my hack to use both ports again.
Patch below. A pre-compiled Flickernoise binary compatible with
the 2011-07-13 system is at
http://downloads.qi-hardware.com/people/werner/tmp/flickernoise-fs.fbi.bz2
Operation at full-speed is very shaky. The keyboard loses characters,
can get garbage, can get endless auto-repeat, and so on. but if you
type very slowly, it almost works ;-)
Of course, all these problems are what a stack that, with my patch,
has zero error handling (and probably still with timing issues left)
richly deserves. I'd expect the situation to improve dramatically
once ACK generation moves into the SoC.
- Werner
diff --git a/softusb-input/main.c b/softusb-input/main.c
index 40f877e..f7e43e4 100644
--- a/softusb-input/main.c
+++ b/softusb-input/main.c
@@ -26,6 +26,11 @@
#include "host.h"
#include "crc.h"
+//#define TRIGGER
+
+#define print_string(s) (void) (s)
+#define dump_hex(x, y) (void) (x)
+
enum {
USB_PID_OUT = 0xe1,
USB_PID_IN = 0x69,
@@ -94,6 +99,16 @@ static void usb_tx(unsigned char *buf, unsigned char len)
while(rio8(SIE_TX_BUSY));
}
+static void usb_ack(void)
+{
+ wio8(SIE_TX_DATA, 0x80); /* send SYNC */
+ while(rio8(SIE_TX_PENDING));
+ wio8(SIE_TX_DATA, USB_PID_ACK); /* send ACK */
+ while(rio8(SIE_TX_PENDING));
+ wio8(SIE_TX_VALID, 0);
+ while(rio8(SIE_TX_BUSY));
+}
+
static const char transfer_start[] PROGMEM = "Transfer start: ";
static const char timeout_error[] PROGMEM = "RX timeout error\n";
static const char bitstuff_error[] PROGMEM = "RX bitstuff error\n";
@@ -163,6 +178,7 @@ static const char out_reply[] PROGMEM = "IN reply:\n";
static char control_transfer(unsigned char addr, struct setup_packet *p, char
out, unsigned char *payload, int maxlen)
{
+ unsigned char usb_token[3];
unsigned char usb_buffer[11];
char toggle;
char rxlen;
@@ -172,13 +188,19 @@ static char control_transfer(unsigned char addr, struct
setup_packet *p, char ou
toggle = 0;
/* send SETUP token */
- make_usb_token(USB_PID_SETUP, addr, usb_buffer);
- usb_tx(usb_buffer, 3);
+ make_usb_token(USB_PID_SETUP, addr, usb_token);
/* send setup packet */
usb_buffer[0] = get_data_token(&toggle);
memcpy(&usb_buffer[1], p, 8);
usb_crc16(&usb_buffer[1], 8, &usb_buffer[9]);
+#ifdef TRIGGER
+wio8(SIE_SEL_TX, 3);
+#endif
+ usb_tx(usb_token, 3);
usb_tx(usb_buffer, 11);
+#ifdef TRIGGER
+wio8(SIE_SEL_TX, 2);
+#endif
/* get ACK token from device */
rxlen = usb_rx(usb_buffer, 11);
if((rxlen != 1) || (usb_buffer[0] != USB_PID_ACK)) {
@@ -230,6 +252,8 @@ static char control_transfer(unsigned char addr, struct
setup_packet *p, char ou
usb_tx(usb_buffer, 3);
/* get DATAx packet */
rxlen = usb_rx(usb_buffer, 11);
+ if (rxlen >= 3)
+ usb_ack(); /* @@@ */
if((rxlen < 3) || ((usb_buffer[0] != USB_PID_DATA0) &&
(usb_buffer[0] != USB_PID_DATA1))) {
if((rxlen > 0) &&
@@ -240,15 +264,15 @@ static char control_transfer(unsigned char addr, struct
setup_packet *p, char ou
dump_hex(usb_buffer, rxlen);
return -1;
}
+
+ /* send ACK token */
+ // usb_ack();
+
chunklen = rxlen - 3; /* strip token and CRC */
if(chunklen > (maxlen - transferred))
chunklen = maxlen - transferred;
memcpy(payload, &usb_buffer[1], chunklen);
- /* send ACK token */
- usb_buffer[0] = USB_PID_ACK;
- usb_tx(usb_buffer, 1);
-
transferred += chunklen;
payload += chunklen;
if(chunklen < 8)
@@ -263,6 +287,8 @@ retry:
if(out) {
/* get DATAx packet */
rxlen = usb_rx(usb_buffer, 11);
+ if (rxlen == 3)
+ usb_ack(); /* @@@ */
if((rxlen != 3) || ((usb_buffer[0] != USB_PID_DATA0) &&
(usb_buffer[0] != USB_PID_DATA1))) {
if((rxlen > 0) && (usb_buffer[0] == USB_PID_NAK))
@@ -274,8 +300,7 @@ retry:
return -1;
}
/* send ACK token */
- usb_buffer[0] = USB_PID_ACK;
- usb_tx(usb_buffer, 1);
+// usb_ack();
} else {
/* send DATAx packet */
usb_buffer[0] = get_data_token(&toggle);
@@ -312,19 +337,18 @@ static void poll(struct ep_status *ep, char keyboard)
len = usb_rx(usb_buffer, 11);
if(len < 6)
return;
+ usb_ack(); /* @@@ */
if(usb_buffer[0] != ep->expected_data) {
if((usb_buffer[0] == USB_PID_DATA0) ||
(usb_buffer[0] == USB_PID_DATA1)) {
/* ACK */
- usb_buffer[0] = USB_PID_ACK;
- usb_tx(usb_buffer, 1);
+// usb_ack();
print_string(datax_mismatch);
}
return; /* drop */
}
/* ACK */
- usb_buffer[0] = USB_PID_ACK;
- usb_tx(usb_buffer, 1);
+// usb_ack();
if(ep->expected_data == USB_PID_DATA0)
ep->expected_data = USB_PID_DATA1;
else
@@ -619,8 +643,10 @@ static void sof()
unsigned char usb_buffer[3];
mask = 0;
+#ifndef TRIGGER
if(port_a.full_speed && (port_a.state > PORT_STATE_BUS_RESET))
mask |= 0x01;
+#endif
if(port_b.full_speed && (port_b.state > PORT_STATE_BUS_RESET))
mask |= 0x02;
if(mask != 0) {
@@ -636,8 +662,10 @@ static void keepalive()
unsigned char mask;
mask = 0;
+#ifndef TRIGGER
if(!port_a.full_speed && (port_a.state == PORT_STATE_RESET_WAIT))
mask |= 0x01;
+#endif
if(!port_b.full_speed && (port_b.state == PORT_STATE_RESET_WAIT))
mask |= 0x02;
if(mask != 0) {
@@ -681,9 +709,11 @@ int main()
for(i=0;i<128;i++)
asm("nop");
+#ifndef TRIGGER
wio8(SIE_SEL_RX, 0);
wio8(SIE_SEL_TX, 0x01);
port_service(&port_a, 'A');
+#endif
wio8(SIE_SEL_RX, 1);
wio8(SIE_SEL_TX, 0x02);
diff --git a/softusb-input/navre.ld b/softusb-input/navre.ld
index 652f554..4ec1578 100644
--- a/softusb-input/navre.ld
+++ b/softusb-input/navre.ld
@@ -3,7 +3,7 @@ OUTPUT_FORMAT("elf32-avr","elf32-avr","elf32-avr")
OUTPUT_ARCH(avr:2)
MEMORY
{
- text (rx) : ORIGIN = 0, LENGTH = 8K
+ text (rx) : ORIGIN = 0, LENGTH = 4K
data (rw!x) : ORIGIN = 0, LENGTH = 32K
}
SECTIONS
_______________________________________________
http://lists.milkymist.org/listinfo.cgi/devel-milkymist.org
IRC: #milkymist@Freenode