JongYong Park / Mbed 2 deprecated NUCLEO-F767_LIFI_4CH_os2_v2

Dependencies:   mbed

lifiReceiver.cpp

Committer:
JongYongPark
Date:
2019-04-09
Revision:
27:19ee6e15ba5e
Parent:
26:26474003e443
Child:
30:75cb79acdcff

File content as of revision 27:19ee6e15ba5e:

#include "app.h"
//#include "../arduino.h"
//#include "mbed.h"
//#include <string>

#include "lifiTranceiver.h"
#include "lifiTranceiverLocal.h"

//#define USE_SLOW_TXRX_DEMO
//#define USE_SERIAL_COMMAND

//// OLED를 활성화 시키면 FreeRTOS가 정상 동작 안한다. 이문제는 다음에 해결하기로 하자.
//// 한글 입력이 잘 되네.

// TODO 1 :  ADCREF 3.3 Volt - Done
// TODO 2 :  Check Max/Max ADC
///////////////////////////////////////////////////////
///////// HEADER //////////////////////////////////////

enum op_mode {
    OP_HF, OP_LF, OP_PLOT_ADC, OP_RESERVED
};

enum receiver_state {
    IDLE_STATE = 0, //waiting for sync
    SYNC_STATE, //synced, waiting for STX
    START_STATE, //STX received
    LENGTH_LSB_STATE,
    LENGTH_MSB_STATE,
    DATA_STATE, //receiving DATA
    END_STATE
};

///////////////////////////////////////////////////////
////////////  GLOBAL VARIABLES   //////////////////////
int waiting_count_for_all_channel_finished =0 ;
unsigned char incomingByte;
int lines = 0;
int chars = 0;

////////////

//manechester decoder state variable
//long shift_reg = 0;
//
//int oldValue = 0 ;
//int steady_count = 0 ;
//int dist_last_sync = 0 ;
//unsigned int detected_word = 0;
//int new_word = 0;
//int old_edge_val = 0 ;
//int probe_adc_high = 0;
//int probe_adc_low = 0;
//int probe_adc_gap = 0;

struct RX_VARS {
    int sensorValue;
    int oldValue;
    int edge_val;
    int steady_count;
    int dist_last_sync;
    unsigned int detected_word;
    int new_word;
    long shift_reg;
    int old_edge_val;
    int probe_adc_high;
    int probe_adc_low;
    int probe_adc_gap;
    enum receiver_state frame_state;
    uint8_t rx_frame_buffer[FRAME_BUFFER_SIZE];
    //////////// keep received message
    bool is_valid;
    bool is_received;
 //   uint8_t rx_frame_buffer_save[FRAME_BUFFER_SIZE];
    int probe_adc_high_received;
    int probe_adc_low_received;
    int probe_adc_gap_received;
    ///////////
    // no auxiliary security header
    int rx_frame_index;
    int rx_frame_size;
    uint16_t pdu_length;
    uint16_t pdu_length_count;
//    uint16_t pdu_length_save;
//    uint16_t pdu_length_count_save;
    uint16_t frame_length;
//    uint16_t frame_length_save;
};
// __attribute__((packed));

struct RX_VARS_RECEIVED {
    int probe_adc_high;
    int probe_adc_low;
    int probe_adc_gap;
    uint8_t rx_frame_buffer[FRAME_BUFFER_SIZE];
    //////////// keep received message
    bool is_valid;
    bool is_received;
    ///////////
    int rx_frame_size;
    uint16_t pdu_length;
    uint16_t pdu_length_count;
    uint16_t frame_length;
};

static RX_VARS rx_vars[LIFI_MIMO_CHANNEL_NUM];
static RX_VARS_RECEIVED rx_vars_received[LIFI_MIMO_CHANNEL_NUM];

void LifiRx_CopyAdcInfo_FromReceivedFrame(int channel, int high, int low)
{
    rx_vars_received[channel].probe_adc_high = high ;
    rx_vars_received[channel].probe_adc_low = low ;
    rx_vars_received[channel].probe_adc_gap = high - low ;
}

void LifiRx_CopyData_FromReceivedFrame(int channel)
{
    rx_vars_received[channel].is_received = rx_vars[channel].is_received ;
    rx_vars_received[channel].is_valid = rx_vars[channel].is_valid ;

    rx_vars_received[channel].rx_frame_size = rx_vars[channel].rx_frame_size ;
    rx_vars_received[channel].pdu_length = rx_vars[channel].pdu_length ;
    rx_vars_received[channel].pdu_length_count = rx_vars[channel].pdu_length_count ;
    rx_vars_received[channel].frame_length = rx_vars[channel].frame_length ;

    memcpy( rx_vars_received[channel].rx_frame_buffer, rx_vars[channel].rx_frame_buffer, FRAME_BUFFER_SIZE) ;
}

