most functionality to splashdwon, find neutral and start mission. short timeouts still in code for testing, will adjust to go directly to sit_idle after splashdown

Dependencies:   mbed MODSERIAL FATFileSystem

MbedLogger/MbedLogger.cpp

Committer:
tnhnrl
Date:
2018-06-29
Revision:
70:0e5180befedd
Parent:
69:919ac8d7e023
Child:
71:939d179478c4

File content as of revision 70:0e5180befedd:

#include "MbedLogger.hpp"
#include "StaticDefs.hpp"

  //Timer t;    //used to test time to create packet    //timing debug

MbedLogger::MbedLogger(string file_system_input_string) {
    _file_system_string = file_system_input_string;
    _full_file_path_string = _file_system_string + "LOG000.csv";    //use multiple logs in the future? (after file size is too large)  
    _file_number = 0;
    _file_transmission = true;
    _confirmed_packet_number = 0;   //must set this to zero
    _transmit_counter = 0;
    _file_transmission_state = -1;
    _total_number_of_packets = 0;
    _mbed_transmit_loop = false;
    _received_filename = "";
    
    _log_file_line_counter = 0;     //used to set timer in finite state machine based on size of log
    
    _heading_string = "state_string,state_ID,timer,depth_cmd,depth_ft,pitch_cmd,pitch_deg,bce_cmd,bce_mm,batt_cmd,batt_mm,pitchRate_degs,depthRate_fps,sys_amps,sys_volts,int_press_PSI\n";
    
    _transmit_packet_num = 0;
    
    _fsm_transmit_complete = false;
}

//this function has to be called for the time to function correctly
void MbedLogger::setLogTime() {
    pc().printf("\n%s log time set.\n\r", _file_system_string.c_str());
    set_time(1518467832);   // Set RTC time to Mon, 12 FEB 2018 15:37
}

//in the future create the ability to set the start time
int MbedLogger::getSystemTime() {
    time_t seconds = time(NULL);    // Time as seconds since January 1, 1970
    
    return seconds;
}

void MbedLogger::recordData(int current_state) {
    int data_log_int = mbedLogger().getSystemTime();                 //read the system timer to get unix timestamp
    //_data_log[0] = mbedLogger().getSystemTime();                 //read the system timer to get unix timestamp
    _data_log[1] = depthLoop().getCommand();        //depth command
    _data_log[2] = depthLoop().getPosition();       //depth reading
    _data_log[3] = pitchLoop().getCommand();        //pitch command
    _data_log[4] = pitchLoop().getPosition();       //pitch reading
    _data_log[5] = bce().getSetPosition_mm();       //BCE command
    _data_log[6] = bce().getPosition_mm();          //BCE reading
    _data_log[7] = batt().getSetPosition_mm();      //Batt command
    _data_log[8] = batt().getPosition_mm();         //Batt reading    
    _data_log[9] = pitchLoop().getVelocity();       // pitchRate_degs (degrees per second)
    _data_log[10] = depthLoop().getVelocity();      // depthRate_fps (feet per second)
    
    // extrapolated from graph if V_s = 5.0
    // https://www.nxp.com/docs/en/data-sheet/MPXA6115A.pdf 
    float press_xducer_PSI = (22.029*(5.0*adc().readCh5()/4095.0) + 10.884) * 0.145038; // Press_Xducer (on-board)
    float voltage_input = (adc().readCh6()/4095.0) * 5.0 * 7.8;  //Vin_Mon on PCB schematic (system input voltage from power supply)
    float current_input = adc().readCh7()/4095.0; // I_mon (appears to be one-to-one from the schematic)
    // presssure onboard
    
    
    _data_log[11] = current_input;      // i_in
    _data_log[12] = voltage_input;      // v_in
    _data_log[13] = press_xducer_PSI;   // int_press_PSI
    
    //check what the current state is and create that string
    string string_state;
    if (current_state == SIT_IDLE)
        string_state = "SIT_IDLE";
    else if (current_state == FIND_NEUTRAL)
        string_state = "FIND_NEUTRAL";
    else if (current_state == DIVE)
        string_state = "DIVE";
    else if (current_state == RISE)
        string_state = "RISE";
    else if (current_state == FLOAT_LEVEL)
        string_state = "FLOAT_LEVEL";
    else if (current_state == FLOAT_BROADCAST)
        string_state = "FLOAT_BROADCAST";          
    else if (current_state == EMERGENCY_CLIMB)
        string_state = "EMERGENCY_CLIMB";
    else if (current_state == MULTI_DIVE)
        string_state = "MULTI_DIVE";
    else if (current_state == MULTI_RISE)
        string_state = "MULTI_RISE";
    else if (current_state == KEYBOARD)
        string_state = "KEYBOARD";
    else if (current_state == CHECK_TUNING)
        string_state = "CHECK_TUNING";
    else if (current_state == POSITION_DIVE)
        string_state = "POSITION_DIVE"; 
    else if (current_state == POSITION_RISE)
        string_state = "POSITION_RISE";
    else if (current_state == TRANSMIT_MBED_LOG) 
        string_state = "TRANSMIT_MBED_LOG";
    else if (current_state == RECEIVE_SEQUENCE) 
        string_state = "RECEIVE_SEQUENCE";    
        
        
    string blank_space = ""; //to get consistent spacing in the file
    
    //record the string state, integer state, and then the data
    //_heading_string is 160 characters long
    
    //make function that checks length of header versus string below, add padding
    
    fprintf(_fp, "%16s,%.2d,",string_state.c_str(),current_state);
    fprintf(_fp, "%11d,",data_log_int); //length 10
    fprintf(_fp, "%6.1f,%6.1f,%6.1f,%6.1f,%6.1f,%6.1f,%6.1f,%6.1f,%6.1f,%6.1f,%6.3f,%6.2f,%6.1f%38s\n",_data_log[1],
    _data_log[2],_data_log[3],_data_log[4],_data_log[5],_data_log[6],_data_log[7],_data_log[8],_data_log[9],_data_log[10],_data_log[11],_data_log[12],_data_log[13],blank_space.c_str());
    
    //each line in the file is 160 characters long text-wise, check this with a file read
}

void MbedLogger::printMbedDirectory() {
    DIR *dir;
    struct dirent   *dp;        //dirent.h is the format of directory entries
    int log_found =0,loop=0;
    long int temp=0;
    
    //char * char_pointer;
    char * numstart;
    //char *numstop;
    
    pc().printf("\n\rPrinting out the directory of device %s\n\r", _file_system_string.c_str());
    
    if ( NULL == (dir   = opendir( _file_system_string.c_str() )) ) {
        pc().printf("MBED directory could not be opened\r\n");
    }                   
    else
    {
        while ( NULL != (dp    = readdir( dir )) )
        {
            if(strncmp(dp->d_name,"LOG",3)==0)
            {
                log_found=1;
                /*numstart = dp->d_name; //Look for third character (do safety)
                numstop = strchr(dp->d_name,'.');
                if(numstart!=NULL&&numstop!=NULL)
                {
                    temp=numstop-numstart;
                }
                else
                    log_found=0; //Something is not right. Ignore
                */
                numstart=dp->d_name+3;
                temp=strtol(numstart,NULL,10);      //add in check to see if this is null (start logs at one)
            }
            else
                log_found=0;
            pc().printf( "%d. %s (log file: %d, %d)\r\n", loop, dp->d_name,log_found,temp); 
            
            loop++;
        }
    }
}

//prints current log file to the screen (terminal)
void MbedLogger::printCurrentLogFile() {
    //open the file for reading
    string file_name_string = _file_system_string + "LOG000.csv";
    
    _log_file_line_counter = 0;

    _fp = fopen(file_name_string.c_str(), "r");
       
    char buffer[500];
    
    //read the file line-by-line and print that to the screen
    pc().printf("\n\rCURRENT MBED LOG FILE /local/Log%03d.csv:\n\n\r",_file_number);
    while (!feof(_fp)) {
        // read in the line and make sure it was successful
        if (fgets(buffer,500,_fp) != NULL) {            //stops at new line
            pc().printf("%s\r",buffer);
            _log_file_line_counter++;
        }
    }
    
    //fgets stops when either (n-1) characters are read, the newline character is read,
    // or the end-of-file is reached
    
    //close the file
    closeLogFile();
    pc().printf("\n\rLog file closed. Lines in log file: %d.\n\r", _log_file_line_counter);
}

void MbedLogger::openFileForTransmit() { 
    pc().printf("\n\ropenFileForTransmit\n\r");   
    //open the current file to read the contents
    string file_name_string = _file_system_string + "LOG000.csv";

    _fp = fopen(file_name_string.c_str(), "r");
    
    _file_transmission = true;
}

