This is the first rev of HW3 for IDD

Dependencies:   MMA8451Q USBDevice mbed nRF24L01P

Revision:
3:99ed0483f868
Parent:
2:c3b748d86642
Child:
4:7012a2af25f6
--- a/main.cpp	Mon Sep 29 10:38:39 2014 +0000
+++ b/main.cpp	Mon Sep 29 17:14:42 2014 +0000
@@ -4,13 +4,13 @@
 #include "mbed.h"
 #include "nRF24L01P.h"                              // nordic library
 
-#define DEBUG 0
-#define BASE 1
+#define DEBUG 0                                     // code debug mode
+#define BASE 0                                      // is base station
 
 
 #include "USBMouseKeyboard.h"                       // for the sword - mouse/keyboard combo
 #if(BASE == 1)
-    USBMouseKeyboard MK;                                //Default is REL_MOUSE, bout could use ABS_MOUSE too
+    USBMouseKeyboard MK;                            //Default is REL_MOUSE, bout could use ABS_MOUSE too
 #endif
 
 #define SCALING 50                                  // factor to multiply the accelerometer reading by (usually it is in the scale of g's. Decides sensitivity of mouse. Keep it less 100 (mouse is assigned an int8)
@@ -27,17 +27,11 @@
 #define RX_NRF24L01P_ADDRESS       ((unsigned long long) 0xABABABABAB )
 #define TX_NRF24L01P_ADDRESS       ((unsigned long long) 0xCDCDCDCDCD )
 
-// Masks
-#define LOW8                        0x00FF
-#define HIGH3                       0x0007
-#define LOW5                        0x001F               
-#define HIGH6                       0x003F
-
 // The nRF24L01+ supports transfers from 1 to 32 bytes 
-// Assume 1680x1050 max screen resolution -- MSB to LSB 0 padded, 1 bit pressed, 11 bits x, 11 bits y for Fruit Ninja
-// For Blade Symphony, way fewer than 24 control bits for keyboard/house
-// From PC, only need (zero padded) 1 bit flag indicating if hit + 1 bit indicating Fruit Ninja (0) or Blade Symphony (1)
-#define TRANSFER_SIZE   3
+// To base station: roll | cycle 1 2 3 | space = jump | left click = attack | right click = defend | w | s | d | a | 8-bit Y mouse movement | 8-bit X mouse movement
+// WASD = forward, left, back, right
+// From PC, only need (zero padded) 1 bit flag indicating if hit
+#define TRANSFER_SIZE   4
 
 Serial pc(USBTX, USBRX);                                    // PC communication
 
@@ -45,7 +39,9 @@
 
 nRF24L01P nordic(PTD2, PTD3, PTC5, PTD0, PTD5, PTA13);      // mosi, miso, sck, csn, ce, irq
 
-DigitalIn modeSW(D15);                                      // base station or sword mode
+DigitalIn modeSW(D15);                                      // base station or sword mode can be selected w/ jumper
+
+DigitalOut greenLED(LED_GREEN);
 
 // Accelerometer
 MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS);
@@ -53,31 +49,32 @@
 void Calibrate(void);
 void Acc_GetXY(void);
 
-int16_t x,y;                                              // variables to hold acceleration data after call to Acc_Get_All
-float x_b, y_b;                                           // acc bias
+    int16_t x,y;                                            // variables to hold acceleration data after call to Acc_Get_All
+float x_b, y_b;                                             // acc bias
 
 // Debug
 //DigitalOut greenLED(LED_GREEN);
 //DigitalOut redLED(LED_RED);
 
-
-AnalogIn ATTACK(A0);
-AnalogIn SELECT(A1);
-AnalogIn XJOY(A2);
-AnalogIn YJOY(A3);
+AnalogIn ATTACK(A0);                                        // attack FSR
+AnalogIn SELECT(A1);                                        // defense/mode FSR
+AnalogIn XJOY(A2);                                          // joystick x axis
+AnalogIn YJOY(A3);                                          // joystick y axis
 
 DigitalIn JOYSEL(D3);
 
-
 bool isBaseStation;
