• Welcome to Overclockers Forums! Join us to reply in threads, receive reduced ads, and to customize your site experience!

NES controller w/Accelerometer code...C++ issues

Overclockers is supported by our readers. When you click a link to make a purchase, we may earn a commission. Learn More.

attack

Member
Joined
May 23, 2002
Well I'm almost complete with my NES HTPC! I'm waiting for the parts to mount the mobo, and lastly completing the code for the controller!

I'm using a teensy 2.0 USB chip, with an accelerometer attached. Right now the code works for the controller portion...anytime a button is pressed it send the corresponding letter.
The mouse portion kind of works and that's where I'm getting into issues. I have it setup so when I press both the start and select buttons on the NES controller it will activate the accelerometer and send the mouse commands. It works, but the problem is it still outputs the keyboard letters which I'm not sure why. I've attached the full code below, the code is broken into sections with full code last. I have the if statement setup to run the fcnmouse if the 2 buttons are pressed, and that works, however, the else statement is still run or something because the letters are sent.

Lastly, the mouse click isn't working...I think this is propietary code unique to arduino but i've commented the code out and it's at the bottom of the fcn mouse because it won't compile.

*edit* after gaming, I can't send 2 key inputs at once...it always sends each key one at a time? Help would be greatly appreciate!

*LASTLY* please note the vast majority for the code below was completed by Ladyada! I take no credit for the abortion I did to her code!
http://www.ladyada.net/make/usbgamepad/index.html

decalring values and constants:
Code:
const int pAnXin = 3;
const int pAnYin = 2;
const int pAnZin = 1;
const int pAnDumb = 0;
 
#define KEYREPEAT 100  // milliseconds
#define KEYDELAY 200 // delay from first to second character
 
const int pUp = 0;
const int pRight = 1;
const int pDown = 2;
const int pLeft = 3;
const int pB = 4;
const int pA = 5;
const int pSelect = 6;
const int pStart = 7;
const int pinLED = 11;
 
 
//Variables for the states of the NES buttons
byte buttons[] = {pUp, pRight, pDown, pLeft, pB, pA, pSelect, pStart};
byte keys[] = {KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H};
 
#define NUMBUTTONS sizeof(buttons)
 
//How far the accelerometer is tilted before the controller starts moving the mouse:
const int cintMovementThreshold = 18;
 
//The average zero acceleration values read from the accelerometer for each axis:
const int cintZeroXValue = 328;
const int cintZeroYValue = 328;
const int cintZeroZValue = 328;
 
 
//The maximum (positive) acceleration values read from the accelerometer for each axis:
const int cintMaxXValue = 396;
const int cintMaxYValue = 396;
const int cintMaxZValue = 396;
 
 
//The minimum (negative) acceleration values read from the accelerometer for each axis:
const int cintMinXValue = 256;
const int cintMinYValue = 256;
const int cintMinZValue = 256;
 
//The sign of the mouse movement relative to the acceleration:
const int cintXSign = -1;
const int cintYSign = -1;
const int cintZSign = 1;
 
//const float cfloatMovementMultiplier = 1;
//The maximum speed in each axis (x and y) that the cursor should move:
 
const int cintMaxMouseMovement = 15;
 
//This reduces the 'twitchiness' of the cursor by calling a delay function at the end of the main loop.
const int cintMouseDelay = 6;
void setup:
Code:
void setup() {
 
  //Analog Reference, use default
  analogReference( DEFAULT );
 
  //Setup the pin modes.
  pinMode( pinLED, OUTPUT );
 
  //Enable pullup resitor on the pins.
  for (byte i=0; i< NUMBUTTONS; i++) {
 
  pinMode(buttons[i], INPUT_PULLUP);
 
  }
 
}
void loop:
Code:
void loop() {
 
  //Determine if chip will be used as a mouse or controller
  if (digitalRead(buttons[pStart]) == 0 && digitalRead(buttons[pSelect]) ==0) {
 
  //Process the accelerometer to make the cursor move.
  fcnMouse();
 
  }
 
  else {
 
  //Progess the NES controller buttons to send keystrokes.
  fcnController();
 
  }  
 
  //Delay to avoid 'twitchiness' and bouncing inputs due to too fast of sampling.
  delay(cintMouseDelay);
 
}
fcnmouse:
Code:
//Function to process the acclerometer as a mouse and send clicks
void fcnMouse()
 
