APP4 S5

Dependencies:   mbed-rtos mbed

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