The patch below makes full-speed USB work for my HHKB Pro. At least
to the point of F1 and Esc producing the usual result when rendering.
The elements in there:
- Navre progmem set to 4 kB, because I didn't get the 8 kB
SoC+BIOS+etc. to work yet. Also commented out most of the debug
output, so that the Navre firmware still fits.
- port A disabled. I use it to signal sending of SETUP instead, so
that I can trigger on it. (Trying to wade through all the SOFs
would be hopeless.)
- send all the ACKs as early as possible. Unfortunately, this means
I have to send them even before checking whether the data is any
good. (I tried to do it after the check, but I still missed the
16 bit times deadline sometimes.)
- prepare the DATA0 packet in a SETUP transfer before sending the
SETUP. This to reduce the time between SETUP and DATA0, which
apparently also runs against a timeout. (The USB spec is not very
clear about it.)
While it may be possible to meet timing requirements by shifting
things around a bit more, the only proper solution will be to
generate the ACK in hardware.
The good news is that timing seems to be the only major obstacle
for full-speed USB. At least as far as my HHKB is concerned ;-)
- Werner
diff --git a/softusb-input/main.c b/softusb-input/main.c
index 40f877e..3c538be 100644
--- a/softusb-input/main.c
+++ b/softusb-input/main.c
@@ -26,6 +26,9 @@
#include "host.h"
#include "crc.h"
+#define print_string(s) (void) (s)
+#define dump_hex(x, y) (void) (x)
+
enum {
USB_PID_OUT = 0xe1,
USB_PID_IN = 0x69,
@@ -94,6 +97,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 +176,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 +186,15 @@ 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]);
+wio8(SIE_SEL_TX, 3);
+ usb_tx(usb_token, 3);
usb_tx(usb_buffer, 11);
+wio8(SIE_SEL_TX, 2);
/* get ACK token from device */
rxlen = usb_rx(usb_buffer, 11);
if((rxlen != 1) || (usb_buffer[0] != USB_PID_ACK)) {
@@ -230,6 +246,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 +258,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 +281,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 +294,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 +331,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 +637,8 @@ static void sof()
unsigned char usb_buffer[3];
mask = 0;
- if(port_a.full_speed && (port_a.state > PORT_STATE_BUS_RESET))
- mask |= 0x01;
+// if(port_a.full_speed && (port_a.state > PORT_STATE_BUS_RESET))
+// mask |= 0x01;
if(port_b.full_speed && (port_b.state > PORT_STATE_BUS_RESET))
mask |= 0x02;
if(mask != 0) {
@@ -636,8 +654,8 @@ static void keepalive()
unsigned char mask;
mask = 0;
- if(!port_a.full_speed && (port_a.state == PORT_STATE_RESET_WAIT))
- mask |= 0x01;
+// if(!port_a.full_speed && (port_a.state == PORT_STATE_RESET_WAIT))
+// mask |= 0x01;
if(!port_b.full_speed && (port_b.state == PORT_STATE_RESET_WAIT))
mask |= 0x02;
if(mask != 0) {
@@ -681,13 +699,17 @@ int main()
for(i=0;i<128;i++)
asm("nop");
+#if 0
wio8(SIE_SEL_RX, 0);
wio8(SIE_SEL_TX, 0x01);
port_service(&port_a, 'A');
+#endif
+#if 1
wio8(SIE_SEL_RX, 1);
wio8(SIE_SEL_TX, 0x02);
port_service(&port_b, 'B');
+#endif
/* set RX speed for new detected devices */
set_rx_speed();
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