-
Notifications
You must be signed in to change notification settings - Fork 5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature request: Full-Speed PRE handling #15
Comments
FS-hub-LS-keyboard-IN-NAK.sal.zip is zipped (zipped because GitHub does not accept |
I have experimented with reconfiguring transceiver to either The patch applied on top of 9e3cd34 was diff --git a/software/fpga/ov3/ovhw/ulpi.py b/software/fpga/ov3/ovhw/ulpi.py
index 677bf48..59461e7 100644
--- a/software/fpga/ov3/ovhw/ulpi.py
+++ b/software/fpga/ov3/ovhw/ulpi.py
@@ -69,6 +69,14 @@ class ULPI_ctrl(Module):
ulpi_data_tristate_next = Signal()
ulpi_stp_next = Signal()
+ first_byte_received = Signal()
+ switch_to_low_speed = Signal()
+ switch_to_full_speed = Signal()
+ full_speed_after_eop = Signal()
+ reg_write_addr = Signal(8)
+ reg_write_data = Signal(8)
+ internal_reg_write = Signal(1)
+
ulpi_state_rx = Signal()
ulpi_state_rrd = Signal()
@@ -144,19 +152,37 @@ class ULPI_ctrl(Module):
ulpi_data_next.eq(0x00), # NOOP
ulpi_data_tristate_next.eq(0),
ulpi_stp_next.eq(0),
- If(~ulpi_bus.dir & ~ulpi_bus.nxt & ~(RegWriteReq | RegReadReq),
+ If(~ulpi_bus.dir & ~ulpi_bus.nxt & ~(switch_to_low_speed | switch_to_full_speed | RegWriteReq | RegReadReq),
NextState("IDLE")
).Elif(ulpi_bus.dir, # TA, and then either RXCMD or Data
NextState("RX"),
+ NextValue(first_byte_received, 0),
ulpi_data_tristate_next.eq(1),
# If dir & nxt, we're starting a packet, so stuff a custom SOP
If(ulpi_bus.nxt,
ulpi_rx_stuff.eq(1),
ulpi_rx_stuff_d.eq(RXCMD_MAGIC_SOP)
)
+ ).Elif(switch_to_low_speed,
+ NextState("RW0"),
+ ulpi_data_next.eq(0x84), # REGW FUNC_CTL
+ NextValue(reg_write_addr, 0x84),
+ NextValue(reg_write_data, 0x4b),
+ NextValue(internal_reg_write, 1),
+ ulpi_data_tristate_next.eq(0),
+ ).Elif(switch_to_full_speed,
+ NextState("RW0"),
+ ulpi_data_next.eq(0x84), # REGW FUNC_CTL
+ NextValue(reg_write_addr, 0x84),
+ NextValue(reg_write_data, 0x49),
+ NextValue(internal_reg_write, 1),
+ ulpi_data_tristate_next.eq(0),
).Elif(RegWriteReq,
NextState("RW0"),
ulpi_data_next.eq(0x80 | ulpi_reg.waddr), # REGW
+ NextValue(reg_write_addr, 0x80 | ulpi_reg.waddr),
+ NextValue(reg_write_data, ulpi_reg.wdata),
+ NextValue(internal_reg_write, 0),
ulpi_data_tristate_next.eq(0),
ulpi_stp_next.eq(0)
).Elif(RegReadReq,
@@ -172,12 +198,24 @@ class ULPI_ctrl(Module):
If(ulpi_bus.dir, # stay in RX
NextState("RX"),
ulpi_state_rx.eq(1),
- ulpi_data_tristate_next.eq(1)
+ ulpi_data_tristate_next.eq(1),
+ If(ulpi_bus.nxt & ~first_byte_received,
+ NextValue(first_byte_received, 1),
+ If(ulpi_bus.di == 0x3C,
+ # Request stop on PRE packet ID
+ ulpi_stp_next.eq(1),
+ NextValue(switch_to_low_speed, 1)
+ )
+ )
).Else( # TA back to idle
# Stuff an EOP on return to idle
ulpi_rx_stuff.eq(1),
ulpi_rx_stuff_d.eq(RXCMD_MAGIC_EOP),
- ulpi_data_tristate_next.eq(0),
+ ulpi_data_tristate_next.eq(0),
+ If(full_speed_after_eop,
+ NextValue(switch_to_full_speed, 1),
+ NextValue(full_speed_after_eop, 0),
+ ),
NextState("IDLE")
))
@@ -186,7 +224,7 @@ class ULPI_ctrl(Module):
NextState("RX"),
ulpi_data_tristate_next.eq(1),
).Elif(~ulpi_bus.dir,
- ulpi_data_next.eq(0x80 | ulpi_reg.waddr), # REGW
+ ulpi_data_next.eq(reg_write_addr), # REGW
ulpi_data_tristate_next.eq(0),
ulpi_stp_next.eq(0),
If(ulpi_bus.nxt, NextState("RWD")).Else(NextState("RW0")),
@@ -200,7 +238,7 @@ class ULPI_ctrl(Module):
ulpi_data_tristate_next.eq(1)
).Elif(~ulpi_bus.dir & ulpi_bus.nxt,
NextState("RWS"),
- ulpi_data_next.eq(ulpi_reg.wdata),
+ ulpi_data_next.eq(reg_write_data),
ulpi_data_tristate_next.eq(0),
ulpi_stp_next.eq(0)
).Else(
@@ -214,7 +252,14 @@ class ULPI_ctrl(Module):
ulpi_data_next.eq(0x00), # NOOP
ulpi_data_tristate_next.eq(0),
ulpi_stp_next.eq(1),
- RegWriteAckSet.eq(1)
+ If(internal_reg_write,
+ NextValue(internal_reg_write, 0),
+ NextValue(full_speed_after_eop, switch_to_low_speed),
+ NextValue(switch_to_low_speed, 0),
+ NextValue(switch_to_full_speed, 0),
+ ).Else(
+ RegWriteAckSet.eq(1),
+ )
).Elif(ulpi_bus.dir,
NextState("RX"),
ulpi_data_tristate_next.eq(1), However it seems that this approach cannot really work. The I think manual steps to extract the bits out of the unsynchronized stream are doomed to fail. 2023-04-11 FS hub LS keyboard.zip contains two capture files where the same LS packet is offset by one LS bit (from each other capture). Probably the only way to handle PRE packets is to do FS/LS capture in gateware (D+ and D- lines are connected to FPGA however whether the pins the signals are connected to are suitable for the task is currently unknown). |
Actually it seems that setting Reset bit in Function Control alongside speed bit makes it possible to receive Low-speed packets correctly. However it needs careful state transitions because it is easy to prematurely switch back to Full-speed. |
Copied from openvizsla#54
Currently the capture speed is fixed for a capture session duration. This is always fine for High-Speed and Low-Speed captures and mostly fine for Full-Speed captures. There is one corner case when it is not fine for Full-Speed captures: when capture the link between host and hub while there is Low-Speed device connected.
Due to very strict timings, the speed change must be handled by FPGA. The Low-Speed packet captured on Full-Speed link should probably be indicated with new flag.
Universal Serial Bus Specification Revision 2.0
section8.6.5 Low-speed Transactions
describes what is sent at Full-Speed and what at Low-Speed.To obtain best Wireshark experience, the data would have to be written to pcapng format. I can handle the pcapng related work if the bitstream handles the PRE processing and sets low-speed flag on packets.
The text was updated successfully, but these errors were encountered: