Jump to content
lawrence_jeff

Launchpad USB example and documentation additions/labs

Recommended Posts

So your debouncing requires that no buttons change for 5 cycles before they are reported? What about if button A is held down for say 100 but button B cycles state every 4 cycles? Would it ever send button A?

 

I was thinking something like a circular buffer where you save the last 5 states of all buttons and then AND'ing the states of each bit across the last 5 and any that have stayed the same get reported (if its different than the last sent value). I think in the example above that would send button A after 5 cycles but not send button B until it had been stable for 5. 

Share this post


Link to post
Share on other sites

@@lawrence_jeff

 

Hmm, from my reading, most microswitches like are used on arcade controls have a maximum bounce period of around 8ms.  I'm not checking the state of individual buttons, I'm checking the state of each entire virtual USB device.  If one button is being held down, and another button is pressed, the state of the device has changed, and if it holds stable for five systicks before hitting the five systick oscillation timeout, an updated packet with the most recently acquired device state will be sent.  This way, it is a known that the devices state has been stable for at least five out of nine cycles, and the most recent state has been stable for a minimum of two cycles.  It shouldn't be physically possible to intentionally cycle a button faster than the 9ms (~111Hz) combined max before timout and reset.

 

Since I track entire devices together as a whole, not individual buttons, I'm not sure how your ring buffer idea would work.  Actually, I'm not exactly sure how that would work at all.

 

I am still a very green programmer, so I'm just working with what logic I can come up with on the fly and off the top of my head.  Some of it my be a little unorthodoxed compared to a veteran programmer.  I'll do a little research on software debouncing for an entire 8bit port and see if I can find something that will work better.  What I implemented is the best I could think of at the time.

Share this post


Link to post
Share on other sites

@@lawrence_jeff

 

I've seen that site before.  I'll see if I can work out how to use that method in this context.  There will have to be 6 of those checks during each 1ms tick cycle, hopefully they aren't too computationally intensive for thing to keep up...  I'll update once I've had a chance to work on it.

Share this post


Link to post
Share on other sites

@@lawrence_jeff

 

Completely rewrote the debouncing and USB transmit routines.  All switches are now debounced through a buffer as per your suggestions, and USB transmits only happen when there is a change in state.  Updated on my Github https://github.com/Rhys79/Launchpad-Mame-Control.  Attached is the updated code.

 

Fully tested and functional if the R9/10 resistors are removed with the exception of the trackball input.  I added a #define for a mouse scalar value as well, as you indicated the value may need scaling depending on the input device resolution.

 

Let me know what you think!

usb_dev_mame.c

Share this post


Link to post
Share on other sites

@@lawrence_jeff

 

Completely rewrote the debouncing and USB transmit routines.  All switches are now debounced through a buffer as per your suggestions, and USB transmits only happen when there is a change in state.  Updated on my Github https://github.com/Rhys79/Launchpad-Mame-Control.  Attached is the updated code.

 

Fully tested and functional if the R9/10 resistors are removed with the exception of the trackball input.  I added a #define for a mouse scalar value as well, as you indicated the value may need scaling depending on the input device resolution.

 

Let me know what you think!

 

Sounds awesome, I will test it out and get back to you!

Share this post


Link to post
Share on other sites

@@lawrence_jeff

 

Did you get a change to check the code with your trackball?  Want to make sure the mouse code works correctly.

 

Next project is to modularize the code and add a defines header to make it easy to change out what the device presents as and add a DFU bootloader.  Then I can code a front end configuration tool to allow end users to custom configure it.

Share this post


Link to post
Share on other sites

Sounds awesome, I will test it out and get back to you!

 

Ok - I forked your code and made the changes required for my device (I have less buttons on mine). The trackball code worked fine except you need to put () before the multiply (I think without it is multiplying the -127 * 2.)

 

Great work, it seems to do the job quite well - Keep us in the loop as you make other improvements!!

 

I made some changes to your code in my revision though:

  • Moved all the pin assignments to Mame_pins.c and h (I only have pad 1 defined in .c at this point)
  • Moved the X and Y reads of the trackball to the StoreSwitches function so all the reads were together
  • Simplified the CustomHid handler to remove the loops and the extra variables
  • Renamed some of the variables a bit to make it more readable
  • Added comments
  • Used the Max_Checks to also control how often the CustomHid function is ran

You can see the changes here if you want to use any

 

https://github.com/lawrence-jeff/Launchpad-Mame-Control

Share this post


Link to post
Share on other sites

@@lawrence_jeff

 