void MbedLogger::createDataPacket() {     
    // packet is 7565 0001 FFFF EEEE CC DATA DATA DATA ... CRC1 CRC2
    
    //CLEAR: Removes all elements from the vector (which are destroyed), leaving the container with a size of 0.
    _data_packet.clear();
    
    //DATA PACKET HEADER
    _data_packet.push_back(117);                             //0x75
    _data_packet.push_back(101);                             //0x65    
    
    _data_packet.push_back(_packet_number/256);                //current packet number in 0x#### form
    _data_packet.push_back(_packet_number%256);                //current packet number in 0x#### form
    
    _data_packet.push_back(_total_number_of_packets/256);                //total number of packets, 0x#### form
    _data_packet.push_back(_total_number_of_packets%256);                //total number of packets, 0x#### form
    
    _data_packet.push_back(_current_line_length);

    //pc().printf("DEBUG: Current line buffer: %s\n\r", _line_buffer);        //debug

    //DATA FROM LINE READ (read string character by chracter)
    for (int i = 0; i < _current_line_length; i++) {
        _data_packet.push_back(_line_buffer[i]);
    }
    
    //CRC CALCULATIONS BELOW
    //character version of calculation screws up on null character 0x00, scrapped and using vector of integers

    int crc_one = calcCrcOne();
    int crc_two = calcCrcTwo();
    
    //place the crc bytes into the data packet that is transmitted
    _data_packet.push_back(crc_one);
    _data_packet.push_back(crc_two);
}

//new 6/27/2018
void MbedLogger::createDataPacket(char line_buffer_sent[], int line_length_sent) {     
    // packet is 7565 0001 FFFF EEEE CC DATA DATA DATA ... CRC1 CRC2
    
    //CLEAR: Removes all elements from the vector (which are destroyed), leaving the container with a size of 0.
    _data_packet.clear();
    
    //DATA PACKET HEADER
    _data_packet.push_back(117);                             //0x75
    _data_packet.push_back(101);                             //0x65    
    
    _data_packet.push_back(_packet_number/256);                //current packet number in 0x#### form
    _data_packet.push_back(_packet_number%256);                //current packet number in 0x#### form
    
    _data_packet.push_back(_total_number_of_packets/256);                //total number of packets, 0x#### form
    _data_packet.push_back(_total_number_of_packets%256);                //total number of packets, 0x#### form
    
    _data_packet.push_back(line_length_sent);

    //pc().printf("DEBUG: Current line buffer: %s\n\r", _line_buffer);        //debug

    //DATA FROM LINE READ (read string character by chracter)
    for (int i = 0; i < line_length_sent; i++) {
        _data_packet.push_back(line_buffer_sent[i]);
    }
    
    //CRC CALCULATIONS BELOW
    //character version of calculation screws up on null character 0x00, scrapped and using vector of integers

    int crc_one = calcCrcOne();
    int crc_two = calcCrcTwo();
    
    //place the crc bytes into the data packet that is transmitted
    _data_packet.push_back(crc_one);
    _data_packet.push_back(crc_two);
    
    //pc().printf("debug createDataPacket(char line_buffer_sent[], int line_length_sent)\n\r");
}

//should i save it as a string and transmit the string?  next iteration maybe

void MbedLogger::transmitDataPacket() {
    //WRITE the data (in bytes) to the serial port
    for (_it=_data_packet.begin(); _it < _data_packet.end(); _it++) {
        pc().putc(*_it); //send integers over serial port one byte at a time
    }
}

// test to see if transmitDataPacket is working slower than you think.

// REACH ONE CHAR AT A TIME (EACH ITERATION OF STATE MACHINE...)


void MbedLogger::continuouslyTransmitDataNoTimer() {
    string file_name_string = _file_system_string + "LOG000.csv";
    
    _fp = fopen(file_name_string.c_str(), "r");
    
    static int packet_num = 0;
    
    while(!feof(_fp)) {
    
        _packet_number = packet_num;
        
        //fseek
            
        readPacketInSeries();   //not using this but for testing purposes...
    
    //    // createDataPacket requires _packet_number, _total_number_of_packets, _current_line_length (data packet size)
    //    // uses char _line_buffer[256] variable to hold characters read from the file
    //    // packs this into a vector for transmission         
        
        createDataPacket();                                                    
            
        transmitDataPacket(); 
            
        packet_num++;
        
        led3() = !led3();
        
        //check for incoming request
    }
    
    closeLogFile(); //close log file if open
    led4() = !led4();
}

bool MbedLogger::fsmTransmitData() {    //using the finite state machine   
    //pc().printf("debug fsmTransmitData (%d) (tpn: %d)\n\r",_fp,_transmit_packet_num);
     
    if (!feof(_fp) and (!_fsm_transmit_complete)) {   //check for end of file
        wait(0.1);

        //based on the internal packet number of the class 
        //createDataPacket
        //transmit data packet   
        
        transmitPacketNumber(_packet_number);
        
        pc().printf("\r");  // for proper spacing
    
        _packet_number++;
        led2() = !led2();
        
        return true;
    }
    
    else {
        //is there a better way to do this?
        //this flag was required because the additional requests kept generating two packets through the FSM
        // by calling         mbedLogger().fsmTransmitData();
        //and                 mbedLogger().checkForPythonTransmitRequest();
        _fsm_transmit_complete = true;
    
        return false;
    }
}

void MbedLogger::continuouslyTransmitData() {
    static int packet_num = 0;
    
    while(!feof(_fp)) {
        wait(0.1);
        
        _packet_number = packet_num;

        transmitPacketNumber(packet_num);
        
        //check for incoming transmission
        //python?
    
        packet_num++;
    
        led3() = !led3();
    }
}

void MbedLogger::transmitPacketNumber(int line_number) {
    int line_size = 160;    //length of lines in the log file, EVERY LINE MUST BE THE SAME LENGTH
        
    fseek(_fp,(line_size+1)*line_number,SEEK_SET);      //fseek must use the +1 to get the newline character
           
    //write over the internal _line_buffer               //start from the beginning and go to this position   
    fread(_line_buffer, 1, line_size, _fp);              //read the line that is exactly 160 characters long
    
    //pc().printf("Debug (transmitPacketNumber): line_buffer <<%s>> (line size: %d)\n\r", line_buffer,line_size);
    
    //    createDataPacket requires _packet_number, _total_number_of_packets, _current_line_length (data packet size)
    //    uses char _line_buffer[256] variable to hold characters read from the file
    //    packs this into a vector for transmission                 
    
    createDataPacket(_line_buffer, line_size);  //create the data packet from the _line_buffer (char array)

    transmitDataPacket();   //transmit the assembled packet
}


//sample packet
//1E 1F 00 01 2E F6     //packet 1
//1E 1F 00 02 2F B6     //packet 2
//receive correct data packet from python, immediately send a transmit packet from the MBED
void MbedLogger::checkForPythonTransmitRequest() {
    static int transmit_state = HEADER_117;     //state in switch statement
    int incoming_byte = -1;                     //reset each time a character is read
    int requested_packet_number = -1;           //reset each time a character is read
    static int input_packet[4];                 //changed from char in previous iteration 03/28/2018
    static int transmit_crc_one = 0;            //hold crc values until they're reset with calculations
    static int transmit_crc_two = 0;
        
    while (pc().readable()) {
        incoming_byte = pc().getc();
        
        switch(transmit_state) {
        case HEADER_117:
            //continue processing
            if (incoming_byte == 30){   //1E
                transmit_state = HEADER_101;
            }
            //did not receive byte 1
            else {
                transmit_state = HEADER_117;    //go back to checking the first packet
            }
            break;
                        
        case HEADER_101:
            if(incoming_byte == 31) {   //1F
                transmit_state = TRANSMIT_PACKET_1;
            }
            break;
        
        case TRANSMIT_PACKET_1:
            if (incoming_byte >= 0) {
                input_packet[0] = 30;
                input_packet[1] = 31;
                input_packet[2] = incoming_byte;
                
                transmit_state = TRANSMIT_PACKET_2;
                //_reply_byte3 = incoming_byte;
            }
            break;
            
        case TRANSMIT_PACKET_2:
            
            if (incoming_byte >= 0) {                    
                input_packet[3] = incoming_byte;
                //_reply_byte4 = incoming_byte;
            }
            transmit_state = PACKET_CRC_ONE;
            
            break;
            
        case (PACKET_CRC_ONE):
            transmit_crc_one = calcCrcOneArray(input_packet, 4);        //calc CRC 1 from the input packet (size 4)
            
            if (incoming_byte == transmit_crc_one) {
                transmit_state = PACKET_CRC_TWO;
            }
            
            else
                transmit_state = HEADER_117;
            //or state remains the same?
            
            break;
        
        case (PACKET_CRC_TWO):
            transmit_state = HEADER_117;
            transmit_crc_two = calcCrcTwoArray(input_packet, 4);        //calc CRC 2 from the input packet (size 4)
                   
            //check if CRC TWO is correct (then send full packet)
            if (incoming_byte == transmit_crc_two) {                
                requested_packet_number = input_packet[2] * 256 + input_packet[3];        //compute the numbers 0 through 65535 with the two bytes
                
                //receive correct checksum, immediately send this packet
                transmitPacketNumber(requested_packet_number);
                
                //fseek(_fp, 0, SEEK_END);    //reset _fp (this was causing errors with the other function)
                led3() = !led3();
                
            }   //end of checksum (incoming_byte) if statement
            
            break;
        }   //switch statement complete
    } //while statement complete    
}

