Skip to main content
Rollback to Revision 2
Source Link
Juraj
  • 18.3k
  • 4
  • 32
  • 50

I'm fairly new to this, and I haven't been able to find any answers after searching repeatedly.

I have a Startscreen() function that I run during my setup sequence, and within that function i use various while loops and if/else conditionals. This function runs the startup screen of my program on my touch screen.

Well, when certain conditions are met inside a switch case, inside a while loop, I want to load my main screen and then immediately stop the whole Startscreen() function, like this:

LoadMainScreen();
return;

However, I end up seeing my main screen load up, and then my Startscreen() function continues!

Apparently, "return;" does not work as advertised. If I wanted to break out of the current loop, I'd use "break;", right?

So my question is, does it matter that I'm using return; inside a while loop, inside a switch case? How do I exit the whole top-level function completely?

I already tried breaking out of the function and going straight to my main loop this way:

LoadMeasScrn();
loop();
return;

and the same thing happens.

So here's (most Here's a bit of) my entire code pseudocode that will hopefully show how I have things organized:

//////////REMOVED/////////THANKSvoid FORsetup(){
Startscreen(); YOUR ANSWERS///////this screen provides user options
}

void loop(){
do all the other main functions of the program;
}

void Startscreen(){

if this thing, show this
if that thing, show that
take readings
switch(reading){
case(number):
    while(1){
        check for button presses
        if (this){
             if (that){
                    LoadMainScreen();
                     return;         //this is supposed to quit the startscreen function completely and allow the program to move on to the main loop
case(other number);
    do other stuff
    break;
 } //end of case stuff
Do other stuff that the startscreen program may need to do  //this is what I'm seeing after calling return. should not see happening

I'm fairly new to this, and I haven't been able to find any answers after searching repeatedly.

I have a Startscreen() function that I run during my setup sequence, and within that function i use various while loops and if/else conditionals. This function runs the startup screen of my program on my touch screen.

Well, when certain conditions are met inside a switch case, inside a while loop, I want to load my main screen and then immediately stop the whole Startscreen() function, like this:

LoadMainScreen();
return;

However, I end up seeing my main screen load up, and then my Startscreen() function continues!

Apparently, "return;" does not work as advertised. If I wanted to break out of the current loop, I'd use "break;", right?

So my question is, does it matter that I'm using return; inside a while loop, inside a switch case? How do I exit the whole top-level function completely?

I already tried breaking out of the function and going straight to my main loop this way:

LoadMeasScrn();
loop();
return;

and the same thing happens.

So here's (most of) my entire code:

//////////REMOVED/////////THANKS FOR YOUR ANSWERS/////////////

I'm fairly new to this, and I haven't been able to find any answers after searching repeatedly.

I have a Startscreen() function that I run during my setup sequence, and within that function i use various while loops and if/else conditionals. This function runs the startup screen of my program on my touch screen.

Well, when certain conditions are met inside a switch case, inside a while loop, I want to load my main screen and then immediately stop the whole Startscreen() function, like this:

LoadMainScreen();
return;

However, I end up seeing my main screen load up, and then my Startscreen() function continues!

Apparently, "return;" does not work as advertised. If I wanted to break out of the current loop, I'd use "break;", right?

So my question is, does it matter that I'm using return; inside a while loop, inside a switch case? How do I exit the whole top-level function completely?

I already tried breaking out of the function and going straight to my main loop this way:

LoadMeasScrn();
loop();
return;

and the same thing happens. Here's a bit of pseudocode that will hopefully show how I have things organized:

void setup(){
Startscreen();  //this screen provides user options
}

void loop(){
do all the other main functions of the program;
}

void Startscreen(){

if this thing, show this
if that thing, show that
take readings
switch(reading){
case(number):
    while(1){
        check for button presses
        if (this){
             if (that){
                    LoadMainScreen();
                     return;         //this is supposed to quit the startscreen function completely and allow the program to move on to the main loop
case(other number);
    do other stuff
    break;
 } //end of case stuff
Do other stuff that the startscreen program may need to do  //this is what I'm seeing after calling return. should not see happening
deleted 27907 characters in body
Source Link
///////THIS VERSION IS DEVELOPED FOR THE AT MEGA 

#include <stdint.h>//For Seedstudio Touch
#include <TFTv2.h>//For Seedstudio Touch
#include <SPI.h>
#include <SeeedTouchScreen.h>   //Seedstudio LCD touch screen Library File
#include <SD.h>//For Seedstudio Touch
#include <XBee.h>   //Zigbee Wireless transciever Library File
#include <Printers.h>   //Zigbee Wireless transciever Library File

#define MAX_BMP         10         // bmp file num  //////////////////////////////Seedstudio Touchscreen///////////////////////Seedstudio Touchscreen///////////////////////Seedstudio Touchscreen////
#define FILENAME_LEN    20         // max file name length
const int PIN_SD_CS = 4;         // pin of sd card
const int __Gnbmp_height = 320;    // bmp hight
const int __Gnbmp_width = 240;      // bmp width
unsigned char __Gnbmp_image_offset = 0;   // offset
int __Gnfile_num = 5;             // num of files (change num)
char __Gsbmp_files[5][FILENAME_LEN] = { "boeblue.bmp", "boeblue2.bmp", "787dl.bmp", "Measure3.bmp", "Measure5.bmp" }; // add file name(s) here (change num)//////  The files are zero-indexed into an array
File bmpFile;

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) // mega
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 54   // can be a digital pin, this is A0
#define XP 57   // can be a digital pin, this is A3 
#elif defined(__AVR_ATmega32U4__) // leonardo
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 18   // can be a digital pin, this is A0
#define XP 21   // can be a digital pin, this is A3 
#else //168, 328, something else
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 14   // can be a digital pin, this is A0
#define XP 17   // can be a digital pin, this is A3 
#endif

#ifdef SEEEDUINO
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 14   // can be a digital pin, this is A0
#define XP 17   // can be a digital pin, this is A3 
#endif

#ifdef MEGA
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 54   // can be a digital pin, this is A0
#define XP 57   // can be a digital pin, this is A3 
#endif 

#define TS_MINX 116*2
#define TS_MAXX 890*2
#define TS_MINY 83*2
#define TS_MAXY 913*2
// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// The 2.8" TFT Touch shield has 300 ohms across the X plate
#define BUFFPIXEL       60                    // must be a divisor of 240 
#define BUFFPIXEL_X3    180                // BUFFPIXELx3
TouchScreen ts = TouchScreen(XP, YP, XM, YM); //////////////////////////////Seedstudio Touchscreen///////////////////////Seedstudio Touchscreen///////////////////////Seedstudio Touchscreen////

XBee xbee = XBee();
XBeeResponse response = XBeeResponse();
// create reusable response objects for responses we expect to handle 
Rx16Response rx16 = Rx16Response();
Rx64Response rx64 = Rx64Response();

uint8_t option[] = { 'D', '3' };
uint8_t high[] = { 0x05 };
uint8_t low[] = { 0x04 };
XBeeAddress64 remoteAddress = XBeeAddress64(0x0013a200, 0x0000FFFF); //  SH + SL of the remote radio  //THE HI / LOW ADDRESSES ARE THE 64 BIT ADDRESSES IN HEX OF THE SPECIFIC RADIO THAT IS TO BE COMMANDED.. OR USE 0x0000FFFF AS A BROADCAST ADDRESS
// Create a remote AT request with the IR command
RemoteAtCommandRequest remoteAtRequestD3High = RemoteAtCommandRequest(remoteAddress, option, high, sizeof(high));
RemoteAtCommandRequest remoteAtRequestD3Low = RemoteAtCommandRequest(remoteAddress, option, low, sizeof(low));
// Create a Remote AT response object
RemoteAtCommandResponse remoteAtResponse = RemoteAtCommandResponse();

uint8_t SlpCmd[] = { 0x26 };  //byte '&' used for remote sleep command
Tx64Request txSleepCmd = Tx64Request(remoteAddress, SlpCmd, sizeof(SlpCmd));  //object for transmit request

uint8_t AdptCmd[] = { 0x25 };  //byte '%' used for Auto Adapt command
Tx64Request txAdptCmd = Tx64Request(remoteAddress, AdptCmd, sizeof(AdptCmd));  //object for transmit request

uint8_t InCmd[] = { 0x49 };  //byte 'I' used for Inch units command
Tx64Request txInCmd = Tx64Request(remoteAddress, InCmd, sizeof(InCmd));  //object for transmit request

uint8_t HashCmd[] = { 0x48 };  //byte 'H' used for hashmark units command
Tx64Request txHashCmd = Tx64Request(remoteAddress, HashCmd, sizeof(HashCmd));  //object for transmit request

uint8_t Capt[] = { 0x7c };  //byte '|' used for captive command
Tx64Request txCapt = Tx64Request(remoteAddress, Capt, sizeof(Capt));  //object for transmit request

uint8_t Cancl[] = { 0x43 };  //byte 'C' used for cancel captive command
Tx64Request txCancl = Tx64Request(remoteAddress, Cancl, sizeof(Cancl));  //object for transmit request

TxStatusResponse txStatus = TxStatusResponse();

char stringval[6];  //buffers for individual measurement values
char laststringval[6] = {};
char stringvalin[7];
char laststringvalin[7] = {};
int outFormat;
int dotpos;
int lastdot = 0;
byte errcode;

const int bufsize = 14;
char Payload[bufsize] = {};   //recieved string
int L; //data length 

unsigned long t1 = 0;
unsigned long t2 = 0;
const int D = 22;// Standard delay to allow for next frame to come in


int greenled = 11;
int redled = 12;
int blueled = 13;  ////Analog pins for RGB LED control


bool startFresh = true;
int frametype;
const int scantime = 20000;  ////time alloted in ms for initial scan for IR cam
int E = 0;  //no frame found counter
int Er = 0;  //frame Rx error counter
bool MeasRx = false;


void setup()
{
    pinMode(redled, OUTPUT);
    pinMode(greenled, OUTPUT);
    pinMode(blueled, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, OUTPUT);
    pinMode(7, OUTPUT);

    Serial.begin(57600);
    xbee.setSerial(Serial);

    pinMode(PIN_SD_CS, OUTPUT);
    digitalWrite(PIN_SD_CS, HIGH);
    Sd2Card card;
    card.init(SPI_FULL_SPEED, PIN_SD_CS);
    Tft.TFTinit();  // init TFT library
    Tft.setDisplayDirect(DOWN2UP);
    if (!SD.begin(PIN_SD_CS))
    {
        Serial.println("SD failed!");
        while (1);                               // init fail, die here
    }
    Serial.println("SD ok!");
    for (int f = 0; f < 5; f++) {   //odd problem fix- queries touchscreen 5 times to clear any erronious values. This prevents problem where the first point retrieved is sometimes invalid 
        Point p = ts.getPoint();
        delay(20);
    }
    digitalWrite(7, HIGH); //  ( TFT_BL_ON; ) //these functions exist in TFTv2.h, but are bypassed here because of compiler issues with recognizing the Arduino101 board definition. 
    if (startFresh) { StartScreen(); }
}

void loop()    //////////////////////////////////////////MAIN SEQUENCE////////////////////////////////////////////////////////////////
{

    RxPacket();
    RxCheck();
    Parse();
    Readout();
    //ButtonStuff();
}

///////////////////////////////////////////SUBROUTINES////////////////////////////////////////////////////////////////////////

void StartScreen(void) {

    if (startFresh == true) {
        loadSplash();
        burnSerial();
        Tft.drawString("Scanning...", 125, 300, 3, WHITE);
        t1 = millis(); t2 = millis();
        while (t2 - t1 < scantime) {// Scans for packets for scantime or until a good packet is received
            RxPacket();
            if (frametype == 81 || frametype == 83) {
                break;  //Stop if either sleep or measurement frame is found
            }
            t2 = millis();
        }
    }


     
    if (frametype == 0 || frametype == -1) {  // Scan returned no sleep or measurement frames within scan time. If frametype is now 0 or -1, it would have been set in the last, most recent iteration of RxPacket
        Tft.fillRectangle(117, 319, 55, 320, RED);
        Tft.drawString("No device found. ", 135, 283, 2, WHITE);
        Tft.fillRectangle(170, 319, 75, 320, GRAY2);
        delay(375);
        Tft.drawRectangle(182, 105, 40, 120, YELLOW);
        Tft.drawString("Rescan? ", 195, 220, 2, WHITE);
        while (1) {
            delay(D);
            Point p = ts.getPoint(); //Monitor buttons
            p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);  //Monitor buttons
            p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320);  //Monitor buttons
            if (p.x > 155 && p.x < 219 && p.y > 55 && p.y < 225) {   //// Choose to rescan (only other option is to turn the unit off and try again later)
                Tft.drawRectangle(182, 105, 40, 120, MAGENTA);
                delay(375);
                startFresh = true;
                StartScreen();
            }
        }
    }
    switch (frametype) {
    case (81) : //measurement frame detected. System found measuring //////////////////////////////////////////measurement frame detected. System found measuring
        WakePinReset();
        Tft.fillRectangle(117, 319, 70, 320, DARK_GREEN);
        Tft.drawString("Rudder Cam Detected", 132, 310, 2, WHITE);
        Tft.drawString("Status:", 160, 310, 2, WHITE);
        Tft.drawString("Sleep Mode", 160, 173, 2, DARK_GREEN);
        Tft.drawString("Measuring", 160, 168, 2, WHITE);
        Tft.fillRectangle(185, 319, 55, 320, GRAY2);
        Tft.drawString(" Measure     Sleep", 200, 315, 2, WHITE);
        Tft.drawRectangle(192, 182, 30, 125, YELLOW);
        Tft.drawRectangle(192, 18, 30, 100, YELLOW);
        t1 = millis();  t2 = millis();
        while (1) {
            t2 = millis();
            if (t2 - t1 > 5000) { Recheckframe(); } //scan again every 5 seconds in case status has changed
            Point p = ts.getPoint();   //Monitor buttons
            p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);
            p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320);
            if (p.x > 185 && p.x < 220 && p.y > 1 && p.y < 125) {     //// Choose to sleep //do stuff to sleep   //// Choose to sleep //do stuff to sleep   //// Choose to sleep //do stuff to sleep
                Tft.drawRectangle(192, 18, 30, 100, MAGENTA);
                delay(375);
                Tft.fillRectangle(185, 319, 55, 320, GRAY2);
                Tft.drawString(" IR Cam Power Save", 200, 315, 2, WHITE);
                delay(375);
                if (Captivate()) { //this sequence calls captive, then sends sleep command. if either function returns false, noresponse() makes an alert and starts the scan over
                    if (SendSlpCmd()) { 
                        startFresh = true; 
                        StartScreen(); 
                    }
                    else {noresponse();}
                }
                else {noresponse();}
            }
            if (p.x > 185 && p.x < 220 && p.y > 165 && p.y < 320) {   //// Choose to measure //do stuff to measure   //// Choose to measure //do stuff to measure   //// Choose to measure //do stuff to measure
                Tft.drawRectangle(192, 182, 30, 125, MAGENTA);
                delay(375);   
                p.x = 0;  //set arbitrary value so sleep screen is not possible (odd problem fix)
                LoadMeasScrn();
                loop();
                return;
            }
        }
        break;  //81 case done
    case (83) : //Sleep frame detected; system found sleeping //Sleep frame detected; system found sleeping////////////////////Sleep frame detected; system found sleeping
        Tft.fillRectangle(117, 319, 70, 320, GRAY2);
        Tft.drawString("Rudder Cam Detected", 132, 310, 2, WHITE);
        Tft.drawString("Status:", 160, 310, 2, WHITE);
        Tft.drawString("Measuring", 160, 168, 2, GRAY2);
        Tft.drawString("Sleep Mode", 160, 173, 2, WHITE);
        Tft.fillRectangle(185, 319, 55, 320, GRAY2);
        Tft.drawString(" Measure     Sleep", 200, 315, 2, WHITE);
        Tft.drawRectangle(192, 182, 30, 125, YELLOW);
        t1 = millis();
        t2 = millis();
        while (1) {
            t2 = millis();
            if (t2 - t1 > 5000) {//scan again every 5 seconds in case status has changed
                Recheckframe();
            }
            Point p = ts.getPoint();   //Monitor buttons
            p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);
            p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320);
            if (p.x > 185 && p.x < 220 && p.y > 165 && p.y < 320) {   //// Choose to measure //do stuff to measure   //// Choose to measure //do stuff to measure   //// Choose to measure //do stuff to measure
                Tft.drawRectangle(192, 182, 30, 125, MAGENTA);
                delay(375);
                p.x = 0;  //set arbitrary value so sleep screen is not possible (odd problem fix)
                Tft.fillRectangle(185, 319, 55, 320, GRAY2);
                Tft.drawString(" Waking Rudder Cam", 200, 315, 2, WHITE);
                delay(375);
                WakePin();
                delay(2000);
                if (ListenForChar('O')) { //Listen for confirmation that the main unit woke from sleep
                    LoadMeasScrn();
                    loop();
                    return;
                }
                else { noresponse(); }
            }
        }
    } 
}

void LoadMeasScrn() {
    bmpFile = SD.open(__Gsbmp_files[3]);      ///////////////////////////THIS SELECTS THE .bmp FILE TO OPEN. CHANGE THE INDEX NUMBER.
    if (!bmpFile) { Serial.println("didnt find image"); while (1); }   ////This loads the measurement screen/////////
    if (!bmpReadHeader(bmpFile)) { Serial.println("bad bmp"); return; } ////This loads the measurement screen/////////
    bmpdraw(bmpFile, 0, 0); ////This loads the measurement screen/////////
    bmpFile.close(); ////This loads the measurement screen/////////
}

bool Recheckframe(void) {//For use in start screen, function rechecks frame type. Returns true if frametype has switched from sleep to meas or vice versa
    int lastframetype = frametype;  //remember frametype when stepping into this function
    Tft.drawRectangle(192, 182, 30, 125, GRAY2);
    Tft.drawRectangle(192, 18, 30, 100, GRAY2); //gray out buttons for a sec while rescanning
    t1 = millis(); t2 = millis();
    while (t2 - t1 < 100) {  //read packets for 100ms and look change in frametype
        t2 = millis();
        RxPacket();
        delay(D); //slow it down for new frames to come in- rxpacket returns 0 frametype if no new frame is found
        if (lastframetype == 81 && frametype == 83) {  //went to sleep //indicates change in sleep/meas state, ignoring errors and nonconforming frames
            startFresh = false;  //do not re-run scan, just change frametype.
            StartScreen();
            break;
        }
        if (lastframetype == 83 && frametype == 81) {  //woke up //indicates change in sleep/meas state, ignoring errors and nonconforming frames
            startFresh = false;  //do not re-run scan, just change frametype.
            StartScreen();
            break;
        }
        if (E >= 20 || Er >= 20) {  //have recieved 20 bad frames without a good frame. Signal must be lost
        Tft.fillRectangle(185, 319, 55, 320, GRAY2);
        Tft.drawString("Signal Lost", 200, 315, 2, WHITE);
        delay(2000);
        startFresh = true;
        E = 0; Er = 0;
        StartScreen();  //Start all over 
        }
    }
    frametype = lastframetype; //leave frametype unchanged by new scans if no change in state is found. This effectively ignored 0 and -1 frametypes generated during rescans
    Tft.drawRectangle(192, 182, 30, 125, YELLOW);
    if (frametype == 81) { Tft.drawRectangle(192, 18, 30, 100, YELLOW); } // re-yellow buttons. Sleep button only gets re-yellowed if it was available before scan
}

bool Captivate(void) {//Sends the captive command and makes sure it is recieved. Outputs true if captive. Runs for a total of about 5 seconds maximum
    for (int i = 0; i <= 50; ++i) {
        xbee.send(txCapt);  //transmit the remote sleep command.
        delay(D);
        if (ListenForChar('|')) { return true; }
    }
    return false;
}

bool SendSlpCmd(void) { //Send sleep command char
    for (int i = 0; i <= 60; ++i) {   //Runs for a total of about 6 seconds maximum
        xbee.send(txSleepCmd);  //transmit the remote sleep command.
        delay(D);
        if (ListenForFrametype(83, 100)) { return true; }
    }
    return false;
}

bool ListenForFrametype(int X , int Y) { //X is the frametype, Y is the duration of listening in miliseconds
    t1 = millis();
    t2 = millis();
    while (t2 - t1 < Y) {  //read packets for 100ms and look for response
        t2 = millis();
        RxPacket();
        delay(D); //slow it down for new frames to come in- rxpacket returns 0 if no new frame is found
        if (frametype == X) { //Sleep Blip Detected- IR cam unit is now in sleep mode
            return true;
        }
    }
    return false;
}

bool WakePin(void){  //wakes Arduino by setting Xbee D3 low. Immidiately resets D3 back to high and returns true if all is executed.
    for (int i = 0; i <= 50; ++i) {   //Runs for a total of about 5 seconds maximum
        xbee.send(remoteAtRequestD3Low);  //transmit the remote sleep command.
        delay(D);
        if (ListenForRATCmdResponse(100)) { return true; }
    }
    return false;
}

bool WakePinReset(void) { //sets D3 high and returns true if executed.
    for (int i = 0; i <= 50; ++i) {   //Runs for a total of about 5 seconds maximum
        xbee.send(remoteAtRequestD3High);  
        delay(D);
        if (ListenForRATCmdResponse(100)) {return true;}
    }
    return false;
}

bool ListenForRATCmdResponse(int Y) { //Y is the while loop time in ms
    t1 = millis();
    t2 = millis();
    while (t2 - t1 < Y) {  //read packets for 100ms and look for response
        t2 = millis();
        xbee.readPacket();
        delay(D); //slow it down for new frames to come in- rxpacket returns 0 if no new frame is found
        if (xbee.getResponse().getApiId() == REMOTE_AT_COMMAND_RESPONSE) { //It's a remote AT command response
            xbee.getResponse().getRemoteAtCommandResponse(remoteAtResponse);  //retrieve the response
            if (remoteAtResponse.getStatus() == 0 && remoteAtResponse.isOk() == true) {  //It was successfully transmitted, received, and executed
                return true;
            }
        }
    }
    return false; //returns false unless affirmative remote AT response was found
}

bool ListenForChar(char X) {
    t1 = millis();
    t2 = millis();
    while (t2 - t1 < 5000) {  //read packets for 100ms and look for response
        t2 = millis();
        xbee.readPacket();
        delay(D); //slow it down for new frames to come in- rxpacket returns 0 if no new frame is found
        if (xbee.getResponse().isAvailable()) { //got a response
            xbee.getResponse().getTxStatusResponse(txStatus);  //retrieve the response
            if (xbee.getResponse().getApiId() == RX_16_RESPONSE) { //It's serial data
                L = rx16.getDataLength();
                char string[32] = {};
                for (int p = 0; p <= L - 1; p++) {  //This scans all of the incoming string for the captive confirmation byte. This allows for any possible variation in packetization timing
                    string[p] = rx16.getData(p);
                    if (string[p] == X) {  
                        return true;
                    }
                }
            }
        }
    }
    return false; //returns false unless character was found
}

void RxPacket(void) {// Scans for packets for (timeout) seconds or until a packet is received. 

    xbee.readPacket(); //Reads all available serial bytes until a packet is parsed, an error occurs, or the buffer is empty.

    if (xbee.getResponse().isAvailable()) {   // got a packet

        if (xbee.getResponse().getApiId() == RX_16_IO_RESPONSE) {  // got an rx packet: frame type 83 -periodic sleep blip
            frametype = 83;
            MeasRx = false;
            E = 0; //resets  "no good frame" counter
            Er = 0;
        }

        if (xbee.getResponse().getApiId() == RX_16_RESPONSE) {  // got an rx packet: frame type 81 -measurement packet (or in general a packet that contains serial data)***************************
            xbee.getResponse().getRx16Response(rx16);
            frametype = 81;
            MeasRx = false;//not yet true until the below conditions are met. 
            E = 0; //resets  "no good frame" counter
            Er = 0;
            L = rx16.getDataLength();
            for (int p = 0; p <= L - 1; p++) {
                Payload[p] = rx16.getData(p);
            }
            //Tft.drawNumber(L, 45, 182, 2, RED);  //debug
            Payload[L - 1] = '\0'; // valid string now constructed -->  Note: At L = 14, rx16.getDataLength() is longer than the actual data string length by one. Unknown why.
            if (Payload[0] == '`' && Payload[11] == '*' && L == 14) {//got a valid measurement string
                MeasRx = true; //got a valid measurement string
                outFormat = Payload[1];
            }
        }

        if (xbee.getResponse().getApiId() == TX_STATUS_RESPONSE) {  // got an rx packet: frame type 89 -transmit status : acts as command confirmation (not referring to Xbee remote AT commands)
            xbee.getResponse().getRx16Response(rx16);
            frametype = 89;
            MeasRx = false;
        }

    }
    else {  ////frametype 0 means no frames picked up. Frametype -1 means frame was in error
        frametype = 0;
        if (xbee.getResponse().isError()) {frametype = -1; }
        E++;
        MeasRx = false;
    }
}

void Parse(void) {
    if (Payload[0] == '<' && Payload[2] == '>') {
        errcode = Payload[1];  //extracts errcode and leaves it in char format
        ERROR();
        MeasRx = false;
    }
    if (MeasRx == true) {

        if (Payload[1] == '0') {
            outFormat = 0;
            stringval[0] = Payload[3];
            stringval[1] = Payload[4];
            stringval[2] = Payload[5];
            stringval[3] = Payload[6];
            stringval[4] = Payload[7];
            stringval[5] = '\0';

        }
        if (Payload[1] == '1') {
            outFormat = 1;
            stringvalin[0] = Payload[2];
            stringvalin[1] = Payload[3];
            stringvalin[2] = Payload[4];
            stringvalin[3] = Payload[5];
            stringvalin[4] = Payload[6];
            stringvalin[5] = Payload[7];
            stringvalin[6] = '\0';
        }
        if (Payload[8] == '@') {
            char tempstring[3] = { Payload[9], Payload[10], '\0' };  //if the dot position was a two digit number, the @ was sent in the hundreds place as a placeholder
            dotpos = atoi(tempstring); //save dot position as an integer
        }
        else {
            char tempstring2[4] = { Payload[8], Payload[9], Payload[10], '\0' };
            dotpos = atoi(tempstring2);//save dot position as an integer
        }
    }
}

void RxCheck(void) {  //this function checks what frames are being recieved 

    if (E > 20) {   //20 consecutive loops with an empty buffer and no valid string/////

        Blackout();
        Tft.drawString("SIGNAL", 65, 175, 3, WHITE);
        Tft.drawString("Rx ERR", 95, 175, 3, WHITE);//indicates that the signal has been lost. 
        delay(1000);
        Tft.drawString("SIGNAL", 65, 175, 3, BLACK);
        Tft.drawString("Rx ERR", 95, 175, 3, BLACK);
        E = 0;  //reset "no frame" counter
        clearLast();
        burnSerial();//pick up with fresh serial data
    }

    if (frametype == 83) {  //sleep mode has been detected
        Tft.fillCircle(152, dotpos, 20, BLACK);
        Tft.fillCircle(152, lastdot, 20, BLACK);
        Tft.fillRectangle(63, 215, 100, 200, BLACK);  //covers display area
        Tft.drawString("SLEEP", 65, 175, 3, WHITE);
        Tft.drawString("MODE", 95, 175, 3, WHITE);//Denotes that the unit is in sleep mode
        delay(4000);
        Tft.drawString("SLEEP", 65, 175, 3, BLACK);
        Tft.drawString("MODE", 95, 175, 3, BLACK);//Denotes that the unit is in sleep mode
        clearLast();
        burnSerial();//pick up with fresh serial data
    }
}

void Readout(void) {
    //Tft.drawNumber(frametype, 30, 198, 2, RED);//debug
    //delay(5);//debug
    //Tft.drawNumber(frametype, 30, 198, 2, BLACK);  //debug
    if (MeasRx == true) {
        if (outFormat == 0) {

            if (stringval[1] != laststringval[1] || stringval[3] != laststringval[3] || stringval[4] != laststringval[4]) {
                Tft.drawString("Hashmarks:", 30, 182, 2, WHITE);
                Tft.drawString(laststringval, 70, 215, 5, BLACK);   //overwrite old
                Tft.drawString(stringval, 70, 215, 5, WHITE);   //print output to screen
            }

            memcpy(laststringval, stringval, 6);  //save string to determine if overwrite needed********This is the fastest way to copy the string, but is not supported on the Arduino 101
            /*laststringval[0] = stringval[0];
            laststringval[1] = stringval[1];
            laststringval[2] = stringval[2];
            laststringval[3] = stringval[3];
            laststringval[4] = stringval[4];
            laststringval[5] = stringval[5];*/
        }
        if (outFormat == 1) {
            if (stringvalin[1] != laststringvalin[1] || stringvalin[3] != laststringvalin[3] || stringvalin[4] != laststringvalin[4] || stringvalin[5] != laststringvalin[5]) {
                Tft.drawString("Inches:", 30, 182, 2, WHITE);
                Tft.drawString(laststringvalin, 70, 215, 4, BLACK);  //overwrite
                Tft.drawString(stringvalin, 70, 215, 4, WHITE);   //print output to screen
            }

            memcpy(laststringvalin, stringvalin, 7);  //save string to determine if overwrite needed  ********This is the fastest way to copy the string, but is not supported on the Arduino 101
            /*laststringvalin[0] = stringvalin[0];
            laststringvalin[1] = stringvalin[1];
            laststringvalin[2] = stringvalin[2];
            laststringvalin[3] = stringvalin[3];
            laststringvalin[4] = stringvalin[4];
            laststringvalin[5] = stringvalin[5];
            laststringvalin[6] = stringvalin[6];*/
        }

        if (dotpos != lastdot) {
            Tft.fillCircle(152, lastdot, 20, BLACK);
            Tft.fillCircle(152, dotpos, 12, WHITE);   //Draws the circle at the new location
            Tft.drawTriangle(152 - 6, dotpos - 10, 152 - 6, dotpos + 10, 152 + 12, dotpos, RED);  //(int poX1, int poY1, int poX2, int poY2, int poX3, int poY3, INT16U color)
            //Tft.drawNumber(lastdot, 150, 215, 2, BLACK);  //overwrite for debug
            //Tft.drawNumber(dotpos, 150, 215, 2, WHITE);   //print output to screen for debug
        }
        lastdot = dotpos;
    }
}

void clearLast(void) {
    memset(laststringval, '\0', 6);  //destroy payload
    memset(laststringvalin, '\0', 7);  //destroy payload
    lastdot = 0;
}

void loadSplash(void) {   //Loads the boeing blue splash screen
    bmpFile = SD.open(__Gsbmp_files[1]);      ///////////////////////////THIS SELECTS THE .bmp FILE TO OPEN. CHANGE THE INDEX NUMBER.
    if (!bmpFile) { Serial.println("didnt find image"); while (1); }
    if (!bmpReadHeader(bmpFile)) { Serial.println("bad bmp"); return; }
    bmpdraw(bmpFile, 0, 0);
    bmpFile.close();
    Tft.drawString("Boeing Proprietary", 175, 305, 2, WHITE);
    Tft.drawString("Copyright 2016 Boeing.", 199, 305, 1, WHITE);
    Tft.drawString("All rights reserved.", 215, 305, 1, WHITE);
    delay(1000);
}
//////////REMOVED/////////THANKS FOR YOUR ANSWERS/////////////
///////THIS VERSION IS DEVELOPED FOR THE AT MEGA 

#include <stdint.h>//For Seedstudio Touch
#include <TFTv2.h>//For Seedstudio Touch
#include <SPI.h>
#include <SeeedTouchScreen.h>   //Seedstudio LCD touch screen Library File
#include <SD.h>//For Seedstudio Touch
#include <XBee.h>   //Zigbee Wireless transciever Library File
#include <Printers.h>   //Zigbee Wireless transciever Library File

#define MAX_BMP         10         // bmp file num  //////////////////////////////Seedstudio Touchscreen///////////////////////Seedstudio Touchscreen///////////////////////Seedstudio Touchscreen////
#define FILENAME_LEN    20         // max file name length
const int PIN_SD_CS = 4;         // pin of sd card
const int __Gnbmp_height = 320;    // bmp hight
const int __Gnbmp_width = 240;      // bmp width
unsigned char __Gnbmp_image_offset = 0;   // offset
int __Gnfile_num = 5;             // num of files (change num)
char __Gsbmp_files[5][FILENAME_LEN] = { "boeblue.bmp", "boeblue2.bmp", "787dl.bmp", "Measure3.bmp", "Measure5.bmp" }; // add file name(s) here (change num)//////  The files are zero-indexed into an array
File bmpFile;

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) // mega
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 54   // can be a digital pin, this is A0
#define XP 57   // can be a digital pin, this is A3 
#elif defined(__AVR_ATmega32U4__) // leonardo
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 18   // can be a digital pin, this is A0
#define XP 21   // can be a digital pin, this is A3 
#else //168, 328, something else
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 14   // can be a digital pin, this is A0
#define XP 17   // can be a digital pin, this is A3 
#endif