I'll correct the math on the trackball code in my code and update it.

 

I'm glad it all works well, this is the first MCU project I've written essentially from scratch and actually gotten to work correctly.  Thank you so much for all of your assistance and input through the process.  I likely wouldn't have made it this far without it.

 

Like I mentioned, now that I have the mechanics down and a functional code base to start with, I plan on doing a complete fork and rewrite to make the whole thing modular and configurable through a header file.  Once I get that working, I will attempt to write a graphical frontend for it that will allow a user to drag and drop various arcade controls onto a virtual control panel and assign them to whatever GPIO pins they would like.  It will then generate the necessary header file, compile the code, and send it to the device using a DFU bootloader.  TI provides a ready-made DFU bootloader for the Tiva chips, so that part will be easy.  Modularizing the code into separate files that can be loaded in as functions through the header file shouldn't be too hard either.  I do have to figure out how to modularize the USB stack though so I can change the HID devices without having to recompile the entire USB library every time.  I have an idea for that, and I'll get back with you on it once I've fleshed it out.

 

Again, thank you for all the help!

 

--Edit--

 

I left the mouse delta reads in the HID change handler routine rather than the store switches routine so as to not waste CPU cycles reading the value when it wasn't necessary.  It's redundant to call it every systick rather than every MAXCHECK systicks.  Not that it likely matters as there should be plenty of CPU cycles to spare between 1ms systicks, but it just seemed redundant to me.  If anything, I would stuff it in the debounceSwitches routine, as that also only gets called every MAXCHECK systicks.  That's probably where I'll stick it when I modularize the code.

 

I'm more accustomed to working with 8Mhz Atmel code where I'm pushing the limits of the processor to complete things in time, so I generally try to avoid wasted CPU cycles whenever possible.  The Tiva is about 10 times faster, so I have a little more wiggle room on it than I'm used to....

Share this post


Link to post
Share on other sites

@@bluehash - Thank you, it's only a prototype, but it's a start.

 

@@lawrence_jeff - I found a nifty little macro while looking through the composite HID example that just might make things a little easier on me now that I'm starting to break this down into something I can drop a configuration set over a USB CDC serial connection into EEPROM to make it easily reconfigurable as to what devices it presents as and what pins are assigned to what functions.  HWREGBITW makes it quite simple to read from or write to a single bit in an unsigned long.  Should make it much simpler to read in all of the ports, debounce, and then pick through the individual bits to grab what I need and reassign it into signed char arrays based on the configuration data to send out as USB updates.

 

Still working on the logical flow of how I want to go about what I want to do, but I'm starting to get a rough idea now.  I'll keep you posted as I progress on it.  I'll start a project thread for it once I get the basic framework straightened out in my head.

Share this post


Link to post
Share on other sites

Wow!  Thank you for this walkthrough and examples.

 

I got the Volume demo working.  And it also controls the volume of my phone when I connect the LaunchPad to my phone with an OTG cable such as this.  I have a Samsung Galaxy Nexus.  I suspect this will work with any Android device running Ice Cream Sandwich or later and supporting USB Host.

 

With the LED blink application that came on the LaunchPad, I could connect just one USB cable to the DEBUG port which would both power the device and serve as a serial communications port for a terminal application.  So I wasn't expecting to have to connect a second USB cable to the DEVICE port for the Volume example.  Is it possible to use just one of the LaunchPad's USB ports for both power and the custom HID interface?

 

How are you planning to install this into your game controller?  Are you going to power the controller with one USB cable and use another for the HID interface?

Share this post


Link to post
Share on other sites

Single cable.  There is a switch between the two ports the switches which USB port is used for power.  By default the device ships with the switch set to debug.  Switch it the other way and it will pull power from the device port instead so you only need one cable for power and device interface.

Share this post


Link to post
Share on other sites

@lawrence_jeff

 

Thank you very much for your code and examples. I am having trouble getting the code working however. I have compiled both the volume control example, as well as the gamepad example. It builds and will run on the stellaris launchpad, but it does not connect. It stays 'red', and always enters the loop: while(!g_bConnected)

@all Does anyone know how why my computer doesnt detect the new device?

 

many thanks!

Jesse

Share this post


Link to post
Share on other sites

I have figured it out, it only works when I connect to device. However when I run the gamepad example, the correct drivers dont seem to install. It shows up as Gamepad example, but gamepad drivers are not installed. 

Is this perhaps because the g_pSerialNumberString was already detected on my computer as a Volume control device?

many thanks

Jesse

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×