void LifiRx_CopyAll_FromReceivedFrame(int channel)
{
	LifiRx_CopyAdcInfo_FromReceivedFrame(channel, rx_vars[channel].probe_adc_high, rx_vars[channel].probe_adc_low );
	LifiRx_CopyData_FromReceivedFrame(channel);
}

void print_frame_data(uint8_t* frame, int length)
{
    printf(" frame (%d) = ",length);
    for(int i=0; i < length; i++) {
        // https://simple.wikipedia.org/wiki/ASCII
        if(frame[i] >= 0x20 && frame[i] <= 0x7E ) {
            //printf("[%d]%c_%02x ",i,frame[i],frame[i]);
            printf("%c",frame[i]);
        } else {
            //printf("[%d]_%02x ",i,frame[i]);
            printf(" x%02x ",frame[i]);
        }
    }
}

void print_pdu_data(uint8_t* frame, int length)
{
    printf(" pdu (%d) = ",length);
    for(int i=0; i < length; i++) {
        // https://simple.wikipedia.org/wiki/ASCII
        if(frame[i] >= 0x20 && frame[i] <= 0x7E ) {
            printf("%c",frame[i]);
        } else {
            printf(" ");
        }
    }
}

inline int is_a_word_4ch(int channel, long * manchester_word,
                         int time_from_last_sync, unsigned int * detected_word)
{
#if RX_DEBUG_BIN
    printf("\t %d[%4x] ",channel+1, *detected_word );
#endif
    if (time_from_last_sync >= 20
            || rx_vars[channel].frame_state == IDLE_STATE) { // we received enough bits to test the sync
        if (((*manchester_word) & START_STOP_MASK) == (START_STOP_MASK)) { // testing first position
            (*detected_word) = ((*manchester_word) >> 2) & 0xFFFF;

            if (rx_vars[channel].frame_state == IDLE_STATE) {
                if ((*detected_word) == SYNC_SYMBOL_MANCHESTER) {
                    return 2;
                }
            }
            return 1;
            // byte with correct framing
        } else if (rx_vars[channel].frame_state != IDLE_STATE
                   && time_from_last_sync == 20) {
            (*detected_word) = ((*manchester_word) >> 2) & 0xFFFF;
            return 1;
        }
    }
    return 0;
}

inline int insert_edge_4ch(int channel, long * manchester_word, int edge,
                           int edge_period, int * time_from_last_sync,
                           unsigned int * detected_word)
{
    int new_word = 0;
    int is_a_word_value = 0;
    int sync_word_detect = 0;
    if (((*manchester_word) & 0x01) != edge) { //mak sure we don't have same edge ...
        if (edge_period > (LIFI_RX_SAMPLE_PER_SYMBOL + 1)) {
            unsigned char last_bit = (*manchester_word) & 0x01;
            (*manchester_word) = ((*manchester_word) << 1) | last_bit; // signal was steady for longer than a single symbol,
            (*time_from_last_sync) += 1;
            is_a_word_value = is_a_word_4ch(channel, manchester_word,
                                            (*time_from_last_sync), detected_word);
            if (is_a_word_value > 0) { //found start stop framing
                new_word = 1;
                (*time_from_last_sync) = 0;
                if (is_a_word_value > 1) {
                    sync_word_detect = 1; //we detected framing and sync word in manchester format
#if RX_DEBUG_BIN
                    printf("\n%dS",channel+1);
#endif
                }
            }
        }
        /////////////////////////////
        //storing edge value in word
        if (edge < 0) {
            (*manchester_word) = ((*manchester_word) << 1) | 0x00; // signal goes down
#if RX_DEBUG_BIN
            printf("%d[0]",channel+1);
#endif
        } else {
            (*manchester_word) = ((*manchester_word) << 1) | 0x01; // signal goes up
#if RX_DEBUG_BIN
            printf("%d[1]",channel+1);
#endif
        }
        /////////////////////////////////////
        (*time_from_last_sync) += 1;
        is_a_word_value = is_a_word_4ch(channel, manchester_word,
                                        (*time_from_last_sync), detected_word);
        if (sync_word_detect == 0 && is_a_word_value > 0) { //if sync word was detected at previous position, don't take word detection into account
            new_word = 1;
            (*time_from_last_sync) = 0;
#if RX_DEBUG_BIN
            printf("%dD",channel+1);
#endif
        }
    } else {
        new_word = -1;
#if RX_DEBUG_BIN
        printf("%d_",channel+1);
#endif
    }
    return new_word;
}