{
 
  //Initialize values for the mouse cursor movement.
  int intMouseXMovement = 0;
  int intMouseYMovement = 0;
 
  //Read the dummy analog channel this must be done first because the X analog channel was first and was unstable, it dropped or pegged periodically regardless of pin or source.
  analogRead( pAnDumb );
 
  //Read accelerometer readings  
  int intAnalogXReading = analogRead(pAnXin);
  int intAnalogYReading = analogRead(pAnYin);
  int intAnalogZReading = analogRead(pAnZin);
 
  //Calculate mouse movement if the analog X reading is ouside of the zero threshold...
  if( cintMovementThreshold < abs( intAnalogXReading - cintZeroXValue ) ) {
 
    //...calculate X mouse movement based on how far the X acceleration is from its zero value.
    intMouseXMovement = cintXSign * ( ( ( (float)( 2 * cintMaxMouseMovement ) / ( cintMaxXValue - cintMinXValue ) ) * ( intAnalogXReading - cintMinXValue ) ) - cintMaxMouseMovement );
 
  }
 
  else {
 
    //Within the zero threshold, the cursor does not move in the X.
    intMouseXMovement = 0;
 
  }
 
 
 
  //If the analog Y reading is outside of the zero threshold...
  if( cintMovementThreshold < abs( intAnalogYReading - cintZeroYValue ) )  {
 
    //...calculate Y mouse movement based on how far the Y acceleration is from its zero value.
    intMouseYMovement = cintYSign * ( ( ( (float)( 2 * cintMaxMouseMovement ) / ( cintMaxYValue - cintMinYValue ) ) * ( intAnalogYReading - cintMinYValue ) ) - cintMaxMouseMovement );
    //it could use some improvement, like making it trigonometric.
 
  }
 
  else {
 
    //Within the zero threshold, the cursor does not move in the Y.
 
    intMouseYMovement = 0;
 
  }
 
 
  Mouse.move(intMouseXMovement, intMouseYMovement);
 
 
 
//  //Left and right click for buttons
//
//  if (digitalRead(buttons[pB])==0) {
//
//  Mouse.click(1,0,0);
//
//  }
//
//  else if (digitalRead(buttons[pA])==0) {
//
//  Mouse.click(0,0,1);
//
//  }
//
//  else {Mouse.click(0,0,0);
//
//  }
 
 
 
}
fcnController:
Code:
//Function to process the buttons from the NES controller
void fcnController() {
 
  static long currentkey = 0;
  byte nothingpressed = 1;
 
  // run through all the buttons
  for (byte i = 0; i < NUMBUTTONS; i++) {
 
    // are any of them pressed?
    if (! digitalRead(buttons[i])) {
 
      nothingpressed = 0; // at least one button is pressed!
 
 
      // if its a new button, release the old one, and press the new one
      if (currentkey != keys[i]) {
        Keyboard.set_key1(0);
        Keyboard.send_now();
        Keyboard.set_key1(keys[i]);
        currentkey = keys[i];
        Keyboard.send_now();
        delay(KEYDELAY);
      } else {
 
        // the same button is pressed, so repeat!
        Keyboard.set_key1(keys[i]);
        Keyboard.send_now();
        delay(KEYREPEAT);
 
      }
 
    }
 
  }
 
 
 
  if (nothingpressed) {
 
    // release all keys
    Keyboard.set_key1(0);
    Keyboard.send_now();
 
  }
 
}

Full code alltogether for copy/paste:
Code:
const int pAnXin = 3;
const int pAnYin = 2;
const int pAnZin = 1;
const int pAnDumb = 0;
 
#define KEYREPEAT 100  // milliseconds
 
#define KEYDELAY 200 // delay from first to second character
 
const int pUp = 0;
const int pRight = 1;
const int pDown = 2;
const int pLeft = 3;
 
const int pB = 4;
const int pA = 5;
 
const int pSelect = 6;
const int pStart = 7;
 
const int pinLED = 11;
 
 
//Variables for the states of the NES buttons
 
