Jump to content
Rhys

Energia Tiva USB support

Recommended Posts

Well, my thought at this point is to start small and see if I can get a USB CDC Serial device library working to start with, and then move on to HID.  Unfortunately, I don't have tons of free time to work on it right now, so it may be a bit slow going.  Right now I'm working on picking through a handful of OSS USB stacks to see if I can cherry pick out the bits and bobs to put together the CDC library.  I also have to do some serious digging into the low level USB HAL in the driverlib.  I have to reconcile what the TI USB HAL offers against the HAL layer in the open source stacks before I can even begin to tease the rest of it apart.  It may end up being easier to start from scratch, but if I'm going to do that, I'd rather start with the CMSIS USB HAL.  That would in theory make the library portable across all ARM based chips, assuming the chip manufacturers ever decide to support the new spec....

 

And, even if TI does release the usblib under the BSD license, it is so cumbersome to use for the simple tasks that users of Energia would be likely to need, that it will need half rewritten anyways.  So, I guess knowing that there is a good possibility of TI opening up the license of the usblib, I guess I could just start working from that, as I'm already fairly familiar with it, and have it ready to drop in when the legal nimrods get done writing things to death....

Share this post


Link to post
Share on other sites

Ok, so I've come to the conclusion my coding skill is not up to par for writing a USB stack, or even modifying an existing one, for the purpose of getting USB support into Energia.  I on the other hand, should be able to handle writing a wrapper for the TI usblib to act as a wedge to emulate the USB device functions currently in the Arduino environment.  It's not an ideal solution at this point, but if TI is working on opening up the usblib license to BSD, it would be a workable solution.  In the mean time, the wrapper can be made available with instructions on how to add the TI usblib and wrapper to a users local Energia install.  Using the usblib drivers directly is far beyond the skill level of most of the target audience of Energia.

 

I will start working on the wrapper, code will be available on my github if anyone else would like to contribute.  Once the existing Arduino functionality has been implemented, we can work on extending the USB support to allow for more creative uses of the stack.  Assistance from the Energia devs would be helpful for writing up the install docs for usblib and the wrapper until such time as they can be legally distributed as part of Energia.

 

How does that sound to interested parties?

Share this post


Link to post
Share on other sites

In your researches did you find any particularly nice APIs for programming USB (either host or device)?

I did a little browsing of the USB code in Arduino - and a lot of it could be more accessible.

 

Figured there may be some nicer APIs out there, might be worth designing  the warper to improve on the Arduino API (and then provide a compatible API for backward compatibility).  That said, I do not have any particular API in mind as a good one to use.  (After looking at a few USB examples I have seen a lot of difficult to follow code, but not a lot of clarity.)

Share this post


Link to post
Share on other sites

Yeah, I'm not thrilled with the Arduino USB API, it doesn't really accomplish much, and definitely not anything I would want to do.  I haven't found any others I particular like either.  They are all either WAY too basic like Arduino, or way more complex than is appropriate for Energia like the TI usblib.  I will probably end up developing my own API based on things people actually might want to do, and throw in Arduino API compatibility for support of existing Arduino sketches.

 

Here's a rough list of things I want to include.  I haven't even started planning the actual API itself yet.  I will flesh this out more as I have time and continue to log my progress on here.

 

Device:

 

