Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
lifiReceiver.cpp
- Committer:
 - JongYongPark
 - Date:
 - 2019-04-06
 - Revision:
 - 12:df54493ec7e4
 - Parent:
 - 11:8ffa8a36126f
 - Child:
 - 14:07669aafe0e4
 
File content as of revision 12:df54493ec7e4:
#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   //////////////////////
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;
    unsigned char rx_frame_buffer[FRAME_BUFFER_SIZE];
    //////////// keep received message
    bool is_valid;
    bool is_received ;
    unsigned char rx_frame_buffer_received[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 length;
    uint16_t received_data_count;
};// __attribute__((packed));
static RX_VARS rx_vars[LIFI_MIMO_CHANNEL_NUM] ;
//static int adc_read_value=0;
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 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 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(int channel,unsigned char * 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((*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");
        	}
        }
        else if((*frame_state) == START_STATE ){
#if RX_DEBUG_FRAME
            printf("%dLENGTH_LSB ",channel+1);
#endif
            (*frame_state) = LENGTH_LSB_STATE ;
            rx_vars[channel].length = data;
        }
        else if((*frame_state) == LENGTH_LSB_STATE ){
#if RX_DEBUG_FRAME
            printf("%dLENGTH_MSB ",channel+1);
#endif
            (*frame_state) = LENGTH_MSB_STATE ;
            rx_vars[channel].length = rx_vars[channel].length + (data << 8 );
        }
        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].received_data_count = 1;
        }
        else if((*frame_state) == DATA_STATE ){
#if RX_DEBUG_FRAME
            printf("%dD=%c[%x] ",channel+1,data,data);
#endif
//            (*frame_state) = DATA_STATE ;
            rx_vars[channel].received_data_count++;
            if(rx_vars[channel].received_data_count >= rx_vars[channel].length )
            {
            	(*frame_state) = END_STATE ;
            }
        }
        else if((*frame_state) == END_STATE ){
        	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 Error # got wrong data. it should be ETX");
        		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 {
    		printf("\n Error # unknown 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;
//}
void rx_loop_ook_4ch(int channel)
{
    int i;
    unsigned char received_data;
    //unsigned char received_data_print ;
    //int nb_shift ;
    int byte_added = 0 ;
    int 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 ;
        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) {
            valid_chars = 1;
            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
            rx_vars[channel].probe_adc_high_received = rx_vars[channel].probe_adc_high;
            rx_vars[channel].probe_adc_low_received = rx_vars[channel].probe_adc_low;
            rx_vars[channel].probe_adc_gap_received = 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;
            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 = 0;
                    break;
                } else {
                }
            }
            memcpy(rx_vars[channel].rx_frame_buffer_received, rx_vars[channel].rx_frame_buffer,FRAME_BUFFER_SIZE);
            rx_vars[channel].is_received = true;
            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;
            }
        }
        //if(frame_state != IDLE_STATE) println(received_data, HEX);
    }
}
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{{{");
    printf("\nMSG valid=%d, (ch_%d)[len:%d/%d][%s] Adc[Max=%d Min=%d Gap=%d]", rx_vars[LIFI_CHANNEL_1].is_valid, rx_vars[LIFI_CHANNEL_1].received_data_count, rx_vars[LIFI_CHANNEL_1].length, LIFI_CHANNEL_1, rx_vars[LIFI_CHANNEL_1].rx_frame_buffer_received,rx_vars[LIFI_CHANNEL_1].probe_adc_high_received,rx_vars[LIFI_CHANNEL_1].probe_adc_low_received, rx_vars[LIFI_CHANNEL_1].probe_adc_gap_received);
#endif    
    rx_vars[LIFI_CHANNEL_1].is_received = false;
    
    if(Lifi_IsChannelAvailable(LIFI_CHANNEL_2)) {
#if RX_DEBUG_MAIN_LOOP   
        printf("\nMSG valid=%d, (ch_%d)[len:%d/%d][%s] Adc[Max=%d Min=%d Gap=%d]", rx_vars[LIFI_CHANNEL_2].is_valid, rx_vars[LIFI_CHANNEL_2].received_data_count, rx_vars[LIFI_CHANNEL_2].length, LIFI_CHANNEL_2, rx_vars[LIFI_CHANNEL_2].rx_frame_buffer_received,rx_vars[LIFI_CHANNEL_2].probe_adc_high_received,rx_vars[LIFI_CHANNEL_2].probe_adc_low_received, rx_vars[LIFI_CHANNEL_2].probe_adc_gap_received);
#endif   
        rx_vars[LIFI_CHANNEL_2].is_received = false;
    }
    if(Lifi_IsChannelAvailable(LIFI_CHANNEL_3)) {
#if RX_DEBUG_MAIN_LOOP   
       printf("\nMSG valid=%d, (ch_%d)[len:%d/%d][%s] Adc[Max=%d Min=%d Gap=%d]", rx_vars[LIFI_CHANNEL_3].is_valid, rx_vars[LIFI_CHANNEL_3].received_data_count, rx_vars[LIFI_CHANNEL_3].length, LIFI_CHANNEL_3, rx_vars[LIFI_CHANNEL_3].rx_frame_buffer_received,rx_vars[LIFI_CHANNEL_3].probe_adc_high_received,rx_vars[LIFI_CHANNEL_3].probe_adc_low_received, rx_vars[LIFI_CHANNEL_3].probe_adc_gap_received);
#endif   
        rx_vars[LIFI_CHANNEL_3].is_received = false;
    }
    if(Lifi_IsChannelAvailable(LIFI_CHANNEL_4)) {
#if RX_DEBUG_MAIN_LOOP   
        printf("\nMSG valid=%d, (ch_%d)[len:%d/%d][%s] Adc[Max=%d Min=%d Gap=%d]", rx_vars[LIFI_CHANNEL_4].is_valid,rx_vars[LIFI_CHANNEL_4].received_data_count, rx_vars[LIFI_CHANNEL_4].length, LIFI_CHANNEL_4, rx_vars[LIFI_CHANNEL_4].rx_frame_buffer_received,rx_vars[LIFI_CHANNEL_4].probe_adc_high_received,rx_vars[LIFI_CHANNEL_4].probe_adc_low_received, rx_vars[LIFI_CHANNEL_4].probe_adc_gap_received);
#endif   
        rx_vars[LIFI_CHANNEL_4].is_received = false;
    }
#if RX_DEBUG_MAIN_LOOP    
    printf("\n}}}");
 #endif   
}
void LifiRx_LoopOOK()
{
    //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);
    print_4ch_message();
}
// 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].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 ;
}