int main() { // init robot e_init_port(); e_init_ad_scan(); e_init_uart1(); e_led_clear(); e_init_motors(); e_start_agendas_processing(); // wait for s to start btcomWaitForCommand('s'); btcomSendString("==== READY - IR TESTING ====\n\n"); e_calibrate_ir(); // initialize ircom and start reading ircomStart(); ircomEnableContinuousListening(); ircomListen(); // rely on selector to define the role int selector = getselector(); // show selector choosen int i; long int j; for (i = 0; i < selector; i++) { e_led_clear(); for(j = 0; j < 200000; j++) asm("nop"); e_set_led(i%8, 1); for(j = 0; j < 300000; j++) asm("nop"); e_led_clear(); for(j = 0; j < 300000; j++) asm("nop"); } // activate obstacle avoidance e_activate_agenda(obstacleAvoidance, 10000); // acting as sender if (selector == 1) { btcomSendString("==== EMITTER ====\n\n"); int i; for (i = 0; i < 10000; i++) { // takes ~15knops for a 32window, avoid putting messages too close... for(j = 0; j < 200000; j++) asm("nop"); ircomSend(i % 256); while (ircomSendDone() == 0); btcomSendString("."); } } // acting as receiver else if (selector == 2) { btcomSendString("==== RECEIVER ====\n\n"); int i = 0; while (i < 200) { // ircomListen(); IrcomMessage imsg; ircomPopMessage(&imsg); if (imsg.error == 0) { int val = (int) imsg.value; /* Send Value*/ char tmp[128]; sprintf(tmp, "Receive successful : %d - distance=%f \t direction=%f \n", val, (double)imsg.distance, (double)imsg.direction); btcomSendString(tmp); } else if (imsg.error > 0) { btcomSendString("Receive failed \n"); } // else imsg.error == -1 -> no message available in the queue if (imsg.error != -1) i++; } } // no proper role defined... else { int i = 0; long int j; while(1) { e_led_clear(); for(j = 0; j < 200000; j++) asm("nop"); e_set_led(i, 1); for(j = 0; j < 300000; j++) asm("nop"); i++; i = i%8; } } ircomStop(); return 0; }
void ircomReceiveListen() { //Recognition of the first two bits (0) of synchronization int i; totalDur = 0; int first_sample; unsigned long duration; if(!waiting_second_buffer){ if(bit == FIRST_BIT){ // We have to handle the 6 samples we got. The previous word conteined an even number of 1. Then we go back to the default window size e_sampler_default_sampling_window(); bit = NOT_LAST_BIT; for(i = 2; i < SAMPLING_WINDOW + 1; i++){ duration = received[i] * precision / 1000; // pulse duration in microseconds if(duration > 1000){ // noise, an interval greater than 1000 us is not correct. // We try to recover by keeping this interval as first for a new message transmission ircomReceiveData.done = 1; ircomReceiveData.error = 1; ircomReceiveData.receiving = 0; ircomReceiveData.state = 0; e_sampling_off(); e_sampler_default_sampling_window(); e_sampling_reset_with_samples(SAMPLING_WINDOW + 1 - i); ircomResetReceive(); for(int tempIndex = i; tempIndex < SAMPLING_WINDOW + 1; tempIndex++){ sampling[tempIndex-i] = received[tempIndex]; } // set fsm in idle mode (except continuous listening mode...) if (ircomReceiveData.continuousListening == 1){ ircomListen(); } else { ircomData.fsm = IRCOM_FSM_IDLE; } return; } if(duration > 0) { totalDur += duration; } } } else { // The first sample is discarded for the first bit of a word for(i = 1; i < SAMPLING_WINDOW; i++){ duration = received[i] * precision / 1000; // pulse duration in microseconds if(duration > 0) { totalDur += duration; } if(duration > 1000){ // noise, an interval greater than 1000 us is not correct. // We try to recover by keeping this interval as first for a new message transmission ircomReceiveData.done = 1; ircomReceiveData.error = 1; ircomReceiveData.receiving = 0; ircomReceiveData.state = 0; e_sampling_off(); e_sampler_default_sampling_window(); e_sampling_reset_with_samples(SAMPLING_WINDOW - i); ircomResetReceive(); for(int tempIndex = i; tempIndex < SAMPLING_WINDOW; tempIndex++){ sampling[tempIndex-i] = received[tempIndex]; } // set fsm in idle mode (except continuous listening mode...) if (ircomReceiveData.continuousListening == 1){ ircomListen(); } else { ircomData.fsm = IRCOM_FSM_IDLE; } return; } } } } else { synch_bit_index++; waiting_second_buffer = 0; if(synch_bit_index == 0){ // We have received the first 2 bits of synchronization correctly, we can now receive the payload // ok setup everything : start receiveing word, record all ircomReceiveData.currentBit = 0; ircomReceiveData.done = 0; ircomReceiveData.error = 0; ircomReceiveData.receiving = 1; ircomReceiveData.state = 1; return; } return; } if(totalDur <= IRCOM_HALF_BIT_TOT_DURATION_MAX && !waiting_second_buffer){ // MARK. We have to take other 5 samples waiting_second_buffer = 1; return; }else if(totalDur > IRCOM_HALF_BIT_TOT_DURATION_MAX && totalDur <= IRCOM_COMPLETE_BIT_TOT_DURATION_MAX && !waiting_second_buffer) { // SPACE. The 5 samples we have are enough waiting_second_buffer = 0; odd_edges = !odd_edges; synch_bit_index++; } else { // no significant modulation perceived ? e_sampling_off(); e_sampler_default_sampling_window(); e_sampling_reset(); ircomResetReceive(); if (ircomReceiveData.continuousListening == 1){ //There has been an error in the communication. To recover from this situation we wait a random number of milliseconds before starting sampling again wait_fsm = RANDOM_WAIT; randomWaitSince = millis(); randomInterval = random(MIN_WAIT_INTERVAL, MAX_WAIT_INTERVAL); ircomListen(); } else { ircomData.fsm = IRCOM_FSM_IDLE; } return; } if(synch_bit_index == 0){ // We have received the first 2 bits of synchronization correctly, we can now receive the payload // ok setup everything : start receiveing word, record all ircomReceiveData.currentBit = 0; ircomReceiveData.done = 0; ircomReceiveData.error = 0; ircomReceiveData.receiving = 1; ircomReceiveData.state = 1; } }
// FSM Receive, state 2 // receive a word void ircomReceiveWord() { int signal; long int value; int i; totalDur = 0; unsigned long duration; switch(bit){ case NOT_LAST_BIT: { // We are not receiveing the LAST BIT of the word if(!waiting_second_buffer){ for(i = 1; i < SAMPLING_WINDOW; i++){ duration = received[i] * precision / 1000; // pulse duration in microseconds if(duration > 0) { totalDur += duration; } if(duration > 1000){ // noise, an interval greater than 1000 us is not correct. // We try to recover by keeping this interval as first for a new message transmission ircomReceiveData.done = 1; ircomReceiveData.error = 1; ircomReceiveData.receiving = 0; ircomReceiveData.state = 0; e_sampling_off(); e_sampler_default_sampling_window(); e_sampling_reset_with_samples(SAMPLING_WINDOW - i); ircomResetReceive(); for(int tempIndex = i; tempIndex < SAMPLING_WINDOW; tempIndex++){ sampling[tempIndex-i] = received[tempIndex]; } // set fsm in idle mode (except continuous listening mode...) if (ircomReceiveData.continuousListening == 1){ ircomListen(); } else { ircomData.fsm = IRCOM_FSM_IDLE; } return; } } } else { waiting_second_buffer = 0; ircomReceiveData.word[ircomReceiveData.currentBit++] = IRCOM_MARK; if(ircomReceiveData.currentBit == IRCOM_WORDSIZE + 1){ //For the last bit of the word we take one sample less, since the bit might have one edge less from the others e_sampler_decrease_sampling_window(); bit = LAST_BIT; } return; } if(totalDur <= IRCOM_HALF_BIT_TOT_DURATION_MAX && !waiting_second_buffer){ // MARK. We have to take other 5 samples waiting_second_buffer = 1; return; } else if(totalDur > IRCOM_HALF_BIT_TOT_DURATION_MAX && totalDur <= IRCOM_COMPLETE_BIT_TOT_DURATION_MAX && !waiting_second_buffer) { // SPACE. The 5 samples we have are enough waiting_second_buffer = 0; odd_edges = !odd_edges; ircomReceiveData.word[ircomReceiveData.currentBit++] = IRCOM_SPACE; } else { // no significant modulation perceived ? // stop receiveing, discard message ircomReceiveData.done = 1; ircomReceiveData.error = 1; ircomReceiveData.receiving = 0; ircomReceiveData.state = 0; e_sampler_default_sampling_window(); e_sampling_reset(); ircomResetReceive(); // set fsm in idle mode (except continuous listening mode...) if (ircomReceiveData.continuousListening == 1){ //There has been an error in the communication. To recover from this situation we wait a random number of milliseconds before starting sampling again wait_fsm = RANDOM_WAIT; randomWaitSince = millis(); randomInterval = random(MIN_WAIT_INTERVAL, MAX_WAIT_INTERVAL); ircomListen(); } else { e_sampling_off(); ircomData.fsm = IRCOM_FSM_IDLE; } return; } if(ircomReceiveData.currentBit == IRCOM_WORDSIZE + 1){ //For the last bit of the word we take one sample less, since the bit might have one edge less than the others e_sampler_decrease_sampling_window(); bit = LAST_BIT; } break; } case LAST_BIT: { // LAST BIT of the word if(!waiting_second_buffer){ // We have only SAMPLING_WINDOW - 1 samples and we ignore the first as usual for(i = 1; i < (SAMPLING_WINDOW - 1); i++){ duration = received[i] * precision / 1000; // pulse duration in microseconds if(duration > 0) { totalDur += duration; } if(duration > 1000){ // noise, an interval greater than 2000 us is not correct. // We try to recover by keeping this interval as first for a new message transmission ircomReceiveData.done = 1; ircomReceiveData.error = 1; ircomReceiveData.receiving = 0; ircomReceiveData.state = 0; e_sampling_off(); e_sampler_default_sampling_window(); e_sampling_reset_with_samples(SAMPLING_WINDOW - 1 - i); ircomResetReceive(); for(int tempIndex = i; tempIndex < SAMPLING_WINDOW - 1; tempIndex++){ sampling[tempIndex-i] = received[tempIndex]; } // set fsm in idle mode (except continuous listening mode...) if (ircomReceiveData.continuousListening == 1){ ircomListen(); } else { ircomData.fsm = IRCOM_FSM_IDLE; } return; } } } else { // The last bit is a 0. In both cases (odd or even number of 1) we can go back to the default window size e_sampler_default_sampling_window(); waiting_second_buffer = 0; bit = NOT_LAST_BIT; ircomReceiveData.word[ircomReceiveData.currentBit++] = IRCOM_MARK; // end of message // evaluate CRC ircomReceiveData.error = ircomReceiveCheckCRC(); if(ircomReceiveData.error != 0){ e_sampling_reset(); } // stop receiving ircomReceiveData.done = 1; ircomReceiveData.receiving = 0; ircomReceiveData.state = 0; synch_bit_index = -2; odd_edges = 0; // record in the msg queue value = ircomBin2Int(ircomReceiveData.word); ircomPushMessage(value, ircomReceiveData.error); // set fsm in idle mode (except continuous listening mode...) if (ircomReceiveData.continuousListening == 1){ e_sampling_off(); if(ircomReceiveData.error != 0){ //There has been an error in the communication. To recover from this situation we wait a random number of milliseconds before starting sampling again wait_fsm = RANDOM_WAIT; e_sampler_default_sampling_window(); e_sampling_reset(); ircomResetReceive(); randomWaitSince = millis(); randomInterval = random(MIN_WAIT_INTERVAL, MAX_WAIT_INTERVAL); } ircomListen(); } else { e_sampling_off(); if(ircomReceiveData.error != 0){ e_sampler_default_sampling_window(); e_sampling_reset(); ircomResetReceive(); } ircomData.fsm = IRCOM_FSM_IDLE; } return; } if(totalDur <= IRCOM_HALF_LAST_BIT_TOT_DURATION_MAX && !waiting_second_buffer){ // MARK. We have to take other 5 samples if(!odd_edges){ //If the last bit is a 0 and the number of 1 in the word is even, we have to take other 6 samples to complete the bit e_sampler_increase_sampling_window(); } else { //If the last bit is a 0 and the number of 1 in the word is odd, we have to take other 5 samples to complete the bit e_sampler_default_sampling_window(); } waiting_second_buffer = 1; return; } else if(totalDur > IRCOM_HALF_LAST_BIT_TOT_DURATION_MAX && totalDur <= IRCOM_COMPLETE_LAST_BIT_TOT_DURATION_MAX && !waiting_second_buffer) { // SPACE. The 5 samples we have are enough waiting_second_buffer = 0; odd_edges = !odd_edges; if(!odd_edges){ //The last bit is a 1 and the number of 1 in the word is even with this last one, we will have to take 6 samples in the first bit of the next word (and skip the first 2) e_sampler_increase_sampling_window(); // The state in which we handle the 6 samples of the first bit of the next word bit = FIRST_BIT; } else { //The last bit is a 1 and the number of 1 in the word is odd with this last one, the 4 samples we took are enough e_sampler_default_sampling_window(); bit = NOT_LAST_BIT; } ircomReceiveData.word[ircomReceiveData.currentBit++] = IRCOM_SPACE; // evaluate CRC ircomReceiveData.error = ircomReceiveCheckCRC(); // stop receiving ircomReceiveData.done = 1; ircomReceiveData.receiving = 0; ircomReceiveData.state = 0; synch_bit_index = -2; odd_edges = 0; // record in the msg queue value = ircomBin2Int(ircomReceiveData.word); ircomPushMessage(value, ircomReceiveData.error); // set fsm in idle mode (except continuous listening mode...) if (ircomReceiveData.continuousListening == 1){ e_sampling_off(); if(ircomReceiveData.error != 0){ wait_fsm = RANDOM_WAIT; e_sampler_default_sampling_window(); e_sampling_reset(); ircomResetReceive(); randomWaitSince = millis(); randomInterval = random(MIN_WAIT_INTERVAL, MAX_WAIT_INTERVAL); } ircomListen(); } else { e_sampling_off(); if(ircomReceiveData.error != 0){ e_sampler_default_sampling_window(); e_sampling_reset(); ircomResetReceive(); } ircomData.fsm = IRCOM_FSM_IDLE; } return; } else { // no significant modulation perceived ? // stop receiveing, discard message ircomReceiveData.done = 1; ircomReceiveData.error = 1; ircomReceiveData.receiving = 0; ircomReceiveData.state = 0; e_sampler_default_sampling_window(); e_sampling_reset(); ircomResetReceive(); // set fsm in idle mode (except continuous listening mode...) if (ircomReceiveData.continuousListening == 1){ //There has been an error in the communication. To recover from this situation we wait a random number of milliseconds before starting sampling again wait_fsm = RANDOM_WAIT; randomWaitSince = millis(); randomInterval = random(MIN_WAIT_INTERVAL, MAX_WAIT_INTERVAL); ircomListen(); } else { e_sampling_off(); ircomData.fsm = IRCOM_FSM_IDLE; } return; } break; } } }
int main() { // init robot e_init_port(); e_init_ad_scan(); e_init_uart1(); e_led_clear(); e_init_motors(); e_start_agendas_processing(); // initialise buffer int k; for (k = 0; k < NB_NEIGHBOURS; k++) neighbours[k].id = -1; // wait for s to start /* btcomWaitForCommand('s'); */ btcomSendString("-OK-\n"); e_calibrate_ir(); // initialize ircom, then rng and start listening ircomStart(); //ircomEnableContinuousListening(); //ircomEnableProximity(); initRandomNumberGenerator(); // after rng init we can disable prox sensors //ircomDisableProximity(); ircomEnableContinuousListening(); ircomListen(); id = getselector(); ircomResetTime(); lastClock = ircomGetTime(); // activate movement //e_activate_agenda(move, 2500); organiseInit(); // advertise current direction e_led_clear(); e_set_led(0,1); e_set_led(4,1); while(1) { int messageReceived = 0; while(((ircomGetTime() - lastClock < COM_CYCLE_SPEED) || (ircomIsReceiving() == 1))) { IrcomMessage msg; ircomPopMessage(&msg); if (msg.error == 0) { processNewMessage(&msg); messageReceived = 1; SetRobotSeen(msg); } } e_set_body_led(messageReceived); SendData(); //sendId(); //sendAngleToNeighbours(); lastClock = ircomGetTime(); e_set_body_led(0); } ircomStop(); return 0; }