void sample_signal_edge_4ch(int channel, int sensorValue)
{
    rx_vars[channel].sensorValue = sensorValue;
    //int sensorValue = analogRead(SENSOR_PIN_PORT); // this is too slow and should be replaced with interrupt-driven ADC
    //t sensorValue  = LifiRx_AdcRead(0); // read result of previously triggered conversion
    //ADC_start_conversion(SENSOR_PIN); // start a conversion for next loop

#if RX_DEBUG_ANALOG_SENSOR_VALUE
    printf(" adc:%d ",rx_vars[channel].sensorValue);
#endif
    if ((rx_vars[channel].sensorValue - rx_vars[channel].oldValue)
            > LIFI_RX_EDGE_THRESHOLD) {
        rx_vars[channel].edge_val = 1;

#if CHECK_EDGE_WITH_DEBUG_LED
        if( int LifiRx_GetDebugLed() == 0 ) printf("\n Edge Detect Fail (Up / 0) !!!");
#endif

#if RX_DEBUG_EDGE
        printf("%d/ %d-%d",channel+1,rx_vars[channel].sensorValue,rx_vars[channel].oldValue);
#endif
        if (rx_vars[channel].probe_adc_high < rx_vars[channel].sensorValue)
            rx_vars[channel].probe_adc_high = rx_vars[channel].sensorValue;
    } else if ((rx_vars[channel].oldValue - rx_vars[channel].sensorValue)
               > LIFI_RX_EDGE_THRESHOLD) {
        rx_vars[channel].edge_val = -1;

#if CHECK_EDGE_WITH_DEBUG_LED
        if( int LifiRx_GetDebugLed() == 1 ) printf("\n Edge Detect Fail (Down / 1) !!!");
#endif

#if RX_DEBUG_EDGE
        printf("%d| %d-%d",channel+1,rx_vars[channel].oldValue,rx_vars[channel].sensorValue);
#endif
        if (rx_vars[channel].probe_adc_low > rx_vars[channel].sensorValue)
            rx_vars[channel].probe_adc_low = rx_vars[channel].sensorValue;
    } else {
#if RX_DEBUG_EDGE
        printf("%d=",channel+1);
#endif
        rx_vars[channel].edge_val = 0;
    }

    /////////////
    rx_vars[channel].oldValue = rx_vars[channel].sensorValue;
    if (rx_vars[channel].edge_val == 0
            || rx_vars[channel].edge_val == rx_vars[channel].old_edge_val
            || (rx_vars[channel].edge_val != rx_vars[channel].old_edge_val
                && rx_vars[channel].steady_count < 2)) {
        if (rx_vars[channel].steady_count < (4 * LIFI_RX_SAMPLE_PER_SYMBOL)) {
#if RX_DEBUG_EDGE
            printf("%d+",channel+1);
#endif
            rx_vars[channel].steady_count++;
        }
    } else {

#if RX_DEBUG_EDGE
        if(rx_vars[channel].edge_val == 1) printf("%dH",channel+1);
        else if(rx_vars[channel].edge_val == -1) printf("%dL",channel+1);
#endif
        //inline int insert_edge_4ch(int channel, long  * manchester_word, int edge, int edge_period, int * time_from_last_sync, unsigned int * detected_word)
        rx_vars[channel].new_word = insert_edge_4ch(channel,
                                    &rx_vars[channel].shift_reg, rx_vars[channel].edge_val,
                                    rx_vars[channel].steady_count,
                                    &(rx_vars[channel].dist_last_sync),
                                    &rx_vars[channel].detected_word);
        if (rx_vars[channel].dist_last_sync > (8 * LIFI_RX_SAMPLE_PER_SYMBOL)) { // limit dist_last_sync to avoid overflow problems
            rx_vars[channel].dist_last_sync = 32;
#if RX_DEBUG_FRAME
//            println("\t %dRESET avoid overlow ",channel+1);
#endif
        }

//        if(new_word >= 0) {
#if RX_DEBUG_FRAME
//            println("\t %dRESET COUNTER ",channel+1);
#endif
        rx_vars[channel].steady_count = 0;
//    }
    }
    rx_vars[channel].old_edge_val = rx_vars[channel].edge_val;

#if (USE_MBED_OS5 && USE_LIFI_RX_CHECK_QUEUE)
    if((rx_vars[channel].new_word == 1) && (channel == LIFI_ACTUAL_MAX_CHANNEL_NUM_INDEX)) {
        //printf("!");
        // https://os.mbed.com/forum/bugs-suggestions/topic/28244/?page=1#comment-53612
        lifi_tx_check_queue.call(LifiRx_LoopOOK);
    }
#endif
}

