Working full-speed (12 Mb/s) bit-banging USB Host controller
scanlime
Posts: 106
This is something I've been wanting to try for a while, but I finally had an excuse...
I've been wanting to build more devices that can communicate wirelessly. Sensors, ambient information displays, that sort of thing. To reduce the infrastructure needs, I'd like to use Bluetooth, or preferably Wifi. Problem is: I want these things to be cheap, and it's still fairly expensive to buy a Bluetooth or Wifi adapter that's microcontroller-friendly. I'd much rather stick a $5 USB bluetooth dongle on my Propeller and have a solution with simple/cheap hardware and software which is merely not impossible to write [noparse]:)[/noparse]
Anyway.. I'm still working on writing USB class drivers for it, but I have a working full-speed host controller. So far it supports Control, Bulk IN/OUT, and Interrupt IN transfers. There are a couple simple demos included: Device enumeration and descriptor parsing, a very simple HID demo, and an even simpler mass storage demo.
As you'd expect, there is a huge list of caveats for something that pushes the limits of the Propeller and the USB spec to this extent.. It uses four cogs, requires overclocking the Prop to 96 MHz, and even though the line rate is 12 Mb/s the actual usable data throughput is significantly lower.
But, this lets you talk to a lot of fun new peripherals that were previously unavailable to the Propeller. So it should be fun [noparse]:)[/noparse]
The hardware is really simple: Four resistors and a USB socket. If you try it out, let me know how it goes. Compatibility with different devices still isn't perfect. It works with most of the devices I've tried it with, but some don't work at all, and some work intermittently. But on the devices it does work with, transfers seem to be quite reliable.
My next goal is to write a simple proof-of-concept USB storage class driver ('cuz why not?) then see if I can get Bluetooth working.
--Micah
Post Edited (Micah Dowty) : 4/6/2010 6:30:59 AM GMT
I've been wanting to build more devices that can communicate wirelessly. Sensors, ambient information displays, that sort of thing. To reduce the infrastructure needs, I'd like to use Bluetooth, or preferably Wifi. Problem is: I want these things to be cheap, and it's still fairly expensive to buy a Bluetooth or Wifi adapter that's microcontroller-friendly. I'd much rather stick a $5 USB bluetooth dongle on my Propeller and have a solution with simple/cheap hardware and software which is merely not impossible to write [noparse]:)[/noparse]
Anyway.. I'm still working on writing USB class drivers for it, but I have a working full-speed host controller. So far it supports Control, Bulk IN/OUT, and Interrupt IN transfers. There are a couple simple demos included: Device enumeration and descriptor parsing, a very simple HID demo, and an even simpler mass storage demo.
As you'd expect, there is a huge list of caveats for something that pushes the limits of the Propeller and the USB spec to this extent.. It uses four cogs, requires overclocking the Prop to 96 MHz, and even though the line rate is 12 Mb/s the actual usable data throughput is significantly lower.
But, this lets you talk to a lot of fun new peripherals that were previously unavailable to the Propeller. So it should be fun [noparse]:)[/noparse]
The hardware is really simple: Four resistors and a USB socket. If you try it out, let me know how it goes. Compatibility with different devices still isn't perfect. It works with most of the devices I've tried it with, but some don't work at all, and some work intermittently. But on the devices it does work with, transfers seem to be quite reliable.
My next goal is to write a simple proof-of-concept USB storage class driver ('cuz why not?) then see if I can get Bluetooth working.
--Micah
Post Edited (Micah Dowty) : 4/6/2010 6:30:59 AM GMT
Comments
Unfortunately I don't have a project that can spare 4 COGs for the addition of USB host.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
For me, the past is not over yet.
Congratulations, this is great news indeed. Even if we have to sacrifice 4 cogs it is still excellent news that it can be done.
FWIW, the prop can be overclocked reliably to 104MHz (6.5MHz xtal*16) with the correct layout and I am soon to prove 108MHz (13.5MHz xtal*8).
I am sure there are ways to speed things up. Kuroneko is excellent with counters so he may have some ideas.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Links to other interesting threads:
· Home of the MultiBladeProps: TriBlade,·RamBlade,·SixBlade, website
· Single Board Computer:·3 Propeller ICs·and a·TriBladeProp board (ZiCog Z80 Emulator)
· Prop Tools under Development or Completed (Index)
· Emulators: CPUs Z80 etc; Micros Altair etc;· Terminals·VT100 etc; (Index) ZiCog (Z80) , MoCog (6809)·
· Prop OS: SphinxOS·, PropDos , PropCmd··· Search the Propeller forums·(uses advanced Google search)
My cruising website is: ·www.bluemagic.biz·· MultiBlade Props: www.cluso.bluemagic.biz
Another barrier smashed!
T o n y
Now it will be interesting to see what will play nicely.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Style and grace : Nil point
It will open up a lot of possibilities.
The only down side I can see is that it uses four cogs - however for some applications that is fine, and one can always add another Propeller...
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.mikronauts.com E-mail: mikronauts _at_ gmail _dot_ com 5.0" VGA LCD in stock!
Morpheus dual Prop SBC w/ 512KB kit $119.95, Mem+2MB memory/IO kit $89.95, both kits $189.95 SerPlug $9.95
Propteus and Proteus for Propeller prototyping 6.250MHz custom Crystals run Propellers at 100MHz
Las - Large model assembler Largos - upcoming nano operating system
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter, E.I.
www.brilldea.com - Prop Blade, LED Painter, RGB LEDs, 3.0" 16:9 LCD Composite video display, eProto for SunSPOT, PropNET, PolkaDOT-51
www.tdswieter.com
Thanks for taking up this challenge. Being able to use cheap dongles instead of costly special modules is definitely worth losing COGs. It would be sweet if Propeller has room left for a port of a linux USB host driver for one of those cheap-o WIFI dongles ....
Ooo-rah!
Added: Hope this isn't an April Fool[noparse]:)[/noparse] Doesn't look like one.
Post Edited (jazzed) : 3/31/2010 3:37:59 PM GMT
@jazzed: Not an April fools, though that would have been hilarious!
Regarding the four cogs- there might be ways to reduce this, or at least to repurpose these cogs for other things most of the time. Only one cog is needed to transmit, but I'm using two interleaved cogs for receive, and one just to send ACK packets at exactly the right time.
It would be possible to go to 1 receive cog rather than 2, if you're okay with limiting the maximum received packet size to what will fit in cog memory. The interleaving is necessary so I have time to stream the data back to hub memory.
There also might be a better way to do ACKs, so I don't need a separate cog. The main reason for that is that when I need to send an ACK, the other cogs are all busy- the RX cogs haven't necessarily detected end-of-packet yet (they only get a chance once every 32 bits) and the TX cog is busy babysitting the RX cogs.
It would be possible to have the TX cog send the ACK, but I'm using waitpeq to find the end-of-packet condition- so if the packet never arrives, we're stuck. But I could have the RX cogs take responsibility for waking up the TX cog after a timeout...
That might work. I'll try to remember to give this a shot, it might reduce the number of cogs by 1 at least. Only downside I can see is that the ACK code would take up space in the TX cog that could be used for transmit buffer, so the max transmitted packet size will be smaller.
--Micah
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Nyamekye,
That would work for low-speed devices only. All high-speed (USB 2.0 480 Mb/s) and super-speed (USB 3.0 5 Gb/s) devices still have backward compatibility with USB 1.1 host controllers in 12 Mb/s full-speed mode. So, a low-speed host controller would work with very few devices (mostly mice and keyboards) whereas a full-speed host controller will work with the vast majority of USB devices.
If someone combined both a full-speed and low-speed host controller in one module, we'd have a fairly complete USB 1.1 controller that theoretically would work with any USB device. If there's a good reason to do this, it shouldn't be too hard. The same transmitter can be used with a lower clock rate. And a much simpler receiver cog would work. The rest of the code can be shared between both speeds.
--Micah
But that will give you a pretty large and variable latency of 8 to 16 cycles, right? I think waitpeq gives you single-cycle resolution.
But yeah, I probably overdesigned that. I was trying to make the ACKs really robust so I didn't have to worry about debugging them and everything else at the same time- but it could be that it's okay to tolerate a little bit higher latency.
--Micah
A waitpeq can take up to 15 cycles (7 in your example) to detect a condition less than 4 (1???) to exit.
From my experience, the 2 methods are equivalent, except that timeout latency is more and a pulse < 8 clocks will be missed.
Post Edited (jazzed) : 3/31/2010 7:29:21 PM GMT
A low speed host (1.5mbps) that worked at 80,96 and 100MHz, and supported USB keyboard and USB mouse in as few cogs as possible - ideally one cog.
I know... I am dreaming... probably not feasible.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.mikronauts.com E-mail: mikronauts _at_ gmail _dot_ com 5.0" VGA LCD in stock!
Morpheus dual Prop SBC w/ 512KB kit $119.95, Mem+2MB memory/IO kit $89.95, both kits $189.95 SerPlug $9.95
Propteus and Proteus for Propeller prototyping 6.250MHz custom Crystals run Propellers at 100MHz
Las - Large model assembler Largos - upcoming nano operating system
You win an ultimate license for 12blocks or viewport if you can get it done!
Conditions: I can communicate to/from the Propeller at 100kbps+ with just some passives and a USB bluetooth dongle. 4 cogs is fine, overclocking is fine, limits on datasize is fine, code is MIT license)
Hanno
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Co-author of the official Propeller Guide- available at Amazon
Developer of ViewPort, the premier visual debugger for the Propeller (read the review here, thread here),
12Blocks, the block-based programming environment (thread here)
and PropScope, the multi-function USB oscilloscope/function generator/logic analyzer
Thankyou also for commenting the code so well, and more than that, adding a great background preamble at the start
tubular
Have you been able to host any devices yet?
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
My Prop Info&Apps: ·http://www.rayslogic.com/propeller/propeller.htm
My Prop Products:· http://www.rayslogic.com/Propeller/Products/Products.htm
So far I've tried it with HID, storage, and bluetooth devices- but I just started writing the actual drivers, so right now it's a bit too low-level to use for an application. But anyone who's interested in writing device drivers should be able to pick up this host controller implementation and get started [noparse]:)[/noparse] I was planning on doing a really basic storage and bluetooth driver myself, but if there's a different device class you're interested in, I'd encourage you to try writing your own driver.
It should work with any full-speed devices that use Control, Bulk and Interrupt transfers.
So far it has:
- No-data control transfers
- Control reads
- Interrupt IN (read)
- Bulk IN (read)
- Bulk OUT (write)
I plan to add control writes and interrupt OUT, but haven't had a need so far.
Isochronous (for audio/video streaming) is theoretically possible, but I doubt the performance will be good enough for it to be useful. Also, the SOF markers I'm generating currently have fake frame numbers. Non-isoc devices won't care, but some isoc devices might.
--Micah
And it would have been mean, yet VERY funny if it was an April fool, but I'm glad it's real [noparse]:D[/noparse]
Well done! from the whole prop community, a great addition to it's list of things it can do.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
http://www.propgfx.co.uk/forum/·home of the PropGFX Lite
·
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Propeller Wiki: Share the coolness!
8x8 color 80 Column NTSC Text Object
Safety Tip: Life is as good as YOU think it is!
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
You only ever need two tools in life. If it moves and it shouldn't use Duct Tape. If it does not move and it should use WD40.
if this will let me communicate with my laser keyboard i will be a happy camper. i can just imagine it. robot drives up and projects keyboard in front of you. type in some commands and it drives away.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Check out my brand new site.
I agree 3 cogs would be nice, but if it sacrifices anything (function/reliability/etc.), 4 is a workable solution for most projects.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
April, 2008: when I discovered the answers to all my micro-computational-botherations!
Some of my objects:
MCP3X0X ADC Driver - Programmable Schmitt inputs, frequency reading, and more!
Simple Propeller-based Database - Making life easier and more readable for all your EEPROM storage needs.
String Manipulation Library - Don't allow strings to be the bane of the Propeller, bend them to your will!
Fast Inter-Propeller Comm - Fast communication between two propellers (1.37MB/s @100MHz)!
I immediatly built the hardware on my Protoboard (I had a, USB-A jack from other thests on it), and tried it with
several USB devices:
- no luck with some USB-PICs which has a HID and a CDC firmware. The enumeration test always returns Error -1.
- no luck with an FT232R on a PropPlug clone, there I get Error -10.
- But then, with a cheap MP3 player, the enumeration was sucessful. It is a storage device, and so also the Storage test spin
worked well. No Bulk Read/Write errors.
- So I tried also an external USB harddisk, and the enumeration was successful. But my Propeller host has not enough
power to drive the disk.
All in all a promising result
Some toughts about reducing the needed cogs:
As you already said, the Tx-cog can do the job of the ACK-cog. The EOF state is active for 2 bittimes, so a test without
WAITPEQ should be possible. Here a untested code idea:
If too much cog memory is occupied, why not hold the encoded USB packets in HubRAM ?
A trick to get a timeout for WAITPEQ is to use a free pin and a cog counter. The counter outputs it's state at the pin,
and the pin is also contained in the WATPEQ mask and state. When the counter times out, the pin is changed, and
the WAITPEQ is aborted.
Perhaps with this trick it is even possible that the Tx-cog can also do the job of one of the Rx-Cogs, and we end up with
only 2 cogs.
Thank you very much for releasing this
Andy
Post Edited (Ariba) : 4/1/2010 8:33:42 PM GMT
I also noticed a rather nasty bug in the original release a couple nights ago: I was using WORD[noparse]/noparse to read unaligned data in the VendorID/ProductID convenience functions. So the enumeration demo would return a bogus vendor/product ID. I fixed this in the Subversion repo, but I haven't cut a new release yet.
I had a little bit of time to try moving ACK to the TX cog last night- I wrote some code that looked like it should work, but it didn't right away. The timing is pretty finicky, and I didn't have time then to hook up my logic analyzer. In the next couple days I should have a chance to reexamine it.
If I can tolerate the extra latency in loading the video generator, I can send the ACK using a few waitvids. That'll use very little extra cog memory. If I do have to use a big unrolled loop to send the ACK, I might indeed have to move the TX buffer into hub memory. I liked keeping it in cog memory to make the encoder a bit more efficient, but all things considered it's probably not a big deal either way.
I also might overlay some of the buffers on the hub memory that stores the cog code, just to save hub RAM. (This would preclude stopping/restarting the USB controller at runtime, though...) There are a lot of small things that can be done to optimize memory usage and encoding/decoding speed. I haven't really started to optimize this at all.. I posted it here the day after I got HID working reliably [noparse]:)[/noparse]
@Hanno: Nice find on those cheap bluetooth dongles. I think I'll order a few, so I can make sure the driver works with them!
--Micah
http://www.dealextreme.com/details.dx/sku.24688
802.11 adapter with an Ralink chip, for $10 [noparse]:)[/noparse]
--Micah
http://forums.parallax.com/showthread.php?p=845742
I have the USB host apparently working in 3 cogs, using the video generator to send an ACK. It's an unholy awful hack, but it appears to work. Prior to this code executing, I set up vscl for 'turbo' speed (1 clock per bit) so that the first waitvid has a narrower range of latencies. The actual latency in sending an ACK doesn't have to be super-low, but there's a narrow window I have to hit. Too long and the device gives up on me, too short and I don't give my receiver enough time to detect the end of the previous packet.
Still testing and tidying this up, but expect the next version to need one fewer cog [noparse]:)[/noparse]
--Micah