byte buttons[] = {pUp, pRight, pDown, pLeft, pB, pA, pSelect, pStart};
 
byte keys[] = {KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H};
 
 
 
#define NUMBUTTONS sizeof(buttons)
 
 
 
//How far the accelerometer is tilted before the controller starts moving the mouse:
const int cintMovementThreshold = 18;
 
 
 
//The average zero acceleration values read from the accelerometer for each axis:
const int cintZeroXValue = 328;
const int cintZeroYValue = 328;
const int cintZeroZValue = 328;
 
 
//The maximum (positive) acceleration values read from the accelerometer for each axis:
const int cintMaxXValue = 396;
const int cintMaxYValue = 396;
const int cintMaxZValue = 396;
 
 
//The minimum (negative) acceleration values read from the accelerometer for each axis:
const int cintMinXValue = 256;
const int cintMinYValue = 256;
const int cintMinZValue = 256;
 
//The sign of the mouse movement relative to the acceleration:
const int cintXSign = -1;
const int cintYSign = -1;
const int cintZSign = 1;
 
//const float cfloatMovementMultiplier = 1;
//The maximum speed in each axis (x and y) that the cursor should move:
 
const int cintMaxMouseMovement = 15;
 
//This reduces the 'twitchiness' of the cursor by calling a delay function at the end of the main loop.
const int cintMouseDelay = 6;
 
 
 
 
void setup() {
 
  //Analog Reference, use default
  analogReference( DEFAULT );
 
  //Setup the pin modes.
  pinMode( pinLED, OUTPUT );
 
  //Enable pullup resitor on the pins.
  for (byte i=0; i< NUMBUTTONS; i++) {
 
  pinMode(buttons[i], INPUT_PULLUP);
 
  }
 
}
 
 
 
 
void loop() {
 
  //Determine if chip will be used as a mouse or controller
  if (digitalRead(buttons[pStart]) == 0 && digitalRead(buttons[pSelect]) ==0) {
 
  //Process the accelerometer to make the cursor move.
  fcnMouse();
 
  }
 
  else {
 
  //Progess the NES controller buttons to send keystrokes.
  fcnController();
 
  }  
 
  //Delay to avoid 'twitchiness' and bouncing inputs due to too fast of sampling.
  delay(cintMouseDelay);
 
}
 
 
 
//Function to process the acclerometer as a mouse and send clicks
void fcnMouse()
 
{
 
  //Initialize values for the mouse cursor movement.
  int intMouseXMovement = 0;
  int intMouseYMovement = 0;
 
  //Read the dummy analog channel this must be done first because the X analog channel was first and was unstable, it dropped or pegged periodically regardless of pin or source.
  analogRead( pAnDumb );
 
  //Read accelerometer readings  
  int intAnalogXReading = analogRead(pAnXin);
  int intAnalogYReading = analogRead(pAnYin);
  int intAnalogZReading = analogRead(pAnZin);
 
  //Calculate mouse movement if the analog X reading is ouside of the zero threshold...
  if( cintMovementThreshold < abs( intAnalogXReading - cintZeroXValue ) ) {
 
    //...calculate X mouse movement based on how far the X acceleration is from its zero value.
    intMouseXMovement = cintXSign * ( ( ( (float)( 2 * cintMaxMouseMovement ) / ( cintMaxXValue - cintMinXValue ) ) * ( intAnalogXReading - cintMinXValue ) ) - cintMaxMouseMovement );
 
  }
 
  else {
 
    //Within the zero threshold, the cursor does not move in the X.
    intMouseXMovement = 0;
 
  }
 
 
 
  //If the analog Y reading is outside of the zero threshold...
  if( cintMovementThreshold < abs( intAnalogYReading - cintZeroYValue ) )  {
 
    //...calculate Y mouse movement based on how far the Y acceleration is from its zero value.
    intMouseYMovement = cintYSign * ( ( ( (float)( 2 * cintMaxMouseMovement ) / ( cintMaxYValue - cintMinYValue ) ) * ( intAnalogYReading - cintMinYValue ) ) - cintMaxMouseMovement );
    //it could use some improvement, like making it trigonometric.
 
  }
 
  else {
 
    //Within the zero threshold, the cursor does not move in the Y.
 
    intMouseYMovement = 0;
 
  }
 
 
  Mouse.move(intMouseXMovement, intMouseYMovement);
 
 
 
//  //Left and right click for buttons
//
//  if (digitalRead(buttons[pB])==0) {
//
//  Mouse.click(1,0,0);
//
//  }
//
//  else if (digitalRead(buttons[pA])==0) {
//
//  Mouse.click(0,0,1);
//
//  }
//
//  else {Mouse.click(0,0,0);
//
//  }
 
 
 
}
 
 
 