void MbedLogger::readTransmitPacketOneChar() {
    static int transmit_state = HEADER_117;     //state in switch statement
    int incoming_byte = -1;                     //reset each time a character is read
    int requested_packet_number = -1;           //reset each time a character is read
    static int input_packet[4];                 //changed from char in previous iteration 03/28/2018
    static int transmit_crc_one = 0;            //hold crc values until they're reset with calculations
    static int transmit_crc_two = 0;
    
    
    while (pc().readable()) {
        incoming_byte = pc().getc();
        
        led3() = !led3();
        
        switch(transmit_state) {
        case HEADER_117:
            //continue processing
            if (incoming_byte == 30){   //1E
                transmit_state = HEADER_101;
            }
            //did not receive byte 1
            else {
                transmit_state = HEADER_117;    //go back to checking the first packet
            }
            break;
                        
        case HEADER_101:
            if(incoming_byte == 31) {   //1F
                transmit_state = TRANSMIT_PACKET_1;
            }
            break;
        
        case TRANSMIT_PACKET_1:
            if (incoming_byte >= 0) {
                input_packet[0] = 30;
                input_packet[1] = 31;
                input_packet[2] = incoming_byte;
                
                transmit_state = TRANSMIT_PACKET_2;
                //_reply_byte3 = incoming_byte;
            }
            break;
            
        case TRANSMIT_PACKET_2:
            
            if (incoming_byte >= 0) {                    
                input_packet[3] = incoming_byte;
                //_reply_byte4 = incoming_byte;
            }
            transmit_state = PACKET_CRC_ONE;
            
            break;
            
        case (PACKET_CRC_ONE):
            transmit_crc_one = calcCrcOneArray(input_packet, 4);        //calc CRC 1 from the input packet (size 4)
            
            if (incoming_byte == transmit_crc_one) {
                transmit_state = PACKET_CRC_TWO;
            }
            
            else
                transmit_state = HEADER_117;
            //or state remains the same?
            
            break;
        
        case (PACKET_CRC_TWO):
            transmit_state = HEADER_117;
            transmit_crc_two = calcCrcTwoArray(input_packet, 4);        //calc CRC 2 from the input packet (size 4)
                   
            //check if CRC TWO is correct (then send full packet)
            if (incoming_byte == transmit_crc_two) {                
                requested_packet_number = input_packet[2] * 256 + input_packet[3];        //compute the numbers 0 through 65535 with the two bytes
            
                if (requested_packet_number != _previous_reply_byte) {              //CHANGE THE NAME TO SOMETHING NOT BYTE!                                   
                    //MUST SET THE PACKET NUMBER
                    _packet_number = requested_packet_number;
                
                    // DO NOT READ IF THE CURRENT REQUEST IS PAST THE TOTAL # OF PACKETS (lines of the file)
                    if (_packet_number <= _total_number_of_packets) {       
                        readPacketInSeries();
                        createDataPacket();                                                    
                    }
                
                    _previous_reply_byte = requested_packet_number;                 //RECORD THIS BYTE to prevent new packets being created
                
                    transmitDataPacket();                                           //continuously transmit current packet until it tells you to do the next packet (response from Python program)
                }
                
                else
                    transmitDataPacket();   //if you get the same packet request, send the same packet
                
            }   //end of checksum (incoming_byte) if statement
            
            break;
        }   //switch statement complete
    } //while statement complete
}

int MbedLogger::readTransmitPacket() {      
    _file_transmission = true;
    _file_transmission_state = 0;
    
    //first check if you're receiving data, then read four bytes
    
    int transmit_state = 0; //for state machine
    
    int incoming_byte = -1;
    
    int requested_packet_number = -1;
    
    static int inside_while_loop = 1;
    
    while (inside_while_loop) {         
        if (pc().readable()) {          //don't rely on pc readable being open all the time   
                 
            incoming_byte = pc().getc();
            
            switch(transmit_state) {
            
            case (HEADER_117):
                //continue processing
                if (incoming_byte == 117){
                    transmit_state = HEADER_101;
                }
                //end transmission
                else if (incoming_byte == 16) {
                    transmit_state = END_TRANSMISSION;
                }
                else {
                    transmit_state = HEADER_117;
                }
                break;
                            
            case (HEADER_101):
                if(incoming_byte == 101) {
                    transmit_state = TRANSMIT_PACKET_1;
                }
                break;
            
            case (TRANSMIT_PACKET_1):
                if (incoming_byte >= 0) {
                    transmit_state = TRANSMIT_PACKET_2;
                    _reply_byte3 = incoming_byte;
                }
                break;
                
            case (TRANSMIT_PACKET_2):
                if (incoming_byte >= 0) {                    
                    _reply_byte4 = incoming_byte;
                }
                
                requested_packet_number = _reply_byte3 * 256 + _reply_byte4;        //compute the numbers 0 through 65535 with the two bytes
                
                if (requested_packet_number != _previous_reply_byte) {              //CHANGE THE NAME TO SOMETHING NOT BYTE!                                   
                    //MUST SET THE PACKET NUMBER
                    _packet_number = requested_packet_number;
                                
                    readPacketInSeries();
                    createDataPacket();                                                    
                    _previous_reply_byte = requested_packet_number;                 //RECORD THIS BYTE to prevent new packets being created
                }
                
                //continuously transmit current packet until it tells you to do the next packet (response from Python program)
                transmitDataPacket();

                //TRANSMIT_PACKET_2
                inside_while_loop = 0;  //exit the while loop with this
                pc().printf("(TRANSMIT_PACKET_2)reached inside_while_loop = 0\n\r"); //DEBUG
                break;
            }   //end of switch statement
        } //end of while loop
        
//        else {
//            //pc().printf("pc not readable \n\r");
//        }
//                    
    }
    
    //once you're outside of the while loop
    inside_while_loop = true;   //for next iteration
    
    pc().printf("DEBUG: (readTransmitPacket) Outside of while loop\n\r");
    return false;
}

void MbedLogger::reOpenLineReader() {      
    //open a new one
    string file_name_string = _file_system_string + "LOG000.csv";

    _fp = fopen(file_name_string.c_str(), "r");               //open the log file to read
    
    //check if this actually worked...
    if (!_fp) {
        pc().printf("ERROR: Log file could not be opened\n\r");
    }
    else {
        pc().printf("Current Log file (LOG000.csv) was opened.\n\r");
    }
}

bool MbedLogger::openLineReader() {  
    string file_name_string = _file_system_string + "LOG000.csv";

    _fp = fopen(file_name_string.c_str(), "r");               //open the log file to read
    
    //check if this actually worked...
    if (!_fp) {
        //pc().printf("ERROR: Log file could not be opened\n\r");
        return false;
    }
    else {
        //pc().printf("Current Log file (LOG000.csv) was opened.\n\r");
        return true;
    }
}

//VERIFIED THIS IS WORKING
void MbedLogger::readPacketInSeries(){  
    memset(&_line_buffer[0], 0, sizeof(_line_buffer));  //clear buffer each time, start at the address, fill with zeroes, go to the end of the char array
    
    //read the current line in the file 
    fgets(_line_buffer, 256, _fp);        //reads the line of characters until you reach a newline character
    
    //RECORD THE STRING LENGTH
    _current_line_length = strlen(_line_buffer);
}

int MbedLogger::getNumberOfPacketsInCurrentLog() {    
    _packet_number = 0;

    int ch; 
    
    _total_number_of_packets = 0;   //clear this each time you read the file
    
    //if this is null, use the default, else use the new file
    
    if (_fp == NULL) {
        string file_name_string = _file_system_string + "LOG000.csv";

        _fp = fopen(file_name_string.c_str(), "r");     //open the log file to read
    }
    else {                              //else, use the file that is already open...
        fseek(_fp, 0, SEEK_SET);        // SEEK_SET is the beginning of file
    }
    
    //counts the number of newline characters to generate the packet size
    while (EOF != (ch=getc(_fp))) {
        if ('\n' == ch)
            _total_number_of_packets++;             // records the number of new lines to determine how many packets to send
    }
    
    //move the FILE pointer back to the start
    fseek(_fp, 0, SEEK_SET);        // SEEK_SET is the beginning of file
    
    _file_transmission = true;  //preparing to transmit files from MBED to Python
    
    //pc().printf("debug: _total_number_of_packets: %d\n\r",_total_number_of_packets);
    
    return _total_number_of_packets;
}