#ifdef SEEEDUINO
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 14   // can be a digital pin, this is A0
#define XP 17   // can be a digital pin, this is A3 
#endif

#ifdef MEGA
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 54   // can be a digital pin, this is A0
#define XP 57   // can be a digital pin, this is A3 
#endif 

#define TS_MINX 116*2
#define TS_MAXX 890*2
#define TS_MINY 83*2
#define TS_MAXY 913*2
// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// The 2.8" TFT Touch shield has 300 ohms across the X plate
#define BUFFPIXEL       60                    // must be a divisor of 240 
#define BUFFPIXEL_X3    180                // BUFFPIXELx3
TouchScreen ts = TouchScreen(XP, YP, XM, YM); //////////////////////////////Seedstudio Touchscreen///////////////////////Seedstudio Touchscreen///////////////////////Seedstudio Touchscreen////

XBee xbee = XBee();
XBeeResponse response = XBeeResponse();
// create reusable response objects for responses we expect to handle 
Rx16Response rx16 = Rx16Response();
Rx64Response rx64 = Rx64Response();

uint8_t option[] = { 'D', '3' };
uint8_t high[] = { 0x05 };
uint8_t low[] = { 0x04 };
XBeeAddress64 remoteAddress = XBeeAddress64(0x0013a200, 0x0000FFFF); //  SH + SL of the remote radio  //THE HI / LOW ADDRESSES ARE THE 64 BIT ADDRESSES IN HEX OF THE SPECIFIC RADIO THAT IS TO BE COMMANDED.. OR USE 0x0000FFFF AS A BROADCAST ADDRESS
// Create a remote AT request with the IR command
RemoteAtCommandRequest remoteAtRequestD3High = RemoteAtCommandRequest(remoteAddress, option, high, sizeof(high));
RemoteAtCommandRequest remoteAtRequestD3Low = RemoteAtCommandRequest(remoteAddress, option, low, sizeof(low));
// Create a Remote AT response object
RemoteAtCommandResponse remoteAtResponse = RemoteAtCommandResponse();

