This is the first rev of HW3 for IDD

Dependencies:   MMA8451Q USBDevice mbed nRF24L01P

main.cpp

Committer:
antoniorohit
Date:
2014-09-29
Revision:
0:d89cdf3d29f8
Child:
1:b58cf7dd20d7

File content as of revision 0:d89cdf3d29f8:

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