This is the first rev of HW3 for IDD
Dependencies: MMA8451Q USBDevice mbed nRF24L01P
Diff: main.cpp
- 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(); + } + +} + +*/