app4

Dependencies:   mbed-rtos mbed CRC16

Fork of S5info_APP2 by Éric Bisson

main.cpp

Committer:
JoeyDionne
Date:
2017-03-07
Revision:
23:9c4e4898b741
Parent:
22:7244c3391bac
Child:
24:2034362db66f

File content as of revision 23:9c4e4898b741:

#include "CRC16.h"
#include "mbed.h"
#include "rtos.h"
#include <vector>
using std::vector;
DigitalIn in(p30);
Thread ThreadLecture;
const int PREAMBULE = 0b01010101;
const int START = 0b01111110;
const int END = 0b01111110;
Serial pc(USBTX, USBRX);
DigitalOut out(p8);

bool transmit = false;      //faux pour le debut de demi-periode d'envoie d'un bit, vrai pour la 2ème demi-periode
char trame_sent[80];        //tableau de la trame à envoyer
uint8_t byte_sent_pos,      //position de l'octet dans le tableau d'envoi
        trame_length;       //longueur de la trame complete
        
signed char bit_sent;       //position du bit de l'octet en cours d'envoi (du MSB au LSB) 7..0
bool bTimer1 = false;

void initTimers()
{
    //Timer 1 (match)
    LPC_SC->PCLKSEL0 |= (1 << 4);           // pclk = cclk timer1
    LPC_SC->PCONP |= (1 << 2);              // timer1 power on
    LPC_TIM1->MR0 = 960000 / 2;             // 10/2 ms 
    LPC_TIM1->MCR = 3;                      // interrupt and reset control
    LPC_TIM1->EMR = (3 << 4);               // Interrupt & reset timer on match
    NVIC_EnableIRQ(TIMER1_IRQn);            // enable timer interrupt
    LPC_TIM1->TCR = 0;                      // disable Timer
 
    //Timer 2 (cap)
    LPC_SC->PCLKSEL1 |= (1 << 12);          // pclk = cclk timer2
    LPC_SC->PCONP |= (1 << 22);             // timer2 power on
    LPC_TIM2->TC = 0;                       // clear timer counter
    LPC_TIM2->PC = 0;                       // clear prescale counter
    LPC_TIM2->PR = 0;                       // clear prescale register
    LPC_TIM2->TCR |= (1 << 1);              // reset timer
    LPC_TIM2->TCR &= ~(1 << 1);             // release reset
    LPC_TIM2->IR = 0xFFFFFFFF;              // clear interrupt register
    LPC_TIM2->CCR |= 0x0000007;             // enable rising-edge and falling-edge capture
    NVIC_EnableIRQ(TIMER2_IRQn);            // enable timer interrupt
    LPC_TIM2->TCR = 1;                      // start Timer
}

//encodage manchester
bool codeManchester(bool bit, bool clock)
{
    return (bit == clock);
}

//Envoie de données bit par bit
void send_data()
{
    out = codeManchester(((trame_sent[byte_sent_pos] >> bit_sent) & 0x01), bTimer1);
    if(bTimer1)
    {
        bit_sent--;
    }
    bTimer1 = !bTimer1;     //varier entre la 1ere et 2eme partie de demi-periode
    if (bit_sent < 0)       //Si l'octet a ete envoye
    {     
        bit_sent = 7;       //remettre la position initiale pour le prochain octet
        byte_sent_pos++;    //incrementer l'octet
        if (byte_sent_pos >= trame_length) //Si la trame a ete envoyee
        {  
            byte_sent_pos = 0;
            bTimer1 = false;
            LPC_TIM1->TCR = 0;  // disable Timer
        }
    }
}

extern "C" void TIMER1_IRQHandler()
{
    if ((LPC_TIM1->IR & 0x01) == 0x01)
    {
        send_data();
        
        LPC_TIM1->IR |= 1 << 0; // clear
    }
}