USB HID

 - custom device descriptors

   - simple format for storing custom device descriptors (macros?)

 - composite HID support

   - initialize a composite HID device using standard or custom devices (#define option to enable composite HID)

 - keyboard

   - Arduino API

   - alternative methods of setting keys on/off (faster for alternative keyboard applications - ie. Mame)

 - mouse

   - Arduino API

   - alternative methods of setting mouse buttons on/off (faster)

   - support for hardware QEI for position input

 - joystick

   - simple method to set axis count and type (digital/analog)

   - simple method to set button count

   - simple method to assign ports/pins to buttons/axis

   - Arduino like single button/axis state change commands

   - one shot invert all assigned button ports/pins state to button input command

USB CDC

 - redirect any UART to USB

 - options configuration

USB Mass Storage

 - Access external flash (SD/MMC) as mass storage device

 

Host:

 

USB HID

 - Keyboard

 - Mouse

 - Joystick

USB Mass Storage

 - read/write support

Share this post


Link to post
Share on other sites

Nice list.

A few other things might consider adding (I was toying with a similar list).

 

Device:

Adding HID indicators/outputs as part of joystick, etc.  (Handle LEDs, rumble motors, etc.)

Handle absolute positioning as well as relative (for mouse) - e.g. tablets.

Mouse should also have way to set axis count, number buttons, etc. (3D mice, pressure/tilt sensors on tablets, etc.)

 

Maybe make composite support for other device classes as well.

  (e.g. CDC + HID)

 

Other classes that might consider (or may leave as exercise to the reader):

 

Printer (as device and host).  - nothing fancy, just take basic strings of text

  (e.g. May be simpler alternative if your host software doesn't know how to display things on your neat screen/LED reader board/etc.)

 

Support for simple networking (I assume that would be under CDC) - e.g. there are lots of wireless booster packs, might be handy to have framework for exposing 

  the communications layer to host devices.

 

HID Display (Seems like a natural, with all the little displays on booster packs, text displays, etc.
  However I find very little about implementations of the HID display class - don't know if that indicates there are technical difficulties, or isn't much host software
  to use it, or what)

Share this post


Link to post
Share on other sites

composite devices (ie. CDC & HID) would be a part I forgot to add to the list.

 

custom mouse types would be included in the custom HID descriptor portion of the code.  HID devices are essentially just a descriptor that tells the host how many bytes of data to expect and what to look for in those bytes, and then code to push those packets into the USB FIFO.  Any custom HID descriptor code would therefore allow for the end user to design any HID device they would like.

 

Printer would be a class I wouldn't even touch until I had CDC and HID host/device complete, as I can't really see much use for it.

 

Most wireless booster pack wireless devices uses a uart/spi/i2c type interface to the host MCU, I can't see any reason to deal with any networking related USB code unless someone was wanting the MCU to do USB host for a USB NIC, which seems a little far-fetched.

 

HID display would fall under the category of custom HID device descriptors.  Most graphic LCD displays in their raw state are either RGB or LVDS.  Most smaller displays can be gotten with a built in controller chip that will accept some form of uart/spi/i2c or raw VGA signal.  Larger panels (5" and up) for the most part are raw parallel LVDS (high resolution) or RGB (low resolution) input.  Either way, without specs for the control and timing signals for the display, they are completely useless.  I have a steady supply of 5" 320x240 QVGA full color graphic LCDs that at this point are completely useless because I have neither the skill to disassemble the AT91SAM9 control chip firmware and extract the LCD configuration values, nor have I been able to find the JTAG interface pins on the PCB to connect to the chip while it's running and read them out directly.  They are completely unmarked raw LCD panels, so no way to find out who makes them or get a data sheet. The manufacturer of the device they come out of won't tell me either (already asked nicely).  Laptop LCDs on the other hand are fairly easy to get datasheets for and HDMI/DVI/VGA to LVDS controllers can be had from China on Ebay for under $50.  They will even program them and provide the proper cable for you if you tell them the part# of the LCD when you place the order.  Those are based on purpose built chips that are designed for the sole purpose of converting a standard video signal to LVDS for an LCD.  The other option is to use a stock MCU that has RGB/LVDS LCD support, such as most Cortex A7 or A8 based SBCs, like the Cubieboard.  You can literally attach an LVDS or RGB LCD directly to an AllWinner A10/13/20/31 CPU, create a Linux driver for the LCD, and drive it right off the CPU.  Granted, I'm making that sound entirely simpler than what it actually is, but you get the idea....  For most peoples purposes, HID display would be useless.  Even driving a QVGA display with nothing but static images from the AT91SAM9 CPU requires a decent sized chunk of RAM as an external chip to act as a frame buffer for the display. And the modules I have don't even store the images locally in flash, they are piped to the controller over a USB Bulk connection from a host PC.

Share this post


Link to post
Share on other sites

As far as HID display, I was thinking in terms of the small screens used in booster packs, or text screens ( HD44780, etc. ), VFD (e.g. noritake), e-paper booster pack, OLED, etc.

e.g.

http://forum.stellarisiti.com/topic/643-energia-library-lcd-screen-library-suite/

 

One obvious use for such things might be to connect them up to a computer via software like LCD Smartie http://lcdsmartie.sourceforge.net/, LCD4Linux http://ssl.bulix.org/projects/lcd4linux/, etc.  Windows also had a system for secondary/status displays started (round about Windows Vista or 7).

Or to have a game controller with a small status display.

 

Various of these devices and programs have their own custom protocols, which one could emulate.

In theory, using a standard protocol like HID display might be helpful. Of course that may not play out in practice (e.g. if nobody uses the standard protocol).

Probably something for another topic/separate project.  

Do you have a thread on reverse engineering the devices you mentioned?

Share this post


Link to post
Share on other sites

I see what you mean now.  I can see where that might be useful if you can find host software that supports it.  I do not write windows/Linux software however, so I wouldn't be much help with that.

 

I don't believe I had started a thread on here regarding the LCD/AT91SAM9 combo I would like to reverse engineer.  I do have a project posted on Hackaday regarding it though.  There are pictures and details on the board there.  There is also a link to the firmware and host control software packages hosted on my dropbox.  I would be happy to donate one of these to someone if they are fairly certain they can pull what I need out of the code and find the JTAG pins so it can be reprogramed.

Share this post


Link to post
Share on other sites


//Standard HID devices

//keyboard - Keyboard

//mouse_rel - Mouse - Relative x/y axis

//mouse_abs - Mouse - Absolute x/y axis

//

//Choose only one resolution option each when initializing Joystick 1 and 2

//

//joy1_AN8 - Joystick 1 - x/y axis 8bit resolution (range -127 to 127)

//joy2_AN8 - Joystick 2 - x/y axis 8bit resolution (range -127 to 127)

//

//joy1_AN16 - Joystick 1 - x/y axis 16bit resolution (range -32767 to 32767)

//joy2_AN16 - Joystick 2 - x/y axis 16bit resolution (range -32767 to 32767)

//

//joy1_DIG - Joystick 1 - x/y axis 1bit resolution (range -1 to 1)

//joy2_DIG - Joystick 2 - x/y axis 1bit resolution (range -1 to 1)

//

//custom HID devices can be defined and used as a device type as well - how to define custom device TBD

 

extern bool initializeHID(uint8_t device); //initialize single HID device

extern bool initializeHIDcomp(uint8_t device1, uint8_t device2, uint8_t device3); //Initialize composite HID device

extern bool usb.initializeCDC(uint8_t uart); //Initialize CDC device redirecting UART uart#

extern bool usb.initializeMS; //Initialize Mass Storage device

 

//keyboard commands

extern bool key_change(char key, bool value); //change key state - returns bool success:overrun

extern bool key_press(char key); //press and release key - returns bool success:overrun

extern bool key_modifier_change(char key, bool value); //change modifier key state - returns bool success:overrun

extern void key_report(uint16_t &report); //bypass library processing and send self created HID keyboard report - no return

 

//mouse commands

//

//These defines must be present before initializing an absolute position mouse device

//

//#define mouse_ABS_resX = uint16_t x_res //set X resolution of absolute position mouse device

//#define mouse_ABS_resY = uint16_t y_res //set Y resolution of absolute position mouse device

//

extern void mouse_REL(int16_t x, int16_t y); //update mouse x/y relative coordinates for absolute device

extern void mouse(int16_t x, int16_t y); //update mouse x/y coordinates (relative or absolute depending on initialized mode)

extern void mouse_button_change(uint8_t button, bool value); //change mouse button state (1-3)

extern void mouse_button_press(uint8_tbutton); //press and release mouse button (1-3)

extern void mouse_report(uint16_t &report); //bypass library processing and send self created HID Mouse report

 

//joystick commands

extern void joy1_axis(int16_t x, int16_t y); //update joystick 1 axis positions - use appropriate range for selected device

extern void joy1_button_change(uint8_t button, bool value); //change joystick 1 button state (1-8)

extern void joy1_button_press(uint8_t button); //press and release joystick 1 button (1-8)

extern void joy1_report(uint16_t &report); //bypass library processing and send self created HID Joystick1 report

extern void joy2_AN8(int16_t x, int16_t y); //update joystick 2 axis positions - use appropriate range for selected device

extern void joy2_button_change(uint8_t button, bool value); //change joystick 2 button state (1-8)

extern void joy2_button_press(uint8_t button); //press and release joystick 2 button (1-8)

extern void joy2_report(uint16_t &report); //bypass library processing and send self created HID Joystick2 report

 

//custom HID device commands

extern void device_report(uint8_t device, uint16_t &report); //send device report (uint16_t &report) for custom HID device (uint8_t device)

 

//CDC commands

TBD

 

//Mass Storage commands

TBD

 

Share this post


Link to post
Share on other sites

For the Mass Storage ... would MTP be an option?  I think it would be incredibly useful to produce "files" that are dynamic, think Linux's /proc and /sys filesystems.  Makes for a very easy firmware-to-PC interface.  I'm not too familiar with USB but I think something like MTP is how e.g. Apple and Android devices "share" their filesystem while keeping it mounted internally...

Share this post


Link to post
Share on other sites

I know nothing about MTP, and I don't believe I've seen any reference to it in the TI usblib (may have just missed it).  Not really something I'm looking to do at this time.  I'm not entirely positive if I am even going to bother with Mass Storage mode at this point anyways.  Not something I need for any projects I'm working on.  If someone else wants to add it, they are welcome to do so.  I'm putting the prototype in place as a placeholder at this point.  All I'm looking to do is USB HID and CDC.  This is just a start on the header file for a library wrapper to get some semblance of USB support for the Tiva chips, and being to distribute it included with Energia will be dependent on TI opening up the usblib to a BSD license anyways.  I came to the conclusion I have neither the time nor the skill to write the whole USB stack from scratch....

Share this post


Link to post
Share on other sites

I know nothing about MTP, and I don't believe I've seen any reference to it in the TI usblib (may have just missed it).  Not really something I'm looking to do at this time.  I'm not entirely positive if I am even going to bother with Mass Storage mode at this point anyways.  Not something I need for any projects I'm working on.  If someone else wants to add it, they are welcome to do so.  I'm putting the prototype in place as a placeholder at this point.  All I'm looking to do is USB HID and CDC.  This is just a start on the header file for a library wrapper to get some semblance of USB support for the Tiva chips, and being to distribute it included with Energia will be dependent on TI opening up the usblib to a BSD license anyways.  I came to the conclusion I have neither the time nor the skill to write the whole USB stack from scratch....

Yeah it sounds like several months worth of work to just get up to speed on the necessary intricacies of USB to make a stack, as it stands now I bet this will take a little less...

Share this post


Link to post
Share on other sites

I should be able to knock out the wrapper in a few weeks (if I get time to work on it) along with instructions for how to integrate it and usblib into Energia until such time as TI decides to move the usblib to a BSD license.  TI's usblib is relatively feature complete as far as I'm concerned.  It's not even all that terribly difficult to use if you want pretty decent controls over your device.  However, definitely not friendly to use for the Arduino type crowd.  I just didn't see the point in reinventing the entire wheel when I could just put training wheels on it lol....  I have a reasonable understanding of the USB HID portion of usblib, and a couple of new examples in the latest Tivaware release helped fill in a few gaps.  CDC I haven't used yet, but looks pretty straight forward.  I should be able to cherry pick the bits I need out of the USB_CDC example code.  Mass Storage is a shot in the dark if I decide to even look at it.  I may leave that for some other enterprising individual who has use for it to implement.

 

The partial header file I posted was all I've had time for yet lol....  Although that does allow me solicit comments and suggestions on the user end of the library and adjust things before starting on actual code.  I find it best if I start at the top and work my way down :)

 

BTW, I like the current library call names I decided on, but the internal variable names are simply place holders for readabilities sake and are by no means what I plan on using....  Once I get the header a little more polished, I'll start a new github repo for it and anyone else who cares to chime in and help can submit pulls requests to the repo.

Share this post


Link to post
Share on other sites

Few thoughts on the interface 

extern void joy1_DIG(bool x, bool y); 

How is this going to work?  As far as I know typical digital joystick has 4 buttons (right, left, up, down) - which gives 9 possible states.  

The function prototype given can only take 4 possible inputs.

extern void joy1_button_on(uint8_t button#);
extern void joy1_button_off(uint8_t button#);
// Consider adding or replacing with 
extern void joy1_button(uint8_t button#, bool state) 

Obviously one can translate back and forth between the above calls, so whichever gives the cleanest interface to underlying code might make most sense, with the others as syntactic sugar.  I would expect the latter might be more readily useful from application perspective - often just read a variable or button and want to pass the state on to the joystick - so bother to have to do a conditional and call separate routines instead of just pass in variable.

 

 

Consider adding an interface to send multiple button presses at one time (button chords on mouse or joystick).  (e.g. buttons as bitmask).

Some programs respond to clicking combination of (e.g.) left and right mouse button simultaneously in special way, would be nice to be able to specify that as one atomic action,

rather than having to make 2 calls and hope that they come in close enough together to be interpreted as a chord.  (i.e. no interrupts, etc. intervene)

If the interface will gather up events and wait for a "Send message now" call, then this would not be strictly necessary, but still could be handy.

 

Calling functions joy1/joy2 seems cumbersome (extending to more joysticks means larger api). - consider taking joystick # as parameter

 

Also, having multiple naming schemes for the joysticks and mice are confusing.

Why call the same device joy1_AN8 (function call) and "5", or device 2 and mouse_REL? Invites confusion and programming errors.  

 

If going to define a mouse device as relative, then the mouse_move will obviously be relative.  Is there reasonable meaning for mouse_ABS on a relative mouse?

(Of course there is reasonable meaning for mouse_REL on an absolute mouse).

 

Assume API will be revised to return error codes from the various functions where there are errors that can be detected.

 

Perhaps providing an example would help clarify how interface is supposed to work.

If I have 1 joystick device (an old Microsoft Sidewinder 3D Pro joystick) with an x/y analog stick, a hat controller (x/y digital), an analog lever on the base, stick rotation switches (left, right), a trigger and 8 buttons, how do I set that up?

I guess I declare it as a combo HID device with device # 4,6 and 8?

Which gives me 16 bit analog main stick (joy1_AN16), digital hat (joy1_DIG), and analog lever as 1 axis of the 8 bit analog stick (joy1_AN8).

Then what about the buttons - do I just get 8 buttons shared between the three joystick 1 sticks?  So I have to forgo some of the buttons or rotation switches (or maybe use rotation switches as second axis of 8 bit analog stick).

For some of the fancier sticks one may have to dip into joystick 2.

 

Need scroll wheel interface for mouse. e.g.

void mouse_z_REL(uint16_t z); // e.g. for rotary encoder
void mouse_z_ABS(uint16_t z); // e.g. for z axis in 3d mouse, or for pressure from a pen

Consider allowing >3 buttons on mouse (e.g. Logitech MX 700 has 7 buttons)

Share this post


Link to post
Share on other sites

Digital Joystick - My bad, that should be a signed int, but the valid range is -1 to 1.  If you look at my earlier arcade control panel code, that is what I used.

 

Button toggle code - Your idea makes more sense and makes toggling a button much simpler.  Thank you!

 

Multiple simultaneous presses - That would be covered by the *****_report() command, you can feed a full HID report for that device in a single variable array.  That is still a work in progress and I may come up with a better solution along the way.

 

multiple device names - I had thought about using a device number rather than joy1/joy2.  I see what you mean about mouse_abs not being usefull for a relative positioned mouse, but the functions are generic, not specific to the type of mouse called, and by explicitly labeling them, it prevents confusion on the part of the end user.

 

error handling - that will be added in as I go.  I will update as I decide what kind of errors could present and how best to report them

 

Your questions at the end make no sense in relation to what I'm working on right now.  This is all device code, I haven't even looked at host yet.  USB host for attaching devices to the Launchpad will be completely different.

 

Any use cases for more complex devices would be covered under the create your own HID device descriptor.  These are simple function prototypes to allow someone who wants basic functionality and doesn't want to learn how USB HID works to setup a quick keyboard/mouse/joystick device.  The DIY descriptor will be my shorthand way of enabling users to make more complex devices without having to learn the underlying usblib functions.

 

I hope that all makes sense, trying to watch TV while I typed this lol...

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.


×
×
  • Create New...