int add_byte_to_frame_v1(int channel,uint8_t * rx_frame_buffer, int * rx_frame_index, int * rx_frame_size, enum receiver_state * frame_state,unsigned char data)
{
    if(data == SYNC_SYMBOL/* && (*rx_frame_index) < 0*/) {
        (*rx_frame_index) = 0 ;
        (*rx_frame_size) = 0 ;
        (*frame_state) = SYNC_STATE ;
#if RX_DEBUG_FRAME
        printf("\n%dSYNC ",channel+1);
#endif
        return 0 ;
    }
    if((*frame_state) != IDLE_STATE) { // we are synced
        rx_frame_buffer[*rx_frame_index] = data ;
        (*rx_frame_index) ++ ;
        if(data == STX) {
#if RX_DEBUG_FRAME
            printf("%dSTART ",channel+1);
#endif
            (*frame_state) = START_STATE ;
            return 0 ;
        } else if(data == ETX) {
#if RX_DEBUG_FRAME
            printf("%dEND IDLE ",channel+1);
#endif
            (*rx_frame_size) = (*rx_frame_index) ;
            (*rx_frame_index) = -1 ;
            (*frame_state) = IDLE_STATE ;

            return 1 ;
        } else if((*rx_frame_index) >= FRAME_BUFFER_SIZE) { //frame is larger than max size of frame ...
#if RX_DEBUG_FRAME
            printf("%dIDLE - over FRAME_BUFFER_SIZE ",channel+1);
#endif
            (*rx_frame_index) = -1 ;
            (*rx_frame_size) = -1 ;
            (*frame_state) = IDLE_STATE ;
            return -1 ;
        } else {
#if RX_DEBUG_FRAME
            printf("%dD=%c[%x] ",channel+1,data,data);
#endif
            (*frame_state) = DATA_STATE ;
        }
        return 0 ;
    }
    return -1 ;
}