uint8_t SlpCmd[] = { 0x26 };  //byte '&' used for remote sleep command
Tx64Request txSleepCmd = Tx64Request(remoteAddress, SlpCmd, sizeof(SlpCmd));  //object for transmit request

uint8_t AdptCmd[] = { 0x25 };  //byte '%' used for Auto Adapt command
Tx64Request txAdptCmd = Tx64Request(remoteAddress, AdptCmd, sizeof(AdptCmd));  //object for transmit request

uint8_t InCmd[] = { 0x49 };  //byte 'I' used for Inch units command
Tx64Request txInCmd = Tx64Request(remoteAddress, InCmd, sizeof(InCmd));  //object for transmit request

uint8_t HashCmd[] = { 0x48 };  //byte 'H' used for hashmark units command
Tx64Request txHashCmd = Tx64Request(remoteAddress, HashCmd, sizeof(HashCmd));  //object for transmit request

uint8_t Capt[] = { 0x7c };  //byte '|' used for captive command
Tx64Request txCapt = Tx64Request(remoteAddress, Capt, sizeof(Capt));  //object for transmit request

uint8_t Cancl[] = { 0x43 };  //byte 'C' used for cancel captive command
Tx64Request txCancl = Tx64Request(remoteAddress, Cancl, sizeof(Cancl));  //object for transmit request

TxStatusResponse txStatus = TxStatusResponse();

char stringval[6];  //buffers for individual measurement values
char laststringval[6] = {};
char stringvalin[7];
char laststringvalin[7] = {};
int outFormat;
int dotpos;
int lastdot = 0;
byte errcode;

const int bufsize = 14;
char Payload[bufsize] = {};   //recieved string
int L; //data length 

unsigned long t1 = 0;
unsigned long t2 = 0;
const int D = 22;// Standard delay to allow for next frame to come in


int greenled = 11;
int redled = 12;
int blueled = 13;  ////Analog pins for RGB LED control


bool startFresh = true;
int frametype;
const int scantime = 20000;  ////time alloted in ms for initial scan for IR cam
int E = 0;  //no frame found counter
int Er = 0;  //frame Rx error counter
bool MeasRx = false;


void setup()
{
    pinMode(redled, OUTPUT);
    pinMode(greenled, OUTPUT);
    pinMode(blueled, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, OUTPUT);
    pinMode(7, OUTPUT);

    Serial.begin(57600);
    xbee.setSerial(Serial);

    pinMode(PIN_SD_CS, OUTPUT);
    digitalWrite(PIN_SD_CS, HIGH);
    Sd2Card card;
    card.init(SPI_FULL_SPEED, PIN_SD_CS);
    Tft.TFTinit();  // init TFT library
    Tft.setDisplayDirect(DOWN2UP);
    if (!SD.begin(PIN_SD_CS))
    {
        Serial.println("SD failed!");
        while (1);                               // init fail, die here
    }
    Serial.println("SD ok!");
    for (int f = 0; f < 5; f++) {   //odd problem fix- queries touchscreen 5 times to clear any erronious values. This prevents problem where the first point retrieved is sometimes invalid 
        Point p = ts.getPoint();
        delay(20);
    }
    digitalWrite(7, HIGH); //  ( TFT_BL_ON; ) //these functions exist in TFTv2.h, but are bypassed here because of compiler issues with recognizing the Arduino101 board definition. 
    if (startFresh) { StartScreen(); }
}

void loop()    //////////////////////////////////////////MAIN SEQUENCE////////////////////////////////////////////////////////////////
{

    RxPacket();
    RxCheck();
    Parse();
    Readout();
    //ButtonStuff();
}

///////////////////////////////////////////SUBROUTINES////////////////////////////////////////////////////////////////////////

void StartScreen(void) {

    if (startFresh == true) {
        loadSplash();
        burnSerial();
        Tft.drawString("Scanning...", 125, 300, 3, WHITE);
        t1 = millis(); t2 = millis();
        while (t2 - t1 < scantime) {// Scans for packets for scantime or until a good packet is received
            RxPacket();
            if (frametype == 81 || frametype == 83) {
                break;  //Stop if either sleep or measurement frame is found
            }
            t2 = millis();
        }
    }


     
    if (frametype == 0 || frametype == -1) {  // Scan returned no sleep or measurement frames within scan time. If frametype is now 0 or -1, it would have been set in the last, most recent iteration of RxPacket
        Tft.fillRectangle(117, 319, 55, 320, RED);
        Tft.drawString("No device found. ", 135, 283, 2, WHITE);
        Tft.fillRectangle(170, 319, 75, 320, GRAY2);
        delay(375);
        Tft.drawRectangle(182, 105, 40, 120, YELLOW);
        Tft.drawString("Rescan? ", 195, 220, 2, WHITE);
        while (1) {
            delay(D);
            Point p = ts.getPoint(); //Monitor buttons
            p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);  //Monitor buttons
            p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320);  //Monitor buttons
            if (p.x > 155 && p.x < 219 && p.y > 55 && p.y < 225) {   //// Choose to rescan (only other option is to turn the unit off and try again later)
                Tft.drawRectangle(182, 105, 40, 120, MAGENTA);
                delay(375);
                startFresh = true;
                StartScreen();
            }
        }
    }
    switch (frametype) {
    case (81) : //measurement frame detected. System found measuring //////////////////////////////////////////measurement frame detected. System found measuring
        WakePinReset();
        Tft.fillRectangle(117, 319, 70, 320, DARK_GREEN);
        Tft.drawString("Rudder Cam Detected", 132, 310, 2, WHITE);
        Tft.drawString("Status:", 160, 310, 2, WHITE);
        Tft.drawString("Sleep Mode", 160, 173, 2, DARK_GREEN);
        Tft.drawString("Measuring", 160, 168, 2, WHITE);
        Tft.fillRectangle(185, 319, 55, 320, GRAY2);
        Tft.drawString(" Measure     Sleep", 200, 315, 2, WHITE);
        Tft.drawRectangle(192, 182, 30, 125, YELLOW);
        Tft.drawRectangle(192, 18, 30, 100, YELLOW);
        t1 = millis();  t2 = millis();
        while (1) {
            t2 = millis();
            if (t2 - t1 > 5000) { Recheckframe(); } //scan again every 5 seconds in case status has changed
            Point p = ts.getPoint();   //Monitor buttons
            p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);
            p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320);
            if (p.x > 185 && p.x < 220 && p.y > 1 && p.y < 125) {     //// Choose to sleep //do stuff to sleep   //// Choose to sleep //do stuff to sleep   //// Choose to sleep //do stuff to sleep
                Tft.drawRectangle(192, 18, 30, 100, MAGENTA);
                delay(375);
                Tft.fillRectangle(185, 319, 55, 320, GRAY2);
                Tft.drawString(" IR Cam Power Save", 200, 315, 2, WHITE);
                delay(375);
                if (Captivate()) { //this sequence calls captive, then sends sleep command. if either function returns false, noresponse() makes an alert and starts the scan over
                    if (SendSlpCmd()) { 
                        startFresh = true; 
                        StartScreen(); 
                    }
                    else {noresponse();}
                }
                else {noresponse();}
            }
            if (p.x > 185 && p.x < 220 && p.y > 165 && p.y < 320) {   //// Choose to measure //do stuff to measure   //// Choose to measure //do stuff to measure   //// Choose to measure //do stuff to measure
                Tft.drawRectangle(192, 182, 30, 125, MAGENTA);
                delay(375);   
                p.x = 0;  //set arbitrary value so sleep screen is not possible (odd problem fix)
                LoadMeasScrn();
                loop();
                return;
            }
        }
        break;  //81 case done
    case (83) : //Sleep frame detected; system found sleeping //Sleep frame detected; system found sleeping////////////////////Sleep frame detected; system found sleeping
        Tft.fillRectangle(117, 319, 70, 320, GRAY2);
        Tft.drawString("Rudder Cam Detected", 132, 310, 2, WHITE);
        Tft.drawString("Status:", 160, 310, 2, WHITE);
        Tft.drawString("Measuring", 160, 168, 2, GRAY2);
        Tft.drawString("Sleep Mode", 160, 173, 2, WHITE);
        Tft.fillRectangle(185, 319, 55, 320, GRAY2);
        Tft.drawString(" Measure     Sleep", 200, 315, 2, WHITE);
        Tft.drawRectangle(192, 182, 30, 125, YELLOW);
        t1 = millis();
        t2 = millis();
        while (1) {
            t2 = millis();
            if (t2 - t1 > 5000) {//scan again every 5 seconds in case status has changed
                Recheckframe();
            }
            Point p = ts.getPoint();   //Monitor buttons
            p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);
            p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320);
            if (p.x > 185 && p.x < 220 && p.y > 165 && p.y < 320) {   //// Choose to measure //do stuff to measure   //// Choose to measure //do stuff to measure   //// Choose to measure //do stuff to measure
                Tft.drawRectangle(192, 182, 30, 125, MAGENTA);
                delay(375);
                p.x = 0;  //set arbitrary value so sleep screen is not possible (odd problem fix)
                Tft.fillRectangle(185, 319, 55, 320, GRAY2);
                Tft.drawString(" Waking Rudder Cam", 200, 315, 2, WHITE);
                delay(375);
                WakePin();
                delay(2000);
                if (ListenForChar('O')) { //Listen for confirmation that the main unit woke from sleep
                    LoadMeasScrn();
                    loop();
                    return;
                }
                else { noresponse(); }
            }
        }
    } 
}

