• 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:

    var gamepad = require('USBGamepad');
    // debug easily using http://html5gamepad.com/ ;p
    gamepad.sendGamepadState(0b1111111111111­111, 127, 127, 127, 127);
    gamepad.sendGamepadState(0b1111111111111­111, -127, -127, -127, -127);
    

    I plan to:

    • maybe add possibility of using analog values for buttons as well ?
    • or so only for the "big" triggers ?

    I also consider writing a little wrapper to make it easier to work with if needed:

    // press & release buttons
    gamepad.press(<btnConst>); // press one
    gamepad.press([<btnConst>, <joyConst>, ..]); // press many
    gamepad.<btnConst>.press(); // press one
    gamepad.<joyConst>.press(); // same for joysticks buttons
    gamepad.<btnConst>.release // release one
    gamepad.release(<btnConst>, <joyConst>, ..]); // release many
    // 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>, .. });
    // update
    gamepad.sendState(); // or '.update()' ?
    

    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

    • just add 0xFD, 0x06 & 0x01 before the stuff to be sent ;)

    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 )

    var reportDescriptorProto = [
      { USAGE_PAGE: 'Generic Desktop' },
      { USAGE: 'Mouse' },
      { COLLECTION: 'Application' },
        { USAGE: 'Pointer' },
        { COLLECTION: 'Physical' },
          { USAGE_PAGE: 'Button' },
          { USAGE_MINIMUM: 1 },
          { USAGE_MAXIMUM: 3 },
          { LOGICAL_MINIMUM: 0 },
          { LOGICAL_MAXIMUM: 1 },
          { REPORT_COUNT: 3 },
          { REPORT_SIZE: 1 },
          { INPUT: 'Data,Variable,Absolute' },
          { REPORT_COUNT: 1 },
          { REPORT_SIZE: 5 },
          { INPUT: 'Constant,Variable,Absolute', },
          { USAGE_PAGE: 'Generic Desktop' },
          { USAGE: 'X' },
          { USAGE: 'Y' },
          { LOGICAL_MINIMUM: -127 },
          { LOGICAL_MAXIMUM: 127 },
          { REPORT_SIZE: 8 },
          { REPORT_COUNT: 2 },
          { INPUT: 'Data,Variable,Relative' },
        { END_COLLECTION: null },
      { END_COLLECTION: null },
    ];
    
    var generatedDescriptor = genReportDescriptor(reportDescriptorProt­o);
    console.log(generatedDescriptor);
    
    // result ( make sure it's ok by drag& dropping in https://eleccelerator.com/usbdescreqpars­er/ ;p )
    /*
    ["0x05", "0x01", "0x09", "0x02", "0xa1", "0x01", "0x09", "0x01", "0xa1", "0x00", "0x05", "0x09", "0x19", "0x01", "0x29", "0x03", "0x15", "0x00", "0x25", "0x01", "0x95", "0x03", "0x75", "0x01", "0x81", "0x2", "0x95", "0x01", "0x75", "0x05", "0x81", "0x3", "0x05", "0x01", "0x09", "0x30", "0x09", "0x31", "0x15", "0x81", "0x25", "0x7f", "0x75", "0x08", "0x95", "0x02", "0x81", "0x6", "0xc0", "0xc0"]
    */
    

    Every contribution is welcome ;)
    https://github.com/stephaneAG/usbHidDesc­riptors

    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

  • Nice!

  • ;)

    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(bL­abel){
      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(op­t){
        //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
      ]);
    };
    
    
  • 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(bL­abel){
      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(op­t){
        //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
      ]);
    };
    
  • .. 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(0b1111111111111­111, 127, -127, 127, -127);
    

    https://raw.githubusercontent.com/stepha­neAG/usbHidDescriptors/master/espruino_b­le_hid_gamepad.js

  • 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 ;)

  • 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/stepha­neAG/usbHidDescriptors/master/espruino_h­id_gamepad_draftApi.js

    Second, 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:

    1. List item
    2. https://github.com/espruino/Espruino/blo­b/master/src/jsvar.h
    3. https://github.com/espruino/Espruino/blo­b/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 ?

  • 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/blo­b/master/targetlibs/stm32usb/usbd_cdc_hi­d.c#L79

    As the descriptors for HID are there and I guess it's them that might need tweaking?

  • 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 it

    gamepad.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/xsm­3/ ), 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

  • back :)

    I updated/completed the "roadmap" from Zack zlittell's series of posts on the subject ( http://www.zlittell.com/2015/07/msf-figh­tstick-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 :/ .. )

    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 ;)

  • 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

    • espruino_gamepad_rn42_hid__appearsAsBluetoothGamepad.png
  • 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 :)

  • 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 report

    In 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:

    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,0­x00,0x55,0xAA);
    },5000);
    

    Enjoy :D


    1 Attachment

  • this part was missing in my previous message ;)
    attached sutff:

    • rn42 firmware dump
    • wip "Espruino Open Adaptive Controller" stuff ;)

    1 Attachment

  • sorry for multi-posting, but for some reason I can't get the firmware file upload corectly ? :|


    1 Attachment

  • 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/sea­rch/?q=%23define) HID_EPIN_ADDR                 0x81
    [#define](https://forum.espruino.com/sea­rch/?q=%23define) HID_EPIN_SIZE                 0x06 /* max report size - for GamePad */
    // ( .. )
    [#define](https://forum.espruino.com/sea­rch/?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_stm32f3d­iscovery.bin 0x08000000
    
  • STM32F3DISCOVERY - USB BROKEN
    since sometime in version 1v8 ..
    Does not have the exact version, is on holiday at Fanø, Denmark

  • 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/sea­rch/?q=%23define) HID_EPIN_SIZE                 0x04 // shouldn't be enough, right ?
    
  • 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 ;)

  • 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/ReferenceSTM32F3­DISCOVERY 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/searc­h/?q=%23left) { opacity: 0.1; }
    [#boardcontainer](https://forum.espruino­.com/search/?q=%23boardcontainer):hover [#left2](https://forum.espruino.com/sear­ch/?q=%23left2) { opacity: 0.1; }
    [#boardcontainer](https://forum.espruino­.com/search/?q=%23boardcontainer):hover [#right](https://forum.espruino.com/sear­ch/?q=%23right) { opacity: 0.1; }
    [#boardcontainer](https://forum.espruino­.com/search/?q=%23boardcontainer):hover [#right2](https://forum.espruino.com/sea­rch/?q=%23right2) { opacity: 0.1; }
    [#boardcontainer](https://forum.espruino­.com/search/?q=%23boardcontainer):hover [#left](https://forum.espruino.com/searc­h/?q=%23left):hover { opacity: 1; z-index: 10; }
    [#boardcontainer](https://forum.espruino­.com/search/?q=%23boardcontainer):hover [#left2](https://forum.espruino.com/sear­ch/?q=%23left2):hover { opacity: 1; z-index: 10; }
    [#boardcontainer](https://forum.espruino­.com/search/?q=%23boardcontainer):hover [#right2](https://forum.espruino.com/sea­rch/?q=%23right2):hover { opacity: 1; z-index: 10; }
    [#boardcontainer](https://forum.espruino­.com/search/?q=%23boardcontainer):hover [#right](https://forum.espruino.com/sear­ch/?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/searc­h/?q=%23left) { opacity: 0.1; }' +
      '#boardcontainer:hover [#left2](https://forum.espruino.com/sear­ch/?q=%23left2) { opacity: 0.1; }' +
      '#boardcontainer:hover [#right](https://forum.espruino.com/sear­ch/?q=%23right) { opacity: 0.1; }' +
      '#boardcontainer:hover [#right2](https://forum.espruino.com/sea­rch/?q=%23right2) { opacity: 0.1; }' +
      '#boardcontainer:hover [#left](https://forum.espruino.com/searc­h/?q=%23left):hover { opacity: 1; z-index: 10; } ' +
      '#boardcontainer:hover [#left2](https://forum.espruino.com/sear­ch/?q=%23left2):hover { opacity: 1; z-index: 10; } ' +
      '#boardcontainer:hover [#right2](https://forum.espruino.com/sea­rch/?q=%23right2):hover { opacity: 1; z-index: 10; } ' +
      '#boardcontainer:hover [#right](https://forum.espruino.com/sear­ch/?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/blo­b/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 ;)

  • 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/blo­b/master/boards/pins/stm32f303.csv
      https://github.com/espruino/Espruino/blo­b/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
    }
    //});
    
  • 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...

  • 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 with pinMode(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

  • 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

    @Gordon:

    .. 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 ..

    @Gordon:

    RN42 links and code
    -> my pleasure ;P

    ps: 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 ;)
    +

  • Post a reply
    • Bold
    • Italics
    • Link
    • Image
    • List
    • Quote
    • code
    • Preview
About

Espruino USB HID GamePad - v0.1a ready ! ( may also be Bluetooth & RN42 ready .. )

Posted by Avatar for stephaneAG @stephaneAG

Actions