Jump to content

lawrence_jeff

Members
  • Content Count

    42
  • Joined

  • Last visited

  • Days Won

    3

Everything posted by lawrence_jeff

  1. Its been long enough that I would have to take a look to figure it out - can you post your code? Or email lawrence underscore jeff at hotmail.
  2. Sometimes Windows does get confused. I thought I had some info in the document about that but don't have it in front of me. If you change the PID it should see it as a new device. (Shouldn't be necessary if you delete the device)
  3. Also a UMR alum (ee 99) Hope you had some luck, I'm also in STL (in IT)
  4. If you are using a stellaris launchpad that is your only option. My code example was for a tiva launchpad which has the pwm module.
  5. 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
  6. @ryhs Check out http://www.ganssle.com/debouncing-pt2.HTML specifically the section Handling Multiple Inputs. It describes exactly what I was thinking. With so many buttons potentially being pressed at the same time I think you need to individually denounce vs the whole device.
  7. 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.
  8. Awesome - I had meant to work on that but haven't had a chance, will try it out tonight! When you say the DPAD is pins 0-3 can you confirm the ordering, is 0 up and 1 right and so on clockwise or do you use a different approach?
  9. Couple things I noticed, typo here QEIPositionSet(QEI0_BASE, 128); - One of these should be QEI1 Also the bigger issue with the trackball code is using 128 as the center of a report that maxes out at 256 doesn't work, mine which uses 256 and 512 works fine. I believe this is because the function uses signed char which has a maximum value of 127 per axis and this code is sending 128 at rest. I think the only reason my code works using 256 and 512 is coincidental because its rolling over and ending up within a valid range. So I think its back to taking the QEI value and shifting it so the value being sent for each axis is in the valid -127 to 127 range. The DPad works correctly with your descriptor although all the buttons do the wrong thing (I think I have them wired differently I didn't see in your code any notes about which buttons were wired to which pins). I can fix that through trial and error though. Also what are your thoughts on debouncing? - you check the buttons less frequently than the mouse but you still get a point in time reading that may be transient. I was thinking about reading the value x (TBD) times in a row and only sending a report if the value was the same for all iterations - but not sure the most efficient code for that. Also just so you are aware this code streams constant reports at the PC, a real device sends a single report for a button press and doesn't send another until something changes (and doesn't send any reports at rest). I am looking to recreate this logic also which I have in my PIC code by a simple check if the data has changed since the last send and to not send multiple times (which also solves the at rest since it will detect it already sent a zero'd report)
  10. Can you provide a snipet of the code sending the data that corresponds to that descriptor?
  11. I don't understand that descriptor, it indicates using a 2 bit report to send a value between -1 and 1, i don't see how you can do that since you need a signed value. You could do it in 2 8 bit reports since -1 is 11111111 and +1 is 00000001, but that really isn't that much simpler than -127 and 127. The V-USB mamepanel project uses a similar descriptor (-1 to 1) and somehow does each axis in 4 bits but I would have to dig through his code to understand how. A hat control which I have working can also do it in 4 bits since you send value 1-8 (1 represents straight up, 2 is up/right, 3 is right and so on in a circle). For your keyboard question should be no issue as my current 8 bit PIC controller code (what I'm porting to the Tiva) does exactly this and its much slower. Define a keyboard descriptor that accepts 8 bytes (to support 8 simultaneous keys being pressed). Then put them all on one port on the Tiva (just like your current code does with buttons) and then do something like Read all the buttons into one variable, invert it and & it with 15 so you get 00000000 representing 8 unpressed buttons Check bit 1 to see if it's pressed by & your variable with 1 - if so keyboard[1]=keyboardvalueforbutton1 if not keyboard[1]=0 Check bit 2 to see if it's pressed by & your variable with 2- if so keyboard[2]=keyboardvalueforbutton2 if not keyboard[2]=0 Check bit 3 to see if it's pressed by & your variable with 4- if so keyboard[3]=keyboardvalueforbutton3 if not keyboard[3]=0 and so on 5 more times Send you array (of course debouncing is not covered along with the reserved byte in a keyboard and you will need to change some of the other hid descriptors) Tricky part with keyboards is to make sure the TI tool will handle a keyboard with >6 byte report (BIOS keyboard mode doesn't support this and some frameworks are picky) also you need to handle keyboard modifiers which can be tricky. If you get stuck post or github your code and I can take a look
  12. @Rhys Please share that descriptor if you get that working, I haven't seen that but it would seem to be ideal (make sure it supports the diagonals since those are valid in an 8 way joystick.). You will probably need to add those descriptor constants to the file which contains the Rz and Hat constants since TI didn't seem to include anything related to gamepads/joysticks in their HID files. On the jumpers, with those in place if they are both used for buttons pressing one should register the change on both pins, at least I hope that's the case since I spent the time to remove them...
  13. @Rhys The bit shifting (multiplying the value by 2) is just to double the incremental value sent so that a smaller trackball movement has a larger impact to the onscreen mouse. This is something that probably needs to be tweaked per specific trackball but on mine (Happ) without this you have to roll it quite a bit to have significant movement of the mouse, it just way too fine a pitch, doubling the value makes it appear to be more responsive. On the QEI hitting zero or maxing out - I don't think you need to worry about this, the reporting (and subsequent reset of the QEI) should keep up with it fairly well so 90% of the time you should be reporting something in the range of -5 to 5. I cranked it on mine and it looks like it got up to 64 or so before it caught up and reset (but you need to tweak this with your specific device). You could aways make the QEI have a larger range and then add code to say if outside of the -127 to 127 range report the max -127 or 127. Addition on 9/2 - Playing with this a bit more, in the descriptor you can define the mouse movement as a positive range - so if you do 0 -512 and then set to 256 in your code (to zero it) then you don't have to do the anything more than send the QEI value at any given time (no subtraction to make it negative). Also looking at another real gamepad and how it reports I think the joystick values for a gamepad are probably better sent as a POV hat which is digital instead of the X and Y which is meant for a analog value, I have an example of this in my documentation that I will dig up. One last thing I notice you used pins PD0/1 and PB6/7 -make sure you notice in the schematic that R9 and R10 jumpers connect these pins so if you want to use them independently you need to remove these jumpers from the board.
  14. @@Rhys Looks really good - mostly worked out of the box but I did have to make some changes with the QEI code. For a mouse you need to report the incremental changes since the last report sent, your code reports the absolute QEI value of the encoder each time it hits the report. Here is how I modified it to get it working with my trackball: In the QEIConfigure I set the max value to 256 (This represents the max before the encoder rolls) In the default QEIPositionSet code I set it to 128 (This represents 0) In the handler I mapped these values to the range supported by a mouse (-127 to 127) by subtracting 128 from the encoder position, I also doubled the change with a shift to make the movement more significant mouseReport[1] = (QEIPositionGet(QEI0_BASE)-128) << 1 mouseReport[2] = (QEIPositionGet(QEI1_BASE)-128) << 1; Finally each time you report you need to zero out the QEI values, so after the mouse report I added the lines QEIPositionSet(QEI0_BASE, 128); QEIPositionSet(QEI1_BASE, 128); This makes the trackball work correctly. Also I don't think your XOR on the mouse buttons is correct - if you want PE0 and PE1 to represent the mouse buttons you just need to read the value and invert it (since you have pull ups so they report as 1 when not pressed) mouseReport[0] =~GPIOPinRead(GPIO_PORTE_BASE, GPIO_PIN_0|GPIO_PIN_1); This fixes it.
  15. No problem. I took a look at this and I gave you bad info, it seems you have to send individual reports you can't send it as one report with the report ID embedded, but even with minor changes it should work fine - I have a non Tiva stellaris using interrupt code and reading a QEI Golden Tee trackball and its smooth as silk in Windows with no real optimization - keep in mind mouse movement is incremental so all I do is start at 0 for an axis and then either add or remove 1 for each encoder detection and then when I call the HID function report the delta since the last successful report. This way even if your mouse moves from X value 25 to X value 30 before you send the report, once you report the X value of +5 it syncs things up in Windows (you can't see any choppiness) However if you do want to speed up your code - first in your usbhidmame reduce the endpoint polling interval to a value lower than 16 (last value in uint8_t g_pui8HIDInEndpoint) Then if your main code follows the TI examples and only sends a single report per systick - make sure you have SYSTICKS_PER_SECOND fairly high (the example of 100 means a mandatory delay of 10ms between reports). I changed both these values and if I'm reading that USB analyze tool correctly it looks like it is taking <10 ms to send all 3 reports. I would be interested in your code for reading the buttons - are you reading 8 at a time and reporting it as a byte of gamepad buttons or are you doing some sort of looping?
  16. This should be covered in the pdf included with my stuff you need the size to be the size of the largest report.
  17. Sorry I should have looked more closely - so if you do this as individual reports they are all 4 bytes (for example the gamepad is 1 byte reportID, 1 byte of buttons and 2 bytes of axes so 4 bytes total But in your header file you declare the size to be 1 byte #define CUSTOMHID_REPORT_SIZE 1 You need this to be 4.
  18. At a glance I don't follow the first report - the comments say 12 bits of buttons followed by 4 bits of padding (to end up an even 2 bytes). However you declare 8 buttons/bits not 12 ReportSize(1), ReportCount(8), and then pad that with 4 bits for a total of 12 bits (not at an even byte boundary).
  19. Important to note the example above is fairly simple and not very efficient (in the fact that it sends 3 different reports, one for each device in the descriptor and waits for each reply before sending the next one) in reality once you understand what the code is doing you probably want to read all your buttons/joysticks then create one larger report that includes the identifier and info for each HID device and send that all at once in one USBDHIDCustomHidStateChange call.
  20. Here you go- https://github.com/lawrence-jeff/TivaLaunchpad For now I only have the volume example included but I will add additional examples as I get time (and update the documentation)
  21. One of the main reasons I created my framework was to support the lack of composite HID support in the framework, I'm guessing that is what USB_PID_COMP_HID_HID stands for. Just feel free to either use that value instead of USB_PID_CUSTOM or if you want just assign PID_CUSTOM to an unused value. Product IDs really don't matter they just need to be unique per device you create (and across any examples you install) since the OS caches it and can get confused if the same PID is used for multiple devices. Also I did manage to port my files over to Tivaware this weekend - I can try to post the new files to github tonight.
  22. I would still recommend installing stellarisware and using the instructions to get familiar with the process of using CCS and compiling the library there are lots of little gotchas that can burn lots of time (it would also let you see how it behaves when it works as expected) stellarisware is just a directory tree so you can have it installed in parallel with Tivaware and just delete it when you get comfortable and are ready to tackle Tivaware (which is almost exactly the same except they changed all the variable types) Either way if you do port any of the stuff over please drop me a copy if you don't mind..
  23. This descriptor put in the usbhidcustom.c file from my framework will make the Launchpad a dual gamepad + mouse device. (Each gamepad has 8 buttons + joystick) static const unsigned char g_pucCustomHidReportDescriptor[]= { UsagePage(USB_HID_GENERIC_DESKTOP), Usage(USB_HID_GAMEPAD), Collection(USB_HID_APPLICATION), Collection(USB_HID_PHYSICAL), ReportID(1), // // 8 - 1 bit values for the first set of buttons. // UsagePage(USB_HID_BUTTONS), UsageMinimum(1), UsageMaximum(8), LogicalMinimum(0), LogicalMaximum(1), ReportSize(1), ReportCount(8), Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE | USB_HID_INPUT_ABS), // // The X, Y Z and Rx (Will appear as two thumb controls. // UsagePage(USB_HID_GENERIC_DESKTOP), Usage(USB_HID_X), Usage(USB_HID_Y), LogicalMinimum(-127), LogicalMaximum(127), ReportSize(8), ReportCount(2), Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE | USB_HID_INPUT_ABS), EndCollection, EndCollection, UsagePage(USB_HID_GENERIC_DESKTOP), Usage(USB_HID_GAMEPAD), Collection(USB_HID_APPLICATION), Collection(USB_HID_PHYSICAL), ReportID(2), // // 8 - 1 bit values for the first set of buttons. // UsagePage(USB_HID_BUTTONS), UsageMinimum(1), UsageMaximum(8), LogicalMinimum(0), LogicalMaximum(1), ReportSize(1), ReportCount(8), Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE | USB_HID_INPUT_ABS), // // The X, Y Z and Rx (Will appear as two thumb controls. // UsagePage(USB_HID_GENERIC_DESKTOP), Usage(USB_HID_X), Usage(USB_HID_Y), LogicalMinimum(-127), LogicalMaximum(127), ReportSize(8), ReportCount(2), Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE | USB_HID_INPUT_ABS), EndCollection, EndCollection, UsagePage(USB_HID_GENERIC_DESKTOP), Usage(USB_HID_MOUSE), Collection(USB_HID_APPLICATION), Usage(USB_HID_POINTER), Collection(USB_HID_PHYSICAL), ReportID(3), // // The buttons. // UsagePage(USB_HID_BUTTONS), UsageMinimum(1), UsageMaximum(3), LogicalMinimum(0), LogicalMaximum(1), // // 3 - 1 bit values for the buttons. // ReportSize(1), ReportCount(3), Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE | USB_HID_INPUT_ABS), // // 1 - 5 bit unused constant value to fill the 8 bits. // ReportSize(5), ReportCount(1), Input(USB_HID_INPUT_CONSTANT | USB_HID_INPUT_ARRAY | USB_HID_INPUT_ABS), // // The X and Y axis. // UsagePage(USB_HID_GENERIC_DESKTOP), Usage(USB_HID_X), Usage(USB_HID_Y), LogicalMinimum(-127), LogicalMaximum(127), // // 2 - 8 bit Values for x and y. // ReportSize(8), ReportCount(2), Input(USB_HID_INPUT_DATA | USB_HID_INPUT_VARIABLE | USB_HID_INPUT_RELATIVE), EndCollection, EndCollection, }; This handler will then make all 3 devices do something based on the buttons on the Launchpad: void CustomHidChangeHandler(void) { unsigned long ulRetcode; unsigned long ulButton, ulButton2; // // Initialize all keys to 0 - this unpresses a key if you press one // signed char DeviceReport[3]; DeviceReport[0]=0; //First 8 buttons DeviceReport[1]=0; //X DeviceReport[2]=0; //Y signed char MouseReport[3]; MouseReport[0]=0; //Buttons MouseReport[1]=0; //X MouseReport[2]=0; //Y // //Read Left button and move mouse if pressed // ulButton = ROM_GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_4); if(ulButton == 0) { DeviceReport[0]=0x0F; DeviceReport[1]=-60; DeviceReport[2]=-60; MouseReport[0]=0; //Buttons MouseReport[1]=-10; //X MouseReport[2]=-10; //Y } // //Read Right button and sent ABCDEF if pressed // ulButton2 = ROM_GPIOPinRead(GPIO_PORTF_BASE, GPIO_PIN_0); if(ulButton2 == 0) { DeviceReport[0]=0xF0; DeviceReport[1]=60; DeviceReport[2]=60; MouseReport[0]=0; //Buttons MouseReport[1]=10; //X MouseReport[2]=10; //Y } // // Send Device Report // g_eCustomHidState = CUSTOMHID_STATE_SENDING; ulRetcode = USBDHIDCustomHidStateChange((void *)&g_sCustomHidDevice, 1, DeviceReport); //0 is passed for reportID since this custom device doesn't have multiple reports // Did we schedule the report for transmission? // if(ulRetcode == CUSTOMHID_SUCCESS) { // Wait for the host to acknowledge the transmission if all went well. // if(!WaitForSendIdle(MAX_SEND_DELAY)) { // // The transmission failed, so assume the host disconnected and go // back to waiting for a new connection. // g_bConnected = false; } } g_eCustomHidState = CUSTOMHID_STATE_SENDING; ulRetcode = USBDHIDCustomHidStateChange((void *)&g_sCustomHidDevice, 2, DeviceReport); //0 is passed for reportID since this custom device doesn't have multiple reports //ulRetcode = USBDHIDCustomHidStateChange((void *)&g_sCustomHidDevice, 3, MouseReport); //0 is passed for reportID since this custom device doesn't have multiple reports // Did we schedule the report for transmission? // if(ulRetcode == CUSTOMHID_SUCCESS) { // Wait for the host to acknowledge the transmission if all went well. // if(!WaitForSendIdle(MAX_SEND_DELAY)) { // // The transmission failed, so assume the host disconnected and go // back to waiting for a new connection. // g_bConnected = false; } } g_eCustomHidState = CUSTOMHID_STATE_SENDING; ulRetcode = USBDHIDCustomHidStateChange((void *)&g_sCustomHidDevice, 3, MouseReport); //0 is passed for reportID since this custom device doesn't have multiple reports // Did we schedule the report for transmission? // if(ulRetcode == CUSTOMHID_SUCCESS) { // Wait for the host to acknowledge the transmission if all went well. // if(!WaitForSendIdle(MAX_SEND_DELAY)) { // // The transmission failed, so assume the host disconnected and go // back to waiting for a new connection. // g_bConnected = false; } } }
×
×
  • Create New...