void LoadMeasScrn() {
    bmpFile = SD.open(__Gsbmp_files[3]);      ///////////////////////////THIS SELECTS THE .bmp FILE TO OPEN. CHANGE THE INDEX NUMBER.
    if (!bmpFile) { Serial.println("didnt find image"); while (1); }   ////This loads the measurement screen/////////
    if (!bmpReadHeader(bmpFile)) { Serial.println("bad bmp"); return; } ////This loads the measurement screen/////////
    bmpdraw(bmpFile, 0, 0); ////This loads the measurement screen/////////
    bmpFile.close(); ////This loads the measurement screen/////////
}

bool Recheckframe(void) {//For use in start screen, function rechecks frame type. Returns true if frametype has switched from sleep to meas or vice versa
    int lastframetype = frametype;  //remember frametype when stepping into this function
    Tft.drawRectangle(192, 182, 30, 125, GRAY2);
    Tft.drawRectangle(192, 18, 30, 100, GRAY2); //gray out buttons for a sec while rescanning
    t1 = millis(); t2 = millis();
    while (t2 - t1 < 100) {  //read packets for 100ms and look change in frametype
        t2 = millis();
        RxPacket();
        delay(D); //slow it down for new frames to come in- rxpacket returns 0 frametype if no new frame is found
        if (lastframetype == 81 && frametype == 83) {  //went to sleep //indicates change in sleep/meas state, ignoring errors and nonconforming frames
            startFresh = false;  //do not re-run scan, just change frametype.
            StartScreen();
            break;
        }
        if (lastframetype == 83 && frametype == 81) {  //woke up //indicates change in sleep/meas state, ignoring errors and nonconforming frames
            startFresh = false;  //do not re-run scan, just change frametype.
            StartScreen();
            break;
        }
        if (E >= 20 || Er >= 20) {  //have recieved 20 bad frames without a good frame. Signal must be lost
        Tft.fillRectangle(185, 319, 55, 320, GRAY2);
        Tft.drawString("Signal Lost", 200, 315, 2, WHITE);
        delay(2000);
        startFresh = true;
        E = 0; Er = 0;
        StartScreen();  //Start all over 
        }
    }
    frametype = lastframetype; //leave frametype unchanged by new scans if no change in state is found. This effectively ignored 0 and -1 frametypes generated during rescans
    Tft.drawRectangle(192, 182, 30, 125, YELLOW);
    if (frametype == 81) { Tft.drawRectangle(192, 18, 30, 100, YELLOW); } // re-yellow buttons. Sleep button only gets re-yellowed if it was available before scan
}

bool Captivate(void) {//Sends the captive command and makes sure it is recieved. Outputs true if captive. Runs for a total of about 5 seconds maximum
    for (int i = 0; i <= 50; ++i) {
        xbee.send(txCapt);  //transmit the remote sleep command.
        delay(D);
        if (ListenForChar('|')) { return true; }
    }
    return false;
}

bool SendSlpCmd(void) { //Send sleep command char
    for (int i = 0; i <= 60; ++i) {   //Runs for a total of about 6 seconds maximum
        xbee.send(txSleepCmd);  //transmit the remote sleep command.
        delay(D);
        if (ListenForFrametype(83, 100)) { return true; }
    }
    return false;
}

bool ListenForFrametype(int X , int Y) { //X is the frametype, Y is the duration of listening in miliseconds
    t1 = millis();
    t2 = millis();
    while (t2 - t1 < Y) {  //read packets for 100ms and look for response
        t2 = millis();
        RxPacket();
        delay(D); //slow it down for new frames to come in- rxpacket returns 0 if no new frame is found
        if (frametype == X) { //Sleep Blip Detected- IR cam unit is now in sleep mode
            return true;
        }
    }
    return false;
}

bool WakePin(void){  //wakes Arduino by setting Xbee D3 low. Immidiately resets D3 back to high and returns true if all is executed.
    for (int i = 0; i <= 50; ++i) {   //Runs for a total of about 5 seconds maximum
        xbee.send(remoteAtRequestD3Low);  //transmit the remote sleep command.
        delay(D);
        if (ListenForRATCmdResponse(100)) { return true; }
    }
    return false;
}

bool WakePinReset(void) { //sets D3 high and returns true if executed.
    for (int i = 0; i <= 50; ++i) {   //Runs for a total of about 5 seconds maximum
        xbee.send(remoteAtRequestD3High);  
        delay(D);
        if (ListenForRATCmdResponse(100)) {return true;}
    }
    return false;
}

bool ListenForRATCmdResponse(int Y) { //Y is the while loop time in ms
    t1 = millis();
    t2 = millis();
    while (t2 - t1 < Y) {  //read packets for 100ms and look for response
        t2 = millis();
        xbee.readPacket();
        delay(D); //slow it down for new frames to come in- rxpacket returns 0 if no new frame is found
        if (xbee.getResponse().getApiId() == REMOTE_AT_COMMAND_RESPONSE) { //It's a remote AT command response
            xbee.getResponse().getRemoteAtCommandResponse(remoteAtResponse);  //retrieve the response
            if (remoteAtResponse.getStatus() == 0 && remoteAtResponse.isOk() == true) {  //It was successfully transmitted, received, and executed
                return true;
            }
        }
    }
    return false; //returns false unless affirmative remote AT response was found
}

bool ListenForChar(char X) {
    t1 = millis();
    t2 = millis();
    while (t2 - t1 < 5000) {  //read packets for 100ms and look for response
        t2 = millis();
        xbee.readPacket();
        delay(D); //slow it down for new frames to come in- rxpacket returns 0 if no new frame is found
        if (xbee.getResponse().isAvailable()) { //got a response
            xbee.getResponse().getTxStatusResponse(txStatus);  //retrieve the response
            if (xbee.getResponse().getApiId() == RX_16_RESPONSE) { //It's serial data
                L = rx16.getDataLength();
                char string[32] = {};
                for (int p = 0; p <= L - 1; p++) {  //This scans all of the incoming string for the captive confirmation byte. This allows for any possible variation in packetization timing
                    string[p] = rx16.getData(p);
                    if (string[p] == X) {  
                        return true;
                    }
                }
            }
        }
    }
    return false; //returns false unless character was found
}

void RxPacket(void) {// Scans for packets for (timeout) seconds or until a packet is received. 

    xbee.readPacket(); //Reads all available serial bytes until a packet is parsed, an error occurs, or the buffer is empty.

    if (xbee.getResponse().isAvailable()) {   // got a packet

        if (xbee.getResponse().getApiId() == RX_16_IO_RESPONSE) {  // got an rx packet: frame type 83 -periodic sleep blip
            frametype = 83;
            MeasRx = false;
            E = 0; //resets  "no good frame" counter
            Er = 0;
        }

        if (xbee.getResponse().getApiId() == RX_16_RESPONSE) {  // got an rx packet: frame type 81 -measurement packet (or in general a packet that contains serial data)***************************
            xbee.getResponse().getRx16Response(rx16);
            frametype = 81;
            MeasRx = false;//not yet true until the below conditions are met. 
            E = 0; //resets  "no good frame" counter
            Er = 0;
            L = rx16.getDataLength();
            for (int p = 0; p <= L - 1; p++) {
                Payload[p] = rx16.getData(p);
            }
            //Tft.drawNumber(L, 45, 182, 2, RED);  //debug
            Payload[L - 1] = '\0'; // valid string now constructed -->  Note: At L = 14, rx16.getDataLength() is longer than the actual data string length by one. Unknown why.
            if (Payload[0] == '`' && Payload[11] == '*' && L == 14) {//got a valid measurement string
                MeasRx = true; //got a valid measurement string
                outFormat = Payload[1];
            }
        }

        if (xbee.getResponse().getApiId() == TX_STATUS_RESPONSE) {  // got an rx packet: frame type 89 -transmit status : acts as command confirmation (not referring to Xbee remote AT commands)
            xbee.getResponse().getRx16Response(rx16);
            frametype = 89;
            MeasRx = false;
        }

    }
    else {  ////frametype 0 means no frames picked up. Frametype -1 means frame was in error
        frametype = 0;
        if (xbee.getResponse().isError()) {frametype = -1; }
        E++;
        MeasRx = false;
    }
}

void Parse(void) {
    if (Payload[0] == '<' && Payload[2] == '>') {
        errcode = Payload[1];  //extracts errcode and leaves it in char format
        ERROR();
        MeasRx = false;
    }
    if (MeasRx == true) {

        if (Payload[1] == '0') {
            outFormat = 0;
            stringval[0] = Payload[3];
            stringval[1] = Payload[4];
            stringval[2] = Payload[5];
            stringval[3] = Payload[6];
            stringval[4] = Payload[7];
            stringval[5] = '\0';

        }
        if (Payload[1] == '1') {
            outFormat = 1;
            stringvalin[0] = Payload[2];
            stringvalin[1] = Payload[3];
            stringvalin[2] = Payload[4];
            stringvalin[3] = Payload[5];
            stringvalin[4] = Payload[6];
            stringvalin[5] = Payload[7];
            stringvalin[6] = '\0';
        }
        if (Payload[8] == '@') {
            char tempstring[3] = { Payload[9], Payload[10], '\0' };  //if the dot position was a two digit number, the @ was sent in the hundreds place as a placeholder
            dotpos = atoi(tempstring); //save dot position as an integer
        }
        else {
            char tempstring2[4] = { Payload[8], Payload[9], Payload[10], '\0' };
            dotpos = atoi(tempstring2);//save dot position as an integer
        }
    }
}

void RxCheck(void) {  //this function checks what frames are being recieved 

    if (E > 20) {   //20 consecutive loops with an empty buffer and no valid string/////

        Blackout();
        Tft.drawString("SIGNAL", 65, 175, 3, WHITE);
        Tft.drawString("Rx ERR", 95, 175, 3, WHITE);//indicates that the signal has been lost. 
        delay(1000);
        Tft.drawString("SIGNAL", 65, 175, 3, BLACK);
        Tft.drawString("Rx ERR", 95, 175, 3, BLACK);
        E = 0;  //reset "no frame" counter
        clearLast();
        burnSerial();//pick up with fresh serial data
    }

    if (frametype == 83) {  //sleep mode has been detected
        Tft.fillCircle(152, dotpos, 20, BLACK);
        Tft.fillCircle(152, lastdot, 20, BLACK);
        Tft.fillRectangle(63, 215, 100, 200, BLACK);  //covers display area
        Tft.drawString("SLEEP", 65, 175, 3, WHITE);
        Tft.drawString("MODE", 95, 175, 3, WHITE);//Denotes that the unit is in sleep mode
        delay(4000);
        Tft.drawString("SLEEP", 65, 175, 3, BLACK);
        Tft.drawString("MODE", 95, 175, 3, BLACK);//Denotes that the unit is in sleep mode
        clearLast();
        burnSerial();//pick up with fresh serial data
    }
}

void Readout(void) {
    //Tft.drawNumber(frametype, 30, 198, 2, RED);//debug
    //delay(5);//debug
    //Tft.drawNumber(frametype, 30, 198, 2, BLACK);  //debug
    if (MeasRx == true) {
        if (outFormat == 0) {

            if (stringval[1] != laststringval[1] || stringval[3] != laststringval[3] || stringval[4] != laststringval[4]) {
                Tft.drawString("Hashmarks:", 30, 182, 2, WHITE);
                Tft.drawString(laststringval, 70, 215, 5, BLACK);   //overwrite old
                Tft.drawString(stringval, 70, 215, 5, WHITE);   //print output to screen
            }

            memcpy(laststringval, stringval, 6);  //save string to determine if overwrite needed********This is the fastest way to copy the string, but is not supported on the Arduino 101
            /*laststringval[0] = stringval[0];
            laststringval[1] = stringval[1];
            laststringval[2] = stringval[2];
            laststringval[3] = stringval[3];
            laststringval[4] = stringval[4];
            laststringval[5] = stringval[5];*/
        }
        if (outFormat == 1) {
            if (stringvalin[1] != laststringvalin[1] || stringvalin[3] != laststringvalin[3] || stringvalin[4] != laststringvalin[4] || stringvalin[5] != laststringvalin[5]) {
                Tft.drawString("Inches:", 30, 182, 2, WHITE);
                Tft.drawString(laststringvalin, 70, 215, 4, BLACK);  //overwrite
                Tft.drawString(stringvalin, 70, 215, 4, WHITE);   //print output to screen
            }

            memcpy(laststringvalin, stringvalin, 7);  //save string to determine if overwrite needed  ********This is the fastest way to copy the string, but is not supported on the Arduino 101
            /*laststringvalin[0] = stringvalin[0];
            laststringvalin[1] = stringvalin[1];
            laststringvalin[2] = stringvalin[2];
            laststringvalin[3] = stringvalin[3];
            laststringvalin[4] = stringvalin[4];
            laststringvalin[5] = stringvalin[5];
            laststringvalin[6] = stringvalin[6];*/
        }

        if (dotpos != lastdot) {
            Tft.fillCircle(152, lastdot, 20, BLACK);
            Tft.fillCircle(152, dotpos, 12, WHITE);   //Draws the circle at the new location
            Tft.drawTriangle(152 - 6, dotpos - 10, 152 - 6, dotpos + 10, 152 + 12, dotpos, RED);  //(int poX1, int poY1, int poX2, int poY2, int poX3, int poY3, INT16U color)
            //Tft.drawNumber(lastdot, 150, 215, 2, BLACK);  //overwrite for debug
            //Tft.drawNumber(dotpos, 150, 215, 2, WHITE);   //print output to screen for debug
        }
        lastdot = dotpos;
    }
}