int add_byte_to_frame(int channel, uint8_t * rx_frame_buffer,
                      int * rx_frame_index, int * rx_frame_size,
                      enum receiver_state * frame_state, unsigned char data)
{
    if (data == SYNC_SYMBOL/* && (*rx_frame_index) < 0*/) {
        (*rx_frame_index) = 0;
        (*rx_frame_size) = 0;
        (*frame_state) = SYNC_STATE;
#if RX_DEBUG_FRAME
        printf("\n%dSYNC ",channel+1);
#endif
		printf("\n *** Channel[%d] Rx Started !!! *** ", channel +1 );
        return 0;
    }
    if ((*frame_state) != IDLE_STATE) { // we are synced
        rx_frame_buffer[*rx_frame_index] = data;
        (*rx_frame_index)++;

        if ((*frame_state) == SYNC_STATE) {
            if (data == STX) {
#if RX_DEBUG_FRAME
                printf("%dSTART ",channel+1);
#endif
                (*frame_state) = START_STATE;
                return 0;
            } else if (data == SYNC_SYMBOL) {
                // do nothing
            } else {
                printf("\n Error # got wrong data after SYNC. it should be STX");
                (*frame_state) = IDLE_STATE;
                return -1;
            }

        } else if ((*frame_state) == START_STATE) {
            (*frame_state) = LENGTH_LSB_STATE;
            rx_vars[channel].pdu_length = data;
#if RX_DEBUG_FRAME
            printf("%dLENGTH_LSB(%d) ",channel+1,data);
#endif
        } else if ((*frame_state) == LENGTH_LSB_STATE) {

            (*frame_state) = LENGTH_MSB_STATE;
            rx_vars[channel].pdu_length = rx_vars[channel].pdu_length + (data << 8);
            rx_vars[channel].pdu_length_count = 0;
            rx_vars[channel].frame_length = rx_vars[channel].pdu_length + LIFI_FRAME_HEADER_SIZE;
#if RX_DEBUG_FRAME
            printf("%dLENGTH_MSB(%d) length=%d ",channel+1,data, rx_vars[channel].pdu_length);
#endif

        } else if ((*frame_state) == LENGTH_MSB_STATE) {

#if RX_DEBUG_FRAME
            printf("%dD=%c[%x] ",channel+1,data,data);
#endif
            (*frame_state) = DATA_STATE;
            rx_vars[channel].pdu_length_count++;

        } else if ((*frame_state) == DATA_STATE) {
            rx_vars[channel].pdu_length_count++;
            // when ETX
            if (rx_vars[channel].pdu_length_count
                    > rx_vars[channel].pdu_length) {

                rx_vars[channel].pdu_length_count--; // ETX is not included on data length
////                rx_vars[channel].pdu_length_count_save = rx_vars[channel].pdu_length_count;
//                rx_vars[channel].pdu_length_save = rx_vars[channel].pdu_length;
////                rx_vars[channel].frame_length_save = rx_vars[channel].frame_length;

                if (data == ETX) {
#if RX_DEBUG_FRAME
                    printf("%dEND IDLE ",channel+1);
#endif
                    (*rx_frame_size) = (*rx_frame_index);
                    (*rx_frame_index) = -1;
                    (*frame_state) = IDLE_STATE;
                    return 1;
                } else {
                    printf("\n CH(%d) Error : got wrong data (0x%2x). it should be ETX (0x03)",channel,data);
                    print_frame_data(rx_vars[channel].rx_frame_buffer, rx_vars[channel].frame_length);
                    (*frame_state) = IDLE_STATE;
                    return -1;
                }
            }
            // normal DATA
            else {
#if RX_DEBUG_FRAME
                printf("%dD=%c[%x] ",channel+1,data,data);
#endif
            }
        } else if ((*rx_frame_index) >= FRAME_BUFFER_SIZE) { //frame is larger than max size of frame ...
#if RX_DEBUG_FRAME
            printf("%dIDLE - over FRAME_BUFFER_SIZE ",channel+1);
#endif
            (*rx_frame_index) = -1;
            (*rx_frame_size) = -1;
            (*frame_state) = IDLE_STATE;
            return -1;
        } else {
            printf("\n CH(%d) Error : unknown state (%d)", channel+1 , *frame_state);
            (*frame_state) = IDLE_STATE;
            return 1;
        }
        return 0;  // normal
    }
    return -1;  // error
}

int counter = 0;

void setup_ADC()
{
//
//    if( (m_op_mode != OP_HW_TEST) &&  (m_op_mode != OP_PLOT_ADC))
//    {
//        //analogReference(INTERNAL); // internal reference is 1.1v, should give better accuracy for the mv range of the led output.
//        Timer1.initialize(LIFI_RX_SYMBOL_PERIOD_US/LIFI_RX_SAMPLE_PER_SYMBOL); //1200 bauds oversampled by factor 4
//        Timer1.attachInterrupt(sample_signal_edge);
//    }
}

// the setup routine runs once when you press reset:

//bool isValidNumber(string str)
//{
//    bool isNum=true;
//    for(byte i=0; i<str.length(); i++) {
//        //isNum = isDigit(str.charAt(i)) || str.charAt(i) == '+' || str.charAt(i) == '.' || str.charAt(i) == '-';
////       isNum = isDigit(str.charAt(i)); // || str.charAt(i) == '+' || str.charAt(i) == '.' || str.charAt(i) == '-';
//        if(!isNum) return false;
//    }
//    return isNum;
//}

