App1_S5
/
APP4_IRQ
APP4 S5
Diff: radio.cpp
- Revision:
- 10:c4629b6c42f8
- Parent:
- 9:081324663b8c
- Child:
- 11:1d277e7e272d
--- a/radio.cpp Thu Oct 12 20:48:02 2017 +0000 +++ b/radio.cpp Sun Oct 15 23:13:18 2017 +0000 @@ -1,32 +1,85 @@ +/* +* radio.cpp - Code de radio manchester - Jean-Philippe Fournier (fouj1807) - Jean-Pascal McGee (mcgj2701) +*/ #include "radio.h" +#include "quick_queue.h" #include "mbed.h" #include "rtos.h" -#include <LPC17xx.h> -#define MESSAGE_BUFFER_SIZE 16 +// Vitesse de sortie des message manchester +#define MANCHESTER_SPEED_OUT 50 -#define MANCHESTER_SPEED_OUT 10 - +// Pins de reception et d'entree #define INPUT_RADIO p18 #define OUTPUT_RADIO p6 -radio_message_t out_messages[MESSAGE_BUFFER_SIZE]; -byte out_message_in; -byte out_message_out; +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +// Private API enumerations +// Receiver states +typedef enum { + in_attente = 0, + in_preambule, + in_data +} receive_state_t; + +// Emitter states +typedef enum { + out_preambule = 0, + out_start, + out_options, + out_length, + out_data, + out_crc, + out_end, + out_idle +} emitter_state_t; + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +// Fonctions privee de l'API -radio_message_t in_messages[MESSAGE_BUFFER_SIZE]; -byte in_message_in; -byte in_message_out; +// Setup radio output +void setup_radio_out(); +// Setup radio input +void setup_radio_in(); +// Fonction periodique d'envoi de messages +void radio_out(void const *args); +// Fonction appellee lors de l'interruption sur la pin d'entree +void radio_in(); +// Fonction content la state machine de reception de trame +void receive_frame(byte read_byte); +// Fonction de timeout de la reception de data manchester +void stop_frame(void const *n); +// Fonction du thread d'affichage dans le terminal +void thread_putc(); -InterruptIn input(INPUT_RADIO); +// Fonction qui cree un message et le mets dans un message +void add_new_message(); + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// -RtosTimer out_timer(radio_out, osTimerPeriodic, (void *)out_messages); +// TODO HOW WE DO THIS +Mail<radio_message_t, MESSAGE_BUFFER_SIZE> out_mail; +Mail<radio_message_t, MESSAGE_BUFFER_SIZE> in_mail; +// Utilise pour les interruptions et la lecture de la valeur d'entree de la pin de reception +InterruptIn input(INPUT_RADIO); +// Pin de sortie de la radio, permet l'envoi de code binaire, dans ce cas, manchester DigitalOut output(OUTPUT_RADIO); +// Definition des LED de debug de la radio #ifndef LED DigitalOut in_debug_led4(LED4); DigitalOut out_debug_led3(LED3); @@ -35,53 +88,208 @@ DigitalOut frame_in_end_led1(LED1); #endif -Serial PC(USBTX, USBRX); - -// API functions -void init_radio_system() -{ - setup_radio_in(); - setup_radio_out(); - output = 0; -} - -// Private functions - -typedef enum { - in_attente = 0, - in_preambule, - in_data, - in_idle -} receive_state_t; +// Thread d'output de debugging +Thread thread; int start_speed = MANCHESTER_SPEED_OUT; byte current_state = in_attente; byte current_byte_progress = 0; -void stop_frame(void const *n); +// Timer d'evoi periodic de donnes vers la radio +RtosTimer out_timer(radio_out, osTimerPeriodic, NULL); + +// Timer qui mesure le temps et cree un timer sur la reception de data, permet le timeout du +// data qui arrive de la reception. Termine la reception manchester +RtosTimer ticker_watch(stop_frame, osTimerOnce, NULL); + +// Char used by the debugging serial +volatile int debug_char_output = 0; -RtosTimer ticker_watch(stop_frame, osTimerPeriodic, NULL); +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +// Setup radio input +void setup_radio_in() +{ + //thread.start(callback(thread_putc)); + + input.rise(&radio_in); + input.fall(&radio_in); +} -Thread thread; +// Setup radio output +void setup_radio_out() +{ + out_debug_led3 = 0; + frame_out_end_led2 = 0; + output = 0; + + //add_new_message(); + + wait(1); + out_timer.start(start_speed); +} -void stop_frame(void const *n) +void add_new_message(){ +////////////////////////////////////////////////////// + // Creation d'un message et insertion dans le buffer + radio_message_t* message = get_new_out_message(); + if (message != NULL) + { + message->preambule = HEADER_DELIMITER; + message->start = HEADER_START; + message->options = HEADER_DELIMITER; + message->length = 0x3; + + message->data[0] = 0xC0; + message->data[1] = 0xFF; + message->data[2] = 0xEE; + + // Ajouter calcul + message->control = 0xCE; + + message->end = FOOTER_END; + // On avance dans le buffer; + new_out_message_ready(); + } + ////////////////////////////////////////////////////// +} + +#define SET_VAL_BIT_MASK(val) next_value = 0x1 & val; +#define SET_VAL_SHIFT(val, shift) SET_VAL_BIT_MASK(val >> (7 - shift)) +#define CHECK_NEXT_STATE if (current_byte_progress > 7) \ + { \ + out_current_state++; \ + current_byte_progress = 0; \ + } + +// Fonction appellee periodiquement pour l'envoi du message courant +void radio_out(void const *args) { - frame_in_end_led1 = 0; - current_state = in_attente; - current_byte_progress = 0; - ticker_watch.stop(); -} + static byte current_byte_progress = 0; + static byte current_byte = 0; + static byte out_current_state = out_preambule; + static bool IsBitTransition = false; + static byte next_value = 0; + static radio_message_t* message = NULL; + + if (message == NULL) + { + message = get_last_out_message(); + } -volatile int t = 0; -volatile int c = 0; + if (message != NULL) + { + if (!IsBitTransition) + { + // Dependant du state, on progresse dans l'envoi du message + switch (out_current_state) + { + case out_preambule: // preambule + { + frame_out_end_led2 = 1; + SET_VAL_SHIFT(message->preambule, current_byte_progress++); + CHECK_NEXT_STATE + break; + } + case out_start: // start + { + SET_VAL_SHIFT(message->start, current_byte_progress++); + CHECK_NEXT_STATE + break; + } + case out_options: // entete options + { + SET_VAL_SHIFT(message->options, current_byte_progress++); + CHECK_NEXT_STATE + break; + } + case out_length: // entete lenght + { + SET_VAL_SHIFT(message->length, current_byte_progress++); + CHECK_NEXT_STATE + break; + } + case out_data: // charge utile + { + SET_VAL_SHIFT(message->data[current_byte], current_byte_progress++) + if (current_byte_progress > 7) + { + current_byte++; + current_byte_progress = 0; + if (current_byte >= message->length) + { + current_byte = 0; + out_current_state++; + } + } + //CHECK_NEXT_STATE + break; + } + case out_crc: // controle + { + SET_VAL_SHIFT(message->control, current_byte_progress++); + CHECK_NEXT_STATE + break; + } + case out_end: // end + { + SET_VAL_SHIFT(message->end, current_byte_progress++); + CHECK_NEXT_STATE + break; + } + case out_idle: + { + out_debug_led3 = !out_debug_led3; + message = NULL; + last_out_message_read(); + current_byte = 0; + current_byte_progress = 0; + break; + } + } + + // Changement d'etat pour permettre de faire la bonne transition de valeur + if (next_value != output && out_current_state != out_idle) + { + output = !output; + } + + // Si on est a la fin du packet, on retourne au debut et on reenvoye les donnees + if (out_current_state > out_end) + { + out_debug_led3 = !out_debug_led3; + message = NULL; + last_out_message_read(); + frame_out_end_led2 = 0; + out_current_state = out_preambule; + out_timer.stop(); + out_timer.start(start_speed); + } + } + // Si on est pas dans une transitipon + else if (out_current_state != out_idle) + { + output = !output; + } + IsBitTransition = !IsBitTransition; + } +} + +// Fonction appellee lors de l'interruption sur la pin d'entree void radio_in() { - + // Timer utilise pour le calcul de la periode de l'horloge du code manchester static Timer timer; - static int t_half = 0; - + // Valeur de la demi periode + static int half_period = 0; + // Valeur de la periode de l'horloge + static int calculated_period = 0; + // static byte current_byte = 0; in_debug_led4 = !in_debug_led4; @@ -104,243 +312,196 @@ case in_preambule: { current_byte_progress++; - t = timer.read_ms(); + calculated_period = timer.read_ms(); timer.reset(); if (current_byte_progress > 7) { - t_half = t / 2; - ticker_watch.start(t + t_half); + half_period = calculated_period / 2; + ticker_watch.start(calculated_period + half_period); current_byte_progress = 0; + current_byte = 0; current_state = in_data; - c = t; - thread.signal_set(0x1); + debug_char_output = calculated_period; + // thread.signal_set(0x1); } break; } case in_data: { - if(timer.read_ms() > t + t_half) + // Si ca fait plus longtemps que la periode usuelle de reception de donne + // Cela veut dire que l'on doit recommencer la reception + if(timer.read_ms() > calculated_period) { frame_in_end_led1 = 0; - current_state = in_attente; - current_byte_progress = 0; - timer.stop(); - timer.reset(); + timer.reset(); + if (input == 1) + { + timer.start(); + current_state = in_preambule; + current_byte_progress = 1; + } + else + { + current_state = in_attente; + current_byte_progress = 0; + } } - else if (timer.read_ms() > t_half) + // Si le temps de la demi periode est passe, donc on a une donne reele + else if (timer.read_ms() > half_period) { current_byte = (!input << (7 - current_byte_progress)) | current_byte; - current_byte_progress++ ; - //PC.putc(input); - // Display data - ticker_watch.start(t + t_half); + current_byte_progress++ ; + ticker_watch.start(calculated_period + half_period); timer.reset(); if (current_byte_progress > 7) { - c = current_byte; - thread.signal_set(0x1); + debug_char_output = current_byte; + receive_frame(current_byte); + //thread.signal_set(0x1); + current_byte_progress = 0; current_byte = 0; - current_byte_progress = 0; } } - else - { - //ticker_watch.start(t + t_half); - } - break; - } - case in_idle: - { - frame_in_end_led1 = 0; - current_state = in_attente; - current_byte_progress = 0; break; } } } -void thread_putc() +// Fonction content la state machine de reception de trame +void receive_frame(byte read_byte) { - while(1) + static radio_message_t* current_message; + static byte receive_current_state = out_start; + static int data_index = 0; + + if (current_message == NULL) + { + current_message = get_new_in_message(); + if (current_message != NULL) + receive_current_state = out_start; + } + + if (current_message != NULL) { - Thread::signal_wait(0x1); - PC.printf("0x%x\n\r", c); - } + switch (receive_current_state) + { + case out_start: + { + current_message->start = read_byte; + receive_current_state++; + break; + } + case out_options: + { + current_message->options = read_byte; + receive_current_state++; + break; + } + case out_length: + { + current_message->length = read_byte; + receive_current_state++; + break; + } + case out_data: + { + current_message->data[data_index++] = read_byte; + if (data_index >= current_message->length) + { + data_index = 0; + receive_current_state++; + } + break; + } + case out_crc: + { + current_message->control = read_byte; + receive_current_state++; + break; + } + case out_end: + { + current_message->end = read_byte; + receive_current_state = NULL; + new_in_message_ready(); + break; + } + + } + } } - -void setup_radio_in() +// Fonction de timeout de la reception de data manchester +void stop_frame(void const *n) +{ + frame_in_end_led1 = 0; + current_state = in_attente; + current_byte_progress = 0; + ticker_watch.stop(); +} + +// Fonction du thread d'affichage dans le terminal +/* +void thread_putc() { - in_message_in = 0; - in_message_out = 0; - - thread.start(callback(thread_putc)); - - input.rise(&radio_in); - input.fall(&radio_in); + while(true) + { + Thread::signal_wait(0x1); + debug_output.printf("0x%c\n\r", debug_char_output); + } +}*/ + +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// + +/* +* Public API function +*/ + +/* +* Inits the radio system and begins receiving manchester coded messages +* Sends buffered messages +*/ +void init_radio_system() +{ + setup_radio_in(); + setup_radio_out(); } -void setup_radio_out() + +bool send_message(char* buffer, int length) { - out_message_in = 0; - out_message_out = 0; - - out_debug_led3 = 0; - frame_out_end_led2 = 0; - ////////////////////////////////////////////////////// // Creation d'un message et insertion dans le buffer - radio_message_t* message = (out_messages + out_message_in); - - message->preambule = HEADER_DELIMITER; - message->start = HEADER_START; - message->options = HEADER_DELIMITER; - message->length = 0x3; - - message->data[0] = 0xC0; - message->data[1] = 0xFF; - message->data[2] = 0xEE; - - // Ajouter calcul - message->control = 0xCE; - - message->end = FOOTER_END; - // On avance dans le buffer; - out_message_in++; + radio_message_t* message = get_new_out_message(); + if (length <= MAX_MESSAGE_LENGTH && message != NULL) + { + message->preambule = HEADER_DELIMITER; + message->start = HEADER_START; + message->options = HEADER_DELIMITER; + message->length = length; + + for (int i = 0; i < length; i++){ + message->data[i] = buffer[i]; + } + + // Ajouter calcul du CRC + message->control = 0xCE; + + message->end = FOOTER_END; + // On avance dans le buffer; + return new_out_message_ready(); + } + return false; ////////////////////////////////////////////////////// - output = 0; - wait(1); - out_timer.start(start_speed); } -typedef enum { - out_preambule = 0, - out_start, - out_options, - out_length, - out_data, - out_crc, - out_end, - out_idle -} out_state_t; - -void radio_out(void const *args) -{ - static byte current_byte_progress = 0; - static byte current_byte = 0; - static byte out_current_state = 0; - static bool IsBitTransition = false; - static byte next_value = 0; - - radio_message_t* message = (radio_message_t*)(out_messages + out_message_out); - - #define OUTPUT_HIGH output = 1; - #define OUTPUT_LOW output = 0; - - #define SET_VAL_BIT_MASK(val) next_value = 0x1 & val; - #define SET_VAL_SHIFT(val, shift) SET_VAL_BIT_MASK(val >> (7 - shift)) - - - #define CHECK_NEXT_STATE if (current_byte_progress > 7) \ - { \ - out_current_state++; \ - current_byte_progress = 0; \ - } - - out_debug_led3 = !out_debug_led3; - - if (!IsBitTransition) - { - // Dependant du state, on progresse dans l'envoi du message - switch (out_current_state) - { - case out_preambule: // preambule - { - frame_out_end_led2 = 1; - SET_VAL_SHIFT(message->preambule, current_byte_progress++); - CHECK_NEXT_STATE - break; - } - case out_start: // start - { - SET_VAL_SHIFT(message->start, current_byte_progress++); - CHECK_NEXT_STATE - break; - } - case out_options: // entete options - { - SET_VAL_SHIFT(message->options, current_byte_progress++); - CHECK_NEXT_STATE - break; - } - case out_length: // entete lenght - { - SET_VAL_SHIFT(message->length, current_byte_progress++); - CHECK_NEXT_STATE - break; - } - case out_data: // charge utile - { - SET_VAL_SHIFT(message->data[current_byte], current_byte_progress++) - if (current_byte_progress > 7) - { - current_byte++; - current_byte_progress = 0; - if (current_byte >= message->length) - { - current_byte = 0; - out_current_state++; - } - } - //CHECK_NEXT_STATE - break; - } - case out_crc: // controle - { - SET_VAL_SHIFT(message->control, current_byte_progress++); - CHECK_NEXT_STATE - break; - } - case out_end: // end - { - SET_VAL_SHIFT(message->end, current_byte_progress++); - CHECK_NEXT_STATE - break; - } - case out_idle: - { - //current_state = 0; - current_byte = 0; - current_byte_progress = 0; - break; - } - } - - // Changement d'etat pour permettre de faire la bonne transition de valeur - if (next_value != output && out_current_state != out_idle) - { - output = !output; - } - - // Si on est a la fin du packet, on retourne au debut et on reenvoye les donnees - if (out_current_state > out_end) - { - frame_out_end_led2 = 0; - out_current_state = out_preambule; - out_timer.stop(); - start_speed += 1; - out_timer.start(start_speed); - } - } - // Si on est pas dans une transitipon - else if (out_current_state != out_idle) - { - output = !output; - } - - IsBitTransition = !IsBitTransition; - -} +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////// \ No newline at end of file