+bool motorOnFlag;
+int motorCycle = 0;
 
 int main() {
     int8_t mouse_x, mouse_y;
-    Calibrate();
+    Calibrate();                                            // Calibrate accelerometer
 
-    modeSW.mode(PullUp);                                  // Configure pull down to minimize wire
+    modeSW.mode(PullUp);                                    // Configure pull up to minimize wire on sword
     
-    isBaseStation = (bool) !modeSW;                          // Detect device via jumper connection
+    isBaseStation = (bool) !modeSW;                         // Detect device via jumper connection
+    
     wait(5);
 
     // Power up wireless
@@ -112,24 +109,22 @@
     motor.period(0.001f);       // 1ms period
     motor.write(0.0f);          // initially not on
     
-   // motor.write(0.40f);                         // 95% duty cycle, relative to period
-
     // Status flags
-    bool isBladeSymphony = false;
-    bool sensor1ON = false; 
-    
     bool motorON = false; 
+    bool mouse1 = false;
+    bool mouse2 = false;
+    bool mouse3 = false;
+    bool mouse4 = false;
+    bool mouse5 = false;
+    bool attackflag = false;
 
     int rxDataCnt = 0;
     
-    // Debug
-    int testcount = 0;
-    
     // counting the mode
     uint8_t mode_count = 0;
 
     while (1) {
-        // Only reads 1 byte from PC + sends to other mcu (pads w/ 0 bytes) if base station
+        // Only reads 1 byte from PC + sends to other mcu (pads w/ bytes) if base station
         if (isBaseStation){
 
             // If we've received anything over the host serial link...
@@ -138,7 +133,8 @@
                 // ...add it to the transmit buffer -- only care about first byte
                 txData[0] = pc.getc();
                 txData[1] = 100;
-                txData[2] = '\n';
+                txData[2] = 100;
+                txData[3] = '\n';
                 
                 // Send the transmitbuffer via the nRF24L01+
                 nordic.write( NRF24L01P_PIPE_P0, txData, TRANSFER_SIZE );
@@ -154,15 +150,15 @@
                 // ...read the data into the receive buffer
                 rxDataCnt = nordic.read( NRF24L01P_PIPE_P0, rxData, TRANSFER_SIZE );
 
-                //NOTE: NEED TO INTERPRET AS KEYS/MOUSE HERE
-                
-                int8_t dx = rxData[0];
-                int8_t dy = rxData[1];
+                //Get data and convert to mouse x,y and key entry
+                // To base station: roll | cycle 1 2 3 | space = jump | left click = attack | right click = defend | w | s | d | a | 8-bit Y mouse movement | 8-bit X mouse movement
                 
+                int8_t dx = rxData[0];                      // change in x
+                int8_t dy = rxData[1];                      // change in y
                 
-                bool mode_stat = (rxData[2] >> 7) & 1;
+                bool mode_stat = (rxData[2] >> 7) & 1;      // checking flag bits
                 bool joy_but = (rxData[2] >> 6) & 1;
-                bool sel_stat = (rxData[2] >> 5) & 1;
+                bool def_stat = (rxData[2] >> 5) & 1;
                 bool attack_stat = (rxData[2] >> 4) & 1;
                 bool key_w = (rxData[2] >> 3) & 1;
                 bool key_s = (rxData[2] >> 2) & 1;
@@ -171,167 +167,194 @@
 
                 bool roll = (rxData[3] >> 0) & 1;
 
-                #if(BASE == 1)
-                    MK.move(dy, dx); 
-
-                    if(joy_but)
+                #if(BASE == 1)                              // Only if base station
+                    MK.move(dy, dx);                        // move mouse relative                  
+                    
+                    if(joy_but)                             // do keyboard events
+                        MK.putc(' ');  
+                        
+                    if(attack_stat)
+                    {
+                        MK.press(MOUSE_LEFT);
+                        mouse1 = true;
+                    }
+                    if(!attack_stat && mouse1)
+                    {
+                        MK.release(MOUSE_LEFT);
+                        mouse1 = false;
+                    }
+                    if(key_a)                       // move left
                     {
-                        MK.putc(' ');
-                    }                
-                    if(key_w)
+                        MK.press(MOUSE_RIGHT);
+                        mouse2 = true;
+                    }
+                    if(!key_a && mouse2)
+                    {
+                        MK.release(MOUSE_RIGHT);
+                        mouse2 = false;
+                    }
+                    if(key_d)                       // move right
                     {
+                        MK.press(MOUSE_MIDDLE);
+                        mouse3 = true;
+                    }
+                    if(!key_d && mouse3)
+                    {
+                        MK.release(MOUSE_MIDDLE);
+                        mouse3 = false;
+                    }
+                    // mouse 4, 5 have issues on windows
+                    if(key_w)                       // move forward
+                    {
+                        //MK.press(16);               // mouse5
+                        //mouse5 = true;
                         MK.putc('w');
                     }
-                    if(key_a)
+                    /*if(!key_w && mouse5)
                     {
-                        MK.putc('a');
-                    }
-                    if(key_s)
+                        MK.release(16);
+                        mouse5 = false;
+                    }*/
+                    if(key_s)                       // move backward
                     {
+                        //MK.press(8);                // mouse4
+                        //mouse4 = true;
                         MK.putc('s');
                     }
-                    if(key_d)
-                    {
-                        MK.putc('d');
-                    }
-                    if(sel_stat)
+                    /*if(!key_s && mouse4)
                     {
-                        MK.click(MOUSE_RIGHT);
-                    }
-                    if(attack_stat)
-                    {
-                        MK.click(MOUSE_LEFT);
-                    }
+                        MK.release(8);
+                        mouse4 = false;
+                    }*/
+                    
+                    // Single push commands
+                    if(def_stat)
+                        MK.putc('d');
+                        
                     if(mode_stat)
                     {
                         MK.putc('1'+mode_count);
                         mode_count = (mode_count+1)%3;
                     }
                     if(roll)
-                    {
-                        //MK.putc('r');
-                    }                    
+                        MK.putc('r'); 
+                                        
                 #endif
 
-
-                pc.printf("x: %d y: %d \r\n",dx,dy);
+                //pc.printf("x: %d y: %d \r\n",dx,dy);
 
                 // Display the receive buffer contents via the host serial link
                 /*for ( int i = 0; i < TRANSFER_SIZE; i++ ) {
 
                     pc.putc( rxData[i] );
                 }*/
-
-                // Toggle LED2 (to help debug nRF24L01+ -> Host communication)
-                if (rxData[0] == 65 && rxData[1] == 66 && rxData[2] == 67){
-//                    redLED = !redLED;
-                }
             }
         }
 