//Function to process the buttons from the NES controller
void fcnController() {
 
  static long currentkey = 0;
  byte nothingpressed = 1;
 
  // run through all the buttons
  for (byte i = 0; i < NUMBUTTONS; i++) {
 
    // are any of them pressed?
    if (! digitalRead(buttons[i])) {
 
      nothingpressed = 0; // at least one button is pressed!
 
 
      // if its a new button, release the old one, and press the new one
      if (currentkey != keys[i]) {
        Keyboard.set_key1(0);
        Keyboard.send_now();
        Keyboard.set_key1(keys[i]);
        currentkey = keys[i];
        Keyboard.send_now();
        delay(KEYDELAY);
      } else {
 
        // the same button is pressed, so repeat!
        Keyboard.set_key1(keys[i]);
        Keyboard.send_now();
        delay(KEYREPEAT);
 
      }
 
    }
 
  }
 
 
 
  if (nothingpressed) {
 
    // release all keys
    Keyboard.set_key1(0);
    Keyboard.send_now();
 
  }
 
}
 
Last edited:
Well It looks like I've figured everything out except for the mouse clicks....I want to be able to click and drag ideally....but right now it clicks with a built in delay.

I also reworked the code so more than 1 button can be pressed at once, this was a necessity, it's impossible to play NES one button at a time.

Also after tinkering and finding out it's annoying and hard to hold start and select at the same time, I programmed a while loop... So now if I hold start and select ever it moves into a while loop which is broken when down is pressed!

so a lot of new code...cutout some crap and cleaned it up.

Any advice on the click/drag?

Code:
//USB NES Controller with accelerometer.  Holding Start and Select will activate mouse function, pressing down will disable mouse functions
//Mouse function code is based off Ladyada code: http://www.ladyada.net/make/usbgamepad/index.html

//Accelerometer inputs
const int pinanXin = 3;
const int pinanYin = 2;
const int pinanZin = 1;
const int pinanDumb = 0;

//NES Pin inputs
const int pinright = 0;
const int pinleft = 1;
const int pindown = 2;
const int pinup = 3;
const int pina = 4;
const int pinb = 5;
const int pinselect = 6;
const int pinstart = 7;

//Variables for the states of the NES buttons
byte buttons[] = {pinright, pinleft, pinup, pindown, pina, pinb, pinselect, pinstart};
byte keys[] = {KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H};

#define NUMBUTTONS sizeof(buttons)

//How far the accelerometer is tilted before the controller starts moving the mouse:
const int cintMovementThreshold = 10; 

//The average zero acceleration values read from the accelerometer for each axis:
const int cintZeroXValue = 328;
const int cintZeroYValue = 328;

//The maximum (positive) acceleration values read from the accelerometer for each axis:
const int cintMaxXValue = 396;
const int cintMaxYValue = 396;

//The minimum (negative) acceleration values read from the accelerometer for each axis:
const int cintMinXValue = 256;
const int cintMinYValue = 256;

//The sign of the mouse movement relative to the acceleration:
const int cintXSign = -1;
const int cintYSign = -1;
 
//The maximum speed in each axis (x and y) that the cursor should move: 
const int cintMaxMouseMovement = 15;

//This reduces the 'twitchiness' of the cursor by calling a delay function at the end of the main loop.
const int cintMouseDelay = 8;


void setup() {
    //Analog Reference, use default
  analogReference( DEFAULT );
  //Pullup resistor on all buttons
  for (byte i=0; i< NUMBUTTONS; i++) {
    pinMode(buttons[i], INPUT_PULLUP);
  }
}



