Part 1 + 3

Dependencies:   Joystick_skeleton_Pengineers mbed

Fork of ESE519_Lab6_part1_skeleton by Carter Sharer

main.cpp

Committer:
csharer
Date:
2016-10-20
Revision:
0:0ebe6f55caee
Child:
1:98c414bbfe8a

File content as of revision 0:0ebe6f55caee:

//ESE519 Lab6 Controller Part 1 (FULL IMPLIMENTATION)
//Author: Carter Sharer
//Date: 10/18/2016
//Sources: ESE350 Whack-A-Mole: https://developer.mbed.org/users/mlab4/code/ESE350-Whack-a-Mole/
//This is a simple working templete for sending and receving between two MRF24J40 Modules
//Contains a communication protocol for sending a receiving 

#include "mbed.h"
#include "MRF24J40.h"
#include <string>
#include "Joystick.h"

#define SEND        //Uncomment if you want to transmit data
//#define RECEIVE     //Uncomment if you want to receive data

#define NONE 250

//============================
//==    Pin Assignments     ==
//============================
//Knobs
#define POT1 p17  //Knob1
#define POT2 p18  //Knob2
#define POT3 p16  //Knob3
#define POT4 p15  //Knob4
//JoyStick
#define POTV p19 //Vertial
#define POTH p20 //Horizontal
//MRF24J
#define SDI p11
#define SDO p12
#define SCK p13
#define CS p7
#define RESET p8
//Button
#define BUTTON1 p21
#define COMMUNICATION_FORMAT "Jstick_h: %0.0f Jstick_v: %0.0f Knob1 %0.2f Knob2 %0.2f Knob3 %0.2f Knob4 %0.2f Button: %d"

//============================
//==        Objects         ==
//============================
//Knobs
AnalogIn pot1(POT1);
AnalogIn pot2(POT2);
AnalogIn pot3(POT3);
AnalogIn pot4(POT4);
float knob1, knob2, knob3, knob4;

//Joystick
Joystick jstick(POTV, POTH);
float jstick_h, jstick_v;


//MRF24J40
PinName mosi(SDI);
PinName miso(SDO);
PinName sck(SCK);
PinName cs(CS);
PinName reset(RESET);
// RF tranceiver
MRF24J40 mrf(mosi, miso, sck, cs, reset);

//Button
DigitalIn Button(BUTTON1);
bool button;

// LEDs
DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

// Timer
Timer timer;

// Serial port for showing RX data.
Serial pc(USBTX, USBRX);


// Send / receive buffers.
// IMPORTANT: The MRF24J40 is intended as zigbee tranceiver; it tends
// to reject data that doesn't have the right header. So the first
// 8 bytes in txBuffer look like a valid header. The remaining 120
// bytes can be used for anything you like.
char txBuffer[128];
char rxBuffer[128];
int rxLen;

//***************** Do not change these methods (please) *****************//
/**
* Receive data from the MRF24J40.
*
* @param data A pointer to a char array to hold the data
* @param maxLength The max amount of data to read.
*/
int rf_receive(char *data, uint8_t maxLength)
{
    uint8_t len = mrf.Receive((uint8_t *)data, maxLength);
    uint8_t header[8]= {1, 8, 0, 0xA1, 0xB2, 0xC3, 0xD4, 0x00};

    if(len > 10) {
        //Remove the header and footer of the message
        for(uint8_t i = 0; i < len-2; i++) {
            if(i<8) {
                //Make sure our header is valid first
                if(data[i] != header[i])
                    return 0;
            } else {
                data[i-8] = data[i];
            }
        }
        //pc.printf("Received: %s length:%d\r\n", data, ((int)len)-10);
    }
    return ((int)len)-10;
}

/**
* Send data to another MRF24J40.
*
* @param data The string to send
* @param maxLength The length of the data to send.
*                  If you are sending a null-terminated string you can pass strlen(data)+1
*/
void rf_send(char *data, uint8_t len)
{
    //We need to prepend the message with a valid ZigBee header
    uint8_t header[8]= {1, 8, 0, 0xA1, 0xB2, 0xC3, 0xD4, 0x00};
    uint8_t *send_buf = (uint8_t *) malloc( sizeof(uint8_t) * (len+8) );

    for(uint8_t i = 0; i < len+8; i++) {
        //prepend the 8-byte header
        send_buf[i] = (i<8) ? header[i] : data[i-8];
    }
    //pc.printf("Sent: %s\r\n", send_buf+8);

    mrf.Send(send_buf, len+8);
    free(send_buf);
}
//***************** You can start coding here *****************//

//Returns true if c is a letter, false otherwise
bool isLetter(char c) {
    if(('a'<=c & c<='z') | ('A'<=c & c<='Z'))
        return true;
    return false;
}

//Returns true if c is a number, false otherwise
bool isNumber(char c) {
    if('0'<=c & c<='9')
        return true;
    return false;
}

