-
• #2
not posting my file ? :/
-
• #3
Nice!
-
• #4
;)
what's less nice is the following wip code that's driving me nuts: it seems I can't find the reason why I can't have 'gamepad.btnState' bigger than 256 ?!
( and also, stuff has to be done regarding the joysticks to be able to give them methods ( like is done for btns )--> if anyone wanna finish the following ( mostly find a fix ), I'd be glad :)
nb: also, if someone has a better pattern in mind, help's as always appreciated ;)/* == Draf API == == current API == gamepad.press(<btnConst>); // press one --> gamepad.release([BUTTONS.A]); gamepad.press([<btnConst>, <joyConst>, ..]); // press many --> gamepad.press([BUTTONS.A, BUTTONS.SELECT, BUTTONS.START]); gamepad.<btnConst>.press(); // press one --> gamepad.A.press(); gamepad.<joyConst>.press(); // same for joysticks buttons gamepad.<btnConst>.release // release one --> gamepad.A.release(); gamepad.release(<btnConst>, <joyConst>, ..]); // release many --> gamepad.release([BUTTONS.A, BUTTONS.SELECT, BUTTONS.START]); // joysticks only: range [-127..127] gamepad.<joyConst>.move(<xValue>, <yValue>); gamepad.<joyConst>.moveX(<value>); gamepad.<joyConst>.moveY(<value>); // triggers only: range [0..255] gamepad.<trigConst>.press(<value>); // if analog, 'll range [0..255] // global gamepad.set({ <const>:<value>, .. }); --> gamepad.set({START:1, SELECT: 1, LJOY_X: 120}) gamepad.unset(); --> gamepad.unset(); // update gamepad.sendState(); // or '.update()' ? --> gamepad.sendState(); */ var BUTTONS = { START: 0x0001, // SELECT: 0x0002, // PAD_UP: 0x0004, // PAD_DOWN: 0x0008, // works gamepad.btnState = ( gamepad.btnState | (1<<0x0008) ) PAD_LEFT: 0x0010, // stop working from here ? :| but gamepad.btnState = ( gamepad.btnState | (1<<0x0010) ) works ??! PAD_RIGHT: 0x0020, // Y: 0x0040, // YELLOW: 0x0040, // A: 0x0080, // GREEN: 0x0080, // X: 0x0100, // BLUE: 0x0100, // B: 0x0200, // RED: 0x0200, // L1: 0x0400, // R1: 0x0800, // L2: 0x1000, // R2: 0x2000, // L3: 0x4000, // R3: 0x8000, // }; var button = function(bLabel, bValue){ this.bLabel = bLabel; this.bValue = bValue & 0xFFFF; }; button.prototype.bLabel = ''; button.prototype.bValue = 0; // set corresponding bit in gamepad obj button.prototype.press = function(){ //gamepad.btnState = ( gamepad.btnState | (1<<this.bValue) ) & 0xFFFF; //console.log('WTF: gamepad.btnState | ( (1<<this.bValue) & 0xFFFF) & 0xFFFF -->' + ( gamepad.btnState | ( (1<<this.bValue) & 0xFFFF) & 0xFFFF) ); console.log('WTF: gamepad.btnState | ( (1<<this.bValue) & 0xFFFF) & 0xFFFF -->' + ( gamepad.btnState | 1<<this.bValue) ); //gamepad.btnState = gamepad.btnState | ( (1<<this.bValue) & 0xFFFF) & 0xFFFF; gamepad.btnState = gamepad.btnState | (1<<this.bValue) & 0xFFFFFFFF; console.log('button const value: ' + this.bValue); console.log('gamepad state: 0b' + gamepad.btnState.toString(2) ); } // unset corresponding bit in gamepad obj button.prototype.release = function(){ gamepad.btnState = ( gamepad.btnState & ~(1<<this.bValue)) & 0xFFFF; console.log('button const value: ' + this.bValue); console.log('gamepad state: 0b' + gamepad.btnState.toString(2) ); } var joystick = function(bLabel, bValue){ this.bLabel = bLabel; this.bValue = bValue & 0xFFFF; }; button.prototype.bLabel = ''; button.prototype.bValue = 0; var gamepad = { lastBtnState: 0b0000000000000000, btnState: 0b0000000000000000, x1: 0, y1: 0, x2: 0, y2: 0 } // pass an array of btn to be pressed // depending on the const(s) passed, we set the bits mapped from the const's value gamepad.press = function(btnsArr){ for(var i=0; i< btnsArr.length; i++){ this.btnState = ( this.btnState | (1<<btnsArr[i]) ) & 0xFFFF; console.log('gamepad state: 0b' + this.btnState.toString(2) ); } }; // pass an array of btn to be pressed // depending on the const(s) passed, we unset the bits mapped from the const's value gamepad.release = function(btnsArr){ for(var i=0; i< btnsArr.length; i++){ this.btnState = ( this.btnState & ~(1<<btnsArr[i]) ) & 0xFFFF; console.log('gamepad state: 0b' + this.btnState.toString(2) ); } }; // "populate" the gamepad object with children offering press() & release() methods Object.keys(BUTTONS).forEach(function(bLabel){ gamepad[bLabel] = new button(bLabel, BUTTONS[bLabel]); }); // pass an array of elements to be set ( updated ) gamepad.set = function(optsObj){ var that = this; Object.keys(optsObj).forEach(function(opt){ //that[opt] = optsObj[opt]; // nope: overwrites our objs -> we want to // if the label is present in the BUTTONS consts, then we act depending on the value passed to set or unset correspondign bit if(typeof BUTTONS[opt] !== 'undefined'){ if(optsObj[opt] === 1) that.btnState = that.btnState | (1<<BUTTONS[opt]); else that.btnState = that.btnState & ~(1<<BUTTONS[opt] ) & 0xFFFF; } // else, somehow map to the correct joystick & set its value directly // Thnk: accept 'LJOY':[x, y] ? else { (opt === 'LJOY_X') ? that.x1 = optsObj[opt] : (opt === 'LJOY_Y') ? that.y1 = optsObj[opt] : (opt === 'RJOY_X') ? that.x2 = optsObj[opt] : (opt === 'RJOY_Y') ? that.y2 = optsObj[opt] : null ; } }); }; // resets the gamepad ( unset all pressed stuff & cie - aka release all btns & center joysticks ) gamepad.unset = function(optsObj){ this.btnState = 0b0000000000000000; this.x1 = 0; this.y1 = 0; this.x2 = 0; this.y2 = 0; }; // send the current state of the gamepad object over usb gamepad.sendState = function(){ E.sendUSBHID([ this.btnState & 0xFF, // Byte0 (this.btnState>>8) & 0xFF, // Byte1 this.x1, // Byte2 this.y1, // Byte3 this.x2, // Byte4 this.y2, // Byte5 ]); };
-
• #5
Back again: I updated the code to support the joysticks but still not luck with the troubles expressed above :/
the current api
gamepad.A.press(); // press a btn - 1st way gamepad.A.release(); // release a btn - 1st way gamepad.press([BUTTONS.A]); // release a btn - 2nd way gamepad.release([BUTTONS.A]); // release a btn - 2nd way gamepad.press([BUTTONS.A, BUTTONS.SELECT, BUTTONS.START]); // press multiple gamepad.release([BUTTONS.A, BUTTONS.SELECT, BUTTONS.START]); // release multiple gamepad.LJOY_X.move(45); // move joytick axis gamepad.set({START:1, SELECT: 1, LJOY_X: 120}); // set many stuff at once gamepad.unset(); // reset all to default gamepad.sendState(); // send current buttons/joysticks/triggers positions over usb
var button = function(bLabel, bValue){ this.bLabel = bLabel; this.bValue = bValue & 0xFFFF; }; button.prototype.bLabel = ''; button.prototype.bValue = 0; // set corresponding bit in gamepad obj button.prototype.press = function(){ //gamepad.btnState = ( gamepad.btnState | (1<<this.bValue) ) & 0xFFFF; //console.log('WTF: gamepad.btnState | ( (1<<this.bValue) & 0xFFFF) & 0xFFFF -->' + ( gamepad.btnState | ( (1<<this.bValue) & 0xFFFF) & 0xFFFF) ); console.log('WTF: gamepad.btnState | ( (1<<this.bValue) & 0xFFFF) & 0xFFFF -->' + ( gamepad.btnState | 1<<this.bValue) ); //gamepad.btnState = gamepad.btnState | ( (1<<this.bValue) & 0xFFFF) & 0xFFFF; gamepad.btnState = gamepad.btnState | (1<<this.bValue) & 0xFFFFFFFF; console.log('button const value: ' + this.bValue); console.log('gamepad state: 0b' + gamepad.btnState.toString(2) ); } // unset corresponding bit in gamepad obj button.prototype.release = function(){ gamepad.btnState = ( gamepad.btnState & ~(1<<this.bValue)) & 0xFFFF; console.log('button const value: ' + this.bValue); console.log('gamepad state: 0b' + gamepad.btnState.toString(2) ); } var joystick = function(bLabel, objAttr){ this.bLabel = bLabel; this.objAttr = objAttr; }; joystick.prototype.bLabel = ''; joystick.prototype.objAttr = null; joystick.prototype.move = function(value){ console.log('joystick ' + this.bLabel + ' value: ' + value); console.log('joystick ' + this.objAttr + ' value: ' + value); //gamepad[this.bLabel] = value; gamepad[this.objAttr] = value; //this.objAttr = value; }; var gamepad = { lastBtnState: 0b0000000000000000, btnState: 0b0000000000000000, x1: 0, y1: 0, x2: 0, y2: 0 } // pass an array of btn to be pressed // depending on the const(s) passed, we set the bits mapped from the const's value gamepad.press = function(btnsArr){ for(var i=0; i< btnsArr.length; i++){ this.btnState = ( this.btnState | (1<<btnsArr[i]) ) & 0xFFFF; console.log('gamepad state: 0b' + this.btnState.toString(2) ); } }; // pass an array of btn to be pressed // depending on the const(s) passed, we unset the bits mapped from the const's value gamepad.release = function(btnsArr){ for(var i=0; i< btnsArr.length; i++){ this.btnState = ( this.btnState & ~(1<<btnsArr[i]) ) & 0xFFFF; console.log('gamepad state: 0b' + this.btnState.toString(2) ); } }; // "populate" the gamepad object with buttons children offering press() & release() methods Object.keys(BUTTONS).forEach(function(bLabel){ gamepad[bLabel] = new button(bLabel, BUTTONS[bLabel]); }); // "populate" the gamepad object with joysticks children offering move(), moveX() & moveY() methods var JOYSTICKS = { LJOY_X: 'x1', LJOY_Y: 'y1', RJOY_X: 'x2', RJOY_Y: 'y2' }; Object.keys(JOYSTICKS).forEach(function(bLabel){ //gamepad[bLabel] = new joystick(bLabel, gamepad[ JOYSTICKS[bLabel] ]); gamepad[bLabel] = new joystick(bLabel, JOYSTICKS[bLabel]); }); // pass an array of elements to be set ( updated ) gamepad.set = function(optsObj){ var that = this; Object.keys(optsObj).forEach(function(opt){ //that[opt] = optsObj[opt]; // nope: overwrites our objs -> we want to // if the label is present in the BUTTONS consts, then we act depending on the value passed to set or unset correspondign bit if(typeof BUTTONS[opt] !== 'undefined'){ if(optsObj[opt] === 1) that.btnState = that.btnState | (1<<BUTTONS[opt]); else that.btnState = that.btnState & ~(1<<BUTTONS[opt] ) & 0xFFFF; } // else, somehow map to the correct joystick & set its value directly // Thnk: accept 'LJOY':[x, y] ? else { (opt === 'LJOY_X') ? that.x1 = optsObj[opt] : (opt === 'LJOY_Y') ? that.y1 = optsObj[opt] : (opt === 'RJOY_X') ? that.x2 = optsObj[opt] : (opt === 'RJOY_Y') ? that.y2 = optsObj[opt] : null ; } }); }; // resets the gamepad ( unset all pressed stuff & cie - aka release all btns & center joysticks ) gamepad.unset = function(optsObj){ this.btnState = 0b0000000000000000; this.x1 = 0; this.y1 = 0; this.x2 = 0; this.y2 = 0; }; // send the current state of the gamepad object over usb gamepad.sendState = function(){ E.sendUSBHID([ this.btnState & 0xFF, // Byte0 (this.btnState>>8) & 0xFF, // Byte1 this.x1, // Byte2 this.y1, // Byte3 this.x2, // Byte4 this.y2, // Byte5 ]); };
-
• #6
.. and the Puckjs version is below ( I'll have to find a way to update the firmware of my puckjs since I have no ble on my phone & just access it via a dongle on my laptop .. ) -> can someone test it ?
var gamepad = require("ble_hid_gamepad"); NRF.setServices(undefined, { hid : gamepad.report }); gamepad.sendGamepadState(0b1111111111111111, 127, -127, 127, -127);
https://raw.githubusercontent.com/stephaneAG/usbHidDescriptors/master/espruino_ble_hid_gamepad.js
-
• #7
Hi there ( not many answers here .. ;) ): is anyone used to modding the way the Espruino enumerates over USB ?
To go further on the gamepad subject & as I can't test the pucks nor the RN42 version of the module, I think it'd be quite neat to implement an Xbox 360 gamepad module for Espruino :)) ..
.. but this controller is NOT a HID device but instead a XInput one .. :/( I have to finish reading some code for a TeensyLC & need few infos on the way Espruino handles the USB stack & cie to port the code ).
I'll also plan to digg the std usb & hid stuff for STM32F to help in the process ;) -
• #8
back !
So, first, an early version of the Espruino GamePad API ( could be used when using either USB HID, BLE HID, & RN-42 HID .. and soon XInput to act as an Xbox360 controller ;p ):
https://raw.githubusercontent.com/stephaneAG/usbHidDescriptors/master/espruino_hid_gamepad_draftApi.jsSecond, I am currently debugging a test implementation of an Xbox360 controller using Teensy+Espruino ( Thee teensy emulates the controller on the Xbox360 USB port while the Espruino controls the Teensy using Serial ).
To be able to use only the Espruino, I am investigating some STM32 stuff as well as the Espruino sources.
I found ( parts of ? ) the stuff related to USB, HID & CDC, but this involves knowing Espruino & STM32F USB stuff more than I currently do :/ ..So, if anyone interested in working on the opportunity to get more advanced USB stuff on the Espruino, these files seems of particular interest:
- List item
- https://github.com/espruino/Espruino/blob/master/src/jsvar.h
- https://github.com/espruino/Espruino/blob/master/src/jswrap_espruino.c
The 3rd link is particularly interesting on the lines starting from 1544
I'll try some of the STM32 USB stuff as soon as can do & 'll come back for updates on the subject.
On a close subject, anyone with a working HID implementation of a PS3 controller ?
- List item
-
• #9
Is the issue with
btnState
just that all the HID values being sent down USB will be expected to be 8 bits? If you want to do 16 you'd need to do something like:[...,btnState,btnState>>8,....]
to get the two bytes that make up the full 16 bits?With the STM32F4 USB I think this is probably of most interest: https://github.com/espruino/Espruino/blob/master/targetlibs/stm32usb/usbd_cdc_hid.c#L79
As the descriptors for HID are there and I guess it's them that might need tweaking?
-
• #10
Hi there !
( btw: I just added a pull request for another example on using a PN532 to read RFID cards ;p )Thanks for the hint, but it didn't come from sending ( I do the following ):
// .. this.btnState & 0xFF, // Byte0 (this.btnState>>8) & 0xFF, // ..
It actually came from being tired & not doing the right bitwise operations ;)
the following fixed itgamepad.btnState |= this.bValue; // to set stuff gamepad.btnState &=~ this.bValue; // to unset stuff
For the STM32F stuff, I'll have to digg what you suggested & more ..
(..) xbox 360 controller is a HID controller with the HID report descriptor removed and the device class, subclass, and protocol set to 0xFF (255)
Moreover, if I read correctly, the "Xbox 360 Controller Security" is not yet broken ( while said to be reverse engineered on a per console basis ? https://oct0xor.github.io/2017/05/03/xsm3/ ), so connecting to a console instead of a pc will be a harder than expected ..
Anyway, as I'll have to port the current code, here's a "roadmap" to be applied to the Espruino/STM32F platform ( attached pdf file )
1 Attachment
-
• #11
back :)
I updated/completed the "roadmap" from Zack zlittell's series of posts on the subject ( http://www.zlittell.com/2015/07/msf-fightstick-teensylc-xinput-controller-8/ ).
The same author published a more-arduino-library-like version of his code, but as his writeup focuses on the former, I'll start with that & see how it goes before trying porting the latter ( which I'm already using in my Espruino<->Teensy tests )On the current "deadend" I'm facing regarding the way genuine controllers are recognized, the following posts seems of interest but I have no clues yet on how to trick/bypass this ( and this is mandatory for the controller to be used on an actual console :/ .. )
- https://brandonw.net/360bridge/doc.php
- https://oct0xor.github.io/2017/05/03/xsm3/
- https://github.com/oct0xor/xbox_security_method_3
- https://www.tapatalk.com/groups/blissbox/working-with-xbox-360-protocal-t219.html
- http://tattiebogle.net/index.php/ProjectRoot/Xbox360Controller/WirelessUsbInfo
This being said, I have some RFID code to produce before getting my hands dirty on the STM32 stuff ( nb: I have a discovery board not yet tested I consider trying on instead of messing with one of my Espruino boards ;p ), so I'll come back as usual when I got things done or with more questions ;)
- https://brandonw.net/360bridge/doc.php
-
• #12
quick update & good news on the RN42 topic: I received the neccessary & succefully flashed an hc-05's firmware, then enabled HID gamepad, to finish by quickly testing connection to a laptop & sending gampepad states: it just "worked" ( too bad we currently don't have any way to access a less high-level API to be able to set custom HID descriptors instead of the provided ones .. )
I plan to digg the SPP||HID GPIO toggle pin stuff, why I don't have any LEDs & things on the PCM audio pins later today, additionally to updating the Gamepad.js "draft" API ;)
( & maybe flash some more hc-05 ? .. too bad software used is currently only for Windows :/ .. )So, a little teaser for now .. ;P
1 Attachment
-
• #13
Wow, very cool.
So just to get this straight, you took a standard HC-05 module, flashed it with the RN42 HID firmware, and it became a magic configurable USB HID device?
Do you have a link to instructions for the flashing process and the firmware?
I have a bunch of HC-05 just sitting here from the first KickStarter. I doubt it'd be legal for me to reflash and sell them, but I'm very interested in how easy it'd be for others to update the firmware :)
-
• #14
Hi there !
Indeed :)
BUT it didn't became a "magic configurable USB HID device": it now allows to specifiy via AT-like commands which HID profile to use & then pass serially the stuff related to that HID reportIn short, you'll need:
- BlueSuite_2_6_6_1311.zip
- csr-spi-ftdi-0.5.3-a5.zip // IMPORTANT ( else you could get an error looking like you may have wire shorts )
- zadig-2.4.exe
- an RN42 with HID firmware to be dumped ..
- an HC-05 from which we'll dump, mod & reflash the firmware
I'll be doing a quick writeup of my notes on the subject, but you can already follow these:
Alternative method ( using FTDI adapter instead of parallel port):
https://www.youtube.com/watch?v=y8PcNbAA6AQ
Evan Kale's Bluetooth PS2 controller mod:
https://www.youtube.com/watch?v=mt8uF9IblUU
same authors' PS2 keyboard/mouse Bluetooth adapter:
https://www.youtube.com/watch?v=UJaqHnPR-XE&feature=youtu.be
HC-05 infos:
https://components101.com/wireless/hc-05-bluetooth-module
In the attached archive, you'll find all the necessary ;p
nb: for the "Open Adaptive Controller" I'm working on ( currently using Espruino WiFi & flashed HC-05* .. and teensy for xbox360 stuff that I hope to move onto Espruino USB stuff ), I am trying to optimize the usage of the available pins & was wondering what was the best way to put a pin on "high impedance" ( floating ? ) to be able to light either 2 leds: both at same time, only former, only latter
The above goal is somewhat close to what does the "STAT" pin in the below schematic
*same for me: I guess for the final implementation of the said controller, I'll have to switch to Espruino bluetooth + wifi to be able to achieve fully custom Bluetooth HID reports ( I plan to retry the Puckjs code posted above & maybe soon purchase your latest board ;) ).
Of course, I'll be posting the blueprints here ( I am currently finishing those & 'll be moving to the 3d part soon ) ;p
last but not least, the debug code I used to interface the freshly flashed HC-05 .. and it worked ;p
ps: yes, I could have done things better the way// setting the RN42 firmware as a HID gamepad device // we connect to the hc05 module using itd breakout's Vcc,Gnd, Txd & Rxd Serial1.setup(115200, { tx:B6, rx:B7 }); Serial1.on('data', function (data) {console.log(data);}); // R: using PIO11: HIGH ? HID selected, LOW ? using profile selected in flash // ==== CMD mode ==== // wait a little bit then send '$$$' THEN SILENCE ( no line ending ) to enter command mode /* >Serial1.print('$$$'); =undefined C MD */ // then enter commands with CR line ending /* SF,1 // factory reset: //> AOK D // see current settings E // see advanced settings SM,6 // pairing //> AOK SN,OpenAdaptiveController // set name //> AOK S~,0 // SPP mode //> AOK S~,6 // HID mode //> AOK // HID report descriptors //SH,0230 // appear as keyboard+mouse combo SH,0240 // appear as a gamepad //> AOK GH // get current value of HID flag register R,1 // reboot module */ /* Current sequence used from above stuff to setup an "RN42" as a Bluetooth Gamepad: Serial1.println('SF,1'); Serial1.println('S~,6'); Serial1.println('SN,EspruinoGamepad'); Serial1.println('SH,0240'); Serial1.println('GH'); Serial1.println('R,1'); */ /* Gamepad HID report format: 1 2 3 4 0xFD,0x06,0x00,0x00,0x00,0x00,0x55,0xAA 1: Raw report decriptor 2: length, must be 6 3: joysticks states 4: buttons states bitmasks */ // Ex: //Serial1.write(0xFD,0x06,0x00,0x00,0x00,0x00,0x55,0xAA); // the following gives enough time to focus the HTML5 gamepad tester page ;) setTimeout(function(){ Serial1.write(0xFD,0x06,0x00,0x00,0x00,0x00,0x55,0xAA); },5000);
Enjoy :D
1 Attachment
- BlueSuite_2_6_6_1311.zip
-
• #15
this part was missing in my previous message ;)
attached sutff:- rn42 firmware dump
- wip "Espruino Open Adaptive Controller" stuff ;)
1 Attachment
- rn42 firmware dump
-
• #16
sorry for multi-posting, but for some reason I can't get the firmware file upload corectly ? :|
1 Attachment
-
• #17
Hi there !
I'll be writing the hc-05->RN42 guide the coming week ( with screenshots ;p )
on another subject, I uncovered dust from a STM32F3DISCOVERY yesterday & this time, took enough time to experiment with CubeMX-generated & modded stuff as well as flashing the thing.
( the goal is to familiarize myself enough with the stm32 environment without messing with one of my Espruino boards ;) ).
I succefully flashed a mouse HID & a keyboard+media HID to it, but for some reason, I can't get the GamePad HID to work as intended: it's detected as such, but I still have a byte-related trouble with the buttons ( the joysticks works fine ).Thing is: I'm still wondering why the heck is doing so, since after multiple readings of the following code, I see no errors ? :|
Shouldn't it work if "sizeof(struct gamepadHID_t)" equals to "HID_EPIN_SIZE" ?/* ==== main.c ==== */ /* USER CODE BEGIN 1 */ struct gamepadHID_t { //uint16_t buttons; uint8_t buttons1; uint8_t buttons2; int8_t left_x; int8_t left_y; int8_t right_x; int8_t right_y; }; struct gamepadHID_t gamepadHID; //gamepadHID.buttons = 0b0000000000000000; gamepadHID.buttons1 = 0b00000000; gamepadHID.buttons2 = 0b00000000; gamepadHID.left_x = 0b00000000; gamepadHID.left_y = 0b00000000; gamepadHID.right_x = 0b00000000; gamepadHID.right_y = 0b00000000; /* USER CODE END 1 */ /* USER CODE BEGIN 3 */ //gamepadHID.buttons = 0x55AA; //gamepadHID.buttons = 0b0000000011111111; // works ?! //gamepadHID.buttons = 0b0000000111111111; // also works ?!! //gamepadHID.buttons = 0b0111111111111111; // also works .. //gamepadHID.buttons = 0b1111111111111111; //gamepadHID.buttons1 = 0x55; //gamepadHID.buttons2 = 0xAA; //gamepadHID.buttons1 = 0b11111111; //gamepadHID.buttons2 = 0b11111111; gamepadHID.buttons1 = 0b01111111; gamepadHID.buttons2 = 0b01111111; gamepadHID.left_x = 127; gamepadHID.left_y = 127; gamepadHID.right_x = -127; gamepadHID.right_y = -127; //USBD_HID_SendReport(&hUsbDeviceFS, &gamepadHID, sizeof(struct gamepadHID_t)); //USBD_HID_SendReport(&hUsbDeviceFS, &gamepadHID, sizeof(struct gamepadHID_t)+2); //USBD_HID_SendReport(&hUsbDeviceFS, &gamepadHID, 8); //USBD_HID_SendReport(&hUsbDeviceFS, &gamepadHID, sizeof(struct gamepadHID_t)+1); //HAL_Delay(30); //gamepadHID.buttons = 0; USBD_HID_SendReport(&hUsbDeviceFS, &gamepadHID, sizeof(struct gamepadHID_t)); //HAL_Delay(30); //unsigned char data[HID_DATA_IN_PACKET_SIZE] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //unsigned char data[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //uint8_t data[6] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; //uint8_t data[6] = { 0x00, 0x00, 127, 127, 127, 127}; // works with below T //uint8_t data[6] = { 127, 00, 127, 127, 127, 127}; // nope //USBD_HID_SendReport(data, 6); //USBD_HID_SendReport(&hUsbDeviceFS, &data, sizeof(data)); // "T" works, but 'implicit declaration' .. /* USER CODE END 3 */ /* ==== usb_hid.h ==== */ /** @defgroup USBD_HID_Exported_Defines * @{ */ [#define](https://forum.espruino.com/search/?q=%23define) HID_EPIN_ADDR 0x81 [#define](https://forum.espruino.com/search/?q=%23define) HID_EPIN_SIZE 0x06 /* max report size - for GamePad */ // ( .. ) [#define](https://forum.espruino.com/search/?q=%23define) HID_CUSTOM_REPORT_DESC_SIZE 46 /* GamePad HID report size */ /* ==== usb_hid.c ==== */ // TEF Edit: change 'bInterfaceSubClass' to 0 ( gamepad does not respect boot specifications ) // & 'nInterfaceProtocol' to 5 ( gamepad ) __ALIGN_BEGIN static uint8_t USBD_HID_CfgDesc[USB_HID_CONFIG_DESC_SIZ] __ALIGN_END = { // ( .. ) 0x00, /*bInterfaceSubClass : 1=BOOT, 0=no boot*/ 0x05, /*nInterfaceProtocol : 0=none, 1=keyboard, 2=mouse, 5=gamepad */ // ( .. ) // custom descriptor for GamePad __ALIGN_BEGIN static uint8_t HID_CUSTOM_ReportDesc[HID_CUSTOM_REPORT_DESC_SIZE] __ALIGN_END = { // 46 bytes 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x05, // USAGE (Game Pad) - Hut1_12v2.pdf p28 of 128 0xA1, 0x01, // COLLECTION (Application) 0xA1, 0x00, // COLLECTION (Physical) 0x05, 0x09, // USAGE_PAGE (Button) 0x19, 0x01, // USAGE_MINIMUM (Button 1) 0x29, 0x10, // USAGE_MAXIMUM (Button 16) 0x15, 0x00, // LOGICAL_MINIMUM (0) 0x25, 0x01, // LOGICAL_MAXIMUM (1) 0x95, 0x10, // REPORT_COUNT (16) 0x75, 0x01, // REPORT_SIZE (1) 0x81, 0x02, // INPUT (Data,Var,Abs) 0x05, 0x01, // USAGE_PAGE (Generic Desktop) 0x09, 0x30, // USAGE (X) 0x09, 0x31, // USAGE (Y) 0x09, 0x32, // USAGE (Z) - Hut1_12v2.pdf p26 = represents R X-axis 0x09, 0x33, // USAGE (Rx) - Hut1_12v2.pdf p26 = represents R Y-axis 0x15, 0x81, // LOGICAL_MINIMUM (-127) 0x25, 0x7F, // LOGICAL_MAXIMUM (127) 0x75, 0x08, // REPORT_SIZE (8) 0x95, 0x04, // REPORT_COUNT (4) 0x81, 0x06, // INPUT (Data,Var,Abs) - absolute for joysticks ( != rel for mouse ) 0xC0, // END_COLLECTION 0xc0 // END_COLLECTION };
Once the above is fixed, one of the next steps is porting the Xbox360 controller code to it ( and then continue digging how to use an existing controller for the handshake part .. ).
As a side note, I tried but coouldn't get Espruino on the board ?
I used the Espruino_1V92 & Espruino_1V92.3 firmwares ( it seems 1V99 isn't available on the repos for the STM32F3DISCOVERY )
( I took not of the need for unplugging & replugging the 'USB USER' plug, but no /dev/tty<..> ever appear on my mac :/ )
The cli commands I used are the following:// to flash any firmware generated from a 'make' call on CubeMX-generated files st-flash --format ihex write ./build/stm32f3discovery_hidTest1.hex // to flash Espruino firmware ? :| st-flash erase // to clean stuff st-flash write ./espruino_1v92/espruino_1v92.3_stm32f3discovery.bin 0x08000000
-
• #18
STM32F3DISCOVERY - USB BROKEN
since sometime in version 1v8 ..
Does not have the exact version, is on holiday at Fanø, Denmark -
• #19
a quick update on "fixing stuff": it seems I can get the buttons to appear but not in a reliable manner ( I'd say if I'm fast enough plugging the usb cable ? this is weird .. ) and while code shouldn't work ?!
could this in part come from not waiting enough on init or within the main while loop ?
also, it could also come from the page I'm using for my tests ( http://html5gamepad.com/ ), but since it worked great until now, I bet the error in in my messy code ;p/* ==== main.c ==== */ // still trying .. and 'sometimes' works with "#define HID_EPIN_SIZE 0x04" in "usbd_hid.h" ?! ;D //uint8_t bufferHID[6] = {0, 0, 0, 0, 0}; uint8_t bufferHID[6] = {0, 0, 0, 0, 0, 0}; // nope ?! //uint8_t bufferHID[6] = {}; // gives 'implicit declaration ..' but works ? .. //uint8_t bufferHID[6]; bufferHID[0] = (gamepadHID.buttons & 0xFF); bufferHID[1] = ( (gamepadHID.buttons >> 8) & 0xFF); bufferHID[2] = gamepadHID.left_x; bufferHID[3] = gamepadHID.left_y; bufferHID[4] = gamepadHID.right_x; bufferHID[5] = gamepadHID.right_y; USBD_HID_SendReport(&hUsbDeviceFS, &bufferHID, sizeof(bufferHID)); //USBD_HID_SendReport(&hUsbDeviceFS, &bufferHID, sizeof(struct gamepadHID_t)); //USBD_HID_SendReport(&hUsbDeviceFS, &gamepadHID, sizeof(struct gamepadHID_t)); HAL_Delay(30);
/* ==== usbd_hid.h ==== */ [#define](https://forum.espruino.com/search/?q=%23define) HID_EPIN_SIZE 0x04 // shouldn't be enough, right ?
-
• #20
Hi !
Thanks for your hint, I actually didn't check the readme on https://github.com/espruino/Espruino :/ ..I'd be happy to fix things up, but I'm wondering what it'd imply & "how" is USB broken: I guess simply checking <1V8 implm & get back that code for >1V8 wouldn't work as expected ..
anyway, thanks a lot: I'll be checking quickly a build <1V8 & see I can get something working/connecting ;)
-
• #21
All right !
So:
Thanks to @Frida, I checked few versions of the Espruino firmwares & found one working:1V50 ( yup, a nice release from 2014-02-06 ;p )Heading to the http://www.espruino.com/ReferenceSTM32F3DISCOVERY page, I hacked something up to better visualize the overlay legends for the row of pins: this solution is the best I have in mind ( doesn't move the pins legends ), involves no modification of the page html structure & is purely css.
I didn't take the time to check if other boards overlay legends had the same overlapping problem, but I think this solution may come quite handy for some :)// proposal for the ReferenceSTM32F3DISCOVERY page ( & others ? ) // generic css way to prevent overlapping pin rows legends ;) [#boardcontainer](https://forum.espruino.com/search/?q=%23boardcontainer):hover [#left](https://forum.espruino.com/search/?q=%23left) { opacity: 0.1; } [#boardcontainer](https://forum.espruino.com/search/?q=%23boardcontainer):hover [#left2](https://forum.espruino.com/search/?q=%23left2) { opacity: 0.1; } [#boardcontainer](https://forum.espruino.com/search/?q=%23boardcontainer):hover [#right](https://forum.espruino.com/search/?q=%23right) { opacity: 0.1; } [#boardcontainer](https://forum.espruino.com/search/?q=%23boardcontainer):hover [#right2](https://forum.espruino.com/search/?q=%23right2) { opacity: 0.1; } [#boardcontainer](https://forum.espruino.com/search/?q=%23boardcontainer):hover [#left](https://forum.espruino.com/search/?q=%23left):hover { opacity: 1; z-index: 10; } [#boardcontainer](https://forum.espruino.com/search/?q=%23boardcontainer):hover [#left2](https://forum.espruino.com/search/?q=%23left2):hover { opacity: 1; z-index: 10; } [#boardcontainer](https://forum.espruino.com/search/?q=%23boardcontainer):hover [#right2](https://forum.espruino.com/search/?q=%23right2):hover { opacity: 1; z-index: 10; } [#boardcontainer](https://forum.espruino.com/search/?q=%23boardcontainer):hover [#right](https://forum.espruino.com/search/?q=%23right):hover { opacity: 1; z-index: 10; }
This got me wondering if we could have ( or if there is ) a way to have js as well as css for /boards/STM32F3DISCOVERY.py & others ?
board["_js"] = """ /* Espruino - prevent pins overlay legends from overlapping when hovering */ var customStyle = document.createElement('style'); customStyle.textContent = '#boardcontainer:hover [#left](https://forum.espruino.com/search/?q=%23left) { opacity: 0.1; }' + '#boardcontainer:hover [#left2](https://forum.espruino.com/search/?q=%23left2) { opacity: 0.1; }' + '#boardcontainer:hover [#right](https://forum.espruino.com/search/?q=%23right) { opacity: 0.1; }' + '#boardcontainer:hover [#right2](https://forum.espruino.com/search/?q=%23right2) { opacity: 0.1; }' + '#boardcontainer:hover [#left](https://forum.espruino.com/search/?q=%23left):hover { opacity: 1; z-index: 10; } ' + '#boardcontainer:hover [#left2](https://forum.espruino.com/search/?q=%23left2):hover { opacity: 1; z-index: 10; } ' + '#boardcontainer:hover [#right2](https://forum.espruino.com/search/?q=%23right2):hover { opacity: 1; z-index: 10; } ' + '#boardcontainer:hover [#right](https://forum.espruino.com/search/?q=%23right):hover { opacity: 1; z-index: 10; } '; document.body.appendChild(customStyle); """
This being said, I don't know yet which file to edit to add a little more content to the generated page ( espruino.com/ReferenceSTM32F3DISCOVERY ): I took some notes on the LEDS positions, colors & mapping that could be neat to have on this page as a reminder
pin onboard label Espruino label color position E9 LD3 LED1 RED UP E8 LD4 LED2 BLUE UP-LEFT E10 LD5 LED3 ORANGE UP-RIGHT E15 LD6 LED4 GREEN LEFT E11 LD7 LED5 GREEN RIGHT E14 LD8 LED6 ORANGE DOWN-LEFT E12 LD9 LED7 BLUE DOWN-RIGHT E13 LD10 LED8 RED DOWN I could as well add code for the supported* onboard peripherals
*I read CAN is not supported ( or is it ? ), but I'm wondering about the 'audio' pins ..Last but not least, I wonder if there is a typo in one of the labels in the corresponding .py file ?
// https://github.com/espruino/Espruino/blob/master/boards/STM32F3DISCOVERY.py#L78 'MEMS' : { 'device' : 'LSM303DLHC)', // is the ')' at the end ok ?
This being said, hopefully @Gordon has an idea on how to fix the 'broken' USB & I'll learn the necessary to free him the time it 'd take to implement the fixes ^^ ( to find where it 'broke', the 1st thing I think about is testing firmwares from the 1V50 one up to where it no longer work & then check the diffs between their respective sources, but I don't know how much & which files are :/ )
I'll digg few more tuts on the stm32f3 to better grasp the subject before being able to investigate the troubles & also port the xbox360 controller code to it ( .. )
now onto doing few quick tests with the freshly flashed Espruino 1V50 firmware ;)
-
• #22
Since attaching a file didn't work for the image I tried to attach & I just finished testing basic stuff around on Espruino 1V50 firmware for stm32f3discovery, here I try again the attachement ( & post stm's test code here as well ;) )
/* Espruino on STM32F3DISCOVERY Docs: https://github.com/espruino/Espruino/blob/master/boards/pins/stm32f303.csv https://github.com/espruino/Espruino/blob/master/boards/STM32F3DISCOVERY.py R: connect 'USB ST-LINK' to update Espruino firmware using st-flash utility R: connect 'USB USER' only for using Espruino R: to 'refresh' the board, unplug/replug 'USB USER' Nb: currently has troubles when code is 'sent' from right side of IDE, even at 9600 bauds & with throttling .. //> Prompt not detected - upload failed. Trying to recover... */ function buttonWatcher(e) { console.log('Hello World Espruino STM32F3DISCOVERY !'); } function btnPressed(){ var btnState = digitalRead(BTN1); if( btnState == 1 ){ console.log(e.time); } } var btnPollT; //pinMode(BTN1, 'input'); // on A0 - same as below //pinMode(BTN1, 'input_pulldown'); // on press, digitalRead displays 1 //setWatch(buttonWatcher, BTN1, {edge:"falling", repeat:true}); // USB.setConsole(); to prevent 'Console Moved from Serial1' on boot ? // WARNING: Parent must be a proper object - not a String, Integer, etc. ? //E.on('init', function() { // didn't work // worked :) function onInit(){ digitalWrite(LED2, 1); // blue led on console.log("Hello World!"); digitalWrite(LED3, 1); // orange led on //setWatch(buttonWatcher, BTN1, {edge:"falling", repeat:true}); // nope //setWatch(buttonWatcher, BTN1, {edge:"rising", repeat:true}); // nope btnPollT = setTimeout(btnPressed, 1000); // btn polling - nope digitalWrite(LED4, 1); // green led on USB.setConsole(); digitalWrite(LED1, 1); // red led on } //});
-
• #23
both LEDs (post #14)
...is using one and the other time multiplexed: out low, out high, and then some tri-state/floating. I guess you do already so.
For tri-state plain input is sufficient.
You just leave it auto, do writes H or L, or HLHKLHL..., and for off do a read. That's the smallest foot print.
pinMode
is a resource hog - sorry, no offense - that makes it very easy to read what's going on. If you have to flip dynamically mode for a bunch at a time, you can only bundle auto configured pins, w/ read and write. All others you have to do individually and explicitly... -
• #24
Nice! Thanks for the RN42 links and code!
wondering what was the best way to put a pin on "high impedance" ( floating ? )
As @allObjects says, literally just
digitalRead(pin)
should do it - or you can force it withpinMode(pin, "input")
STM32F3 Espruino USB
Honestly, no ideas. ST's USB stack is a mess with Espruino because they kept changing it - the F1 has a different stack to the F4, and while I think the F3 is similar to F4 I believe it's different enough that some decent size changes are required :(
Just IMO, but it's not worth it trying to target just because you have an F3 board. Spend £10 on an F4 board of some kind and save yourself weeks of pain :)
Shouldn't it work if "sizeof(struct gamepadHID_t)" equals to "HID_EPIN_SIZE" ?
You may find that GCC/whatever is padding the elements inside
gamepadHID_t
to 4 byte boundaries, which is causing your trouble? It looks like it's 6 bytes but it may get reported as 8. I'm not certain on that though -
• #25
Back ;)
@allObjects thanks for the confirmation, I guessed so but wasn't quite sure ;)
This being said, in your 'HLHKLHL' chunk, does 'K' stands for tri-state/floating ? ( or is it just that you typed quite fast & that the 'K' keystroke was not meant to happen ? ^^ )
I read so for the 'bundle auto configured pins' & cie in the pinMode ref, but didn't actually do tests on pinMode to consider it a resource hog ;)
If theres' no need to 'force' it by using pinMode ( as Gordon says ) I guess I can consider this 'solved' ('d be better actually test 1st, but the logic is validated :) )@Gordon I don't know enough yet on the F3 USB stack to even consider being able to see the differences between it & the F1's / F4's so yup, switching boards is 'd be indeed a 'faster & safer' way ( although I could acquire quite a - not that useful afterward- knowledge on their particular implm changes ..)
Digging how to do stuff directly on the F3 already showed me some changes that did happen// basic example of changes in namings of constants USER_BUTTON_GPIO_Port, USER_BUTTON_Pin // are now B1_GPIO_Port, B1_Pin // same goes for LEDS - some consts are kept ( fcn name, GPIO_PIN_SET, GPIO_PIN_RESET, ..) HAL_GPIO_WritePin(USER_LED_9_GPIO_Port, USER_LED_9_Pin, GPIO_PIN_SET); // is now HAL_GPIO_WritePin(LD9_GPIO_Port, LD9_Pin, GPIO_PIN_SET);
If I recall coreectly, I noticed some Espruino files you pointed me to use 'stdPeriph' stuff & not HAL ? ( I may be incorrect on this, I'm still getting my head around the stm32f platform ..)
On the examples I'm currently trying, I gotta switch from HID to CDC* ( then try the combo ;p ) & implement the xbox360 controller on that. If I manage to do so, adding its functionnality to Espruino builds would then 'just' be some js wrappers for C++ calls ( but this is a part I have yet to discover & cover ;P )
*to try an example doing UART communication with either a laptop or another uC. next on the list is I2C, then SPI ;)
Do you have in mind a F4 board that would be a kick ass with many pins ? I plan ( & 'd love ) to use Espruino on a client project but I have to use something reliable ( so not my own mess around the F3 .. ), and since it focuses on an 'Escape Game' room, having plenty of pins is quite handy :D
On the "Espruino Open Adaptive gamepad' topic, I was wondering if there's any USB stack on the nRF boards or the MDBT42Q ?
My reasons:
- I really wished a flashed HC-05 allowed custom HID over bluetooth, but it doesn't ( only presets )
- I need something that can appear as a custom periph( HID or xbox360controller ) over USB
- having embed WiFi is a plus, allowing realtime buttons mapping changes through an app on laptop/tablet/smartphone when connecting the uC as either a server or client while acting as a bluetooth or usb device
Currently, I'm using an Espruino WiFi for the wifi part & the usb HID part, & a teensy for the xbox360controller part
Once I achieve an xbox360controller on the Espruino WiFi over USB, I won't need the teensy anymore, but 'd still need a platform to do custom HID ( & more ? ) over bluetooth ..
The best 'd be a board that offers both & works fully with Espruino with plenty of pins :p.. GCC/whatever is padding the elements inside gamepadHID_t to 4 byte boundaries* ..
.. ooks like it's 6 bytes but it may get reported as 8**. ..
I'll have to digg those, yet it seems the Gamepad HID I implemented on the f3 acts as expected using the following:// while(1) if(HAL_GPIO_ReadPin(B1_GPIO_Port, B1_Pin) == GPIO_PIN_SET){ HAL_GPIO_WritePin(LD9_GPIO_Port, LD9_Pin, GPIO_PIN_SET); // stuff is set above in code, whatever the 'actual' state of the button press .. USBD_HID_SendReport(&hUsbDeviceFS, &gamepadHID, sizeof(struct gamepadHID_t)); HAL_Delay(50); gamepadHID.buttons = 0; gamepadHID.left_x = 0; gamepadHID.left_y = 0; gamepadHID.right_x = 0; gamepadHID.right_y = 0; USBD_HID_SendReport(&hUsbDeviceFS, &gamepadHID, sizeof(struct gamepadHID_t)); HAL_Delay(200); HAL_GPIO_WritePin(LD9_GPIO_Port, LD9_Pin, GPIO_PIN_RESET); }
*, ** how to know if padding is allowed by GCC ? do you have a quick way to log the size of a report being sent ? ( I'm windering how much I'd need to mod the HID code I'm using to be able to use one of the available uarts to print debig stuff .. since I don't know gdb yet :/ .. )
From my tests on another little program, using the struct with on uint16_t or 2 uint8t led, quite logically, to 6 bytes, but I wonder how to get the 'final' report size before its gets sent over ..RN42 links and code
-> my pleasure ;Pps: I plan to produce 3ds for the 'espruino_OpenAdaptiveController.pdf ' at the end of the week :)
ps2: I wonder how much more 'd be involved to get a 'modified' Espruino WiFi board with more broken out pins ( fro the datasheet, 35/50/81 ? :D )I'll be back with updates as soon as can do, as usual :)
Big thanks for the hints ;)
+ - I really wished a flashed HC-05 allowed custom HID over bluetooth, but it doesn't ( only presets )
Hi there !
I was finally able to find the time to implement a "standard" USB HID GamePad as an Espruino module ( js only for now ) :D
Currently, the triggers are treated as digital buttons, but I'll soon take the time to update the code to support analog triggers ;)
So, YES, Espruino's should now be able to play CoD & GTA ;p .. and make some perfects on guitar hero hardcore ? -> better: make it count & let's do an Espruino-adaptive-controller !!! ;P ( seriously, I'm on it ;) )
=> enjoy :)
basic usage is as simple as Gordon's keyboard & mouse modules:
I plan to:
I also consider writing a little wrapper to make it easier to work with if needed:
Advises are welcome to the above draf of api :)
I also wonder if it'd be somewhat useful to retain the last gamepad state before any further update, as well as the timestamp & the timestamp diff with previous one ? ..
The module should also work to send stuff to an RN42* ( or an HC-05 with its HID firmware ) or an Espruino board based on bluetooth
I'll also try to get 2 gamepads & adding the possibility to pass a number of those to the module before it calls 'E.setUSBHID()' after a little rest ( digging through the USB HID docs can make one's eyes burn .. )
On a near subject ( & sorry if I repeat myself ), I have a wip lib aimed to generate hid report descriptors ( currently just easing the mapping between constants & their values ): it's not much but it 'd have been very helpful to write the above ;/ ( I'll add the constants digged to it as soon as can do ;p )
Every contribution is welcome ;)
https://github.com/stephaneAG/usbHidDescriptors
Last but not least, if anyone has suggestions on the 'hid way' to get output descriptors working on Espruino, it 'd be daaaaaaaamn cool :) ( the goal is to be able to send stuff from host to Espruino - and for the moment, the 'stuff' is not quite defined ^^ )
ps: while at it & if enough time to do so, I have some idea of a feedback mouse ;)
+
2 Attachments