void clearLast(void) {
    memset(laststringval, '\0', 6);  //destroy payload
    memset(laststringvalin, '\0', 7);  //destroy payload
    lastdot = 0;
}

void loadSplash(void) {   //Loads the boeing blue splash screen
    bmpFile = SD.open(__Gsbmp_files[1]);      ///////////////////////////THIS SELECTS THE .bmp FILE TO OPEN. CHANGE THE INDEX NUMBER.
    if (!bmpFile) { Serial.println("didnt find image"); while (1); }
    if (!bmpReadHeader(bmpFile)) { Serial.println("bad bmp"); return; }
    bmpdraw(bmpFile, 0, 0);
    bmpFile.close();
    Tft.drawString("Boeing Proprietary", 175, 305, 2, WHITE);
    Tft.drawString("Copyright 2016 Boeing.", 199, 305, 1, WHITE);
    Tft.drawString("All rights reserved.", 215, 305, 1, WHITE);
    delay(1000);
}
//////////REMOVED/////////THANKS FOR YOUR ANSWERS/////////////
added 27085 characters in body
Source Link

and the same thing happens. Here's a bit

So here's (most of pseudocode that will hopefully show how I have things organized) my entire code:

///////THIS VERSION IS DEVELOPED FOR THE AT MEGA 

#include <stdint.h>//For Seedstudio Touch
#include <TFTv2.h>//For Seedstudio Touch
#include <SPI.h>
#include <SeeedTouchScreen.h>   //Seedstudio LCD touch screen Library File
#include <SD.h>//For Seedstudio Touch
#include <XBee.h>   //Zigbee Wireless transciever Library File
#include <Printers.h>   //Zigbee Wireless transciever Library File

#define MAX_BMP         10         // bmp file num  //////////////////////////////Seedstudio Touchscreen///////////////////////Seedstudio Touchscreen///////////////////////Seedstudio Touchscreen////
#define FILENAME_LEN    20         // max file name length
const int PIN_SD_CS = 4;         // pin of sd card
const int __Gnbmp_height = 320;    // bmp hight
const int __Gnbmp_width = 240;      // bmp width
unsigned char __Gnbmp_image_offset = 0;   // offset
int __Gnfile_num = 5;             // num of files (change num)
char __Gsbmp_files[5][FILENAME_LEN] = { "boeblue.bmp", "boeblue2.bmp", "787dl.bmp", "Measure3.bmp", "Measure5.bmp" }; // add file name(s) here (change num)//////  The files are zero-indexed into an array
File bmpFile;

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) // mega
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 54   // can be a digital pin, this is A0
#define XP 57   // can be a digital pin, this is A3 
#elif defined(__AVR_ATmega32U4__) // leonardo
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 18   // can be a digital pin, this is A0
#define XP 21   // can be a digital pin, this is A3 
#else //168, 328, something else
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 14   // can be a digital pin, this is A0
#define XP 17   // can be a digital pin, this is A3 
#endif

#ifdef SEEEDUINO
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 14   // can be a digital pin, this is A0
#define XP 17   // can be a digital pin, this is A3 
#endif

#ifdef MEGA
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 54   // can be a digital pin, this is A0
#define XP 57   // can be a digital pin, this is A3 
#endif 

#define TS_MINX 116*2
#define TS_MAXX 890*2
#define TS_MINY 83*2
#define TS_MAXY 913*2
// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// The 2.8" TFT Touch shield has 300 ohms across the X plate
#define BUFFPIXEL       60                    // must be a divisor of 240 
#define BUFFPIXEL_X3    180                // BUFFPIXELx3
TouchScreen ts = TouchScreen(XP, YP, XM, YM); //////////////////////////////Seedstudio Touchscreen///////////////////////Seedstudio Touchscreen///////////////////////Seedstudio Touchscreen////

XBee xbee = XBee();
XBeeResponse response = XBeeResponse();
// create reusable response objects for responses we expect to handle 
Rx16Response rx16 = Rx16Response();
Rx64Response rx64 = Rx64Response();

uint8_t option[] = { 'D', '3' };
uint8_t high[] = { 0x05 };
uint8_t low[] = { 0x04 };
XBeeAddress64 remoteAddress = XBeeAddress64(0x0013a200, 0x0000FFFF); //  SH + SL of the remote radio  //THE HI / LOW ADDRESSES ARE THE 64 BIT ADDRESSES IN HEX OF THE SPECIFIC RADIO THAT IS TO BE COMMANDED.. OR USE 0x0000FFFF AS A BROADCAST ADDRESS
// Create a remote AT request with the IR command
RemoteAtCommandRequest remoteAtRequestD3High = RemoteAtCommandRequest(remoteAddress, option, high, sizeof(high));
RemoteAtCommandRequest remoteAtRequestD3Low = RemoteAtCommandRequest(remoteAddress, option, low, sizeof(low));
// Create a Remote AT response object
RemoteAtCommandResponse remoteAtResponse = RemoteAtCommandResponse();

uint8_t SlpCmd[] = { 0x26 };  //byte '&' used for remote sleep command
Tx64Request txSleepCmd = Tx64Request(remoteAddress, SlpCmd, sizeof(SlpCmd));  //object for transmit request

uint8_t AdptCmd[] = { 0x25 };  //byte '%' used for Auto Adapt command
Tx64Request txAdptCmd = Tx64Request(remoteAddress, AdptCmd, sizeof(AdptCmd));  //object for transmit request

uint8_t InCmd[] = { 0x49 };  //byte 'I' used for Inch units command
Tx64Request txInCmd = Tx64Request(remoteAddress, InCmd, sizeof(InCmd));  //object for transmit request

uint8_t HashCmd[] = { 0x48 };  //byte 'H' used for hashmark units command
Tx64Request txHashCmd = Tx64Request(remoteAddress, HashCmd, sizeof(HashCmd));  //object for transmit request

uint8_t Capt[] = { 0x7c };  //byte '|' used for captive command
Tx64Request txCapt = Tx64Request(remoteAddress, Capt, sizeof(Capt));  //object for transmit request

uint8_t Cancl[] = { 0x43 };  //byte 'C' used for cancel captive command
Tx64Request txCancl = Tx64Request(remoteAddress, Cancl, sizeof(Cancl));  //object for transmit request

TxStatusResponse txStatus = TxStatusResponse();

char stringval[6];  //buffers for individual measurement values
char laststringval[6] = {};
char stringvalin[7];
char laststringvalin[7] = {};
int outFormat;
int dotpos;
int lastdot = 0;
byte errcode;

const int bufsize = 14;
char Payload[bufsize] = {};   //recieved string
int L; //data length 

unsigned long t1 = 0;
unsigned long t2 = 0;
const int D = 22;// Standard delay to allow for next frame to come in


int greenled = 11;
int redled = 12;
int blueled = 13;  ////Analog pins for RGB LED control


bool startFresh = true;
int frametype;
const int scantime = 20000;  ////time alloted in ms for initial scan for IR cam
int E = 0;  //no frame found counter
int Er = 0;  //frame Rx error counter
bool MeasRx = false;


void setup() 
{
Startscreen    pinMode(redled, OUTPUT);
    pinMode(greenled, OUTPUT);
    pinMode(blueled, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, OUTPUT);
    pinMode(7, OUTPUT);

    Serial.begin(57600);
    xbee.setSerial(Serial);

    pinMode(PIN_SD_CS, OUTPUT);
    digitalWrite(PIN_SD_CS, HIGH);
    Sd2Card card;
    card.init(SPI_FULL_SPEED, PIN_SD_CS);
    Tft.TFTinit();  //this screeninit providesTFT userlibrary
 options   Tft.setDisplayDirect(DOWN2UP);
    if (!SD.begin(PIN_SD_CS))
    {
        Serial.println("SD failed!");
        while (1);                               // init fail, die here
    }
    Serial.println("SD ok!");
    for (int f = 0; f < 5; f++) {   //odd problem fix- queries touchscreen 5 times to clear any erronious values. This prevents problem where the first point retrieved is sometimes invalid 
        Point p = ts.getPoint();
        delay(20);
    }
    digitalWrite(7, HIGH); //  ( TFT_BL_ON; ) //these functions exist in TFTv2.h, but are bypassed here because of compiler issues with recognizing the Arduino101 board definition. 
    if (startFresh) { StartScreen(); }
}

void loop()    //////////////////////////////////////////MAIN SEQUENCE////////////////////////////////////////////////////////////////
{
do 
 all the other mainRxPacket();
 functions of the program;RxCheck();
    Parse();
    Readout();
    //ButtonStuff();
}

void Startscreen(){///////////////////////////////////////////SUBROUTINES////////////////////////////////////////////////////////////////////////

if this thing, show this
if that thing, show that
take readings
switch(reading){
case(number):
    while(1){
        check for button presses
        if (this){
             if (that){
                    LoadMainScreen();
                     return;         //this is supposed to quit the startscreen function completely and allow the program to move on to the main loop
case(other number);
    do other stuff
    break;
 } //end of case stuff
Do other stuff that the startscreen program may need to do  //this is what I'm seeing after calling return. should not see happening
void StartScreen(void) {

    if (startFresh == true) {
        loadSplash();
        burnSerial();
        Tft.drawString("Scanning...", 125, 300, 3, WHITE);
        t1 = millis(); t2 = millis();
        while (t2 - t1 < scantime) {// Scans for packets for scantime or until a good packet is received
            RxPacket();
            if (frametype == 81 || frametype == 83) {
                break;  //Stop if either sleep or measurement frame is found
            }
            t2 = millis();
        }
    }


     
    if (frametype == 0 || frametype == -1) {  // Scan returned no sleep or measurement frames within scan time. If frametype is now 0 or -1, it would have been set in the last, most recent iteration of RxPacket
        Tft.fillRectangle(117, 319, 55, 320, RED);
        Tft.drawString("No device found. ", 135, 283, 2, WHITE);
        Tft.fillRectangle(170, 319, 75, 320, GRAY2);
        delay(375);
        Tft.drawRectangle(182, 105, 40, 120, YELLOW);
        Tft.drawString("Rescan? ", 195, 220, 2, WHITE);
        while (1) {
            delay(D);
            Point p = ts.getPoint(); //Monitor buttons
            p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);  //Monitor buttons
            p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320);  //Monitor buttons
            if (p.x > 155 && p.x < 219 && p.y > 55 && p.y < 225) {   //// Choose to rescan (only other option is to turn the unit off and try again later)
                Tft.drawRectangle(182, 105, 40, 120, MAGENTA);
                delay(375);
                startFresh = true;
                StartScreen();
            }
        }
    }
    switch (frametype) {
    case (81) : //measurement frame detected. System found measuring //////////////////////////////////////////measurement frame detected. System found measuring
        WakePinReset();
        Tft.fillRectangle(117, 319, 70, 320, DARK_GREEN);
        Tft.drawString("Rudder Cam Detected", 132, 310, 2, WHITE);
        Tft.drawString("Status:", 160, 310, 2, WHITE);
        Tft.drawString("Sleep Mode", 160, 173, 2, DARK_GREEN);
        Tft.drawString("Measuring", 160, 168, 2, WHITE);
        Tft.fillRectangle(185, 319, 55, 320, GRAY2);
        Tft.drawString(" Measure     Sleep", 200, 315, 2, WHITE);
        Tft.drawRectangle(192, 182, 30, 125, YELLOW);
        Tft.drawRectangle(192, 18, 30, 100, YELLOW);
        t1 = millis();  t2 = millis();
        while (1) {
            t2 = millis();
            if (t2 - t1 > 5000) { Recheckframe(); } //scan again every 5 seconds in case status has changed
            Point p = ts.getPoint();   //Monitor buttons
            p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);
            p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320);
            if (p.x > 185 && p.x < 220 && p.y > 1 && p.y < 125) {     //// Choose to sleep //do stuff to sleep   //// Choose to sleep //do stuff to sleep   //// Choose to sleep //do stuff to sleep
                Tft.drawRectangle(192, 18, 30, 100, MAGENTA);
                delay(375);
                Tft.fillRectangle(185, 319, 55, 320, GRAY2);
                Tft.drawString(" IR Cam Power Save", 200, 315, 2, WHITE);
                delay(375);
                if (Captivate()) { //this sequence calls captive, then sends sleep command. if either function returns false, noresponse() makes an alert and starts the scan over
                    if (SendSlpCmd()) { 
                        startFresh = true; 
                        StartScreen(); 
                    }
                    else {noresponse();}
                }
                else {noresponse();}
            }
            if (p.x > 185 && p.x < 220 && p.y > 165 && p.y < 320) {   //// Choose to measure //do stuff to measure   //// Choose to measure //do stuff to measure   //// Choose to measure //do stuff to measure
                Tft.drawRectangle(192, 182, 30, 125, MAGENTA);
                delay(375);   
                p.x = 0;  //set arbitrary value so sleep screen is not possible (odd problem fix)
                LoadMeasScrn();
                loop();
                return;
            }
        }
        break;  //81 case done
    case (83) : //Sleep frame detected; system found sleeping //Sleep frame detected; system found sleeping////////////////////Sleep frame detected; system found sleeping
        Tft.fillRectangle(117, 319, 70, 320, GRAY2);
        Tft.drawString("Rudder Cam Detected", 132, 310, 2, WHITE);
        Tft.drawString("Status:", 160, 310, 2, WHITE);
        Tft.drawString("Measuring", 160, 168, 2, GRAY2);
        Tft.drawString("Sleep Mode", 160, 173, 2, WHITE);
        Tft.fillRectangle(185, 319, 55, 320, GRAY2);
        Tft.drawString(" Measure     Sleep", 200, 315, 2, WHITE);
        Tft.drawRectangle(192, 182, 30, 125, YELLOW);
        t1 = millis();
        t2 = millis();
        while (1) {
            t2 = millis();
            if (t2 - t1 > 5000) {//scan again every 5 seconds in case status has changed
                Recheckframe();
            }
            Point p = ts.getPoint();   //Monitor buttons
            p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);
            p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320);
            if (p.x > 185 && p.x < 220 && p.y > 165 && p.y < 320) {   //// Choose to measure //do stuff to measure   //// Choose to measure //do stuff to measure   //// Choose to measure //do stuff to measure
                Tft.drawRectangle(192, 182, 30, 125, MAGENTA);
                delay(375);
                p.x = 0;  //set arbitrary value so sleep screen is not possible (odd problem fix)
                Tft.fillRectangle(185, 319, 55, 320, GRAY2);
                Tft.drawString(" Waking Rudder Cam", 200, 315, 2, WHITE);
                delay(375);
                WakePin();
                delay(2000);
                if (ListenForChar('O')) { //Listen for confirmation that the main unit woke from sleep
                    LoadMeasScrn();
                    loop();
                    return;
                }
                else { noresponse(); }
            }
        }
    } 
}