bool rx_loop_ook_4ch(int channel)
{
    int i;
    bool got_all_frame = false;
    unsigned char received_data;
    //unsigned char received_data_print ;
    //int nb_shift ;
    int byte_added = 0;
    bool valid_chars;
    if (rx_vars[channel].new_word == 1) {
        received_data = 0;
        for (i = 0; i < 16; i = i + 2) { //decoding Manchester
            received_data = received_data << 1;
            if (((rx_vars[channel].detected_word >> i) & 0x03) == 0x01) {
                received_data |= 0x01;
            } else {
                received_data &= ~0x01;
            }
        }
        received_data = received_data & 0xFF;
#if RX_DEBUG_MAIN_LOOP
//        printf("%dRx:%c[%x]",channel+1,(unsigned char) received_data,received_data & 0xFF);
#endif
        rx_vars[channel].new_word = 0;

        // return 1 from add_byte_to_frame() means got ETX
#if LIFI_PACKET_USE_LENGTH
        if ((byte_added = add_byte_to_frame(channel,
                                            rx_vars[channel].rx_frame_buffer,
                                            &rx_vars[channel].rx_frame_index,
                                            &rx_vars[channel].rx_frame_size, &rx_vars[channel].frame_state,
                                            received_data)) > 0)
#else
        if ((byte_added = add_byte_to_frame_v1(channel,
                                               rx_vars[channel].rx_frame_buffer,
                                               &rx_vars[channel].rx_frame_index,
                                               &rx_vars[channel].rx_frame_size, &rx_vars[channel].frame_state,
                                               received_data)) > 0)
#endif
        {
            valid_chars = true;
            // 여기서 ETX를 0으로 변경해 버린다.
            //rx_vars[channel].rx_frame_buffer[rx_vars[channel].rx_frame_size - 1] = 	'\0';
#if RX_DEBUG_MAIN_LOOP
            //printf("%dAdc[Max=%d Min=%d]",channel+1,rx_vars[channel].probe_adc_high,rx_vars[channel].probe_adc_low);
#endif

            LifiRx_CopyAdcInfo_FromReceivedFrame(  channel,  rx_vars[channel].probe_adc_high , rx_vars[channel].probe_adc_low);  

            rx_vars[channel].probe_adc_high = 0;
            rx_vars[channel].probe_adc_low = 1024;
#if 1
//			for (int i = 1; i < (rx_vars[channel].rx_frame_size - 1); i++) {
//				if ((rx_vars[channel].rx_frame_buffer[i] < ' ')
//						|| (rx_vars[channel].rx_frame_buffer[i] > '~')) {
//					valid_chars = false0;
//					break;
//				} else {
//				}
//			}
            valid_chars = true;
#else
            // only valid when char is charactor
            for (int i = 1; i < (rx_vars[channel].rx_frame_size - 1); i++) {
                if ((rx_vars[channel].rx_frame_buffer[i] < ' ')
                        || (rx_vars[channel].rx_frame_buffer[i] > '~')) {
                    valid_chars = false;
                    break;
                } else {
                }
            }
#endif
//			printf("\n=============");
//			print_frame_data(rx_vars[channel].rx_frame_buffer,rx_vars[channel].frame_length_save);

//            memcpy(rx_vars[channel].rx_frame_buffer_save, rx_vars[channel].rx_frame_buffer, FRAME_BUFFER_SIZE);
            rx_vars[channel].is_received = true;
            printf("\n *** Channel[%d] Rx Finished !!! *** ", channel +1 );
            if (valid_chars) {
//                //println(&(rx_frame_buffer[1]));
//                //stringReceive = string(&(rx_frame_buffer[1]));
//                //stringReceive = stringReceive.toUpperCase();
//                //println(stringReceive);
//                printf("\nMSG(ch_%d)[%s]",channel, rx_vars[channel].rx_frame_buffer);
                rx_vars[channel].is_valid = true;
            } else {
//                printf("\nMSG_Invalid(ch_%d)[%s]",channel, rx_vars[channel].rx_frame_buffer);
                rx_vars[channel].is_valid = false;
            }
            // http://www.java2s.com/Tutorial/Cpp/0160__Structure/Usememcpytoduplicatestructures.htm
            //memcpy((void*) &rx_vars_received[channel], (void*) &rx_vars[channel], sizeof( struct RX_VARS));
            //memcpy( &rx_vars_received[channel], &rx_vars[channel], sizeof( struct RX_VARS));
            //memcpy((void*) & (rx_vars_received[channel]), (void*) &(rx_vars[channel]), sizeof(rx_vars[channel]));
            
            LifiRx_CopyData_FromReceivedFrame(channel);
            got_all_frame = true;
        }
        //if(frame_state != IDLE_STATE) println(received_data, HEX);
    }
    return got_all_frame;
}



void print_channel_data(int channel)
{
#if RX_DEBUG_MAIN_LOOP
    printf("\nMSG(%d) valid=%d, [len:%d/%d/%d] Adc[Max=%d Min=%d Gap=%d]",
           channel,
           rx_vars[channel].is_valid,
           rx_vars[channel].pdu_length_count, //rx_vars[channel].pdu_length_count_save,
           rx_vars[channel].pdu_length, //rx_vars[channel].pdu_length_save,
           rx_vars[channel].frame_length, //rx_vars[channel].frame_length_save,
           rx_vars[channel].probe_adc_high,
           rx_vars[channel].probe_adc_low,
           rx_vars[channel].probe_adc_gap);
////	print_frame_data(rx_vars[channel].rx_frame_buffer_save,rx_vars[channel].pdu_length);
//    print_pdu_data(rx_vars[channel].rx_frame_buffer_save + LIFI_RX_FRAME_DATA_OFFSET,rx_vars[channel].pdu_length_save);
//    print_frame_data(rx_vars[channel].rx_frame_buffer_save,rx_vars[channel].frame_length_save);

    print_pdu_data(rx_vars[channel].rx_frame_buffer + LIFI_RX_FRAME_DATA_OFFSET,rx_vars[channel].pdu_length);
    print_frame_data(rx_vars[channel].rx_frame_buffer,rx_vars[channel].frame_length);
#endif
}