void loop() {
  //Checking to see if mouse function should be enabled
  if (digitalRead(pinselect) == 0 && digitalRead(pinstart)==0) {  
    Keyboard.set_key1(0);
    Keyboard.set_key2(0);
    Keyboard.set_key3(0);
    Keyboard.send_now(); 
    delay(100);
    //To break the mouse function, press the down button
    while (digitalRead(pindown)==1){
    fcnMouse();
  }
  }
  fcnController();

}


//Function to process the acclerometer as a mouse and send clicks
void fcnMouse()
{
  
  //Initialize values for the mouse cursor movement.
  int intMouseXMovement = 0;
  int intMouseYMovement = 0;

  //Read the dummy analog channel this must be done first because the X analog channel was first and was unstable, it dropped or pegged periodically regardless of pin or source
  analogRead( pinanDumb ); 

  //Read accelerometer readings  
  int intAnalogXReading = analogRead(pinanXin);
  int intAnalogYReading = analogRead(pinanYin);

  //Calculate mouse movement If the analog X reading is ouside of the zero threshold...
  if( cintMovementThreshold < abs( intAnalogXReading - cintZeroXValue ) )

  {

    //...calculate X mouse movement based on how far the X acceleration is from its zero value.
    intMouseXMovement = cintXSign * ( ( ( (float)( 2 * cintMaxMouseMovement ) / ( cintMaxXValue - cintMinXValue ) ) * ( intAnalogXReading - cintMinXValue ) ) - cintMaxMouseMovement );

  }
  else
  {
    //Within the zero threshold, the cursor does not move in the X.
    intMouseXMovement = 0;
  }

 

  //If the analog Y reading is outside of the zero threshold...
  if( cintMovementThreshold < abs( intAnalogYReading - cintZeroYValue ) )

  {

    //...calculate Y mouse movement based on how far the Y acceleration is from its zero value.
    intMouseYMovement = cintYSign * ( ( ( (float)( 2 * cintMaxMouseMovement ) / ( cintMaxYValue - cintMinYValue ) ) * ( intAnalogYReading - cintMinYValue ) ) - cintMaxMouseMovement );
    //it could use some improvement, like making it trigonometric.
  }

  else
  {

    //Within the zero threshold, the cursor does not move in the Y.
    intMouseYMovement = 0;
  }


  Mouse.move(intMouseXMovement, intMouseYMovement); 

//Left and right click for buttons, still need to improve!
  if (digitalRead(pinb)==0) {
    Mouse.click();
    delay(200);
  }

  else if (digitalRead(pina)==0) {
     Mouse.click();
     delay(200);
  }
  delay(cintMouseDelay);
}


//Function to process the buttons from the NES controller
void fcnController()
{
  static long keynum = 1;
  
  // run through all the buttons
  for (byte i = 0; i < NUMBUTTONS; i++) {
    
    if (! digitalRead(buttons[i])) {
      if (keynum==4){
      Keyboard.set_key1(keys[i]);
      keynum++;}
      else if (keynum==3){
      Keyboard.set_key1(keys[i]);
      keynum++;}
      else if (keynum==2){
      Keyboard.set_key2(keys[i]);
      keynum++;}
      else if (keynum==1){
      Keyboard.set_key3(keys[i]);
      keynum++;}
      
    }}
    Keyboard.send_now();
    keynum=1;
    Keyboard.set_key1(0);
    Keyboard.set_key2(0);
    Keyboard.set_key3(0);
    Keyboard.set_key4(0);
    delay(25);  
}
 
I'm impressed! I was hoping it wouldn't be a frustrating nightmare for you when i suggested it, i thought it might be but clearly it wasn't!


For click/drag, i think the issue lies inside the Mouse function somewhere, from reading the code it should start dragging after 200ms.
I think the Mouse function must send a click+release every time it is called.
I'll see if i can find the guts of the mouse function, seems like it out to have a hold option.
Actually you might try calling Mouse.hold() or Mouse.clickhold() just to see if it changes color in the programmer to indicate a valid function.
 