void MbedLogger::endTransmissionCloseFile() {
    // if the file pointer is null, the file was not opened in the first place
    if (!_fp) {
            pc().printf("\n endTransmissionCloseFile: FILE WAS NOT OPENED!\n\r");
        }
    else {
        pc().printf("\n endTransmissionCloseFile: FILE FOUND AND CLOSED!\n\r");
        closeLogFile();
    }
    
    _file_transmission = false;
}

void MbedLogger::openWriteFile() {
    pc().printf("Opening file for reception.\n\r");
    
    string file_name_string = _file_system_string + "LOG000.csv";

    _fp = fopen(file_name_string.c_str(), "w");
}


//weird bug noticed on 5/25/2018 where if you're not sending data the function is not completing




// function checks for incoming data (receiver function) from a Python program that transmits a file
// current limit is a file that has 255 lines of data
bool MbedLogger::checkForIncomingData() {        
    int receive_packet_number;
    int receive_total_number_packets;
    int receive_packet_size;
    
    bool data_transmission_complete = false;
    
    int incoming_byte;
    
    char char_buffer[256] = {};    //create empty buffer
   
    //starting state
    int process_state = HEADER_117;
    
    //variables for processing data below
    int checksum_one = -1;
    int checksum_two = -1;
    
    int i = 5;
    int serial_timeout = 0;
    
    while (pc().readable() && !data_transmission_complete) {                
        incoming_byte = pc().getc();    //getc returns an unsigned char cast to an int
        //pc().printf("DEBUG: State 0\n\r");
        
        switch(process_state) {
            case HEADER_117:
                //continue processing
                if (incoming_byte == 117){
                    process_state = HEADER_101;
                    //pc().printf("DEBUG: Case 117\n\r");
                }
                //end transmission
                else if (incoming_byte == 16) {
                    process_state = END_TRANSMISSION;
                    pc().printf("DEBUG: State 16 (END_TRANSMISSION)\n\r");
                }
                else {
                    process_state = HEADER_117; // ???
                    //pc().printf("DEBUG: State Header 117\n\r");
                }
                break;
            
            case HEADER_101:
                if(incoming_byte == 101) {
                    process_state = PACKET_NUM;
                    //pc().printf("DEBUG: Case 101\n\r");
                }
                break;
                
            case PACKET_NUM:
                receive_packet_number = incoming_byte;
                process_state = TOTAL_NUM_PACKETS;
                //pc().printf("DEBUG: Case PACKET_NUM\n\r");
                break;
            
            case TOTAL_NUM_PACKETS:
                receive_total_number_packets = incoming_byte;
                process_state = PACKET_SIZE;
                //pc().printf("DEBUG: Case TOTAL_NUM_PACKETS\n\r");
                break;
                
            case PACKET_SIZE:      
                receive_packet_size = incoming_byte;
                //pc().printf("DEBUG: Case PACKET_SIZE\n\r");
                
                //write the header stuff to it
                char_buffer[0] = 117;
                char_buffer[1] = 101;
                char_buffer[2] = receive_packet_number;
                char_buffer[3] = receive_total_number_packets;
                char_buffer[4] = receive_packet_size;    
                
                // tests confirmed that packet number is zero, number of packets is 12, packet size is 12
                //pc().printf("char_buffer 2/3/4: %d %d %d\n\r", receive_packet_number,receive_total_number_packets,receive_packet_size);
                       
                //process packet data, future version will append for larger data sizes, 0xFFFF
                
                // IF YOU GET AN INTERRUPTED DATA STREAM YOU NEED TO BREAK OUT OF THE LOOP
                i = 5;
                serial_timeout = 0;
                
                while (true) {
                    if (pc().readable()) {
                        char_buffer[i] = pc().getc();   //read all of the data packets
                        i++;
                        
                        serial_timeout = 0; //reset the timeout
                    }
                    else {
                        serial_timeout++;        
                    }
                    
                    // When full data packet is received...
                    if (i >= receive_packet_size+5) {     //cannot do this properly with a for loop                        
                        //get checksum bytes
                        checksum_one = pc().getc();
                        checksum_two = pc().getc();
                        
                        //calculate the CRC from the header and data bytes using _data_packet (vector)
                        //found out calculating crc with string was dropping empty or null spaces
                        _data_packet.clear();   //clear it just in case
                        
                        for (int a = 0; a < receive_packet_size+5; a++) {
                            _data_packet.push_back(char_buffer[a]);  //push the character array into the buffer
                        }
                        
                        //calculate the CRC using the vector (strings will cut off null characters)
                        int calc_crc_one = calcCrcOne();
                        int calc_crc_two = calcCrcTwo();

                        //pc().printf("DEBUG: calc crc 1: %d, crc 2: %d\n\r", calc_crc_one, calc_crc_two);
                        
                        // first confirm that the checksum is correct
                        if ((calc_crc_one == checksum_one) and (calc_crc_two == checksum_two)) {                            
                            // CHECKSUM CORRECT & get the filename from the first packet (check that you receive first packet)                                
                            if (receive_packet_number == 0) {
                                char temp_char[receive_packet_size+1];                                 //temp array for memcpy
                                memset(&temp_char[0], 0, sizeof(temp_char));        //clear full array (or get random characters)
                                strncpy(temp_char, char_buffer + 5 /* Offset */, receive_packet_size*sizeof(char) /* Length */); //memcpy introduced random characters
                                
                                //have to terminate the string with '\0'
                                temp_char[receive_packet_size] = '\0';
                                
                                //pc().printf("\n\rDEBUG: ------ Filename? <<%s>>\n\r", temp_char);
                                _received_filename = temp_char;
                                
                                //pc().printf("\n\rDEBUG: _received_filename <<%s>>\n\r", _received_filename);
                                
                                //open a file for writing
                                openReceiveFile(_received_filename);
                                
                                //send a reply to Python transmit program
                                sendReply();
                                
                                led3() = 1;
                                
                                // even if correct CRC, counter prevents the program from writing the same packet twice
                                _confirmed_packet_number++;
                            }
                            
    // check if the packet that you're receiving (receive_packet_number) has been received already...
        
                            //CHECKSUM CORRECT & packet numbers that are 1 through N packets
                            else if (receive_packet_number == _confirmed_packet_number){
                                //save the data (char buffer) to the file if both checksums work...                 
                                
                                // when a packet is received (successfully) send a reply
                                sendReply();
                                
                                // write correct data to file
                                fprintf(_fp, "%s", char_buffer+5);
                                
                                // even if correct CRC, counter prevents the program from writing the same packet twice
                                _confirmed_packet_number++;
                            }
                            
                            //clear the variables
                            checksum_one = -1;
                            checksum_two = -1;
                        }
                        
                        process_state = HEADER_117;
                        
                        break;
                    }
                    
                    //counter breaks out of the loop if no data received
                    if (serial_timeout >= 10000) {
                        //pc().printf("break serial_timeout %d\n\r", serial_timeout);
                        break;      
                    }
                }
                break;   
                
            case END_TRANSMISSION:
                if (pc().getc() == 16) {
                    pc().printf("DEBUG: END_TRANSMISSION REACHED: 1. \n\r");
                    
                    if (pc().getc() == 16) {
                        pc().printf("DEBUG: END_TRANSMISSION REACHED: 2. \n\r");
                        
                        endReceiveData();
                    }
                }
                
                pc().printf("DEBUG: END_TRANSMISSION REACHED: 5. \n\r");
                
                //process_state = HEADER_117; //don't do this unless the check is wrong
                pc().printf("END_TRANSMISSION process_state is %d\n\r", process_state);        //should be 5 (debug) 02/06/2018
                data_transmission_complete = true;
                break;            
        }//END OF SWITCH
        
        if (data_transmission_complete) {
            pc().printf("DEBUG: checkForIncomingData data_transmission_complete \n\r");
            break;  //out of while loop
        }   
    } // while loop
    
    led3() = !led3();
    
    if (data_transmission_complete)
        return false;   //tell state machine class that this is done (not transmitting, false)
    else {
        return true;
    }
}