int sumClocks = 0;
int PeriodLength = 0;
bool bReceivedFirstBit = false;
extern "C" void TIMER2_IRQHandler()
{
    if (PeriodLength > 0)
    {
        if (LPC_TIM2->CR0 >= PeriodLength*1.5 || (sumClocks + LPC_TIM2->CR0) >= PeriodLength*1.5)
        {
            sumClocks = 0;
            
            ThreadLecture.signal_set(1);
        }
        else
        {
            sumClocks += LPC_TIM2->CR0;
        }
    }
    else if (bReceivedFirstBit)
    {
        PeriodLength = LPC_TIM2->CR0 / 2;
        ThreadLecture.signal_set(1);
    }
    else
    {
        bReceivedFirstBit = true;
        ThreadLecture.signal_set(1);
    }
    
    LPC_TIM2->TC = 0;
    LPC_TIM2->IR |= 0xFFFFFFFF; // clear
}

//création de la trame
void create_trame(char message[],unsigned char taille)
{
    CRC16 myCRC;
    unsigned short resultCRC = myCRC.calculateCRC16(message,taille); 
    
    trame_sent[0] = PREAMBULE;    //Preambule
    trame_sent[1] = START;    //Start
    trame_sent[2] = 0x00;    //Type + Flag mis a 0x00
    trame_sent[3] = taille;     //Longueur du message (Max 33 caractères)
    
    //message
    for (char i=0;i<taille;i++)
    {
        trame_sent[taille + 4] = message[i];
    }
        
    //CRC16
    trame_sent[taille + 4] = (resultCRC >> 8) & 0xFF;
    trame_sent[taille + 5] = resultCRC & 0xFF;
    
    trame_sent[taille + 6] = END;    //End
    trame_length = taille + 7;        //Longueur de la trame
}

void write()
{
    byte_sent_pos = 0;
    bit_sent = 7;
    bTimer1 = false;
    LPC_TIM1->TCR = 3; // enable and reset Timer
    //TODO start interrupt timer 1 
    //LPC_RIT->MCR = 1;                      //Permettre les interruption du MAT
    //LPC_RIT->MR0 = LPC_RIT->TC + HALF_PERIOD;  //Faire une interruption a la prochaine demi-periode
}

//obtention du texte
void get_text()
{
    pc.printf("\n\rYour text : ");
    unsigned char count = 0;
    char c = 0x00;
    char text[73];
    while(c != '\r' && count < 73) {
        c = pc.getc();
        text[count] = c;
        pc.putc(c);
        count++;
    }
    
    create_trame(text,count);
    write();
}

void read()
{
    char byte = 0;
    vector<char> bytes;
    char shift = 0;
    char totalsize = 7;
    CRC16 mycrc16;
    while (true)
    {
        ThreadLecture.signal_wait(1);
        
        byte = (byte << 1) + !in; // inversion car 2e période
        
        shift++;
        if (shift == 8)
        {
            shift = 0;
            
            // à partir d'ici, je travaille en byte et non bit
            bytes.push_back(byte);
            
            // Validations de base
            if ((bytes.size() == 1 && bytes[0] != PREAMBULE) ||
                (bytes.size() == 2 && bytes[1] != START))
            {
                bytes.clear();
                
                if (bytes.size() == 1)
                {
                    pc.printf("[DEBUG] - Invalid PREAMBULE : %x\n", bytes[0]);
                }
                else
                {
                    pc.printf("[DEBUG] - Invalid START : %x\n", bytes[1]);
                }
            }
            if (bytes.size() == 4)
            {
                totalsize = 7 + bytes[3];
            }
            
            // fin
            if (totalsize == bytes.size())
            {
                // Calcul du CRC
                unsigned short currentCRC = bytes[bytes.size()-2] + bytes[bytes.size()-3]<<8;
                
                vector<char> charge_utile(&bytes[4], &bytes[bytes.size()-4]);
                
                if (currentCRC == mycrc16.calculateCRC16(&charge_utile[0], charge_utile.size()) && bytes.back() == END)
                {
                    // Affiche à l'écran le message valide
                    pc.printf(&charge_utile[0], charge_utile.size());
                }
                else
                {
                    pc.printf("[DEBUG] - Invalid CRC, dumping message\n");
                }
                bytes.clear();
            }
        }
    }
}

int main() {
    LPC_PINCON->PINSEL0 |= (3 << 8); // pin30
    initTimers();
    ThreadLecture.start(read);
    
    while(true) 
    {
        get_text();
    }
};