Got the pesky mouse button issue solved!
using mouse.set_buttons(left,middle,right); everything works like a charm!
Code is at the bottom, feel free to distro and hack to your hearts content. The mouse function could use more TLC...there's a better way of doing it than delaying the micro controller...and with 8ms delay I'll always get 125 pixels/second movement min...kinda fast for small precise movements. But I'm sure theres better code out there that should be easy to implant.

Pictures!!!
First pic is everything tucked into the controller. I should've shortened my wires about a 1cm, but I thought I'd have more room!

1001245r.jpg


Second pic is the front side of the PCB. You can see where I broke the PCB...I had to do that to make room for the USB connector and also just get more clearance for the teensy chip fit. I'd highly recommend using a dremel! All I had was pliers, so it's a very poor job. The only drawback of doing this is I had to break the traces to 3 pin holes. (if not done carefully you can break more traces too, so make sure you know what your cutting!)

1001246r.jpg


That leads us to the 3rd pic...soldering onto traces SUCKS. I don't have all the right tools so it couldn've been easier (i.e. flux, a more fine soldering iron, clamp to hold the chip and a magnafying glass), but I was able to make it work.

1001247.jpg


The last pic is a USB mini-B (I think) plug. This was a PITA! The plastic housing was thick enough to make fitting it inside the controller impossible. Taking a knife and carefullying removing the housing exposed about 1" of the 4 USB leads, which I soldered into a USB cord (for initial programming only)...this will be resoldered into an NES connector, but that'll have to wait a week. When cutting the mini-B, I just put my knife on the metal casing and the top and slide it back toward the cord peeling it away. Just be carefull and make small cuts...it's possible to remove the mini-B connector on the teensy chip but those traces are half the size of the NES traces that gave me hell.

1001248i.jpg

http://img340.imageshack.us/img340/2610/1001245r.jpg
http://img716.imageshack.us/img716/4300/1001246r.jpg
http://img375.imageshack.us/img375/3400/1001247.jpg
http://img707.imageshack.us/img707/2849/1001248i.jpg


Lastly, the Code!
//USB NES Controller with accelerometer. Holding Start and Select will activate mouse function, pressing down will disable mouse functions
//Mouse function code is based off Ladyada code: http://www.ladyada.net/make/usbgamepad/index.html

//Accelerometer inputs
const int pinanXin = 3;
const int pinanYin = 2;
const int pinanZin = 1;
const int pinanDumb = 0;

//NES Pin inputs
const int pinright = 0;
const int pinleft = 1;
const int pindown = 2;
const int pinup = 3;
const int pina = 4;
const int pinb = 5;
const int pinselect = 6;
const int pinstart = 7;

//Variables for the states of the NES buttons
byte buttons[] = {pinright, pinleft, pinup, pindown, pina, pinb, pinselect, pinstart};
byte keys[] = {KEY_A, KEY_B, KEY_C, KEY_D, KEY_E, KEY_F, KEY_G, KEY_H};

#define NUMBUTTONS sizeof(buttons)

//How far the accelerometer is tilted before the controller starts moving the mouse:
const int cintMovementXThreshold = 6;
const int cintMovementYThreshold = 6;

//The average zero acceleration values read from the accelerometer for each axis:
const int cintZeroXValue = 335;
const int cintZeroYValue = 344;

//The maximum (positive) acceleration values read from the accelerometer for each axis:
const int cintMaxXValue = 396;
const int cintMaxYValue = 396;

//The minimum (negative) acceleration values read from the accelerometer for each axis:
const int cintMinXValue = 256;
const int cintMinYValue = 256;

//The sign of the mouse movement relative to the acceleration:
const int cintXSign = -1;
const int cintYSign = -1;

//The maximum speed in each axis (x and y) that the cursor should move:
const int cintMaxMouseMovement = 15;

//This reduces the 'twitchiness' of the cursor by calling a delay function at the end of the main loop.
const int cintMouseDelay = 8;

//So down is not sent after mouse function is broken
int nodown = 0;
//Initiate keynum for number of keys that are being pressed
int keynum = 1;


void setup() {
//Analog Reference, use default
analogReference( DEFAULT );
//Pullup resistor on all buttons
for (byte i=0; i< NUMBUTTONS; i++) {
pinMode(buttons, INPUT_PULLUP);
}
}



