Working full-speed (12 Mb/s) bit-banging USB Host controller

12346»

Comments

  • If it works, where were you 10years ago? P1 could had use of this then.
    This is the main file:
    https://github.com/SaucySoliton/propeller-usb-host/blob/master/usb-fs-host.spin
  • Kuroneko has informed me that there are some limitations when assigning the USBNC pin.
    http://forums.parallax.com/discussion/comment/976476/
    Apparently the duty pulses I use for sampling can be occasionally invisible. :-O Any idea how occasional? A rare missed pulse should not cause much more than a CRC failure. In any case the full speed host should be considered a hack and not suitable for medical devices. ;-)


    The program I mentioned transmitting from one cog to another was just for testing if the Propeller could synchronize with and deserialize a mock USB packet. I will put this test program in the repository when I find it. It may be useful for finding a sampling loop for different clock rates.

    I am not aware of any full speed device code for the Propeller. I've tested with a Bluetooth dongle, keyboard, mouse, and SD card reader. I did find one keyboard that seemed to have funny bias voltages on the data lines. It didn't work.

    I'm not sure if the low speed receiver would be considered a DPLL. It just measures the time between edges. This also does the NRZI decoding.
    1 bit time = 0
    2 bit times = 10
    3 bit times = 110
    4 bit times = 1110 .....

    tonyp12 wrote: »
    If it works, where were you 10years ago? P1 could had use of this then.
    Indeed, having a USB host would have made the Propeller an amazing microcontroller for 2007.
    Here's why I was so late in programming the Propeller:
    1. I did not want to learn or write code in spin.
    2. I was not impressed by 20 MIPS/cog number as an SX user (50 MIPS). I now realize this was very wrong.
    3. I didn't think I could develop for the Propeller on Linux.
    And regarding the USB host:
    4. I may not have been able to do this way back then.


    James https://github.com/SaucySoliton/

    Invention is the Science of Laziness
  • That's amazing !
    Tried the test-hid with a keyboard and a mouse and it works perfectly !
    Good job!
  • jmgjmg Posts: 10,208
    I'm not sure if the low speed receiver would be considered a DPLL. It just measures the time between edges. This also does the NRZI decoding.
    1 bit time = 0
    2 bit times = 10
    3 bit times = 110
    4 bit times = 1110 .....
    If it has > < bands on those times, it is effectively edge-sync'd and so is much the same as a DPLL.
    That means the LS USB can expect a higher tolerance of longer packets, than FS USB & especially FS-USB connected to parts with RC-CLock recovery.

    Apparently the duty pulses I use for sampling can be occasionally invisible. :-O Any idea how occasional? A rare missed pulse should not cause much more than a CRC failure.
    If the COGs sample on the same clock edge that generates the pulse, you could get an effect that tpdl/tpdh skews shift one edge after the sampling window, and the other before.
    Nett outcome is a pulse you can see on a scope, but the sampling COG misses.

    You could test the error rate by counting on 7 COGS and generating on one, and looking for ppm count misses.
    Once you find the effect, I think a CAP (47pF?) on the pin may help - it would push both edges to the right, the first one is already missed, but the second one should now always catch.

  • roglohrogloh Posts: 527
    edited April 3 Vote Up1Vote Down
    So I just wired up a USB connector to my proto board with the resistors and have been able to get things going at 80MHz. :-) This is very impressive work SaucySoliton (and Micah)!

    The first generic (cheapo) USB mouse I tried didn't enumerate fully (error -182), but a genuine Microsoft USB mouse worked, and a USB keyboard I tried worked as well. Will try to dig up a few other devices to see what else works and see if I have anything at 12Mbps.

    I wonder if the duty pulse thing is also going to be an issue in a P1V which likely has different timing. I was actually hoping to make use of this (hopefully reasonably reliably) in the P1V, not the real Propeller silicon. Will have to see if it works okay there. Perhaps it was developed on that if SaucySoliton mentioned that P1V knowledge helped during development?
  • jmgjmg Posts: 10,208
    rogloh wrote: »
    So I just wired up a USB connector to my proto board with the resistors and have been able to get things going at 80MHz. :-) This is very impressive work SaucySoliton (and Micah)!

    The first generic (cheapo) USB mouse I tried didn't enumerate fully (error -182), but a genuine Microsoft USB mouse worked, and a USB keyboard I tried worked as well. Will try to dig up a few other devices to see what else works and see if I have anything at 12Mbps.

    To clarify, the Microsoft Mouse and Keyboard, were tested at LS USB ?
    rogloh wrote: »
    I wonder if the duty pulse thing is also going to be an issue in a P1V which likely has different timing. I was actually hoping to make use of this (hopefully reasonably reliably) in the P1V, not the real Propeller silicon. Will have to see if it works okay there.
    Depends on where the pin is sampled, and the Tpd and skews. Usually on a FPGA the delays would be more than Tsu, so it should be more reliable.
    Most reliable would be if the pins were sampled on the opposite edge, giving a whole SysCLK/2 of tolerance.

  • jmg wrote: »
    To clarify, the Microsoft Mouse and Keyboard, were tested at LS USB ?

    I am presuming they would operate at the low speed, yes. But I actually don't yet know definitively. Perhaps I should scope it to check D+/D- voltages or find some other way to know for sure by examining descriptors or something.
  • Glad to hear that it's working! I wonder if dual mode PS2/USB devices are more likely to have issues.
    rogloh wrote: »
    I wonder if the duty pulse thing is also going to be an issue in a P1V which likely has different timing. I was actually hoping to make use of this (hopefully reasonably reliably) in the P1V, not the real Propeller silicon. Will have to see if it works okay there. Perhaps it was developed on that if SaucySoliton mentioned that P1V knowledge helped during development?

    Not an issue with the P1V. You can add a proper shift register. Or an easy solution would be to create a direct signal path from one counter to another. There is no reason the counter signal needs to be routed to a pin. Since I had to use a pin on the real Propeller, I also use it to wake the receiver instead of having it poll the hub. I wish the Propeller treated OUTB as virtual IO pins that could be used for fast cog to cog signaling.

    What could be an issue with the P1V is the video generator, since it needs to operate at some multiple of 12 MHz.

    What the verilog helped with was understanding the CPU cycles. There was probably enough other documentation available to get it working. Written documents can be ambiguous at times, but code has one correct interpretation. ;-)


    An easy way to find out the speed of your device is to change usb-fs-host to only-usb-fs-host.
    If it's low speed, it won't work anymore. I kept that file around because it compiles slightly smaller.
    James https://github.com/SaucySoliton/

    Invention is the Science of Laziness
  • roglohrogloh Posts: 527
    edited April 3 Vote Up0Vote Down
    Oh yeah the video generator, thanks for reminding me SaucySoliton. Not sure about that one in the P1V as it doesn't use a real PLL to smooth things out but I might be able to get some true PLL derived clock to generate 12MHz from the 50MHz on board oscillator with some further Verilog and Quartus hacking. I have played about with the internal PLLs separately on MAX10 once (hated the Quartus tools to control it as they prevented my selected values even though they should have been allowed) and I recall I was ultimately able to get something going there, so with any luck it is not a show stopper for DE0-nano based USB.
  • jmgjmg Posts: 10,208
    What could be an issue with the P1V is the video generator, since it needs to operate at some multiple of 12 MHz.
    Maybe that just needs more constraint on SysCLK, to meet 12*N ?

    An easy way to find out the speed of your device is to change usb-fs-host to only-usb-fs-host.
    If it's low speed, it won't work anymore. I kept that file around because it compiles slightly smaller.
    Could an LED be used to indicate FS/LS ?

  • Heater.Heater. Posts: 19,255
    edited April 3 Vote Up0Vote Down
    rogloh,

    Configuring PLLs in Quartus is a daunting task. There are billions of options. I only started getting into Verilog and Quartus in the last couple of weeks and wanted a 100MHz clock from the 50MHz clock on the DE0 Nano board.

    Luckily with this little tutorial http://www.emb4fun.de/fpga/nutos1/ I got it working in no time.

    After you are done clicking all the buttons all you need in the Verilog to use it is:
        // Generate 100MHz and 10MHz clocks
        pll_sys pll_sys_inst (
            .inclk0 (CLOCK_50),      // The input clok
            .c0 (CLOCK_100),         // 100MHz clock
            .c1 (CLOCK_100_SHIFTED), // 100MHz clock with phase shift of -54 degrees
            .c2 (CLOCK_10),          // 10MHz clock
            .locked (CLOCK_LOCKED)     // PLL is locked signal
        );
    

  • jmg wrote: »
    Could an LED be used to indicate FS/LS ?
    You can check the portc variable to find out the speed. The transmitter and receiver receive the address to portc as txp_portc and rx1p_portc respectively because they need to know the current speed.

    PUB GetPortConnection
    '' Is a device connected? If so, what speed? Returns a PORTC_* constant.
    '' Starts the host controller if it isn't already running.

    Start
    repeat while portc == PORTC_NOT_READY
    return portc

    ' Port connection status codes
    PORTC_NO_DEVICE = STATE_SE0 ' No device (pull-down resistors in host)
    PORTC_FULL_SPEED = STATE_J ' Full speed: pull-up on D+
    PORTC_LOW_SPEED = STATE_K ' Low speed: pull-up on D-
    PORTC_INVALID = STATE_SE1 ' Buggy device? Electrical transient?
    PORTC_NOT_READY = $FF ' Haven't checked port status yet


    James https://github.com/SaucySoliton/

    Invention is the Science of Laziness
  • rogloh wrote: »
    I was actually hoping to make use of this (hopefully reasonably reliably) in the P1V, not the real Propeller silicon. Will have to see if it works okay there.

    Have you tried this? I was reviewing the PLL simulator for another project. It shouldn't be any worse than what is being done with the P2.

    James https://github.com/SaucySoliton/

    Invention is the Science of Laziness
  • roglohrogloh Posts: 527
    edited July 6 Vote Up0Vote Down
    rogloh wrote: »
    I was actually hoping to make use of this (hopefully reasonably reliably) in the P1V, not the real Propeller silicon. Will have to see if it works okay there.

    Have you tried this? I was reviewing the PLL simulator for another project. It shouldn't be any worse than what is being done with the P2.

    Yes in fact I have recently played with it and it now seems to work on the P1V (I have only tested a keyboard and mouse so far).

    However without a change to the Verilog with the PLL I was not able to get it to work. The problem with the P1V is that the 96MHz you use for waitvid is not correctly synthesized just with the internal "fake pll", unlike a genuine Propeller part. So I added some fixes to get it to work.

    I fed the P1V with a 12MHz clock from an external oscillator and used an internal PLL to generate 96MHz (multiplied by 64 then divided by 8 to suit the VCO range of the Altera device). You could probably synthesize this from a main 50MHz crystal oscillator as well, but I already had the 12MHz anyway.

    I then fed this 96MHz clock (clk_reallpll) down into all the Cogs and their counters and modified the counter Verilog (cog_ctr.v file) as such:
    // pll simulator
    
    reg [35:0] pll_fake;
    reg [6:0] pll_real;
    
    always @(posedge clk_pll or negedge ena)
    if (!ena)
    	pll_fake <= 36'b0;
    else if (~&ctr[30:28] && |ctr[27:26])
    	pll_fake <= pll_fake + {4'b0, frq};
    
    always @(posedge clk_realpll)
    if (~&ctr[30:28] && |ctr[27:26])
    	pll_real <= pll_real + 7'b0000001;
    
    wire [15:0] pll_taps	= {pll_real[6:0], clk_realpll, pll_fake[35:28]};
    
    assign pll			= pll_taps[{ctr[31],~ctr[25:23]}];
    
    

    With this small change the previously unused top bit of the counter registers (ctra, ctrb) when set will then select the real 96MHz clock as its output for later use in the video generator to generate the USB packet data. I could also use lower rates if desired using the clock divider bits in ctra[25:23], though alternatively if desired this could be achieved by using the top bits of frqa/frqb. I didn't need that yet so I left it simple and only ever increment my "pll_real" counter by 1. I did it like that as I'm also considering using ctra[25:23] to select a range of HW PLL input clocks for other applications.

    USB appears to work sufficiently well for now in the P1V after a minor patch to your USB code to set this top control control bit.

    Cheers,
    Roger.
  • rogloh wrote: »
    Yes in fact I have recently played with it and it now seems to work on the P1V (I have only tested a keyboard and mouse so far).

    However without a change to the Verilog with the PLL I was not able to get it to work. The problem with the P1V is that the 96MHz you use for waitvid is not correctly synthesized just with the internal "fake pll", unlike a genuine Propeller part. So I added some fixes to get it to work.
    Awesome!

    I forgot about the 96MHz, which is above the Nyquist frequency for the 160MHz fake PLL clock. I wonder if if would work with 48 or 60MHz. That would add some latency when starting the video generator, but hopefully not too much. Generating a clean 96MHz with one of the FPGA PLLs is a great way to go.

    James https://github.com/SaucySoliton/

    Invention is the Science of Laziness
  • roglohrogloh Posts: 527
    edited July 7 Vote Up0Vote Down
    Yeah it seemed to work out fine that way. And there are usually some spare PLLs in the FPGAs for this sort of thing. Eg. I believe the De0-nano Cyclone 4 FPGA has 4 PLLs. After the first one is used for 160/80MHz P1V clocks, I get to use another for the 96MHz USB and still have a couple free for I2S audio clocking or other hires video uses if required.
Sign In or Register to comment.