int MbedLogger::sendReply() {
    //being explicit in what's being transmitted
    
    //change this method to be more explicit later
    
    //integer vector _data_packet is used here, cleared fist just in case
    
    _data_packet.clear();   //same data packet for transmission
    _data_packet.push_back(117);
    _data_packet.push_back(101);
    
    //_confirmed_packet_number comes from the packet number that is sent from the Python program
    _data_packet.push_back(_confirmed_packet_number / 256);    //packet number only changed when confirmed
    _data_packet.push_back(_confirmed_packet_number % 256);     //split into first and second byte
    
    //compute checksums
    
    int receiver_crc_one = calcCrcOne();
    int receiver_crc_two = calcCrcTwo();
    
    _data_packet.push_back(receiver_crc_one);
    _data_packet.push_back(receiver_crc_two);
    
    //transmit this packet
    for (_it=_data_packet.begin(); _it < _data_packet.end(); _it++) {
        pc().putc(*_it); //send integers over serial port one byte at a time
    }
    
    //change process methodology later...
    
    return _confirmed_packet_number;
}

void MbedLogger::endReceiveData() {                             //DLE character * 4 ==> 10 10 10 10
    closeLogFile();         //close the file here
    pc().printf("endReceiveData closed the file and ended transmission\n\r");
}

//calculate the crc with an integer array
int MbedLogger::calcCrcOneArray(int *input_array, int array_length) {    
    //can't initialize the table in the constructor in c++
    int crc_table [256] = {0, 49345, 49537, 320, 49921, 960, 640, 49729, 50689, 1728, 1920, 51009, 1280, 50625, 50305,  1088, 52225,  3264,  3456, 52545,  3840, 53185, 52865,  3648,  2560, 51905, 52097,  2880, 51457,  2496,  2176, 51265, 55297,  6336,  6528, 55617,  6912, 56257, 55937,  6720,  7680, 57025, 57217,  8000, 56577,  7616,  7296, 56385,  5120, 54465, 54657,  5440, 55041,  6080,  5760, 54849, 53761,  4800,  4992, 54081,  4352, 53697, 53377,  4160, 61441, 12480, 12672, 61761, 13056, 62401, 62081, 12864, 13824, 63169, 63361, 14144, 62721, 13760, 13440, 62529, 15360, 64705, 64897, 15680, 65281, 16320, 16000, 65089, 64001, 15040, 15232, 64321, 14592, 63937, 63617, 14400, 10240, 59585, 59777, 10560, 60161, 11200, 10880, 59969, 60929, 11968, 12160, 61249, 11520, 60865, 60545, 11328, 58369,  9408,  9600, 58689,  9984, 59329, 59009,  9792,  8704, 58049, 58241,  9024, 57601,  8640,  8320, 57409, 40961, 24768, 24960, 41281, 25344, 41921, 41601, 25152, 26112, 42689, 42881, 26432, 42241, 26048, 25728, 42049, 27648, 44225, 44417, 27968, 44801, 28608, 28288, 44609, 43521, 27328, 27520, 43841, 26880, 43457, 43137, 26688, 30720, 47297, 47489, 31040, 47873, 31680, 31360, 47681, 48641, 32448, 32640, 48961, 32000, 48577, 48257, 31808, 46081, 29888, 30080, 46401, 30464, 47041, 46721, 30272, 29184, 45761, 45953, 29504, 45313, 29120, 28800, 45121, 20480, 37057, 37249, 20800, 37633, 21440, 21120, 37441, 38401, 22208, 22400, 38721, 21760, 38337, 38017, 21568, 39937, 23744, 23936, 40257, 24320, 40897, 40577, 24128, 23040, 39617, 39809, 23360, 39169, 22976, 22656, 38977, 34817, 18624, 18816, 35137, 19200, 35777, 35457, 19008, 19968, 36545, 36737, 20288, 36097, 19904, 19584, 35905, 17408, 33985, 34177, 17728, 34561, 18368, 18048, 34369, 33281, 17088, 17280, 33601, 16640, 33217, 32897, 16448};
    int crc = 0;
    for (int z = 0; z < array_length; z++) {
        crc = (crc_table[(input_array[z] ^ crc) & 0xff] ^ (crc >> 8)) & 0xFFFF;
    }
    return crc / 256; //second-to-last byte
}

int MbedLogger::calcCrcTwoArray(int *input_array, int array_length) {    
    //can't initialize the table in the constructor in c++
    int crc_table [256] = {0, 49345, 49537, 320, 49921, 960, 640, 49729, 50689, 1728, 1920, 51009, 1280, 50625, 50305,  1088, 52225,  3264,  3456, 52545,  3840, 53185, 52865,  3648,  2560, 51905, 52097,  2880, 51457,  2496,  2176, 51265, 55297,  6336,  6528, 55617,  6912, 56257, 55937,  6720,  7680, 57025, 57217,  8000, 56577,  7616,  7296, 56385,  5120, 54465, 54657,  5440, 55041,  6080,  5760, 54849, 53761,  4800,  4992, 54081,  4352, 53697, 53377,  4160, 61441, 12480, 12672, 61761, 13056, 62401, 62081, 12864, 13824, 63169, 63361, 14144, 62721, 13760, 13440, 62529, 15360, 64705, 64897, 15680, 65281, 16320, 16000, 65089, 64001, 15040, 15232, 64321, 14592, 63937, 63617, 14400, 10240, 59585, 59777, 10560, 60161, 11200, 10880, 59969, 60929, 11968, 12160, 61249, 11520, 60865, 60545, 11328, 58369,  9408,  9600, 58689,  9984, 59329, 59009,  9792,  8704, 58049, 58241,  9024, 57601,  8640,  8320, 57409, 40961, 24768, 24960, 41281, 25344, 41921, 41601, 25152, 26112, 42689, 42881, 26432, 42241, 26048, 25728, 42049, 27648, 44225, 44417, 27968, 44801, 28608, 28288, 44609, 43521, 27328, 27520, 43841, 26880, 43457, 43137, 26688, 30720, 47297, 47489, 31040, 47873, 31680, 31360, 47681, 48641, 32448, 32640, 48961, 32000, 48577, 48257, 31808, 46081, 29888, 30080, 46401, 30464, 47041, 46721, 30272, 29184, 45761, 45953, 29504, 45313, 29120, 28800, 45121, 20480, 37057, 37249, 20800, 37633, 21440, 21120, 37441, 38401, 22208, 22400, 38721, 21760, 38337, 38017, 21568, 39937, 23744, 23936, 40257, 24320, 40897, 40577, 24128, 23040, 39617, 39809, 23360, 39169, 22976, 22656, 38977, 34817, 18624, 18816, 35137, 19200, 35777, 35457, 19008, 19968, 36545, 36737, 20288, 36097, 19904, 19584, 35905, 17408, 33985, 34177, 17728, 34561, 18368, 18048, 34369, 33281, 17088, 17280, 33601, 16640, 33217, 32897, 16448};
    int crc = 0;
    for (int z = 0; z < array_length; z++) {
        crc = (crc_table[(input_array[z] ^ crc) & 0xff] ^ (crc >> 8)) & 0xFFFF;
    }
    return crc % 256; //second-to-last byte
}

int MbedLogger::calcCrcOne() {
    //can't initialize the table in the constructor in c++
    int crc_table [256] = {0, 49345, 49537, 320, 49921, 960, 640, 49729, 50689, 1728, 1920, 51009, 1280, 50625, 50305,  1088, 52225,  3264,  3456, 52545,  3840, 53185, 52865,  3648,  2560, 51905, 52097,  2880, 51457,  2496,  2176, 51265, 55297,  6336,  6528, 55617,  6912, 56257, 55937,  6720,  7680, 57025, 57217,  8000, 56577,  7616,  7296, 56385,  5120, 54465, 54657,  5440, 55041,  6080,  5760, 54849, 53761,  4800,  4992, 54081,  4352, 53697, 53377,  4160, 61441, 12480, 12672, 61761, 13056, 62401, 62081, 12864, 13824, 63169, 63361, 14144, 62721, 13760, 13440, 62529, 15360, 64705, 64897, 15680, 65281, 16320, 16000, 65089, 64001, 15040, 15232, 64321, 14592, 63937, 63617, 14400, 10240, 59585, 59777, 10560, 60161, 11200, 10880, 59969, 60929, 11968, 12160, 61249, 11520, 60865, 60545, 11328, 58369,  9408,  9600, 58689,  9984, 59329, 59009,  9792,  8704, 58049, 58241,  9024, 57601,  8640,  8320, 57409, 40961, 24768, 24960, 41281, 25344, 41921, 41601, 25152, 26112, 42689, 42881, 26432, 42241, 26048, 25728, 42049, 27648, 44225, 44417, 27968, 44801, 28608, 28288, 44609, 43521, 27328, 27520, 43841, 26880, 43457, 43137, 26688, 30720, 47297, 47489, 31040, 47873, 31680, 31360, 47681, 48641, 32448, 32640, 48961, 32000, 48577, 48257, 31808, 46081, 29888, 30080, 46401, 30464, 47041, 46721, 30272, 29184, 45761, 45953, 29504, 45313, 29120, 28800, 45121, 20480, 37057, 37249, 20800, 37633, 21440, 21120, 37441, 38401, 22208, 22400, 38721, 21760, 38337, 38017, 21568, 39937, 23744, 23936, 40257, 24320, 40897, 40577, 24128, 23040, 39617, 39809, 23360, 39169, 22976, 22656, 38977, 34817, 18624, 18816, 35137, 19200, 35777, 35457, 19008, 19968, 36545, 36737, 20288, 36097, 19904, 19584, 35905, 17408, 33985, 34177, 17728, 34561, 18368, 18048, 34369, 33281, 17088, 17280, 33601, 16640, 33217, 32897, 16448};
    
    int crc = 0;
    for (_it=_data_packet.begin(); _it < _data_packet.end(); _it++)
        crc = (crc_table[(*_it ^ crc) & 0xff] ^ (crc >> 8)) & 0xFFFF;

    return crc / 256; //second-to-last byte
}