void print_channel_received_data(int channel)
{
#if RX_DEBUG_MAIN_LOOP
    printf("\nMSG(%d) valid=%d, [len:%d/%d/%d] Adc[Max=%d Min=%d Gap=%d]",
           channel,
           rx_vars_received[channel].is_valid,
           rx_vars_received[channel].pdu_length_count,
           rx_vars_received[channel].pdu_length,
           rx_vars_received[channel].frame_length,
           rx_vars_received[channel].probe_adc_high,
           rx_vars_received[channel].probe_adc_low,
           rx_vars_received[channel].probe_adc_gap);
//	print_frame_data(rx_vars[channel].rx_frame_buffer_save,rx_vars[channel].pdu_length);
    print_pdu_data(rx_vars_received[channel].rx_frame_buffer + LIFI_RX_FRAME_DATA_OFFSET,rx_vars_received[channel].pdu_length);
    print_frame_data(rx_vars_received[channel].rx_frame_buffer,rx_vars_received[channel].frame_length);

#endif
}

void print_4ch_message()
{
//	int channel = LIFI_CHANNEL_1;
//	for (; channel <= LIFI_ACTUAL_MAX_CHANNEL_NUM_INDEX; channel++) {
//		if (rx_vars[channel].is_received == false)
//			return;
//	}
#if RX_DEBUG_MAIN_LOOP
    printf("\n----------------");
#endif
    print_channel_data(LIFI_CHANNEL_1);

    rx_vars[LIFI_CHANNEL_1].is_received = false;

    if (Lifi_IsChannelAvailable(LIFI_CHANNEL_2)) {
        print_channel_data(LIFI_CHANNEL_2);
        rx_vars[LIFI_CHANNEL_2].is_received = false;
    }
    if (Lifi_IsChannelAvailable(LIFI_CHANNEL_3)) {
        print_channel_data(LIFI_CHANNEL_3);
        rx_vars[LIFI_CHANNEL_3].is_received = false;
    }
    if (Lifi_IsChannelAvailable(LIFI_CHANNEL_4)) {
        print_channel_data(LIFI_CHANNEL_4);
        rx_vars[LIFI_CHANNEL_4].is_received = false;
    }
}
int LifixRx_FinishedChannlCount()
{
    int channel = LIFI_CHANNEL_1;
    int got_frame_count = 0;
    for (; channel <= LIFI_ACTUAL_MAX_CHANNEL_NUM_INDEX; channel++) {
        if (rx_vars[channel].is_received == true) got_frame_count++;
    }
    return got_frame_count;
}

int LifixRx_PrintUnfinishedChannl()
{
    int channel = LIFI_CHANNEL_1;
    int got_frame_count = 0;
    for (; channel <= LIFI_ACTUAL_MAX_CHANNEL_NUM_INDEX; channel++) {
        if (rx_vars[channel].is_received == true) ;//printf("CH[%d] Finished ooo", channel + 1);
        else printf("\n CH[%d]XXX", channel + 1);
    }
    return got_frame_count;
}

bool LifixRx_FinishedFromAllChannel()
{
    int channel = LIFI_CHANNEL_1;
    for (; channel <= LIFI_ACTUAL_MAX_CHANNEL_NUM_INDEX; channel++) {
        if (rx_vars[channel].is_received == false) {
            //waiting_count_for_all_channel_finished++;
            return false;
        }
    }
    //waiting_count_for_all_channel_finished = 0;
    return true;
}