void LoadMeasScrn() {
    bmpFile = SD.open(__Gsbmp_files[3]);      ///////////////////////////THIS SELECTS THE .bmp FILE TO OPEN. CHANGE THE INDEX NUMBER.
    if (!bmpFile) { Serial.println("didnt find image"); while (1); }   ////This loads the measurement screen/////////
    if (!bmpReadHeader(bmpFile)) { Serial.println("bad bmp"); return; } ////This loads the measurement screen/////////
    bmpdraw(bmpFile, 0, 0); ////This loads the measurement screen/////////
    bmpFile.close(); ////This loads the measurement screen/////////
}

bool Recheckframe(void) {//For use in start screen, function rechecks frame type. Returns true if frametype has switched from sleep to meas or vice versa
    int lastframetype = frametype;  //remember frametype when stepping into this function
    Tft.drawRectangle(192, 182, 30, 125, GRAY2);
    Tft.drawRectangle(192, 18, 30, 100, GRAY2); //gray out buttons for a sec while rescanning
    t1 = millis(); t2 = millis();
    while (t2 - t1 < 100) {  //read packets for 100ms and look change in frametype
        t2 = millis();
        RxPacket();
        delay(D); //slow it down for new frames to come in- rxpacket returns 0 frametype if no new frame is found
        if (lastframetype == 81 && frametype == 83) {  //went to sleep //indicates change in sleep/meas state, ignoring errors and nonconforming frames
            startFresh = false;  //do not re-run scan, just change frametype.
            StartScreen();
            break;
        }
        if (lastframetype == 83 && frametype == 81) {  //woke up //indicates change in sleep/meas state, ignoring errors and nonconforming frames
            startFresh = false;  //do not re-run scan, just change frametype.
            StartScreen();
            break;
        }
        if (E >= 20 || Er >= 20) {  //have recieved 20 bad frames without a good frame. Signal must be lost
        Tft.fillRectangle(185, 319, 55, 320, GRAY2);
        Tft.drawString("Signal Lost", 200, 315, 2, WHITE);
        delay(2000);
        startFresh = true;
        E = 0; Er = 0;
        StartScreen();  //Start all over 
        }
    }
    frametype = lastframetype; //leave frametype unchanged by new scans if no change in state is found. This effectively ignored 0 and -1 frametypes generated during rescans
    Tft.drawRectangle(192, 182, 30, 125, YELLOW);
    if (frametype == 81) { Tft.drawRectangle(192, 18, 30, 100, YELLOW); } // re-yellow buttons. Sleep button only gets re-yellowed if it was available before scan
}

bool Captivate(void) {//Sends the captive command and makes sure it is recieved. Outputs true if captive. Runs for a total of about 5 seconds maximum
    for (int i = 0; i <= 50; ++i) {
        xbee.send(txCapt);  //transmit the remote sleep command.
        delay(D);
        if (ListenForChar('|')) { return true; }
    }
    return false;
}

bool SendSlpCmd(void) { //Send sleep command char
    for (int i = 0; i <= 60; ++i) {   //Runs for a total of about 6 seconds maximum
        xbee.send(txSleepCmd);  //transmit the remote sleep command.
        delay(D);
        if (ListenForFrametype(83, 100)) { return true; }
    }
    return false;
}

bool ListenForFrametype(int X , int Y) { //X is the frametype, Y is the duration of listening in miliseconds
    t1 = millis();
    t2 = millis();
    while (t2 - t1 < Y) {  //read packets for 100ms and look for response
        t2 = millis();
        RxPacket();
        delay(D); //slow it down for new frames to come in- rxpacket returns 0 if no new frame is found
        if (frametype == X) { //Sleep Blip Detected- IR cam unit is now in sleep mode
            return true;
        }
    }
    return false;
}

bool WakePin(void){  //wakes Arduino by setting Xbee D3 low. Immidiately resets D3 back to high and returns true if all is executed.
    for (int i = 0; i <= 50; ++i) {   //Runs for a total of about 5 seconds maximum
        xbee.send(remoteAtRequestD3Low);  //transmit the remote sleep command.
        delay(D);
        if (ListenForRATCmdResponse(100)) { return true; }
    }
    return false;
}

bool WakePinReset(void) { //sets D3 high and returns true if executed.
    for (int i = 0; i <= 50; ++i) {   //Runs for a total of about 5 seconds maximum
        xbee.send(remoteAtRequestD3High);  
        delay(D);
        if (ListenForRATCmdResponse(100)) {return true;}
    }
    return false;
}

bool ListenForRATCmdResponse(int Y) { //Y is the while loop time in ms
    t1 = millis();
    t2 = millis();
    while (t2 - t1 < Y) {  //read packets for 100ms and look for response
        t2 = millis();
        xbee.readPacket();
        delay(D); //slow it down for new frames to come in- rxpacket returns 0 if no new frame is found
        if (xbee.getResponse().getApiId() == REMOTE_AT_COMMAND_RESPONSE) { //It's a remote AT command response
            xbee.getResponse().getRemoteAtCommandResponse(remoteAtResponse);  //retrieve the response
            if (remoteAtResponse.getStatus() == 0 && remoteAtResponse.isOk() == true) {  //It was successfully transmitted, received, and executed
                return true;
            }
        }
    }
    return false; //returns false unless affirmative remote AT response was found
}

bool ListenForChar(char X) {
    t1 = millis();
    t2 = millis();
    while (t2 - t1 < 5000) {  //read packets for 100ms and look for response
        t2 = millis();
        xbee.readPacket();
        delay(D); //slow it down for new frames to come in- rxpacket returns 0 if no new frame is found
        if (xbee.getResponse().isAvailable()) { //got a response
            xbee.getResponse().getTxStatusResponse(txStatus);  //retrieve the response
            if (xbee.getResponse().getApiId() == RX_16_RESPONSE) { //It's serial data
                L = rx16.getDataLength();
                char string[32] = {};
                for (int p = 0; p <= L - 1; p++) {  //This scans all of the incoming string for the captive confirmation byte. This allows for any possible variation in packetization timing
                    string[p] = rx16.getData(p);
                    if (string[p] == X) {  
                        return true;
                    }
                }
            }
        }
    }
    return false; //returns false unless character was found
}

void RxPacket(void) {// Scans for packets for (timeout) seconds or until a packet is received. 

    xbee.readPacket(); //Reads all available serial bytes until a packet is parsed, an error occurs, or the buffer is empty.

    if (xbee.getResponse().isAvailable()) {   // got a packet

        if (xbee.getResponse().getApiId() == RX_16_IO_RESPONSE) {  // got an rx packet: frame type 83 -periodic sleep blip
            frametype = 83;
            MeasRx = false;
            E = 0; //resets  "no good frame" counter
            Er = 0;
        }

        if (xbee.getResponse().getApiId() == RX_16_RESPONSE) {  // got an rx packet: frame type 81 -measurement packet (or in general a packet that contains serial data)***************************
            xbee.getResponse().getRx16Response(rx16);
            frametype = 81;
            MeasRx = false;//not yet true until the below conditions are met. 
            E = 0; //resets  "no good frame" counter
            Er = 0;
            L = rx16.getDataLength();
            for (int p = 0; p <= L - 1; p++) {
                Payload[p] = rx16.getData(p);
            }
            //Tft.drawNumber(L, 45, 182, 2, RED);  //debug
            Payload[L - 1] = '\0'; // valid string now constructed -->  Note: At L = 14, rx16.getDataLength() is longer than the actual data string length by one. Unknown why.
            if (Payload[0] == '`' && Payload[11] == '*' && L == 14) {//got a valid measurement string
                MeasRx = true; //got a valid measurement string
                outFormat = Payload[1];
            }
        }

        if (xbee.getResponse().getApiId() == TX_STATUS_RESPONSE) {  // got an rx packet: frame type 89 -transmit status : acts as command confirmation (not referring to Xbee remote AT commands)
            xbee.getResponse().getRx16Response(rx16);
            frametype = 89;
            MeasRx = false;
        }

    }
    else {  ////frametype 0 means no frames picked up. Frametype -1 means frame was in error
        frametype = 0;
        if (xbee.getResponse().isError()) {frametype = -1; }
        E++;
        MeasRx = false;
    }
}

void Parse(void) {
    if (Payload[0] == '<' && Payload[2] == '>') {
        errcode = Payload[1];  //extracts errcode and leaves it in char format
        ERROR();
        MeasRx = false;
    }
    if (MeasRx == true) {

        if (Payload[1] == '0') {
            outFormat = 0;
            stringval[0] = Payload[3];
            stringval[1] = Payload[4];
            stringval[2] = Payload[5];
            stringval[3] = Payload[6];
            stringval[4] = Payload[7];
            stringval[5] = '\0';

        }
        if (Payload[1] == '1') {
            outFormat = 1;
            stringvalin[0] = Payload[2];
            stringvalin[1] = Payload[3];
            stringvalin[2] = Payload[4];
            stringvalin[3] = Payload[5];
            stringvalin[4] = Payload[6];
            stringvalin[5] = Payload[7];
            stringvalin[6] = '\0';
        }
        if (Payload[8] == '@') {
            char tempstring[3] = { Payload[9], Payload[10], '\0' };  //if the dot position was a two digit number, the @ was sent in the hundreds place as a placeholder
            dotpos = atoi(tempstring); //save dot position as an integer
        }
        else {
            char tempstring2[4] = { Payload[8], Payload[9], Payload[10], '\0' };
            dotpos = atoi(tempstring2);//save dot position as an integer
        }
    }
}

void RxCheck(void) {  //this function checks what frames are being recieved 

    if (E > 20) {   //20 consecutive loops with an empty buffer and no valid string/////

        Blackout();
        Tft.drawString("SIGNAL", 65, 175, 3, WHITE);
        Tft.drawString("Rx ERR", 95, 175, 3, WHITE);//indicates that the signal has been lost. 
        delay(1000);
        Tft.drawString("SIGNAL", 65, 175, 3, BLACK);
        Tft.drawString("Rx ERR", 95, 175, 3, BLACK);
        E = 0;  //reset "no frame" counter
        clearLast();
        burnSerial();//pick up with fresh serial data
    }

    if (frametype == 83) {  //sleep mode has been detected
        Tft.fillCircle(152, dotpos, 20, BLACK);
        Tft.fillCircle(152, lastdot, 20, BLACK);
        Tft.fillRectangle(63, 215, 100, 200, BLACK);  //covers display area
        Tft.drawString("SLEEP", 65, 175, 3, WHITE);
        Tft.drawString("MODE", 95, 175, 3, WHITE);//Denotes that the unit is in sleep mode
        delay(4000);
        Tft.drawString("SLEEP", 65, 175, 3, BLACK);
        Tft.drawString("MODE", 95, 175, 3, BLACK);//Denotes that the unit is in sleep mode
        clearLast();
        burnSerial();//pick up with fresh serial data
    }
}

void Readout(void) {
    //Tft.drawNumber(frametype, 30, 198, 2, RED);//debug
    //delay(5);//debug
    //Tft.drawNumber(frametype, 30, 198, 2, BLACK);  //debug
    if (MeasRx == true) {
        if (outFormat == 0) {

            if (stringval[1] != laststringval[1] || stringval[3] != laststringval[3] || stringval[4] != laststringval[4]) {
                Tft.drawString("Hashmarks:", 30, 182, 2, WHITE);
                Tft.drawString(laststringval, 70, 215, 5, BLACK);   //overwrite old
                Tft.drawString(stringval, 70, 215, 5, WHITE);   //print output to screen
            }

            memcpy(laststringval, stringval, 6);  //save string to determine if overwrite needed********This is the fastest way to copy the string, but is not supported on the Arduino 101
            /*laststringval[0] = stringval[0];
            laststringval[1] = stringval[1];
            laststringval[2] = stringval[2];
            laststringval[3] = stringval[3];
            laststringval[4] = stringval[4];
            laststringval[5] = stringval[5];*/
        }
        if (outFormat == 1) {
            if (stringvalin[1] != laststringvalin[1] || stringvalin[3] != laststringvalin[3] || stringvalin[4] != laststringvalin[4] || stringvalin[5] != laststringvalin[5]) {
                Tft.drawString("Inches:", 30, 182, 2, WHITE);
                Tft.drawString(laststringvalin, 70, 215, 4, BLACK);  //overwrite
                Tft.drawString(stringvalin, 70, 215, 4, WHITE);   //print output to screen
            }

            memcpy(laststringvalin, stringvalin, 7);  //save string to determine if overwrite needed  ********This is the fastest way to copy the string, but is not supported on the Arduino 101
            /*laststringvalin[0] = stringvalin[0];
            laststringvalin[1] = stringvalin[1];
            laststringvalin[2] = stringvalin[2];
            laststringvalin[3] = stringvalin[3];
            laststringvalin[4] = stringvalin[4];
            laststringvalin[5] = stringvalin[5];
            laststringvalin[6] = stringvalin[6];*/
        }

        if (dotpos != lastdot) {
            Tft.fillCircle(152, lastdot, 20, BLACK);
            Tft.fillCircle(152, dotpos, 12, WHITE);   //Draws the circle at the new location
            Tft.drawTriangle(152 - 6, dotpos - 10, 152 - 6, dotpos + 10, 152 + 12, dotpos, RED);  //(int poX1, int poY1, int poX2, int poY2, int poX3, int poY3, INT16U color)
            //Tft.drawNumber(lastdot, 150, 215, 2, BLACK);  //overwrite for debug
            //Tft.drawNumber(dotpos, 150, 215, 2, WHITE);   //print output to screen for debug
        }
        lastdot = dotpos;
    }
}

void clearLast(void) {
    memset(laststringval, '\0', 6);  //destroy payload
    memset(laststringvalin, '\0', 7);  //destroy payload
    lastdot = 0;
}

void loadSplash(void) {   //Loads the boeing blue splash screen
    bmpFile = SD.open(__Gsbmp_files[1]);      ///////////////////////////THIS SELECTS THE .bmp FILE TO OPEN. CHANGE THE INDEX NUMBER.
    if (!bmpFile) { Serial.println("didnt find image"); while (1); }
    if (!bmpReadHeader(bmpFile)) { Serial.println("bad bmp"); return; }
    bmpdraw(bmpFile, 0, 0);
    bmpFile.close();
    Tft.drawString("Boeing Proprietary", 175, 305, 2, WHITE);
    Tft.drawString("Copyright 2016 Boeing.", 199, 305, 1, WHITE);
    Tft.drawString("All rights reserved.", 215, 305, 1, WHITE);
    delay(1000);
}