//Pulls data out of rxBuffer and updates global variables accordingly 
void communication_protocal(int len)
{
    bool found_name = false;
    bool found_num = false;
    bool complete_name = false;
    bool complete_num = false;
    uint8_t name_start = NONE; uint8_t name_end = NONE;
    uint8_t num_start = NONE; uint8_t num_end = NONE;
    
    //Loop through all charaters in rxBuffer
    for(uint8_t i = 0; i <= rxLen; i++) {
        char c = rxBuffer[i];
        //pc.printf("Indexed char '%c'\r\n", c);

        //Is is the start of a name? (Check if its a letter)
        if(isLetter(c) & name_start==NONE) { //if a num
            //If We havent found a name yet, this is start of a name
            if(found_name == false) {
                //pc.printf("found name start at: '%c'\r\n", c);
                name_start = i;
                found_name = true;
            }
        }
        //Is is a 'end of name' charater? Check for ' ', ':', '-'
        else if(((c == ' ') | (c == ':') | (c == '-')) & found_name & !complete_name) {// found end name character
            if(found_name) {
                complete_name = true;
                name_end = i;
                //pc.printf("found end of name at: '%c'\r\n", txBuffer[name_end]);
            }
        }

        //Is it a 'start of a number' charater? Check if its a number, or '-', or a '.'
        else if( (isNumber(c) | (c=='-') | (c=='.')) & complete_name & num_start==NONE) {
            if(found_num == false) {
                //pc.printf("found num start at: '%c'\r\n",c);
                num_start = i;
                found_num = true;
            }
        }
        //Is it a 'end of number' character? Check if its a ' ', ':', '-', or a letter
        else if( (((c==' ')|(c==':')|(c=='-')) | isLetter(c)) & found_num & complete_name) {
            if(found_num) {
                complete_num = true;
                num_end = i;
                //pc.printf("found end of num at: '%c' \r\n", txBuffer[num_end]);
            }
        }
        
        //If we have a complete name AND number value (ie. start and end of each != NONE)
        if(found_name & found_num & complete_name & complete_num) {
            //pc.printf("Found MATCH\r\n");
            //Reset flags
            found_name = false;
            found_num = false;
            complete_name = false;
            complete_num = false;
            
            //Set name
            uint8_t nameLen = uint8_t((name_end-name_start) + 1);
            char * name[nameLen];
            *name = &rxBuffer[name_start];
            rxBuffer[name_end] = '\0';
            
            //Set num
            uint8_t numLen = uint8_t((num_end-num_start) + 1);
            char * num[numLen];
            *num = &rxBuffer[num_start];
            rxBuffer[num_end] = '\0';
            
            //Set variables
            if(strcmp(*name, "Jstick_h\0")==0)
                jstick_h = atof(*num);
            else if(strcmp(*name, "Jstick_v\0")==0) 
                jstick_v = atof(*num);
            else if(strcmp(*name, "Knob1\0")==0) 
                knob1 = atof(*num);
            else if(strcmp(*name, "Knob2\0")==0) 
                knob2 = atof(*num);
            else if(strcmp(*name, "Knob3\0")==0)
                knob3 = atof(*num);
            else if(strcmp(*name, "Knob4\0")==0) 
                knob4 = atof(*num);
            else if(strcmp(*name, "Button\0")==0) 
                button = atof(*num);
            
            //Reset flags
            name_start = NONE;
            name_end = NONE;
            num_start = NONE;
            num_end = NONE;
        }
    }
}

int main (void)
{
    //Set the Channel. 0 is default, 15 is max
    uint8_t channel = 2;
    mrf.SetChannel(channel);

    //Set Baud rate (9600-115200 is ideal)
    pc.baud(115200);
    pc.printf("\r\n Start! \r\n");

    //Start Timer
    timer.start();

    //Scale Joystick Values
    jstick.setScale(-50, 25);

    while(1) {
        //(1) Read Joystick Values, round to int8_t presision
        jstick_h = (int8_t)jstick.horizontal();
        jstick_v = (int8_t)jstick.vertical();
        //pc.printf("H: %d V:%d \r\n", jstick_h, jstick_v);

        //(2) Read Pot Values, Scale, and round to precision
        knob1 = (uint8_t)(pot1.read() * 100); //rounded to uint8_t
        knob2 = (pot2.read() * 100);
        knob3 = (pot3.read());
        knob4 = (int)(pot4.read() * 100);  //rounded to float

        //(3)Read Button Val, Add to buffer
        button = !Button.read(); //button is active low

#ifdef RECEIVE
        //RECEIVE DATA: Try to receive some data
        rxLen = rf_receive(rxBuffer, 128);
        if(rxLen > 0) {
            //Toggle the Led
            led1 = led1^1;
           
            //(4) Process data with our protocal 
            communication_protocal(rxLen);
            
            //Print values once we recieve and process data
            pc.printf(COMMUNICATION_FORMAT, jstick_h, jstick_v, knob1, knob2, knob3, knob4, button);
            pc.printf("\r\n");
        }//main if
#endif

#ifdef SEND    
        //SEND DATA: Send some data every 1/2 second
        if(timer.read_ms() >= 500) {
            //Reset the timer to 0
            timer.reset();
            // Toggle LED 2.
            led2 = led2^1;

            //(5) Add all values to buffer to be sent
            sprintf(txBuffer, COMMUNICATION_FORMAT, jstick_h, jstick_v, knob1, knob2, knob3, knob4, button);
    
            //(6) Send the buffer
            rf_send(txBuffer, strlen(txBuffer) + 1);
            pc.printf("%s\r\n", txBuffer);
        }   
#endif

    } //end loop
}//end main