void LifiRx_LoopOOK()
{
    static uint64_t loop_count = 0;
    int finished_channel = 0;
    //printf("!");
    // for 1 channel, it works well.
    // data corrupted when open 2 channels
    // LIFI_RX_SYMBOL_PERIOD_SEC  (0.01)  = works well for 2 channels *********
    rx_loop_ook_4ch(LIFI_CHANNEL_1);
    if (Lifi_IsChannelAvailable(LIFI_CHANNEL_2))
        rx_loop_ook_4ch(LIFI_CHANNEL_2);
    if (Lifi_IsChannelAvailable(LIFI_CHANNEL_3))
        rx_loop_ook_4ch(LIFI_CHANNEL_3);
    if (Lifi_IsChannelAvailable(LIFI_CHANNEL_4))
        rx_loop_ook_4ch(LIFI_CHANNEL_4);


//	if(LifixRx_FinishedFromAllChannel()){
//		print_4ch_message();
//		loop_count = 0;
//	}
//	else {
//		loop_count++;
//		if(loop_count > 2 )
//		{
//			LifixRx_PrintUnFinishedChannl();
//			print_4ch_message();
//			LifiRx_Init();
//			loop_count = 0;
//		}
//	}

    finished_channel = 	LifixRx_FinishedChannlCount();
    if( finished_channel == LIFI_ACTUAL_MAX_CHANNEL_NUM ) {
        print_4ch_message();
        loop_count = 0;
    }
    // 4 channel 에서 하나의 유효한 channel 에서 데이타를 받으면 나머지는 어디서 문제가 발생했는지 알 수 있다.
    else if(finished_channel >= 1 ) {
        loop_count++;
        if(loop_count > 1000 ) {
            printf("\nHERE 1 Finished channel count (%d)",finished_channel);
            LifixRx_PrintUnfinishedChannl();
            print_4ch_message();
            LifiRx_Init();
            loop_count = 0;
        }
    }
//	else
//	{
//		loop_count++;
//		if(loop_count > 10000000 )
//		{
//			printf("\nHERE 2 Finished(%d)",finished_channel);
//			LifixRx_PrintUnfinishedChannl();
//			print_4ch_message();
//			LifiRx_Init();
//			loop_count = 0;
//		}
//	}
}

// the loop routine runs over and over again forever:

void LifiRx_SampleSignalEdge()
{
    int sensorValue, sensorValue2, sensorValue3, sensorValue4;

    sensorValue = LifiRx_AdcRead(LIFI_CHANNEL_1);
    if (Lifi_IsChannelAvailable(LIFI_CHANNEL_2))
        sensorValue2 = LifiRx_AdcRead(LIFI_CHANNEL_2);
    if (Lifi_IsChannelAvailable(LIFI_CHANNEL_3))
        sensorValue3 = LifiRx_AdcRead(LIFI_CHANNEL_3);
    if (Lifi_IsChannelAvailable(LIFI_CHANNEL_4))
        sensorValue4 = LifiRx_AdcRead(LIFI_CHANNEL_4);

    sample_signal_edge_4ch(LIFI_CHANNEL_1, sensorValue);
    if (Lifi_IsChannelAvailable(LIFI_CHANNEL_2))
        sample_signal_edge_4ch(LIFI_CHANNEL_2, sensorValue2);
    if (Lifi_IsChannelAvailable(LIFI_CHANNEL_3))
        sample_signal_edge_4ch(LIFI_CHANNEL_3, sensorValue3);
    if (Lifi_IsChannelAvailable(LIFI_CHANNEL_4))
        sample_signal_edge_4ch(LIFI_CHANNEL_4, sensorValue4);
}

void LifiRx_Init()
{
    rx_vars[LIFI_CHANNEL_1].rx_frame_index = -1;
    rx_vars[LIFI_CHANNEL_2].rx_frame_index = -1;
    rx_vars[LIFI_CHANNEL_3].rx_frame_index = -1;
    rx_vars[LIFI_CHANNEL_4].rx_frame_index = -1;
    rx_vars[LIFI_CHANNEL_1].rx_frame_size = -1;
    rx_vars[LIFI_CHANNEL_2].rx_frame_size = -1;
    rx_vars[LIFI_CHANNEL_3].rx_frame_size = -1;
    rx_vars[LIFI_CHANNEL_4].rx_frame_size = -1;
    rx_vars[LIFI_CHANNEL_1].frame_state = IDLE_STATE;
    rx_vars[LIFI_CHANNEL_2].frame_state = IDLE_STATE;
    rx_vars[LIFI_CHANNEL_3].frame_state = IDLE_STATE;
    rx_vars[LIFI_CHANNEL_4].frame_state = IDLE_STATE;

    rx_vars[LIFI_CHANNEL_1].is_received = false;
    rx_vars[LIFI_CHANNEL_2].is_received = false;
    rx_vars[LIFI_CHANNEL_3].is_received = false;
    rx_vars[LIFI_CHANNEL_4].is_received = false;
}