int MbedLogger::calcCrcTwo() {
    int crc_table [256] = {0, 49345, 49537, 320, 49921, 960, 640, 49729, 50689, 1728, 1920, 51009, 1280, 50625, 50305,  1088, 52225,  3264,  3456, 52545,  3840, 53185, 52865,  3648,  2560, 51905, 52097,  2880, 51457,  2496,  2176, 51265, 55297,  6336,  6528, 55617,  6912, 56257, 55937,  6720,  7680, 57025, 57217,  8000, 56577,  7616,  7296, 56385,  5120, 54465, 54657,  5440, 55041,  6080,  5760, 54849, 53761,  4800,  4992, 54081,  4352, 53697, 53377,  4160, 61441, 12480, 12672, 61761, 13056, 62401, 62081, 12864, 13824, 63169, 63361, 14144, 62721, 13760, 13440, 62529, 15360, 64705, 64897, 15680, 65281, 16320, 16000, 65089, 64001, 15040, 15232, 64321, 14592, 63937, 63617, 14400, 10240, 59585, 59777, 10560, 60161, 11200, 10880, 59969, 60929, 11968, 12160, 61249, 11520, 60865, 60545, 11328, 58369,  9408,  9600, 58689,  9984, 59329, 59009,  9792,  8704, 58049, 58241,  9024, 57601,  8640,  8320, 57409, 40961, 24768, 24960, 41281, 25344, 41921, 41601, 25152, 26112, 42689, 42881, 26432, 42241, 26048, 25728, 42049, 27648, 44225, 44417, 27968, 44801, 28608, 28288, 44609, 43521, 27328, 27520, 43841, 26880, 43457, 43137, 26688, 30720, 47297, 47489, 31040, 47873, 31680, 31360, 47681, 48641, 32448, 32640, 48961, 32000, 48577, 48257, 31808, 46081, 29888, 30080, 46401, 30464, 47041, 46721, 30272, 29184, 45761, 45953, 29504, 45313, 29120, 28800, 45121, 20480, 37057, 37249, 20800, 37633, 21440, 21120, 37441, 38401, 22208, 22400, 38721, 21760, 38337, 38017, 21568, 39937, 23744, 23936, 40257, 24320, 40897, 40577, 24128, 23040, 39617, 39809, 23360, 39169, 22976, 22656, 38977, 34817, 18624, 18816, 35137, 19200, 35777, 35457, 19008, 19968, 36545, 36737, 20288, 36097, 19904, 19584, 35905, 17408, 33985, 34177, 17728, 34561, 18368, 18048, 34369, 33281, 17088, 17280, 33601, 16640, 33217, 32897, 16448};
    
    int crc = 0;
    for (_it=_data_packet.begin(); _it < _data_packet.end(); _it++)
        crc = (crc_table[(*_it ^ crc) & 0xff] ^ (crc >> 8)) & 0xFFFF;
    
    //pc().printf("DEBUG: calcCrcTwo string length: %d crc: %d\n\r", input_array.length(), crc % 256);

    return crc % 256; //last byte
}

void MbedLogger::resetReplyPacket() {
    _confirmed_packet_number = 0;
}

void MbedLogger::openNewMissionFile() {
    pc().printf("Opening Mission file (sequence.txt) for reception.\n\r");
    string filename_string = _file_system_string + "sequence.txt";
    
    pc().printf("openNewMissionFile: %s\n\r", filename_string.c_str());

    _fp = fopen(filename_string.c_str(), "w");
}

void MbedLogger::openReceiveFile(string filename) {
    string filename_string = _file_system_string + filename;   //example "sequence.txt"

    _fp = fopen(filename_string.c_str(), "w");                 //open a file for writing
}

void MbedLogger::setDataCounter(int input_counter) {
    _transmit_counter = input_counter;
}

void MbedLogger::closeIncompleteFile() {
    fprintf(_fp, "TRANSMISSION INTERRUPTED!"); //write this warning to the file
    closeLogFile();    //close file
}

void MbedLogger::appendLogFile(int current_state, int option) {
    //option one means write to file
    
    if (option == 1) {
        if (!_fp) {     //if not present
            _fp = fopen(_full_file_path_string.c_str(), "a");
        }
        
        //record data using the recordData function (takes in the state integer)
        recordData(current_state);
    }
    
    else {
        closeLogFile();
    }
}

// initialize and close the file
// log file freezes at 0x0000006c
void MbedLogger::initializeLogFile() {
    string file_name_string = _file_system_string + "LOG000.csv";
    pc().printf("%s file system init\n\r", _file_system_string.c_str());
    
    //try to open this file...
    _fp = fopen(file_name_string.c_str(), "r");
    
    //if the file is empty, create this.
    if (!_fp) {
        _fp = fopen(file_name_string.c_str(), "w");     //write,print,close
        //fprintf(_fp,"state_string,state_ID,timer,depth_cmd,depth_ft,pitch_cmd,pitch_deg,bce_cmd,bce_mm,batt_cmd,batt_mm,pitchRate_degs,depthRate_fps\nempty log file!\n");
        fprintf(_fp,_heading_string.c_str());
        closeLogFile();
    }
    else
        closeLogFile();   //close the opened read file
}

int MbedLogger::fileTransmitState() {
    return _file_transmission_state;
}

int MbedLogger::calcCrcOneString (string input_string) {    
    int crc_table [256] = {0, 49345, 49537, 320, 49921, 960, 640, 49729, 50689, 1728, 1920, 51009, 1280, 50625, 50305,  1088, 52225,  3264,  3456, 52545,  3840, 53185, 52865,  3648,  2560, 51905, 52097,  2880, 51457,  2496,  2176, 51265, 55297,  6336,  6528, 55617,  6912, 56257, 55937,  6720,  7680, 57025, 57217,  8000, 56577,  7616,  7296, 56385,  5120, 54465, 54657,  5440, 55041,  6080,  5760, 54849, 53761,  4800,  4992, 54081,  4352, 53697, 53377,  4160, 61441, 12480, 12672, 61761, 13056, 62401, 62081, 12864, 13824, 63169, 63361, 14144, 62721, 13760, 13440, 62529, 15360, 64705, 64897, 15680, 65281, 16320, 16000, 65089, 64001, 15040, 15232, 64321, 14592, 63937, 63617, 14400, 10240, 59585, 59777, 10560, 60161, 11200, 10880, 59969, 60929, 11968, 12160, 61249, 11520, 60865, 60545, 11328, 58369,  9408,  9600, 58689,  9984, 59329, 59009,  9792,  8704, 58049, 58241,  9024, 57601,  8640,  8320, 57409, 40961, 24768, 24960, 41281, 25344, 41921, 41601, 25152, 26112, 42689, 42881, 26432, 42241, 26048, 25728, 42049, 27648, 44225, 44417, 27968, 44801, 28608, 28288, 44609, 43521, 27328, 27520, 43841, 26880, 43457, 43137, 26688, 30720, 47297, 47489, 31040, 47873, 31680, 31360, 47681, 48641, 32448, 32640, 48961, 32000, 48577, 48257, 31808, 46081, 29888, 30080, 46401, 30464, 47041, 46721, 30272, 29184, 45761, 45953, 29504, 45313, 29120, 28800, 45121, 20480, 37057, 37249, 20800, 37633, 21440, 21120, 37441, 38401, 22208, 22400, 38721, 21760, 38337, 38017, 21568, 39937, 23744, 23936, 40257, 24320, 40897, 40577, 24128, 23040, 39617, 39809, 23360, 39169, 22976, 22656, 38977, 34817, 18624, 18816, 35137, 19200, 35777, 35457, 19008, 19968, 36545, 36737, 20288, 36097, 19904, 19584, 35905, 17408, 33985, 34177, 17728, 34561, 18368, 18048, 34369, 33281, 17088, 17280, 33601, 16640, 33217, 32897, 16448};
    
    int crc = 0;
    for (unsigned int i = 0; i < input_string.length(); i++) {
        //convert each character to an integer
        int character_to_integer = input_string[i]; //correct

        crc = (crc_table[(character_to_integer ^ crc) & 0xff] ^ (crc >> 8)) & 0xFFFF;
    }
    
    //pc().printf("DEBUG: calcCrcOne string length: %d crc: %d\n\r", input_string.length(), crc/256);

    return crc / 256; //second-to-last byte
}