void loop() {


//Checking to see if mouse function should be enabled
if (digitalRead(pinselect) == 0 && digitalRead(pinstart)==0) {
Keyboard.set_key1(0);
Keyboard.set_key2(0);
Keyboard.set_key3(0);
Keyboard.set_key4(0);
Keyboard.send_now();
delay(100);
//To break the mouse function, press the down button
while (digitalRead(pindown)==1){
fcnMouse();
if (digitalRead(pindown)==0) {
nodown = 1;
}
}
}
fcnController();

}


//Function to process the acclerometer as a mouse and send clicks
void fcnMouse() {

//Initialize values for the mouse cursor movement.
int intMouseXMovement = 0;
int intMouseYMovement = 0;

//Read the dummy analog channel this must be done first because the X analog channel was first and was unstable, it dropped or pegged periodically regardless of pin or source
analogRead( pinanDumb );

//Read accelerometer readings
int intAnalogXReading = analogRead(pinanXin);
int intAnalogYReading = analogRead(pinanYin);

//Calculate mouse movement If the analog X reading is ouside of the zero threshold...
if( cintMovementXThreshold < abs( intAnalogXReading - cintZeroXValue ) )

{

//...calculate X mouse movement based on how far the X acceleration is from its zero value.
intMouseXMovement = cintXSign * ( ( ( (float)( 2 * cintMaxMouseMovement ) / ( cintMaxXValue - cintMinXValue ) ) * ( intAnalogXReading - cintMinXValue ) ) - cintMaxMouseMovement );

}
else
{
//Within the zero threshold, the cursor does not move in the X.
intMouseXMovement = 0;
}


//If the analog Y reading is outside of the zero threshold...
if( cintMovementYThreshold < abs( intAnalogYReading - cintZeroYValue ) )

{

//...calculate Y mouse movement based on how far the Y acceleration is from its zero value.
intMouseYMovement = cintYSign * ( ( ( (float)( 1.5 * cintMaxMouseMovement ) / ( cintMaxYValue - cintMinYValue ) ) * ( intAnalogYReading - cintMinYValue ) ) - cintMaxMouseMovement );
//it could use some improvement, like making it trigonometric.
}

else
{

//Within the zero threshold, the cursor does not move in the Y.
intMouseYMovement = 0;
}


Mouse.move(intMouseXMovement, intMouseYMovement);

//Left and right click for buttons, still need to improve!
if (digitalRead(pinb)==0) {
Mouse.set_buttons(1,0,0);
}
if (digitalRead(pina)==0) {
Mouse.set_buttons(0,0,1);
}
if (digitalRead(pinb)==1 && digitalRead(pina)==1) {
Mouse.set_buttons(0,0,0);
}

delay(cintMouseDelay);
}


//Function to process the buttons from the NES controller
void fcnController()
{

//This small portion delays the Controller function for 200ms after coming out of mouse mode so keyboard commands aren't sent after coming out of fcnmouse
if (nodown ==1) {
delay(200);
nodown = 0;
}

// run through all the buttons
for (byte i = 0; i < NUMBUTTONS; i++) {

if (! digitalRead(buttons)) {
if (keynum==4){
Keyboard.set_key4(keys);
keynum++;}
else if (keynum==3){
Keyboard.set_key3(keys);
keynum++;}
else if (keynum==2){
Keyboard.set_key2(keys);
keynum++;}
else if (keynum==1){
Keyboard.set_key1(keys);
keynum++;}

}}
Keyboard.send_now();
keynum=1;
Keyboard.set_key1(0);
Keyboard.set_key2(0);
Keyboard.set_key3(0);
Keyboard.set_key4(0);
delay(25);
}


Madden 2011
69922979.png
? Who cares.

http://imageshack.us
 
Last edited:
Awesome! Very happy to hear that it works!


Mouse thoughts: There's a static multiplier in the mouse movement code, that could be adjusted to allow slower movement. That'd drop max speed too though.

Alternatively you could use one of the direction arrows to set slow mode (or fast mode), make that static multi into a variable and check for the up button being pressed, then either set the variable to normal or to a lower setting. If it did that each time through the movement code it ought to work decently.

(Fair warning: my programming tends toward tediously nested if statements.
 
Back