-
         // sword
         else{
-            int ATTACKVAL = ATTACK.read_u16();
-            int SELECTVAL = SELECT.read_u16();
-            int XJOYVAL = XJOY.read_u16();
-            int YJOYVAL = YJOY.read_u16();
-            int JOYSELVAL = (int) JOYSEL;
+            int ATTACKVAL = ATTACK.read_u16();          // attack FSR
+            int SELECTVAL = SELECT.read_u16();          // mode/defense FSR
+            int XJOYVAL = XJOY.read_u16();              // joystick x
+            int YJOYVAL = YJOY.read_u16();              // joystick y
+            int JOYSELVAL = (int) JOYSEL;               // joystick select value
             
+            // if joystick push/pulled all the way on axis, do roll/move faster in direction
+            //bool roll = ((XJOYVAL > 64000) || (XJOYVAL < 1000) ||  (YJOYVAL > 64000) || (YJOYVAL < 1000)) ? true: 0;
+            // Disable backward roll due to lack of continuous MOUSE buttons
+            bool roll = ((XJOYVAL > 64000) || (XJOYVAL < 1000) ||  (YJOYVAL > 64000)) ? true: 0;
 
-            bool roll = ((XJOYVAL > 65000) || (XJOYVAL < 500) ||  (YJOYVAL > 65000) || (YJOYVAL < 500)) ? true: 0;
-
-            bool mode_stat = (SELECTVAL > 45000) ? true: 0;
+            // thresholding
+            bool mode_stat = (SELECTVAL > 45000) ? true: 0;                     // 1, 2, 3 rotated (defense/mode FSR pressed all the way)
             bool joy_but = JOYSEL == 0? true: 0;
-            bool sel_stat = (SELECTVAL > 10000 && SELECTVAL < 45000) ? true: 0;
-            bool attack_stat = ATTACKVAL > 10000? true: 0;
-            bool key_d = XJOYVAL > 35000 ? true: 0;
+            bool def_stat = (SELECTVAL > 10000 && SELECTVAL < 45000) ? true: 0; // defend if defense/mode FSR slightly pressed
+            bool attack_stat = ATTACKVAL > 10000? true: 0;                      // attack if attack FSR pressed
+            bool key_d = XJOYVAL > 35000 ? true: 0;                             // if joystick moves in direction, direction key should be pressed
             bool key_a = XJOYVAL < 30000 ? true : 0;
             bool key_w = YJOYVAL > 35000 ? true: 0;
             bool key_s = YJOYVAL < 30000 ? true: 0;
             
-            uint8_t key_stat = mode_stat<<7|joy_but<<6|sel_stat<<5|attack_stat<<4|key_w<<3|key_s<<2|key_d<<1|key_a<<0;
+            // turn on motor at start of attack
+            
+            if (attack_stat == true)
+                attackflag = true;
+            if (attackflag == true){
+                if (motorCycle < 250){
+                    motorCycle++;
+                    motor.write(0.80f);                         // 40% duty cycle, relative to period
+
+                }
+                else {
+                    motorCycle = 0;
+                    attackflag = false;
+                    motor.write(0.00f);                         
+                }
+            }
             
             
-            pc.printf("F1: %d \t F2: %d \t X: %d \t Y: %d \t SEL: %d \r\n", ATTACKVAL, SELECTVAL, XJOYVAL, YJOYVAL, JOYSELVAL);
-      
-//            greenLED = JOYSEL;
+            
+            // make byte 2 of packet
+            uint8_t key_stat = mode_stat<<7|joy_but<<6|def_stat<<5|attack_stat<<4|key_w<<3|key_s<<2|key_d<<1|key_a<<0;
+            
+            //pc.printf("F1: %d \t F2: %d \t X: %d \t Y: %d \t SEL: %d \r\n", ATTACKVAL, SELECTVAL, XJOYVAL, YJOYVAL, JOYSELVAL);
 
             // Let serial read catch up on base station/PC side
             wait_us(150);
 
             char swordData[TRANSFER_SIZE]; 
             
-            int16_t deltax = 768;
-            int16_t deltay = 345;
-            
-            if (testcount <= 2000){
-                deltax = testcount;
-                deltay = 2000-testcount;
-                testcount++;
-            }
-            else
-                testcount = 0;
-            
-            Acc_GetXY();
+            Acc_GetXY();                                // Get X, Y acceleration
         
-            mouse_x = x;
+            mouse_x = x;                                // x, y assigned in prev function
             mouse_y = y;
         
-            char lowX = char(mouse_x & LOW8);
-            char lowY = char(mouse_y & LOW8);
+            char lowX = char(mouse_x & 0x00FF);         // only use lowest 8 bits of data
+            char lowY = char(mouse_y & 0x00FF);
+            
+            //pc.printf("x: %f \t y: %f \r\n", mouse_x,mouse_y);
             
             // left A, right D, back S, up W
             
-            // MSB -- LSB, 
+            // MSB -- LSB send packet
             swordData[0] = lowX;
             swordData[1] = lowY; 
             swordData[2] = char(key_stat); 
-            swordData[3] = char(roll); 
+            swordData[3] = char(roll);                  // cast bool into char
             
             // Send the transmitbuffer via the nRF24L01+
             nordic.write( NRF24L01P_PIPE_P0, swordData, TRANSFER_SIZE );
 
-            // NOTE: Action settings depending on type of game. Accelerometer data. Force sensitive resistor thresholding, etc. 
-
             // If we've received anything from base station 
+            if ( nordic.readable() ) {
                 
-            if ( nordic.readable() ) {
+                greenLED = !greenLED;
+                
                 char rxData[TRANSFER_SIZE];
                 // ...read the data into the receive buffer
                 rxDataCnt = nordic.read( NRF24L01P_PIPE_P0, rxData, TRANSFER_SIZE );
 
                 #if DEBUG == 1
-                    // Toggle LED1 (to help debug Host -> nRF24L01+ communication)
-                    pc.printf("x: %f \t y: %f \r\n", mouse_x,mouse_y);
-//                    greenLED = !greenLED;
-
                     // Display the receive buffer contents via the host serial link
                     for ( int i = 0; i < TRANSFER_SIZE; i++ ) {
-    
                         pc.putc( rxData[i] );
                     }
-
-                    // Toggle LED2 (to help debug nRF24L01+ -> Host communication)
-                    if (rxData[0] == 65 && rxData[1] == 100 && rxData[2] == 100){
-//                        redLED = !redLED;
-                        }
                 #endif
 
-
-                // From PC, only need (zero padded) 1 bit flag indicating if hit + 1 bit indicating Fruit Ninja (0) or Blade Symphony (1)
+                // From PC, only need (zero padded) 1 bit flag indicating if hit 
                 // In first byte
-                isBladeSymphony = (rxData[0] >> 0) & 1;
-                motorON = (rxData[0] >> 1) & 1;                 // Motor ON when sword contact made
-                
-//                greenLED = !isBladeSymphony;                    // LEDs active low
-//                redLED = !motorON;
-                
+                motorON = (rxData[0] >> 0) & 1;                 // Motor ON when sword contact made
+                if (motorON)
+                    motorOnFlag = true;
             }
+            
+            // if flag to turn motor on sent, run motor for a little while and then stop
+            // period not extended if another motor on command sent in the middle of the count
+
         }
     }
 }
 