int MbedLogger::calcCrcTwoString (string input_string) {
    int crc_table [256] = {0, 49345, 49537, 320, 49921, 960, 640, 49729, 50689, 1728, 1920, 51009, 1280, 50625, 50305,  1088, 52225,  3264,  3456, 52545,  3840, 53185, 52865,  3648,  2560, 51905, 52097,  2880, 51457,  2496,  2176, 51265, 55297,  6336,  6528, 55617,  6912, 56257, 55937,  6720,  7680, 57025, 57217,  8000, 56577,  7616,  7296, 56385,  5120, 54465, 54657,  5440, 55041,  6080,  5760, 54849, 53761,  4800,  4992, 54081,  4352, 53697, 53377,  4160, 61441, 12480, 12672, 61761, 13056, 62401, 62081, 12864, 13824, 63169, 63361, 14144, 62721, 13760, 13440, 62529, 15360, 64705, 64897, 15680, 65281, 16320, 16000, 65089, 64001, 15040, 15232, 64321, 14592, 63937, 63617, 14400, 10240, 59585, 59777, 10560, 60161, 11200, 10880, 59969, 60929, 11968, 12160, 61249, 11520, 60865, 60545, 11328, 58369,  9408,  9600, 58689,  9984, 59329, 59009,  9792,  8704, 58049, 58241,  9024, 57601,  8640,  8320, 57409, 40961, 24768, 24960, 41281, 25344, 41921, 41601, 25152, 26112, 42689, 42881, 26432, 42241, 26048, 25728, 42049, 27648, 44225, 44417, 27968, 44801, 28608, 28288, 44609, 43521, 27328, 27520, 43841, 26880, 43457, 43137, 26688, 30720, 47297, 47489, 31040, 47873, 31680, 31360, 47681, 48641, 32448, 32640, 48961, 32000, 48577, 48257, 31808, 46081, 29888, 30080, 46401, 30464, 47041, 46721, 30272, 29184, 45761, 45953, 29504, 45313, 29120, 28800, 45121, 20480, 37057, 37249, 20800, 37633, 21440, 21120, 37441, 38401, 22208, 22400, 38721, 21760, 38337, 38017, 21568, 39937, 23744, 23936, 40257, 24320, 40897, 40577, 24128, 23040, 39617, 39809, 23360, 39169, 22976, 22656, 38977, 34817, 18624, 18816, 35137, 19200, 35777, 35457, 19008, 19968, 36545, 36737, 20288, 36097, 19904, 19584, 35905, 17408, 33985, 34177, 17728, 34561, 18368, 18048, 34369, 33281, 17088, 17280, 33601, 16640, 33217, 32897, 16448};
    
    int crc = 0;
    for (unsigned int i = 0; i < input_string.length(); i++) {
        //convert each character to an integer
        int character_to_integer = input_string[i]; //correct

        crc = (crc_table[(character_to_integer ^ crc) & 0xff] ^ (crc >> 8)) & 0xFFFF;
    }
    
    //pc().printf("DEBUG: calcCrcTwo string length: %d crc: %d\n\r", input_string.length(), crc % 256);

    return crc % 256; //last byte
}

void MbedLogger::createEmptyLog() {    
    string file_name_string = _file_system_string + "LOG000.csv";
    string empty_log = "EMPTY LOG";

    _fp = fopen(file_name_string.c_str(), "w");
    
    fprintf(_fp, "%.25s\n",empty_log.c_str());              //just write this string to the log (processing needs a file size that is not zero)
    closeLogFile();
}

int MbedLogger::getFileSize(string filename) {    
    // fixed the const char * errror:
    // https://stackoverflow.com/questions/347949/how-to-convert-a-stdstring-to-const-char-or-char
    const char * char_filename = filename.c_str();  // Returns a pointer to an array that contains a null-terminated sequence of characters (i.e., a C-string) representing the current value of the string object.
    //http://www.cplusplus.com/reference/string/string/c_str/
    
    _fp = fopen(filename.c_str(), "rb");     //open the file for reading as a binary file
    
    fseek(_fp, 0, SEEK_END);                     //SEEK_END is a constant in cstdio (end of the file)    
    unsigned int file_size = ftell(_fp);        //For binary streams, this is the number of bytes from the beginning of the file.
    fseek(_fp, 0, SEEK_SET);                    //SEEK_SET is hte beginning of the file, not sure this is necessary
    
    closeLogFile();                                //can probably just close the file pointer and not worry about position
    
    pc().printf("%s file size is %d\n\r", filename.c_str(), file_size);

    return file_size;
}

int MbedLogger::debugFileState() {
    pc().printf("What is _fp right now? %p\n\r", _fp);  //pointer notation
    
    if (_fp)
        return 1;   //file pointer does exist
    else
        return 0;   //file pointer does not exist
}

void MbedLogger::specifyFileForTransmit(string input_string) { 
    pc().printf("specifyFileForTransmit\n\r");   
    
    string file_string = _file_system_string + input_string;
    
    pc().printf("file_string is <%s>\n\r", file_string.c_str());
    
    //open this file to read
    _fp = fopen(file_string.c_str(), "r");
    
    //transmit that file
    //transmitDataWithTicker();     //replaced ticker
    
    _file_transmission = true;
}

void MbedLogger::transmitFileFromDirectory( int file_number ) {
    file_number = file_number + 1;  //to get the correct number
    
    DIR *dir;
    struct dirent   *dp;        //dirent.h is the format of directory entries
    int log_found =0, loop=1;    //start file numbers at 1
    long int temp=0;
    
//    char * char_pointer;
//    char * numstart, *numstop;
    
    if ( NULL == (dir   = opendir( _file_system_string.c_str() )) ) {
        pc().printf("MBED directory could not be opened\r\n");
    }                   
    else
    {
        while ( NULL != (dp    = readdir( dir )) )
        {
            pc().printf( "%d. %s (log file: %d, %d)\r\n", loop, dp->d_name,log_found,temp); 
            
            //process current file if it matches the file number
            if (file_number == loop) {
                char * current_file_name = dp->d_name;  //pointer to this char array
                
                specifyFileForTransmit(current_file_name);
                                
                break;
            }
            
            loop++;
        }
    }
}

void MbedLogger::accessMbedDirectory() {
    printMbedDirectory();
    
    pc().printf("Type in the number of the file you want to transmit.\n\r");
    
    char message[42];
    
    pc().scanf("%41s", message);
    
    pc().printf("Input received!\n\r");
    
    //check if char array is an integer
    char* conversion_pointer;
    long converted = strtol(message, &conversion_pointer, 10);
    
    if (*conversion_pointer) {
        //conversion failed because the input was not a number
        pc().printf("NOT A VALID FILE NUMBER!\n\r");
    }
    else {
        //conversion worked!
        pc().printf("You chose file number: %d\n\r", converted);
        
        // transmit the file
        transmitFileFromDirectory(converted);
    }
}

void MbedLogger::closeLogFile() {
    led4() = 1;
    
    if (_fp == NULL){
        pc().printf("MbedLogger: (%s) LOG FILE WAS ALREADY CLOSED!\n\r", _file_system_string.c_str());
    }
    
    else {
        pc().printf("MbedLogger: (%s) CLOSING LOG FILE!\n\r", _file_system_string.c_str());
        
        //close file
        fclose(_fp);
                
        _fp = NULL;     //set pointer to zero
    }    
}

void MbedLogger::activateReceivePacket() {
    _mbed_receive_loop = true;
}

void MbedLogger::receiveMissionDataWithFSM() {   
    checkForIncomingData();  
            
// Example: send reply 75 65 00 00             
// Example: send reply 75 65 00 01
}