and the same thing happens. Here's a bit of pseudocode that will hopefully show how I have things organized:

void setup(){
Startscreen();  //this screen provides user options
}

void loop(){
do all the other main functions of the program;
}

void Startscreen(){

if this thing, show this
if that thing, show that
take readings
switch(reading){
case(number):
    while(1){
        check for button presses
        if (this){
             if (that){
                    LoadMainScreen();
                     return;         //this is supposed to quit the startscreen function completely and allow the program to move on to the main loop
case(other number);
    do other stuff
    break;
 } //end of case stuff
Do other stuff that the startscreen program may need to do  //this is what I'm seeing after calling return. should not see happening

and the same thing happens.

So here's (most of) my entire code:

///////THIS VERSION IS DEVELOPED FOR THE AT MEGA 

#include <stdint.h>//For Seedstudio Touch
#include <TFTv2.h>//For Seedstudio Touch
#include <SPI.h>
#include <SeeedTouchScreen.h>   //Seedstudio LCD touch screen Library File
#include <SD.h>//For Seedstudio Touch
#include <XBee.h>   //Zigbee Wireless transciever Library File
#include <Printers.h>   //Zigbee Wireless transciever Library File

#define MAX_BMP         10         // bmp file num  //////////////////////////////Seedstudio Touchscreen///////////////////////Seedstudio Touchscreen///////////////////////Seedstudio Touchscreen////
#define FILENAME_LEN    20         // max file name length
const int PIN_SD_CS = 4;         // pin of sd card
const int __Gnbmp_height = 320;    // bmp hight
const int __Gnbmp_width = 240;      // bmp width
unsigned char __Gnbmp_image_offset = 0;   // offset
int __Gnfile_num = 5;             // num of files (change num)
char __Gsbmp_files[5][FILENAME_LEN] = { "boeblue.bmp", "boeblue2.bmp", "787dl.bmp", "Measure3.bmp", "Measure5.bmp" }; // add file name(s) here (change num)//////  The files are zero-indexed into an array
File bmpFile;

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__) // mega
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 54   // can be a digital pin, this is A0
#define XP 57   // can be a digital pin, this is A3 
#elif defined(__AVR_ATmega32U4__) // leonardo
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 18   // can be a digital pin, this is A0
#define XP 21   // can be a digital pin, this is A3 
#else //168, 328, something else
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 14   // can be a digital pin, this is A0
#define XP 17   // can be a digital pin, this is A3 
#endif

#ifdef SEEEDUINO
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 14   // can be a digital pin, this is A0
#define XP 17   // can be a digital pin, this is A3 
#endif

#ifdef MEGA
#define YP A2   // must be an analog pin, use "An" notation!
#define XM A1   // must be an analog pin, use "An" notation!
#define YM 54   // can be a digital pin, this is A0
#define XP 57   // can be a digital pin, this is A3 
#endif 

#define TS_MINX 116*2
#define TS_MAXX 890*2
#define TS_MINY 83*2
#define TS_MAXY 913*2
// For better pressure precision, we need to know the resistance
// between X+ and X- Use any multimeter to read it
// The 2.8" TFT Touch shield has 300 ohms across the X plate
#define BUFFPIXEL       60                    // must be a divisor of 240 
#define BUFFPIXEL_X3    180                // BUFFPIXELx3
TouchScreen ts = TouchScreen(XP, YP, XM, YM); //////////////////////////////Seedstudio Touchscreen///////////////////////Seedstudio Touchscreen///////////////////////Seedstudio Touchscreen////

XBee xbee = XBee();
XBeeResponse response = XBeeResponse();
// create reusable response objects for responses we expect to handle 
Rx16Response rx16 = Rx16Response();
Rx64Response rx64 = Rx64Response();

uint8_t option[] = { 'D', '3' };
uint8_t high[] = { 0x05 };
uint8_t low[] = { 0x04 };
XBeeAddress64 remoteAddress = XBeeAddress64(0x0013a200, 0x0000FFFF); //  SH + SL of the remote radio  //THE HI / LOW ADDRESSES ARE THE 64 BIT ADDRESSES IN HEX OF THE SPECIFIC RADIO THAT IS TO BE COMMANDED.. OR USE 0x0000FFFF AS A BROADCAST ADDRESS
// Create a remote AT request with the IR command
RemoteAtCommandRequest remoteAtRequestD3High = RemoteAtCommandRequest(remoteAddress, option, high, sizeof(high));
RemoteAtCommandRequest remoteAtRequestD3Low = RemoteAtCommandRequest(remoteAddress, option, low, sizeof(low));
// Create a Remote AT response object
RemoteAtCommandResponse remoteAtResponse = RemoteAtCommandResponse();

uint8_t SlpCmd[] = { 0x26 };  //byte '&' used for remote sleep command
Tx64Request txSleepCmd = Tx64Request(remoteAddress, SlpCmd, sizeof(SlpCmd));  //object for transmit request

uint8_t AdptCmd[] = { 0x25 };  //byte '%' used for Auto Adapt command
Tx64Request txAdptCmd = Tx64Request(remoteAddress, AdptCmd, sizeof(AdptCmd));  //object for transmit request

uint8_t InCmd[] = { 0x49 };  //byte 'I' used for Inch units command
Tx64Request txInCmd = Tx64Request(remoteAddress, InCmd, sizeof(InCmd));  //object for transmit request

uint8_t HashCmd[] = { 0x48 };  //byte 'H' used for hashmark units command
Tx64Request txHashCmd = Tx64Request(remoteAddress, HashCmd, sizeof(HashCmd));  //object for transmit request

uint8_t Capt[] = { 0x7c };  //byte '|' used for captive command
Tx64Request txCapt = Tx64Request(remoteAddress, Capt, sizeof(Capt));  //object for transmit request

uint8_t Cancl[] = { 0x43 };  //byte 'C' used for cancel captive command
Tx64Request txCancl = Tx64Request(remoteAddress, Cancl, sizeof(Cancl));  //object for transmit request

TxStatusResponse txStatus = TxStatusResponse();

char stringval[6];  //buffers for individual measurement values
char laststringval[6] = {};
char stringvalin[7];
char laststringvalin[7] = {};
int outFormat;
int dotpos;
int lastdot = 0;
byte errcode;

const int bufsize = 14;
char Payload[bufsize] = {};   //recieved string
int L; //data length 

unsigned long t1 = 0;
unsigned long t2 = 0;
const int D = 22;// Standard delay to allow for next frame to come in


int greenled = 11;
int redled = 12;
int blueled = 13;  ////Analog pins for RGB LED control


bool startFresh = true;
int frametype;
const int scantime = 20000;  ////time alloted in ms for initial scan for IR cam
int E = 0;  //no frame found counter
int Er = 0;  //frame Rx error counter
bool MeasRx = false;


void setup() 
{
    pinMode(redled, OUTPUT);
    pinMode(greenled, OUTPUT);
    pinMode(blueled, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, OUTPUT);
    pinMode(7, OUTPUT);

    Serial.begin(57600);
    xbee.setSerial(Serial);

    pinMode(PIN_SD_CS, OUTPUT);
    digitalWrite(PIN_SD_CS, HIGH);
    Sd2Card card;
    card.init(SPI_FULL_SPEED, PIN_SD_CS);
    Tft.TFTinit();  // init TFT library
    Tft.setDisplayDirect(DOWN2UP);
    if (!SD.begin(PIN_SD_CS))
    {
        Serial.println("SD failed!");
        while (1);                               // init fail, die here
    }
    Serial.println("SD ok!");
    for (int f = 0; f < 5; f++) {   //odd problem fix- queries touchscreen 5 times to clear any erronious values. This prevents problem where the first point retrieved is sometimes invalid 
        Point p = ts.getPoint();
        delay(20);
    }
    digitalWrite(7, HIGH); //  ( TFT_BL_ON; ) //these functions exist in TFTv2.h, but are bypassed here because of compiler issues with recognizing the Arduino101 board definition. 
    if (startFresh) { StartScreen(); }
}

void loop()    //////////////////////////////////////////MAIN SEQUENCE////////////////////////////////////////////////////////////////
{
 
    RxPacket();
    RxCheck();
    Parse();
    Readout();
    //ButtonStuff();
}

///////////////////////////////////////////SUBROUTINES////////////////////////////////////////////////////////////////////////

void StartScreen(void) {

    if (startFresh == true) {
        loadSplash();
        burnSerial();
        Tft.drawString("Scanning...", 125, 300, 3, WHITE);
        t1 = millis(); t2 = millis();
        while (t2 - t1 < scantime) {// Scans for packets for scantime or until a good packet is received
            RxPacket();
            if (frametype == 81 || frametype == 83) {
                break;  //Stop if either sleep or measurement frame is found
            }
            t2 = millis();
        }
    }


     
    if (frametype == 0 || frametype == -1) {  // Scan returned no sleep or measurement frames within scan time. If frametype is now 0 or -1, it would have been set in the last, most recent iteration of RxPacket
        Tft.fillRectangle(117, 319, 55, 320, RED);
        Tft.drawString("No device found. ", 135, 283, 2, WHITE);
        Tft.fillRectangle(170, 319, 75, 320, GRAY2);
        delay(375);
        Tft.drawRectangle(182, 105, 40, 120, YELLOW);
        Tft.drawString("Rescan? ", 195, 220, 2, WHITE);
        while (1) {
            delay(D);
            Point p = ts.getPoint(); //Monitor buttons
            p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);  //Monitor buttons
            p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320);  //Monitor buttons
            if (p.x > 155 && p.x < 219 && p.y > 55 && p.y < 225) {   //// Choose to rescan (only other option is to turn the unit off and try again later)
                Tft.drawRectangle(182, 105, 40, 120, MAGENTA);
                delay(375);
                startFresh = true;
                StartScreen();
            }
        }
    }
    switch (frametype) {
    case (81) : //measurement frame detected. System found measuring //////////////////////////////////////////measurement frame detected. System found measuring
        WakePinReset();
        Tft.fillRectangle(117, 319, 70, 320, DARK_GREEN);
        Tft.drawString("Rudder Cam Detected", 132, 310, 2, WHITE);
        Tft.drawString("Status:", 160, 310, 2, WHITE);
        Tft.drawString("Sleep Mode", 160, 173, 2, DARK_GREEN);
        Tft.drawString("Measuring", 160, 168, 2, WHITE);
        Tft.fillRectangle(185, 319, 55, 320, GRAY2);
        Tft.drawString(" Measure     Sleep", 200, 315, 2, WHITE);
        Tft.drawRectangle(192, 182, 30, 125, YELLOW);
        Tft.drawRectangle(192, 18, 30, 100, YELLOW);
        t1 = millis();  t2 = millis();
        while (1) {
            t2 = millis();
            if (t2 - t1 > 5000) { Recheckframe(); } //scan again every 5 seconds in case status has changed
            Point p = ts.getPoint();   //Monitor buttons
            p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);
            p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320);
            if (p.x > 185 && p.x < 220 && p.y > 1 && p.y < 125) {     //// Choose to sleep //do stuff to sleep   //// Choose to sleep //do stuff to sleep   //// Choose to sleep //do stuff to sleep
                Tft.drawRectangle(192, 18, 30, 100, MAGENTA);
                delay(375);
                Tft.fillRectangle(185, 319, 55, 320, GRAY2);
                Tft.drawString(" IR Cam Power Save", 200, 315, 2, WHITE);
                delay(375);
                if (Captivate()) { //this sequence calls captive, then sends sleep command. if either function returns false, noresponse() makes an alert and starts the scan over
                    if (SendSlpCmd()) { 
                        startFresh = true; 
                        StartScreen(); 
                    }
                    else {noresponse();}
                }
                else {noresponse();}
            }
            if (p.x > 185 && p.x < 220 && p.y > 165 && p.y < 320) {   //// Choose to measure //do stuff to measure   //// Choose to measure //do stuff to measure   //// Choose to measure //do stuff to measure
                Tft.drawRectangle(192, 182, 30, 125, MAGENTA);
                delay(375);   
                p.x = 0;  //set arbitrary value so sleep screen is not possible (odd problem fix)
                LoadMeasScrn();
                loop();
                return;
            }
        }
        break;  //81 case done
    case (83) : //Sleep frame detected; system found sleeping //Sleep frame detected; system found sleeping////////////////////Sleep frame detected; system found sleeping
        Tft.fillRectangle(117, 319, 70, 320, GRAY2);
        Tft.drawString("Rudder Cam Detected", 132, 310, 2, WHITE);
        Tft.drawString("Status:", 160, 310, 2, WHITE);
        Tft.drawString("Measuring", 160, 168, 2, GRAY2);
        Tft.drawString("Sleep Mode", 160, 173, 2, WHITE);
        Tft.fillRectangle(185, 319, 55, 320, GRAY2);
        Tft.drawString(" Measure     Sleep", 200, 315, 2, WHITE);
        Tft.drawRectangle(192, 182, 30, 125, YELLOW);
        t1 = millis();
        t2 = millis();
        while (1) {
            t2 = millis();
            if (t2 - t1 > 5000) {//scan again every 5 seconds in case status has changed
                Recheckframe();
            }
            Point p = ts.getPoint();   //Monitor buttons
            p.x = map(p.x, TS_MINX, TS_MAXX, 0, 240);
            p.y = map(p.y, TS_MINY, TS_MAXY, 0, 320);
            if (p.x > 185 && p.x < 220 && p.y > 165 && p.y < 320) {   //// Choose to measure //do stuff to measure   //// Choose to measure //do stuff to measure   //// Choose to measure //do stuff to measure
                Tft.drawRectangle(192, 182, 30, 125, MAGENTA);
                delay(375);
                p.x = 0;  //set arbitrary value so sleep screen is not possible (odd problem fix)
                Tft.fillRectangle(185, 319, 55, 320, GRAY2);
                Tft.drawString(" Waking Rudder Cam", 200, 315, 2, WHITE);
                delay(375);
                WakePin();
                delay(2000);
                if (ListenForChar('O')) { //Listen for confirmation that the main unit woke from sleep
                    LoadMeasScrn();
                    loop();
                    return;
                }
                else { noresponse(); }
            }
        }
    } 
}

