APP4 S5

Dependencies:   mbed-rtos mbed

radio.cpp

Committer:
Cheroukee
Date:
2017-10-12
Revision:
9:081324663b8c
Parent:
8:a878763b0ae3
Child:
10:c4629b6c42f8

File content as of revision 9:081324663b8c:


#include "radio.h"

#include "mbed.h"
#include "rtos.h"

#include <LPC17xx.h>

#define MESSAGE_BUFFER_SIZE 16

#define MANCHESTER_SPEED_OUT 10
    
#define INPUT_RADIO p18
#define OUTPUT_RADIO p6

radio_message_t out_messages[MESSAGE_BUFFER_SIZE];
byte out_message_in;
byte out_message_out;

radio_message_t in_messages[MESSAGE_BUFFER_SIZE];
byte in_message_in;
byte in_message_out;

InterruptIn input(INPUT_RADIO);

RtosTimer out_timer(radio_out, osTimerPeriodic, (void *)out_messages);

DigitalOut output(OUTPUT_RADIO);

#ifndef LED
DigitalOut in_debug_led4(LED4);
DigitalOut out_debug_led3(LED3);

DigitalOut frame_out_end_led2(LED2);
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;

int start_speed = MANCHESTER_SPEED_OUT;

byte current_state = in_attente;
byte current_byte_progress = 0;

void stop_frame(void const *n);

RtosTimer ticker_watch(stop_frame, osTimerPeriodic, NULL);

Thread thread;

void stop_frame(void const *n)
{
    frame_in_end_led1 = 0;
    current_state = in_attente;
    current_byte_progress = 0;
    ticker_watch.stop();
}   

volatile int t = 0;
volatile int c = 0;
    
void radio_in()
{    
    
    static Timer timer;   
    static int t_half = 0;
    
    static byte current_byte = 0;
    
    in_debug_led4 = !in_debug_led4;   
    
    
    switch (current_state)
    {
        case in_attente:
        {     
            frame_in_end_led1 = 0;
            if (input == 1)
            {
                timer.start();
                current_state = in_preambule;   
                current_byte_progress = 1;
                frame_in_end_led1 = 1;
            }
            break;
        }
        case in_preambule:
        {
            current_byte_progress++;
            t = timer.read_ms();           
            timer.reset();
            if (current_byte_progress > 7)
            {             
                t_half = t / 2;
                ticker_watch.start(t + t_half);
                current_byte_progress = 0;
                current_state = in_data;    
                c = t;
                thread.signal_set(0x1);
            }
            break;
        }
        case in_data:
        {        
            if(timer.read_ms() > t + t_half)
            {
                frame_in_end_led1 = 0;
                current_state = in_attente;
                current_byte_progress = 0;
                
                timer.stop();      
                timer.reset();      
            }
            else if (timer.read_ms() > t_half)
            {               
                current_byte = (!input << (7 - current_byte_progress)) | current_byte;
                current_byte_progress++ ;
                //PC.putc(input);
                // Display data 
                ticker_watch.start(t + t_half);
                timer.reset();      
                
                if (current_byte_progress > 7)
                {                    
                    c = current_byte;
                    thread.signal_set(0x1);
                    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()
{
    while(1)
    {
        Thread::signal_wait(0x1);
        PC.printf("0x%x\n\r", c);    
    }   
}


void setup_radio_in()
{
    in_message_in = 0;
    in_message_out = 0;
    
    thread.start(callback(thread_putc));
    
    input.rise(&radio_in);
    input.fall(&radio_in);       
}


void setup_radio_out()
{
    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++;
    //////////////////////////////////////////////////////   
    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;
    
}