void MbedLogger::receiveMissionDataWithTicker() {    
    openNewMissionFile();      //sequence.txt file opened

    _mbed_receive_ticker.attach(callback(this, &MbedLogger::activateReceivePacket), 0.5);
    
    pc().printf("\n\r02/09/2018 MbedLogger receiveMissionData Beginning to receive sequence data...\n\r");
    
    resetReplyPacket();    //reset the reply packet
    
    //idea for stopping this if data not being received
    int current_packet_number = 0;
    int last_packet_number = -1;
    int break_transmission = 0;
            
    while(1) {
        //runs at 10 hz
        if (_mbed_receive_loop) {          
            if (!checkForIncomingData()) {            // run this until it finishes
                //when you complete data reception, this will become false
                pc().printf("\n\rMbedLogger: Data RECEPTION complete.\n\r");    
                _mbed_receive_ticker.detach();
                break;
            }
            else {   
            
// SEND REPLY 75 65 00 00             
// SEND REPLY 75 65 00 01

                //check if you keep getting the same thing                
                current_packet_number = sendReply();
                
                //pc().printf("DEBUG: current packet number %d (last packet number %d) \n\r", current_packet_number, last_packet_number); //debug
                
                //let this count up a few times before it exits
                if (current_packet_number == last_packet_number) {
                    break_transmission++;
                    
                    //break transmission after 50 failed attempts (was 100)
                    if (break_transmission >= 50) {
                        closeIncompleteFile();           //close the file 
                        _mbed_receive_ticker.detach();
                        pc().printf("MbedLogger: TRANSMISSION INTERRUPTED!\n\r");
                        break;
                    }
                }
                else
                    last_packet_number = current_packet_number;
            }
            _mbed_receive_loop = false;                         // wait until the loop rate timer fires again
        }
    }
}

int MbedLogger::getNumberOfPackets() {
    return _total_number_of_packets;
}

//only do this for the MBED because of the limited file size
//write one line to the file (open to write, this will erase all other data) and close it.
void MbedLogger::eraseFile() {    
    _fp = fopen(_full_file_path_string.c_str(), "w"); // LOG000.csv
    
    fprintf(_fp,_heading_string.c_str());
    
    // _heading_string = "state_string,state_ID,timer,depth_cmd,depth_ft,pitch_cmd,pitch_deg,bce_cmd,bce_mm,batt_cmd,batt_mm,pitchRate_degs,depthRate_fps,sys_amps,sys_volts\n(file erased)"
    
    closeLogFile();
}

void MbedLogger::intCreateDataPacket(int data_buffer[],int payload_length) {     
    // packet is 7565 0001 FFFF EEEE CC DATA DATA DATA ... CRC1 CRC2
    
    //check here https://www.rapidtables.com/convert/number/hex-to-decimal.html?x=01c0
    // ieee 754:     http://www6.uniovi.es/~antonio/uned/ieee754/IEEE-754hex32.html
    
    //CLEAR: Removes all elements from the vector (which are destroyed), leaving the container with a size of 0.
    _data_packet.clear();
    
    //DATA PACKET HEADER
    _data_packet.push_back(117);                             //0x75
    _data_packet.push_back(101);                             //0x65    
    
    _data_packet.push_back(_packet_number/256);                //current packet number in 0x#### form
    _data_packet.push_back(_packet_number%256);                //current packet number in 0x#### form
    
    _data_packet.push_back(_total_number_of_packets/256);                //total number of packets, 0x#### form
    _data_packet.push_back(_total_number_of_packets%256);                //total number of packets, 0x#### form
    
    _data_packet.push_back(_current_line_length);

    //DATA FROM INTEGER ARRAY (read the array)
    for (int i = 0; i < payload_length; i++) {
        _data_packet.push_back(data_buffer[i]);
    }
    
    //CRC CALCULATIONS BELOW, character version of calculation screws up on null character 0x00, scrapped and using vector of integers
    int crc_one = calcCrcOne();
    int crc_two = calcCrcTwo();
    
    //place the crc bytes into the data packet that is transmitted
    _data_packet.push_back(crc_one);
    _data_packet.push_back(crc_two);
}

void MbedLogger::sendStatus() {
    led3() = !led3();
    //readPacketInSeries()  //uses this functionality
    
    //get data depth, pitch, heading, timer
    
    //store the data as a hex char array
    char hex_char_depth[256];
    char hex_char_pitch[256];
    char hex_char_heading[256];
    char hex_char_timer[256];
    
    string string_hex_buffer = "";  //buffer to store the hex data as a string
    string string_temp;     // ELIMINATE THIS ASAP
    
    float depth_value = depthLoop().getPosition();
    float pitch_value = imu().getPitch();
    float heading_value = imu().getHeading();
    //float timer_value = stateMachine().getTimer();
    float timer_value = 123.123;
    
    sprintf(hex_char_depth,   "%08X" , *(unsigned int*)&depth_value);
    sprintf(hex_char_pitch,   "%08X" , *(unsigned int*)&pitch_value);
    sprintf(hex_char_heading, "%08X" , *(unsigned int*)&heading_value);
    sprintf(hex_char_timer,   "%08X" , *(unsigned int*)&timer_value);    

    //store the integer values
    int hex_to_int[128];  
    
    //read through hex string and break apart into chunks and save the decimal values
    int hex_counter = 0;  

//////////////////////////
    string_hex_buffer = hex_char_depth;
    
    for (int i = 0; i < 8; i = i+2) {
        //substring starts at x substr(x, length of substring)
        string_temp = string_hex_buffer.substr(i,2);    // get substring from string (converted from char array)
            
        //convoluted, fix this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        // copying the contents of the string to char array
        char temp_char_array[256];
        strcpy(temp_char_array, string_temp.c_str()); 
        
        //store char array hex value as decimal value
        int decimal_value;
        sscanf(temp_char_array,"%x",&decimal_value);

        hex_to_int[hex_counter] = decimal_value;
        hex_counter++;  //iterate to keep up with for loop
        
        //clear the string each time
        //string_temp = "";
        //cout << "string_temp CLEARED? is " << string_temp << endl;
        //cout << "string_temp is " << string_temp << " and the value is " << decimal_value << endl;
    }
    
        string_hex_buffer = hex_char_pitch;
    
    for (int i = 0; i < 8; i = i+2) {
        //substring starts at x substr(x, length of substring)
        string_temp = string_hex_buffer.substr(i,2);
            
        //convoluted, fix this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        // copying the contents of the string to char array
        char temp_char_array[256];
        strcpy(temp_char_array, string_temp.c_str()); 
        
        //store char array hex value as decimal value
        int decimal_value;
        sscanf(temp_char_array,"%x",&decimal_value);

        hex_to_int[hex_counter] = decimal_value;
        hex_counter++;  //iterate to keep up with for loop
        
        //clear the string each time
        //string_temp = "";
        //cout << "string_temp CLEARED? is " << string_temp << endl;
        //cout << "string_temp is " << string_temp << " and the value is " << decimal_value << endl;
    }
    
        string_hex_buffer = hex_char_heading;
    
    for (int i = 0; i < 8; i = i+2) {
        //substring starts at x substr(x, length of substring)
        string_temp = string_hex_buffer.substr(i,2);
            
        //convoluted, fix this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        // copying the contents of the string to char array
        char temp_char_array[256];
        strcpy(temp_char_array, string_temp.c_str()); 
        
        //store char array hex value as decimal value
        int decimal_value;
        sscanf(temp_char_array,"%x",&decimal_value);

        hex_to_int[hex_counter] = decimal_value;
        hex_counter++;  //iterate to keep up with for loop
        
        //clear the string each time
        //string_temp = "";
        //cout << "string_temp CLEARED? is " << string_temp << endl;
        //cout << "string_temp is " << string_temp << " and the value is " << decimal_value << endl;
    }
    
        string_hex_buffer = hex_char_timer;
    
    for (int i = 0; i < 8; i = i+2) {
        //substring starts at x substr(x, length of substring)
        string_temp = string_hex_buffer.substr(i,2);
            
        //convoluted, fix this!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
        // copying the contents of the string to char array
        char temp_char_array[256];
        strcpy(temp_char_array, string_temp.c_str()); 
        
        //store char array hex value as decimal value
        int decimal_value;
        sscanf(temp_char_array,"%x",&decimal_value);

        hex_to_int[hex_counter] = decimal_value;
        hex_counter++;  //iterate to keep up with for loop
        
        //clear the string each time
        //string_temp = "";
        //cout << "string_temp CLEARED? is " << string_temp << endl;
        //cout << "string_temp is " << string_temp << " and the value is " << decimal_value << endl;
    }    
//////////////////////////

    //create new packet based on int array
    _packet_number = 1;             // TEST, FIX THIS
    _total_number_of_packets = 1;
    _current_line_length = 16;
    
    intCreateDataPacket(hex_to_int,16);


    transmitDataPacket();
}

void MbedLogger::setTransmitPacketNumber(int packet_number) {
    _transmit_packet_num = packet_number;
    
    //also needed to reset a boolean flag on the transmit
    _fsm_transmit_complete = false;
}