void LoadMeasScrn() {
    bmpFile = SD.open(__Gsbmp_files[3]);      ///////////////////////////THIS SELECTS THE .bmp FILE TO OPEN. CHANGE THE INDEX NUMBER.
    if (!bmpFile) { Serial.println("didnt find image"); while (1); }   ////This loads the measurement screen/////////
    if (!bmpReadHeader(bmpFile)) { Serial.println("bad bmp"); return; } ////This loads the measurement screen/////////
    bmpdraw(bmpFile, 0, 0); ////This loads the measurement screen/////////
    bmpFile.close(); ////This loads the measurement screen/////////
}

bool Recheckframe(void) {//For use in start screen, function rechecks frame type. Returns true if frametype has switched from sleep to meas or vice versa
    int lastframetype = frametype;  //remember frametype when stepping into this function
    Tft.drawRectangle(192, 182, 30, 125, GRAY2);
    Tft.drawRectangle(192, 18, 30, 100, GRAY2); //gray out buttons for a sec while rescanning
    t1 = millis(); t2 = millis();
    while (t2 - t1 < 100) {  //read packets for 100ms and look change in frametype
        t2 = millis();
        RxPacket();
        delay(D); //slow it down for new frames to come in- rxpacket returns 0 frametype if no new frame is found
        if (lastframetype == 81 && frametype == 83) {  //went to sleep //indicates change in sleep/meas state, ignoring errors and nonconforming frames
            startFresh = false;  //do not re-run scan, just change frametype.
            StartScreen();
            break;
        }
        if (lastframetype == 83 && frametype == 81) {  //woke up //indicates change in sleep/meas state, ignoring errors and nonconforming frames
            startFresh = false;  //do not re-run scan, just change frametype.
            StartScreen();
            break;
        }
        if (E >= 20 || Er >= 20) {  //have recieved 20 bad frames without a good frame. Signal must be lost
        Tft.fillRectangle(185, 319, 55, 320, GRAY2);
        Tft.drawString("Signal Lost", 200, 315, 2, WHITE);
        delay(2000);
        startFresh = true;
        E = 0; Er = 0;
        StartScreen();  //Start all over 
        }
    }
    frametype = lastframetype; //leave frametype unchanged by new scans if no change in state is found. This effectively ignored 0 and -1 frametypes generated during rescans
    Tft.drawRectangle(192, 182, 30, 125, YELLOW);
    if (frametype == 81) { Tft.drawRectangle(192, 18, 30, 100, YELLOW); } // re-yellow buttons. Sleep button only gets re-yellowed if it was available before scan
}

bool Captivate(void) {//Sends the captive command and makes sure it is recieved. Outputs true if captive. Runs for a total of about 5 seconds maximum
    for (int i = 0; i <= 50; ++i) {
        xbee.send(txCapt);  //transmit the remote sleep command.
        delay(D);
        if (ListenForChar('|')) { return true; }
    }
    return false;
}

bool SendSlpCmd(void) { //Send sleep command char
    for (int i = 0; i <= 60; ++i) {   //Runs for a total of about 6 seconds maximum
        xbee.send(txSleepCmd);  //transmit the remote sleep command.
        delay(D);
        if (ListenForFrametype(83, 100)) { return true; }
    }
    return false;
}

bool ListenForFrametype(int X , int Y) { //X is the frametype, Y is the duration of listening in miliseconds
    t1 = millis();
    t2 = millis();
    while (t2 - t1 < Y) {  //read packets for 100ms and look for response
        t2 = millis();
        RxPacket();
        delay(D); //slow it down for new frames to come in- rxpacket returns 0 if no new frame is found
        if (frametype == X) { //Sleep Blip Detected- IR cam unit is now in sleep mode
            return true;
        }
    }
    return false;
}

bool WakePin(void){  //wakes Arduino by setting Xbee D3 low. Immidiately resets D3 back to high and returns true if all is executed.
    for (int i = 0; i <= 50; ++i) {   //Runs for a total of about 5 seconds maximum
        xbee.send(remoteAtRequestD3Low);  //transmit the remote sleep command.
        delay(D);
        if (ListenForRATCmdResponse(100)) { return true; }
    }
    return false;
}

bool WakePinReset(void) { //sets D3 high and returns true if executed.
    for (int i = 0; i <= 50; ++i) {   //Runs for a total of about 5 seconds maximum
        xbee.send(remoteAtRequestD3High);  
        delay(D);
        if (ListenForRATCmdResponse(100)) {return true;}
    }
    return false;
}

bool ListenForRATCmdResponse(int Y) { //Y is the while loop time in ms
    t1 = millis();
    t2 = millis();
    while (t2 - t1 < Y) {  //read packets for 100ms and look for response
        t2 = millis();
        xbee.readPacket();
        delay(D); //slow it down for new frames to come in- rxpacket returns 0 if no new frame is found
        if (xbee.getResponse().getApiId() == REMOTE_AT_COMMAND_RESPONSE) { //It's a remote AT command response
            xbee.getResponse().getRemoteAtCommandResponse(remoteAtResponse);  //retrieve the response
            if (remoteAtResponse.getStatus() == 0 && remoteAtResponse.isOk() == true) {  //It was successfully transmitted, received, and executed
                return true;
            }
        }
    }
    return false; //returns false unless affirmative remote AT response was found
}

bool ListenForChar(char X) {
    t1 = millis();
    t2 = millis();
    while (t2 - t1 < 5000) {  //read packets for 100ms and look for response
        t2 = millis();
        xbee.readPacket();
        delay(D); //slow it down for new frames to come in- rxpacket returns 0 if no new frame is found
        if (xbee.getResponse().isAvailable()) { //got a response
            xbee.getResponse().getTxStatusResponse(txStatus);  //retrieve the response
            if (xbee.getResponse().getApiId() == RX_16_RESPONSE) { //It's serial data
                L = rx16.getDataLength();
                char string[32] = {};
                for (int p = 0; p <= L - 1; p++) {  //This scans all of the incoming string for the captive confirmation byte. This allows for any possible variation in packetization timing
                    string[p] = rx16.getData(p);
                    if (string[p] == X) {  
                        return true;
                    }
                }
            }
        }
    }
    return false; //returns false unless character was found
}

void RxPacket(void) {// Scans for packets for (timeout) seconds or until a packet is received. 

    xbee.readPacket(); //Reads all available serial bytes until a packet is parsed, an error occurs, or the buffer is empty.

    if (xbee.getResponse().isAvailable()) {   // got a packet

        if (xbee.getResponse().getApiId() == RX_16_IO_RESPONSE) {  // got an rx packet: frame type 83 -periodic sleep blip
            frametype = 83;
            MeasRx = false;
            E = 0; //resets  "no good frame" counter
            Er = 0;
        }

        if (xbee.getResponse().getApiId() == RX_16_RESPONSE) {  // got an rx packet: frame type 81 -measurement packet (or in general a packet that contains serial data)***************************
            xbee.getResponse().getRx16Response(rx16);
            frametype = 81;
            MeasRx = false;//not yet true until the below conditions are met. 
            E = 0; //resets  "no good frame" counter
            Er = 0;
            L = rx16.getDataLength();
            for (int p = 0; p <= L - 1; p++) {
                Payload[p] = rx16.getData(p);
            }
            //Tft.drawNumber(L, 45, 182, 2, RED);  //debug
            Payload[L - 1] = '\0'; // valid string now constructed -->  Note: At L = 14, rx16.getDataLength() is longer than the actual data string length by one. Unknown why.
            if (Payload[0] == '`' && Payload[11] == '*' && L == 14) {//got a valid measurement string
                MeasRx = true; //got a valid measurement string
                outFormat = Payload[1];
            }
        }

        if (xbee.getResponse().getApiId() == TX_STATUS_RESPONSE) {  // got an rx packet: frame type 89 -transmit status : acts as command confirmation (not referring to Xbee remote AT commands)
            xbee.getResponse().getRx16Response(rx16);
            frametype = 89;
            MeasRx = false;
        }

    }
    else {  ////frametype 0 means no frames picked up. Frametype -1 means frame was in error
        frametype = 0;
        if (xbee.getResponse().isError()) {frametype = -1; }
        E++;
        MeasRx = false;
    }
}

void Parse(void) {
    if (Payload[0] == '<' && Payload[2] == '>') {
        errcode = Payload[1];  //extracts errcode and leaves it in char format
        ERROR();
        MeasRx = false;
    }
    if (MeasRx == true) {

        if (Payload[1] == '0') {
            outFormat = 0;
            stringval[0] = Payload[3];
            stringval[1] = Payload[4];
            stringval[2] = Payload[5];
            stringval[3] = Payload[6];
            stringval[4] = Payload[7];
            stringval[5] = '\0';

        }
        if (Payload[1] == '1') {
            outFormat = 1;
            stringvalin[0] = Payload[2];
            stringvalin[1] = Payload[3];
            stringvalin[2] = Payload[4];
            stringvalin[3] = Payload[5];
            stringvalin[4] = Payload[6];
            stringvalin[5] = Payload[7];
            stringvalin[6] = '\0';
        }
        if (Payload[8] == '@') {
            char tempstring[3] = { Payload[9], Payload[10], '\0' };  //if the dot position was a two digit number, the @ was sent in the hundreds place as a placeholder
            dotpos = atoi(tempstring); //save dot position as an integer
        }
        else {
            char tempstring2[4] = { Payload[8], Payload[9], Payload[10], '\0' };
            dotpos = atoi(tempstring2);//save dot position as an integer
        }
    }
}

void RxCheck(void) {  //this function checks what frames are being recieved 

    if (E > 20) {   //20 consecutive loops with an empty buffer and no valid string/////

        Blackout();
        Tft.drawString("SIGNAL", 65, 175, 3, WHITE);
        Tft.drawString("Rx ERR", 95, 175, 3, WHITE);//indicates that the signal has been lost. 
        delay(1000);
        Tft.drawString("SIGNAL", 65, 175, 3, BLACK);
        Tft.drawString("Rx ERR", 95, 175, 3, BLACK);
        E = 0;  //reset "no frame" counter
        clearLast();
        burnSerial();//pick up with fresh serial data
    }

    if (frametype == 83) {  //sleep mode has been detected
        Tft.fillCircle(152, dotpos, 20, BLACK);
        Tft.fillCircle(152, lastdot, 20, BLACK);
        Tft.fillRectangle(63, 215, 100, 200, BLACK);  //covers display area
        Tft.drawString("SLEEP", 65, 175, 3, WHITE);
        Tft.drawString("MODE", 95, 175, 3, WHITE);//Denotes that the unit is in sleep mode
        delay(4000);
        Tft.drawString("SLEEP", 65, 175, 3, BLACK);
        Tft.drawString("MODE", 95, 175, 3, BLACK);//Denotes that the unit is in sleep mode
        clearLast();
        burnSerial();//pick up with fresh serial data
    }
}

void Readout(void) {
    //Tft.drawNumber(frametype, 30, 198, 2, RED);//debug
    //delay(5);//debug
    //Tft.drawNumber(frametype, 30, 198, 2, BLACK);  //debug
    if (MeasRx == true) {
        if (outFormat == 0) {

            if (stringval[1] != laststringval[1] || stringval[3] != laststringval[3] || stringval[4] != laststringval[4]) {
                Tft.drawString("Hashmarks:", 30, 182, 2, WHITE);
                Tft.drawString(laststringval, 70, 215, 5, BLACK);   //overwrite old
                Tft.drawString(stringval, 70, 215, 5, WHITE);   //print output to screen
            }

            memcpy(laststringval, stringval, 6);  //save string to determine if overwrite needed********This is the fastest way to copy the string, but is not supported on the Arduino 101
            /*laststringval[0] = stringval[0];
            laststringval[1] = stringval[1];
            laststringval[2] = stringval[2];
            laststringval[3] = stringval[3];
            laststringval[4] = stringval[4];
            laststringval[5] = stringval[5];*/
        }
        if (outFormat == 1) {
            if (stringvalin[1] != laststringvalin[1] || stringvalin[3] != laststringvalin[3] || stringvalin[4] != laststringvalin[4] || stringvalin[5] != laststringvalin[5]) {
                Tft.drawString("Inches:", 30, 182, 2, WHITE);
                Tft.drawString(laststringvalin, 70, 215, 4, BLACK);  //overwrite
                Tft.drawString(stringvalin, 70, 215, 4, WHITE);   //print output to screen
            }

            memcpy(laststringvalin, stringvalin, 7);  //save string to determine if overwrite needed  ********This is the fastest way to copy the string, but is not supported on the Arduino 101
            /*laststringvalin[0] = stringvalin[0];
            laststringvalin[1] = stringvalin[1];
            laststringvalin[2] = stringvalin[2];
            laststringvalin[3] = stringvalin[3];
            laststringvalin[4] = stringvalin[4];
            laststringvalin[5] = stringvalin[5];
            laststringvalin[6] = stringvalin[6];*/
        }

        if (dotpos != lastdot) {
            Tft.fillCircle(152, lastdot, 20, BLACK);
            Tft.fillCircle(152, dotpos, 12, WHITE);   //Draws the circle at the new location
            Tft.drawTriangle(152 - 6, dotpos - 10, 152 - 6, dotpos + 10, 152 + 12, dotpos, RED);  //(int poX1, int poY1, int poX2, int poY2, int poX3, int poY3, INT16U color)
            //Tft.drawNumber(lastdot, 150, 215, 2, BLACK);  //overwrite for debug
            //Tft.drawNumber(dotpos, 150, 215, 2, WHITE);   //print output to screen for debug
        }
        lastdot = dotpos;
    }
}

void clearLast(void) {
    memset(laststringval, '\0', 6);  //destroy payload
    memset(laststringvalin, '\0', 7);  //destroy payload
    lastdot = 0;
}

void loadSplash(void) {   //Loads the boeing blue splash screen
    bmpFile = SD.open(__Gsbmp_files[1]);      ///////////////////////////THIS SELECTS THE .bmp FILE TO OPEN. CHANGE THE INDEX NUMBER.
    if (!bmpFile) { Serial.println("didnt find image"); while (1); }
    if (!bmpReadHeader(bmpFile)) { Serial.println("bad bmp"); return; }
    bmpdraw(bmpFile, 0, 0);
    bmpFile.close();
    Tft.drawString("Boeing Proprietary", 175, 305, 2, WHITE);
    Tft.drawString("Copyright 2016 Boeing.", 199, 305, 1, WHITE);
    Tft.drawString("All rights reserved.", 215, 305, 1, WHITE);
    delay(1000);
}
added 934 characters in body
Source Link
Loading
Source Link
Loading