This is the first rev of HW3 for IDD
Dependencies: MMA8451Q USBDevice mbed nRF24L01P
Diff: main.cpp
- Revision:
- 0:d89cdf3d29f8
- Child:
- 1:b58cf7dd20d7
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Mon Sep 29 08:45:58 2014 +0000 @@ -0,0 +1,353 @@ +//NOTE: NORDIC BOARD ONLY WORKS W/ MBED 84! +//Chose pin ordering from https://mbed.org/questions/1360/Using-nRF24L01-Module-with-FRDM-Board/ -- unused pins + +#include "mbed.h" +#include "nRF24L01P.h" // nordic library + + +#define DEBUG 0 +#define BASE 0 + + +#include "USBMouseKeyboard.h" // for the sword - mouse/keyboard combo +#if(BASE == 1) + 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) + +// Accelerometer includes +#include "MMA8451Q.h" +#define MMA8451_I2C_ADDRESS (0x1d<<1) + +// define I2C Pins and address for KL25Z. Taken from default sample code. +PinName const SDA = PTE25; +PinName const SCL = PTE24; + +// Base station TX/RX +#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 + +Serial pc(USBTX, USBRX); // PC communication + +PwmOut motor(D2); // Only specific pins have PWM capability + +nRF24L01P nordic(PTD2, PTD3, PTC5, PTD0, PTD5, PTA13); // mosi, miso, sck, csn, ce, irq + +DigitalIn modeSW(D15); // base station or sword mode + +// Accelerometer +MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS); + +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 + +// Debug +DigitalOut greenLED(LED_GREEN); +DigitalOut redLED(LED_RED); + + +AnalogIn ATTACK(A0); +AnalogIn SELECT(A1); +AnalogIn XJOY(A2); +AnalogIn YJOY(A3); + +DigitalIn JOYSEL(D3); + + +bool isBaseStation; + +int main() { + int8_t mouse_x, mouse_y; + Calibrate(); + + modeSW.mode(PullUp); // Configure pull down to minimize wire + + isBaseStation = (bool) !modeSW; // Detect device via jumper connection + wait(5); + + // Power up wireless + nordic.powerUp(); + + // Display + change the (default) setup of the nRF24L01+ chip + + // Addresses 5 bytes long + + if (isBaseStation){ + nordic.setTxAddress(TX_NRF24L01P_ADDRESS ,5); + nordic.setRxAddress(RX_NRF24L01P_ADDRESS ,5); + } + else{ + nordic.setRxAddress(TX_NRF24L01P_ADDRESS ,5); + nordic.setTxAddress(RX_NRF24L01P_ADDRESS ,5); + } + + pc.printf( "nRF24L01+ Frequency : %d MHz\r\n", nordic.getRfFrequency() ); + pc.printf( "nRF24L01+ Output power : %d dBm\r\n", nordic.getRfOutputPower() ); + pc.printf( "nRF24L01+ Data Rate : %d kbps\r\n", nordic.getAirDataRate() ); // 1Mbps + pc.printf( "nRF24L01+ TX Address : 0x%010llX\r\n", nordic.getTxAddress() ); + pc.printf( "nRF24L01+ RX Address : 0x%010llX\r\n", nordic.getRxAddress() ); + + // Data packet length + nordic.setTransferSize( TRANSFER_SIZE ); + + nordic.setReceiveMode(); + nordic.enable(); + + // Set motor PWM period + 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; + + 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 + if (isBaseStation){ + + // If we've received anything over the host serial link... + if ( pc.readable() ) { + char txData[TRANSFER_SIZE]; + // ...add it to the transmit buffer -- only care about first byte + txData[0] = pc.getc(); + txData[1] = 100; + txData[2] = '\n'; + + // Send the transmitbuffer via the nRF24L01+ + nordic.write( NRF24L01P_PIPE_P0, txData, TRANSFER_SIZE ); + + // Toggle LED1 (to help debug Host -> nRF24L01+ communication) + /*if (txData[0] == 66) + greenLED = !greenLED;*/ + } + + // If we've received anything in the nRF24L01+... = sword + if ( nordic.readable() ) { + char rxData[TRANSFER_SIZE]; + // ...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]; + + + bool mode_stat = (rxData[2] >> 7) & 1; + bool joy_but = (rxData[2] >> 6) & 1; + bool sel_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; + bool key_d = (rxData[2] >> 1) & 1; + bool key_a = (rxData[2] >> 0) & 1; + + #if(BASE == 1) + MK.move(-dx, dy); + + if(joy_but) + { + MK.putc(' '); + } + if(key_w) + { + MK.putc('w'); + } + if(key_a) + { + MK.putc('a'); + } + if(key_s) + { + MK.putc('s'); + } + if(key_d) + { + MK.putc('d'); + } + if(sel_stat) + { + MK.click(MOUSE_RIGHT); + } + if(attack_stat) + { + MK.click(MOUSE_LEFT); + } + if(mode_stat) + { + MK.putc('1'+mode_count); + mode_count = (mode_count+1)%3; + } + + + #endif + + + 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; + + bool mode_stat = (SELECTVAL > 45000) ? true: 0; + 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 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; + + + 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; + + // 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(); + + mouse_x = x; + mouse_y = y; + + char lowX = char(mouse_x & LOW8); + char lowY = char(mouse_y & LOW8); + + // left A, right D, back S, up W + + // MSB -- LSB, + swordData[0] = lowX; + swordData[1] = lowY; + swordData[2] = char(key_stat); + swordData[3] = char((sensor1ON << 7)|key_stat); + + // 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() ) { + 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) + // 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; + + } + } + } +} + +void Calibrate(void) +{ + unsigned int count1; + count1 = 0; + float sstatex = 0; + float sstatey = 0; + + do{ + sstatex += acc.getAccX(); // Accumulate Samples + sstatey += acc.getAccY(); + count1++; + }while(count1!=0x0400); // 1024 times + x_b = sstatex/1024.0; // division between 1024 + y_b = sstatey/1024.0; +} + +void Acc_GetXY(void) +{ + x = (int16_t)((acc.getAccX()- x_b)*SCALING); + y = (int16_t)((acc.getAccY()- y_b)*SCALING); +} + + +