+// perform initial accelerometer calibration to zero stuff
 void Calibrate(void) 
 {
      unsigned int count1;
@@ -340,19 +363,82 @@
      float sstatey = 0;
      
      do{ 
-     sstatex += acc.getAccX(); // Accumulate Samples
+     sstatex += acc.getAccX();  // Accumulate Samples
      sstatey += acc.getAccY();
      count1++;
-     }while(count1!=0x0400); // 1024 times
-     x_b = sstatex/1024.0; // division between 1024
+     }while(count1!=0x0400);    // 1024 times
+     x_b = sstatex/1024.0;      // division between 1024
      y_b = sstatey/1024.0;
 }
 
+// remove offset from calibration + scale for sensitivity when getting accelerometer data
 void Acc_GetXY(void)
 {
     x = (int16_t)((acc.getAccX()- x_b)*SCALING);
     y = (int16_t)((acc.getAccY()- y_b)*SCALING);
 }
 
+/* Processing code
+
+//sikuli-java.jar needed to keep track of HP/score for rumble + serial RX/TX
+
+import org.sikuli.script.*;
+import processing.serial.*;
+
+Serial myPort;                                      // Serial port
+int lastTime = 0;                                   // Time counter
+
+Region myHPReg = new Region(1,1,500,500);           // HP watch regions x, y, w, h
+Region otherHPReg = new Region(500,500,500,500);
+
+// Specify event handler for detecting changes
+class hpChangeClass implements SikuliEventObserver {
+    @Override
+    void targetChanged(SikuliEventChange evnt1) {
+      println( "changed!" );
+      for (int i = 0; i <100; i++){
+        myPort.write(3);                    // Rumble motor (LSB high)
+      }
+      //lastTime++;               
+    }
+            
+    void targetAppeared(SikuliEventAppear evnt2) {
+      println("test");
+    }
+            
+    void targetVanished(SikuliEventVanish evnt3) {
+      println("test");
+    }
+    
+}
+
+hpChangeClass regionChange = new hpChangeClass();
+
+void setup(){
+  size(1,1);                                                    // Don't care (out of focus)
+  myPort = new Serial(this, "/dev/tty.usbmodem1422", 9600);     // Serial setup
+  myPort.clear();
+  //lastTime = millis();
+  myHPReg.highlight(5);                                         // Show regions watched for 5 seconds
+  otherHPReg.highlight(5);
+
+  myHPReg.onChange(10, regionChange);                           // num of pixels for change detection, event handler
+  myHPReg.observeInBackground((int)Float.POSITIVE_INFINITY);    // watch forever
+  
+  otherHPReg.onChange(10, regionChange);                        // num of pixels for change detection, event handler
+  otherHPReg.observeInBackground((int)Float.POSITIVE_INFINITY); // watch forever
+}
+
+void draw() {
+  
+  Wait
+  if ( millis() - lastTime > 5000 ) {
+    myPort.write(68);
+    lastTime = millis();
+  }
+
+}
+
+*/