APP4 S5
Embed:
(wiki syntax)
Show/hide line numbers
radio.cpp
00001 /* 00002 * radio.cpp - Code de radio manchester - Jean-Philippe Fournier (fouj1807) - Jean-Pascal McGee (mcgj2701) 00003 */ 00004 00005 #include "radio.h" 00006 #include "quick_queue.h" 00007 00008 #include "mbed.h" 00009 #include "rtos.h" 00010 00011 #include "crc.h" 00012 // Vitesse de sortie des message manchester 00013 #define MANCHESTER_SPEED_OUT 4 00014 00015 // Pins de reception et d'entree 00016 #define INPUT_RADIO p18 00017 #define OUTPUT_RADIO p6 00018 00019 //////////////////////////////////////////////////////////////////////////// 00020 //////////////////////////////////////////////////////////////////////////// 00021 //////////////////////////////////////////////////////////////////////////// 00022 //////////////////////////////////////////////////////////////////////////// 00023 00024 // Private API enumerations 00025 // Receiver states 00026 typedef enum { 00027 in_attente = 0, 00028 in_preambule, 00029 in_data 00030 } receive_state_t; 00031 00032 // Emitter states 00033 typedef enum { 00034 out_preambule = 0, 00035 out_start, 00036 out_options, 00037 out_length, 00038 out_data, 00039 out_crc, 00040 out_end, 00041 out_idle 00042 } emitter_state_t; 00043 00044 //////////////////////////////////////////////////////////////////////////// 00045 //////////////////////////////////////////////////////////////////////////// 00046 //////////////////////////////////////////////////////////////////////////// 00047 //////////////////////////////////////////////////////////////////////////// 00048 // Fonctions privee de l'API 00049 00050 // Setup radio output 00051 void setup_radio_out(); 00052 // Setup radio input 00053 void setup_radio_in(); 00054 // Fonction periodique d'envoi de messages 00055 void radio_out(void const *args); 00056 // Fonction appellee lors de l'interruption sur la pin d'entree 00057 void radio_in(); 00058 // Fonction content la state machine de reception de trame 00059 bool receive_frame(byte read_byte); 00060 // Fonction de timeout de la reception de d ata manchester 00061 void stop_frame(void const *n); 00062 // Fonction du thread d'affichage dans le terminal 00063 void thread_putc(); 00064 00065 // Fonction qui cree un message et le mets dans un message 00066 void add_new_message(); 00067 00068 //////////////////////////////////////////////////////////////////////////// 00069 //////////////////////////////////////////////////////////////////////////// 00070 //////////////////////////////////////////////////////////////////////////// 00071 //////////////////////////////////////////////////////////////////////////// 00072 00073 // TODO HOW WE DO THIS 00074 Mail<radio_message_t, MESSAGE_BUFFER_SIZE> out_mail; 00075 Mail<radio_message_t, MESSAGE_BUFFER_SIZE> in_mail; 00076 00077 // Utilise pour les interruptions et la lecture de la valeur d'entree de la pin de reception 00078 InterruptIn input(INPUT_RADIO); 00079 // Pin de sortie de la radio, permet l'envoi de code binaire, dans ce cas, manchester 00080 DigitalOut output(OUTPUT_RADIO); 00081 00082 // Definition des LED de debug de la radio 00083 #ifndef LED 00084 DigitalOut in_debug_led4(LED4); 00085 DigitalOut out_debug_led3(LED3); 00086 00087 DigitalOut frame_out_end_led2(LED2); 00088 DigitalOut frame_in_end_led1(LED1); 00089 #endif 00090 00091 // Thread d'output de debugging 00092 Thread thread; 00093 00094 int start_speed = MANCHESTER_SPEED_OUT; 00095 00096 byte current_state = in_attente; 00097 byte current_byte_progress = 0; 00098 00099 // Timer d'evoi periodic de donnes vers la radio 00100 RtosTimer out_timer(radio_out, osTimerPeriodic, NULL); 00101 00102 // Timer qui mesure le temps et cree un timer sur la reception de data, permet le timeout du 00103 // data qui arrive de la reception. Termine la reception manchester 00104 RtosTimer ticker_watch(stop_frame, osTimerOnce, NULL); 00105 00106 // Char used by the debugging serial 00107 volatile int debug_char_output = 0; 00108 00109 //////////////////////////////////////////////////////////////////////////// 00110 //////////////////////////////////////////////////////////////////////////// 00111 //////////////////////////////////////////////////////////////////////////// 00112 //////////////////////////////////////////////////////////////////////////// 00113 00114 // Setup radio input 00115 void setup_radio_in() 00116 { 00117 //thread.start(callback(thread_putc)); 00118 00119 input.rise(&radio_in); 00120 input.fall(&radio_in); 00121 } 00122 00123 // Setup radio output 00124 void setup_radio_out() 00125 { 00126 out_debug_led3 = 0; 00127 frame_out_end_led2 = 0; 00128 output = 0; 00129 00130 //add_new_message(); 00131 00132 wait(1); 00133 out_timer.start(start_speed); 00134 } 00135 00136 void add_new_message(){ 00137 ////////////////////////////////////////////////////// 00138 // Creation d'un message et insertion dans le buffer 00139 radio_message_t* message = get_new_out_message(); 00140 if (message != NULL) 00141 { 00142 message->preambule = HEADER_DELIMITER; 00143 message->start = HEADER_START; 00144 message->options = HEADER_DELIMITER; 00145 message->length = 0x3; 00146 00147 message->data[0] = 0xC0; 00148 message->data[1] = 0xFF; 00149 message->data[2] = 0xEE; 00150 00151 // Ajouter calcul 00152 message->control = 0xCE; 00153 00154 message->end = FOOTER_END; 00155 // On avance dans le buffer; 00156 new_out_message_ready(); 00157 } 00158 ////////////////////////////////////////////////////// 00159 } 00160 00161 #define SET_VAL_BIT_MASK(val) next_value = 0x1 & val; 00162 #define SET_VAL_SHIFT(val, shift) SET_VAL_BIT_MASK(val >> (7 - shift)) 00163 #define CHECK_NEXT_STATE if (current_byte_progress > 7) \ 00164 { \ 00165 out_current_state++; \ 00166 current_byte_progress = 0; \ 00167 } 00168 00169 // Fonction appellee periodiquement pour l'envoi du message courant 00170 void radio_out(void const *args) 00171 { 00172 static byte current_byte_progress = 0; 00173 static byte current_byte = 0; 00174 static byte out_current_state = out_preambule; 00175 static bool IsBitTransition = false; 00176 static byte next_value = 0; 00177 static radio_message_t* message = NULL; 00178 00179 out_debug_led3 = !out_debug_led3; 00180 // Si on est a la fin du packet, on retourne au debut et on reenvoye les donnees 00181 if (out_current_state > out_idle) 00182 { 00183 // Message termine 00184 message = NULL; 00185 last_out_message_read(); 00186 frame_out_end_led2 = 0; 00187 00188 // Reinitialisation des var de messages 00189 current_byte = 0; 00190 current_byte_progress = 0; 00191 out_current_state = out_preambule; 00192 00193 out_timer.stop(); 00194 out_timer.start(start_speed); 00195 } 00196 00197 if (message == NULL) 00198 { 00199 message = get_last_out_message(); 00200 } 00201 00202 if (message != NULL) 00203 { 00204 if (!IsBitTransition) 00205 { 00206 // Dependant du state, on progresse dans l'envoi du message 00207 switch (out_current_state) 00208 { 00209 case out_preambule: // preambule 00210 { 00211 frame_out_end_led2 = 1; 00212 SET_VAL_SHIFT(message->preambule, current_byte_progress++); 00213 CHECK_NEXT_STATE 00214 break; 00215 } 00216 case out_start: // start 00217 { 00218 SET_VAL_SHIFT(message->start, current_byte_progress++); 00219 CHECK_NEXT_STATE 00220 break; 00221 } 00222 case out_options: // entete options 00223 { 00224 SET_VAL_SHIFT(message->options, current_byte_progress++); 00225 CHECK_NEXT_STATE 00226 break; 00227 } 00228 case out_length: // entete lenght 00229 { 00230 SET_VAL_SHIFT(message->length, current_byte_progress++); 00231 CHECK_NEXT_STATE 00232 break; 00233 } 00234 case out_data: // charge utile 00235 { 00236 SET_VAL_SHIFT(message->data[current_byte], current_byte_progress++) 00237 if (current_byte_progress > 7) 00238 { 00239 current_byte++; 00240 current_byte_progress = 0; 00241 if (current_byte >= message->length) 00242 { 00243 current_byte = 0; 00244 out_current_state++; 00245 } 00246 } 00247 break; 00248 } 00249 case out_crc: // controle 00250 { 00251 SET_VAL_SHIFT(message->control, current_byte_progress++); 00252 CHECK_NEXT_STATE 00253 break; 00254 } 00255 case out_end: // end 00256 { 00257 SET_VAL_SHIFT(message->end, current_byte_progress++); 00258 CHECK_NEXT_STATE 00259 break; 00260 } 00261 case out_idle: 00262 { 00263 /*out_debug_led3 = !out_debug_led3; 00264 message = NULL; 00265 last_out_message_read(); 00266 current_byte = 0; 00267 current_byte_progress = 0;*/ 00268 break; 00269 } 00270 } 00271 00272 // Changement d'etat pour permettre de faire la bonne transition de valeur 00273 if (next_value != output && out_current_state <= out_idle) 00274 { 00275 output = !output; 00276 } 00277 } 00278 // Si on est pas dans une transitipon 00279 else if (out_current_state != out_idle + 1) 00280 { 00281 output = !output; 00282 if (out_current_state == out_idle) 00283 { 00284 out_current_state++; 00285 } 00286 } 00287 IsBitTransition = !IsBitTransition; 00288 } 00289 } 00290 00291 // Fonction appellee lors de l'interruption sur la pin d'entree 00292 void radio_in() 00293 { 00294 // Timer utilise pour le calcul de la periode de l'horloge du code manchester 00295 static Timer timer; 00296 // Valeur de la demi periode 00297 static int half_period = 0; 00298 // Valeur de la periode de l'horloge 00299 static int calculated_period = 0; 00300 // 00301 static byte current_byte = 0; 00302 00303 in_debug_led4 = !in_debug_led4; 00304 00305 00306 switch (current_state) 00307 { 00308 case in_attente: 00309 { 00310 frame_in_end_led1 = 0; 00311 if (input == 1) 00312 { 00313 timer.start(); 00314 current_state = in_preambule; 00315 current_byte_progress = 1; 00316 frame_in_end_led1 = 1; 00317 } 00318 break; 00319 } 00320 case in_preambule: 00321 { 00322 current_byte_progress++; 00323 calculated_period = timer.read_ms(); 00324 timer.reset(); 00325 if (current_byte_progress > 7) 00326 { 00327 half_period = calculated_period / 2; 00328 ticker_watch.start(calculated_period + half_period); 00329 current_byte_progress = 0; 00330 current_byte = 0; 00331 current_state = in_data; 00332 debug_char_output = calculated_period; 00333 // thread.signal_set(0x1); 00334 } 00335 break; 00336 } 00337 case in_data: 00338 { 00339 // Si ca fait plus longtemps que la periode usuelle de reception de donne 00340 // Cela veut dire que l'on doit recommencer la reception 00341 if(timer.read_ms() > calculated_period) 00342 { 00343 frame_in_end_led1 = 0; 00344 timer.stop(); 00345 timer.reset(); 00346 if (input == 1) 00347 { 00348 timer.start(); 00349 current_state = in_preambule; 00350 current_byte_progress = 1; 00351 } 00352 else 00353 { 00354 current_state = in_attente; 00355 current_byte_progress = 0; 00356 } 00357 } 00358 // Si le temps de la demi periode est passe, donc on a une donne reele 00359 else if (timer.read_ms() > half_period) 00360 { 00361 current_byte = (!input << (7 - current_byte_progress)) | current_byte; 00362 current_byte_progress++ ; 00363 ticker_watch.start(calculated_period + half_period); 00364 timer.reset(); 00365 00366 if (current_byte_progress > 7) 00367 { 00368 debug_char_output = current_byte; 00369 if (receive_frame(current_byte)) 00370 { 00371 current_state = in_attente; 00372 } 00373 current_byte_progress = 0; 00374 current_byte = 0; 00375 } 00376 } 00377 break; 00378 } 00379 } 00380 } 00381 00382 // Fonction content la state machine de reception de trame 00383 bool receive_frame(byte read_byte) 00384 { 00385 static radio_message_t* current_message; 00386 static byte receive_current_state = out_start; 00387 static int data_index = 0; 00388 00389 if (current_message == NULL) 00390 { 00391 current_message = get_new_in_message(); 00392 receive_current_state = out_start; 00393 if (current_message == NULL){ 00394 return true; 00395 } 00396 } 00397 00398 if (current_message != NULL) 00399 { 00400 switch (receive_current_state) 00401 { 00402 case out_start: 00403 { 00404 current_message->start = read_byte; 00405 receive_current_state++; 00406 break; 00407 } 00408 case out_options: 00409 { 00410 current_message->options = read_byte; 00411 receive_current_state++; 00412 break; 00413 } 00414 case out_length: 00415 { 00416 current_message->length = read_byte; 00417 receive_current_state++; 00418 break; 00419 } 00420 case out_data: 00421 { 00422 current_message->data[data_index++] = read_byte; 00423 if (data_index >= current_message->length) 00424 { 00425 data_index = 0; 00426 receive_current_state++; 00427 } 00428 break; 00429 } 00430 case out_crc: 00431 { 00432 current_message->control = read_byte; 00433 receive_current_state++; 00434 break; 00435 } 00436 case out_end: 00437 { 00438 current_message->end = read_byte; 00439 new_in_message_ready(); 00440 receive_current_state = out_start; 00441 current_message = NULL; 00442 return true; 00443 break; 00444 } 00445 00446 } 00447 } 00448 return false; 00449 } 00450 00451 // Fonction de timeout de la reception de data manchester 00452 void stop_frame(void const *n) 00453 { 00454 frame_in_end_led1 = 0; 00455 current_state = in_attente; 00456 current_byte_progress = 0; 00457 ticker_watch.stop(); 00458 } 00459 00460 // Fonction du thread d'affichage dans le terminal 00461 /* 00462 void thread_putc() 00463 { 00464 while(true) 00465 { 00466 Thread::signal_wait(0x1); 00467 debug_output.printf("0x%c\n\r", debug_char_output); 00468 } 00469 }*/ 00470 00471 //////////////////////////////////////////////////////////////////////////// 00472 //////////////////////////////////////////////////////////////////////////// 00473 //////////////////////////////////////////////////////////////////////////// 00474 //////////////////////////////////////////////////////////////////////////// 00475 00476 /* 00477 * Public API function 00478 */ 00479 00480 /* 00481 * Inits the radio system and begins receiving manchester coded messages 00482 * Sends buffered messages 00483 */ 00484 void init_radio_system() 00485 { 00486 init_crc_module(); 00487 setup_radio_in(); 00488 setup_radio_out(); 00489 } 00490 00491 00492 00493 bool send_message(char* buffer, int length) 00494 { 00495 ////////////////////////////////////////////////////// 00496 // Creation d'un message et insertion dans le buffer 00497 radio_message_t* message = get_new_out_message(); 00498 if (length <= MAX_MESSAGE_LENGTH && message != NULL) 00499 { 00500 message->preambule = HEADER_DELIMITER; 00501 message->start = HEADER_START; 00502 message->options = HEADER_DELIMITER; 00503 message->length = length; 00504 00505 for (int i = 0; i < length; i++){ 00506 message->data[i] = buffer[i]; 00507 } 00508 00509 // Ajouter calcul du CRC 00510 message->control = get_crc_value(message->data, message->length);//0xCE; 00511 00512 message->end = FOOTER_END; 00513 // On avance dans le buffer; 00514 return new_out_message_ready(); 00515 } 00516 return false; 00517 ////////////////////////////////////////////////////// 00518 } 00519 00520 bool get_message(radio_message_t* message) 00521 { 00522 radio_message_t* received_message; 00523 // Si un message a ete recu par la radio 00524 if((received_message = get_last_in_message()) != NULL) 00525 { 00526 // Si la valeur de CRC est valide par rapport a ce qui est calcule 00527 if (get_crc_value(received_message->data, received_message->length) == received_message->control) 00528 { 00529 message->preambule = received_message->preambule; 00530 message->start = received_message->start; 00531 message->options = received_message->options; 00532 message->length = received_message->length; 00533 // memcopy 00534 memcpy(message->data, received_message->data, received_message->length); 00535 00536 message->control = received_message->control; 00537 message->end = received_message->end; 00538 00539 last_in_message_read(); 00540 return true; 00541 } 00542 } 00543 return false; 00544 } 00545 00546 //////////////////////////////////////////////////////////////////////////// 00547 //////////////////////////////////////////////////////////////////////////// 00548 //////////////////////////////////////////////////////////////////////////// 00549 ////////////////////////////////////////////////////////////////////////////
Generated on Thu Jul 21 2022 17:35:45 by
1.7.2