Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp
- Committer:
- EmileArseneault
- Date:
- 2017-03-08
- Revision:
- 6:3d0735a28b98
- Parent:
- 5:25101883c27a
File content as of revision 6:3d0735a28b98:
#include "mbed.h"
#include "rtos.h"
#define CLOCK_MAX 96000000
#define TRAME_MAX 1024
#define DATA_LEN 80
bool PREAMBULEBOOL[] = {0,1,0,1,0,1,0,1};
bool STARTENDBOOL[] = {0,1,1,1,1,1,1,0};
char PREAMBULE = 0b01010101;
char STARTEND = 0b01111110;
DigitalOut myled(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);
InterruptIn rX(p27);
DigitalOut tX(p28);
Serial pc(USBTX, USBRX);
Mail<char [83], 4> textToPrint;
Queue<int, 1500> envoi;
Queue<int, 1500> recoit;
Queue<int, 200> rise_n_fall_queue;
Thread* listeningThread;
Thread* Push_data;
osThreadId mainThread;
Semaphore ecriture(0);
void printBin(uint16_t data)
{
    uint16_t mask = 1 << 15;
    
    while (mask != 0)
    {
        if ((data & mask) > 0)
        {
            pc.printf("1");
        }
        else
        {
            pc.printf("0");
        }
        mask = mask >> 1;
    }
}
uint16_t GetBit(char *payload, int bitNumber)
{
    int index = bitNumber / 8;
    int bitNo = bitNumber % 8;
    
    return (payload[index] & (0x80 >> bitNo)) > 0;
}
void CRC16(char *payload, int length)
{
    payload[length - 1] = 0;
    payload[length - 2] = 0;
    
    uint16_t polynome = 0x8005; // Les 16 bits du polynome (17ieme bit a 1 est implicitement)
    uint16_t workingSet;
    uint16_t lastBit;
    
    int noBit;
    int nbBit = length * 8;
    
    // Initialiser les données
    lastBit = (payload[0] & 0x80) >> 7; 
    workingSet = (((payload[0] << 8) | payload[1]) << 1) | ((payload[2] & 0x80) >> 7);
    noBit = 16;
    
    // CRC
    while (noBit < (nbBit - 1))
    {   
        if (lastBit > 0)
        {
            workingSet = workingSet xor polynome;
        }
        else
        {
            workingSet = workingSet xor 0;
        }
        
        // Ajouter le prochain bit des valeurs
        lastBit = (workingSet & 0x8000) >> 15;
        workingSet = workingSet << 1;
        workingSet = workingSet | GetBit(payload, noBit);
        
        noBit++;
    }
    
    // Final XOR
    if (lastBit > 0)
    {
        workingSet = workingSet xor polynome;
    }
    else
    {
        workingSet = workingSet xor 0;
    }
    
    // Ecrire la valeur dans le payload
    payload[length - 1] = workingSet & 0x00FF;
    payload[length - 2] = workingSet >> 8;
}
bool compareBoolArray(bool* a, bool* b)
{
    int i = 0;
    while (i < 8)
    {
        if (a[i] != b[i])
        {
            return false;
        }
        i++;
    }
    return true;
}
char msbBooltoChar(bool data[8])
{
    char c = 0;
    for (int i=0; i < 8 ; i++)
        if (data[i])
            c |= 1 << (7 - i);
    return c;
}
void charToMsbBool(char data, bool out[8])
{
    for (int i=0; i < 8; ++i)
        out[i] = (data & (1<<(7 - i))) != 0;
}
void PrintBoolArray(bool* data, int len)
{
    pc.printf("[");
    for (int i = 0; i < len - 1; i++)
    {
        pc.printf("%d, ", data[i]);
    }
    pc.printf("%d]", data[len-1]);
}
bool ManchesterDecodeBit(bool* data, bool* out)     // Tested
{
    if (data[0] == 0 && data[1] == 1)
    {
        out[0] = 1;
    }
    else if (data[0] == 1 &&  data[1] == 0)
    {
        out[0] = 0;
    }
    else
    {
        return false;
    }
    return true;
}
bool ManchesterDecodeByte(bool* data, char* out)    // Tested
{
    bool Valid = true;
    bool tmp = true;
    for (int i = 0; i < 8; i++)
    {
        Valid = ManchesterDecodeBit(data, &tmp);
        data += 2;
        if (!tmp)
        {
            *out = *out & ~(0x1 << (7-i));
        }
        else
        {
            *out = *out | (0x1 << (7-i));
        }
        if (!Valid)
        {
            return false;
        }
    }
    return true;
}
void ManchesterEncodeBit(bool data, bool* out)         // Tested
{
    if (data == 0)
    {
        out[0] = 1;
        out[1] = 0;
    }
    else
    {
        out[0] = 0;
        out[1] = 1;
    }
}
void ManchesterEncodeByte(char data, bool* out)         // Tested       
{
    for (int i = 0; i < 8; i++)
    {
        ManchesterEncodeBit((bool) ((data >> (7 - i)) & 1), &(out[2*i]));
    }
}
int CountData(char* data)                           // Tested
{
    int i = 0;
    while(*data != 0)
    {
        data++;
        i++;
    }
    return i;
}
void AddPreambule(bool* data)
{
    for (int i = 0; i < 8; i++)
    {
        *data = PREAMBULEBOOL[i];
        data++;
    }
}
void AddStartEnd(bool* data)
{
    for (int i = 0; i < 8; i++)
    {
        *data = STARTENDBOOL[i];
        data++;
    }
}
void AnalyseHeading(char* data, int* id, int* frame, int* frame_count, int* len)
{
    *id = data[0] >> 6;
    *frame = (data[0] >> 3) & 7;
    *frame_count = data[0] & 7;
    
    *len = data[1];
}
bool AddHeading(char* out, int id, int frame, int frame_count, char len)     // Tested
{
    char tmp = 0;
    if (frame > frame_count || frame > 7 || frame_count > 7 || len - 2 > DATA_LEN)
    {
        return false;
    }
    // Two first bits -> id
    id = id & 3;
    tmp = tmp | (id << 6);
    
    // Three next -> frame number
    frame = frame & 7;
    tmp = tmp | (frame << 3);
    
    // Three last -> number of frames
    frame_count = frame_count & 7;
    tmp = tmp | frame_count;
    *out = tmp;
    // Last char is lenght
    out++;
    *out = len;
    return true;
}
void AddCRC(char* data, int len)
{
    
}
void ReceiveBits(bool* data, int len);
void SendBits(bool* bits, int len)
{
    // Emile
    // thread.signal_set(0x1);
    // Synchronize with wire
    pc.printf("SendBits - len %d\r\n", len);
    pc.printf("Waiting\r\n");
    //Thread::signal_wait(1);
    ecriture.wait();
    for (int i = 0; i < len; i++)
    {
        envoi.put((int *) bits[i]);
    }
    Push_data->signal_set(0x1);
    //ReceiveBits(bits, len);
}
void SendFormated(bool* data, int len)
{
    pc.printf("SendFormated - len %d\r\n", len);
    bool tmp[len + 3 * 8];
    AddPreambule(tmp);
    AddStartEnd(tmp + 8);
    for (int i = 0; i < len; i++)
    {
        tmp[i + 2 * 8] = data[i];
    }
    AddStartEnd(tmp + len + (2 * 8));
    SendBits(tmp, len + (3 * 8));
}
void SendManchester(char* data, int len)
{
    pc.printf("SendManchester - len %d\r\n", len);
    bool bits[2*len*8];
    for (int i = 0; i < len; i++)
    {
        ManchesterEncodeByte(data[i], bits + 2*i*8);
    }
    SendFormated(bits, 2*len*8);
}
int lastIdUsed = 0;
void SendText(char* data, int len)
{
    pc.printf("SendText - len %d\r\n", len);
    char tmp[len + 4];
    int frame, frames;
    // Gestion des ID
    if (len > DATA_LEN)
    {
        pc.printf("Plz implement multiple trames messages.\r\n");
        return;
    }
    else
    {
        frame = 1;
        frames = 1;
        // Gestion exception
        AddHeading(tmp, lastIdUsed, frame, frames, len + 2);
        for (int i = 0; i < len; i++)
        {
            tmp[i + 2] = data[i];
        }
        tmp[len + 2] = 0;
        tmp[len + 3] = 0;
        CRC16(tmp + 2, len + 2);
        SendManchester(tmp, len + 4);
    }
}
void ReceiveText()
{
    while (1)
    {
        osEvent evt = textToPrint.get();
        if (evt.status == osEventMail){
            led3 = 1;
            char * message = (char *) evt.value.p;
            pc.printf("Received: %s\r\n", message);
            //ReceiveBits((bool *) message->bits, message->len);
            textToPrint.free((char (*)[83]) message);
        }
    }
    
}
void ReceiveFormated(char* data, int len)
{
    pc.printf("ReceiveFormated - len %d\r\n", len);
    //pc.printf("%c%c\r\n",data[2], data[3]);
    char tmp[len - 2];
    int id, frame, frames, predicted_len;
    AnalyseHeading(data, &id, &frame, &frames, &predicted_len);
    // Gestion des id et frames et frame number
    
    if (predicted_len != len - 2)
    {
        pc.printf("DEBUG -- Received payload with wrong lenght. %d %d\r\n", len - 2, predicted_len);
        return;
    }
    // Copy data
    for (int i = 0; i < len - 2; i++)
    {
        tmp[i] = data[i + 2];
    }
    for (int i = len - 4; i < len - 2; i++)
    {
        tmp[i] = 0;
    }
    
    //CRC calculate
    CRC16(tmp, len - 2);
    if (tmp[len - 4] == data[len - 2] && tmp[len - 3] == data[len - 1])
    {
        tmp[len - 4] = '\0';
        char* toPrint = (char *)textToPrint.alloc();
        int i = 0;
        for (; i < len - 3; i++)
        {
            toPrint[i] = tmp[i];
        }
        toPrint[i] = '\r';
        toPrint[i+1] = '\n';
        toPrint[i + 2] = '\0';
        
        textToPrint.put((char (*)[83]) toPrint);
    }
    else
    {
        pc.printf("DEBUG -- Received payload with wrong CRC.\r\n");
        return;
    }
}
void ReceiveManchester(bool* data, int len)
{
    pc.printf("ReceiveManchester - len %d\r\n", len);
    char tmp[len / 16];
    for (int i = 0; i < len / 16; i++)
    {
        ManchesterDecodeByte(data, tmp + i);
        data += 16;
    }
    ReceiveFormated(tmp, len / 16);
}
void ReceiveBits(bool* data, int len)
{   
    /*
    if (compareBoolArray(data, PREAMBULEBOOL))
    {
        data += 8;
        len -= 8;
    }
    else
    {
        pc.printf("DEBUG -- Received payload with wrong Preambule.");PrintBoolArray(data , 8);pc.printf("\r\n");
        return;
    }*/
    
    // Ensure Start and end are present
    if (compareBoolArray(data, STARTENDBOOL) || compareBoolArray(data + (len - 8), STARTENDBOOL))
    {
        ReceiveManchester(data + 8, len - 2 * 8);
    }
    else
    {
        pc.printf("DEBUG -- Received payload with wrong Start or End.\r\n");
        return;
    }
}
void Listening()
{
    while (1)
    {
        Thread::signal_wait(0x1);
        osEvent evt = envoi.get();
        if (evt.status == osEventMessage){
            /*bool message = (message_t*) evt.value.p;
            //ReceiveBits((bool *) message->bits, message->len);
            envoi.free(message);*/
        }
    }
    
}
extern "C" void TIMER2_IRQHandler (void)
{
    if((LPC_TIM2->IR & 0x01) == 0x01)   // if MR0 interrupt, proceed
    {
        LPC_TIM2->IR |= 1 << 0;         // Clear MR0 interrupt flag
        //myled = !myled;                 // Toggle LED1
        Push_data->signal_set(2);   // Envoyer signal au coup de clock pour l'écriture de bit
    }
}
 
void timer2_init(void)
{
    LPC_SC->PCLKSEL1 |=1<<12;       //pclk = cclk timer2
    LPC_SC->PCONP |=1<<22;          //timer2 power on
    LPC_TIM2->MR0 = 960000;          //10 msec
    LPC_TIM2->MCR = 3;              //interrupt and reset control
                                    //3 = Interrupt & reset timer2 on match
                                    //1 = Interrupt only, no reset of timer0
    LPC_TIM2->EMR =3<<4;            //EMC0 = 11 (Toogle)
    NVIC_EnableIRQ(TIMER2_IRQn);    //enable timer2 interrupt
    LPC_TIM2->TCR = 1;              //enable Timer2
}
void SendData()
{
    bool releaseSent = false;
    bool fin = false;
    int valeur = 0;
    
    while(true)
    {
        //osSignalSet(mainThread, 1);
        if (!releaseSent)
            {
                pc.printf("Release sent\r\n");
                ecriture.release();
                releaseSent = true;
            }
        //pc.printf("SendData Waiting\r\n");
        
        //Thread::signal_wait(1);
        
        while(!fin)
        {
            osEvent evt = envoi.get(1000);
            if (evt.status == osEventMessage) 
            {
                valeur = (int)evt.value.p;
                Thread::signal_wait(2);
                tX = valeur;
                releaseSent = false;
            }
            else
            {
                fin = true;
                tX = 1;
            }
            
        }
        fin = false;
    }
}
void StartEnd(int intervale)
{
    bool End = false;
    bool Start = false;
    bool data[1500] = {0};
    int i = 0;
    bool ones[8] = {1, 1, 1, 1, 1, 1, 1, 1};
    while(!End)
    {
        wait_us(intervale);
        data[i] = rX.read();
        led2 = data[i];
        // Regarde si 3 valeurs consécutives sont 0
        if (i >= 2)
        {
            if ((data[i-2] == data[i-1]) && (data[i] == data[i-1]) && (data[i] == 0))
            {
                printf("Ligne coupee\r\n");
                return;   
            }
        }
        
        // Comparer pour les séquence de bits de fin et start
        if (i >= 7)
        {
            if (compareBoolArray(ones, &(data[i-7])))
            {
                printf("Court_circuit\r\n");
                return;
            }
            if (compareBoolArray(STARTENDBOOL, &(data[i-7])))
            {
                if (!Start)
                {
                    Start = true;
                }
                else
                {
                    ReceiveBits(data, i+1);
                    End = true;
                }
            } 
        }
        i++;
    }
}
void Preambule_Check(void const *args) 
{
    int position = 1;
    int valeur = 0;
    int preambule[8] = {0, 1, 0, 1, 0, 1, 0, 1};
    int timeBetween[6] = {0};
    int sum;
    int intervale = 0;
    Timer t;
    
    while(true)
    {
        osEvent evt = rise_n_fall_queue.get();
        if (evt.status == osEventMessage) 
        {
            valeur = (int)evt.value.p;
            if (valeur == preambule[position])
            {
                if (position > 1)
                {
                    t.stop();
                    timeBetween[position - 2] = t.read_us();
                    t.reset();
                    t.start();
                }
                else
                {
                    t.stop();
                    t.reset();
                    t.start();   
                }
            
                if (position < 7)
                {
                    position++;
                }
                else
                {
                    // Calculer la moyenne (pt oter les valeurs extrèmes s'il y en a)
                    sum = 0;
                    for (int i =0; i < 6; i++)
                    {
                        sum += timeBetween[i];
                    }
                    intervale = sum/6;
                    StartEnd(intervale);
                    wait(0.5);
                    position = 1;
                    led4 = !led4;
                }
            }
            else
            {
                position = 1;   
            }
        }
    }
}
void Call_Preambule_Rise()
{
    rise_n_fall_queue.put((int *)1, 0);
}
void Call_Preambule_Fall()
{
    rise_n_fall_queue.put((int *)0, 0);
}
void TestManchester();
void TestUtility();
void mainRaph()
{
    //TestUtility();
   // TestManchester();
   //SendText("A more complex sentence to prove our algorithm is robust!", 57);
   //wait(10);
   tX = 0;
   wait_us(100);
   tX= 1;
   wait_us(100);
   tX = 0;
    //SendText("OK", 2);
    //wait(4);
    //SendText("OK", 2);
    //wait(1);
    //SendText("A more complex sentence to prove our algorithm is robust!", 57);
}
void tick()
{
    myled = !myled;
}
int main() {
    Ticker ticker;
    ticker.attach(&tick, 0.5);
    timer2_init();
    mainThread = osThreadGetId(); 
    
    listeningThread = new Thread();
    listeningThread->start(Listening);
    
    Thread get_data_thread(Preambule_Check);
    Thread push_thread(SendData);
    Thread printing(ReceiveText);
    Push_data = &push_thread;
    
    rX.rise(Call_Preambule_Rise);
    rX.fall(Call_Preambule_Fall);
    
    mainRaph();
    led3 = 1;
    while (1){
        }
}
//--------------------------------TEST---------------------------------------------------//
char ToByte(bool b[8])
{
    char c = 0;
    for (int i=0; i < 8; ++i)
        if (b[i])
            c |= 1 << i;
    return c;
}
void FromByte(char c, bool b[8])
{
    for (int i=0; i < 8; ++i)
        b[i] = (c & (1<<i)) != 0;
}
void TestUtility()
{
    pc.printf("TestUtility -- Begin\r\n");
    char charValue = 1;
    bool boolValue[8] = {0,0,0,0,0,0,0,1};
    bool boolAns[8] = {0,0,0,0,0,0,0,1};
    char charAns;
    
    if (!compareBoolArray(boolValue, boolAns))
    {
        pc.printf("Should be gud");
        return;
    }
    boolAns[7] = 0;
    if (compareBoolArray(boolValue, boolAns))
    {
        pc.printf("Should not be gud");
        return;
    }
    
    charAns = msbBooltoChar(boolValue);
    
    if (charValue != charAns)
    {
        pc.printf("msbBooltoChar error. %d %d\r\n", charValue, charAns);
        return;
    }
    
    charToMsbBool(charValue, boolAns);
    
    if(!compareBoolArray(boolValue, boolAns))
    {
        pc.printf("charToMsbBool error ");PrintBoolArray(boolValue,8);pc.printf(" ");PrintBoolArray(boolAns,8);pc.printf("\r\n");
        return;
    }
    pc.printf("TestUtility -- End\r\n");
}
void TestManchester()
{
    pc.printf("TestManchester - Begin\r\n");
    // ----------------------------ENCODE-----------------------------------------------//
    bool Valid = true;
    bool boolData0 = (char) 0b0;
    bool boolExpected0[] = {1,0};
    bool boolAns0[2];
    
    ManchesterEncodeBit(boolData0, (bool *) boolAns0);
    
    int i = 0;
    Valid = true;
    while (Valid && i < 2)
    {
        Valid = !(boolExpected0[i] ^ boolAns0[i]);
        i++;
    }
    
    if (!Valid)
    {
        pc.printf("TestManchester - encode - bool0 - Failed\r\n");
        pc.printf("Expected: [%d, %d]. Received: [%d, %d].\r\n\n", boolExpected0[0], boolExpected0[1], boolAns0[0], boolAns0[1]);
    }
        
    bool boolData1 = (char) 0b1;
    bool boolExpected1[] = {0,1};
    bool boolAns1[2];
    ManchesterEncodeBit(boolData1, (bool*) boolAns1);
    
    i = 0;
    Valid = true;
    while (Valid && i < 2)
    {
        Valid = !(boolExpected1[i] ^ boolAns1[i]);
        i++;
    }
    if (!Valid)
    {
        pc.printf("TestManchester - encode - boo11 - Failed\r\n");
        pc.printf("Expected: [%d, %d]. Received: [%d, %d].\r\n\n", boolExpected1[0], boolExpected1[1], boolAns1[0], boolAns1[1]);
    }
    
    char charData = (char) 0b01010101;
    bool charExpected[] = {1,0,0,1,1,0,0,1,1,0,0,1,1,0,0,1};
    bool charAns[16];
    ManchesterEncodeByte(charData, (bool*) charAns);
    
    i = 0;
    Valid = true;
    while (Valid && i < 16)
    {
        Valid = !(charExpected[i] ^ charAns[i]);
        i++;
    }
    if (!Valid)
    {
        pc.printf("TestManchester - encode - char - Failed\r\n");
        pc.printf("Expected: [%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d]\r\nReceived: [%d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d].\r\n\n", 
        charExpected[0], charExpected[1], charExpected[2], charExpected[3],
        charExpected[4], charExpected[5], charExpected[6], charExpected[7],
        charExpected[8], charExpected[9], charExpected[10], charExpected[11],
        charExpected[12], charExpected[13], charExpected[14], charExpected[15], 
        charAns[0], charAns[1], charAns[2], charAns[3],
        charAns[4], charAns[5], charAns[6], charAns[7],
        charAns[8], charAns[9], charAns[10], charAns[11],
        charAns[12], charAns[13], charAns[14], charAns[15]);
    }
    
    // ----------------------------DECODE-----------------------------------------------//
    Valid = true;
    bool boolDecodeData0[] = {1,0};
    bool boolDecodeExpected0 = 0b0;
    bool boolDecodeAns0;
    bool Success = true;
    Success = ManchesterDecodeBit((bool *)boolDecodeData0, &boolDecodeAns0);
    
    if (!Success)
    {
        pc.printf("TestManchester - decode - bool0 - Invalid format\r\n");
    }
    
    if (boolDecodeExpected0 != boolDecodeAns0)
    {
        pc.printf("TestManchester - decode - bool0 - Failed\r\n");
        pc.printf("Expected: %d. Received: %d.\r\n\n", boolDecodeExpected0,  boolDecodeAns0);
    } 
   
    bool boolDecodeData1[] = {0,1};
    bool boolDecodeExpected1 = (char) 0b1;
    bool boolDecodeAns1;
    Success = ManchesterDecodeBit((bool *)boolDecodeData1, &boolDecodeAns1);
    
    if (!Success)
    {
        pc.printf("TestManchester - decode - bool1 - Invalid format\r\n");
    }
    if (boolDecodeExpected1 != boolDecodeAns1)
    {
        pc.printf("TestManchester - decode - boo11 - Failed\r\n");
        pc.printf("Expected: %d. Received: %d\r\n\n", boolDecodeExpected1, boolDecodeAns1);
    }
    
    bool boolDataInv0[] = {0,0};
    bool boolDataInv1[] = {1,1};
    bool boolAnsInv;
    Success = ManchesterDecodeBit((bool *)boolDataInv0, (bool*) boolAnsInv);
    if (Success)
    {
        pc.printf("TestManchester - decode - boolInv0 - Invalid format not caught\r\n");
    }
    Success = ManchesterDecodeBit((bool *)boolDataInv1, (bool*) boolAnsInv);
    if (Success)
    {
        pc.printf("TestManchester - decode - boolInv1 - Invalid format not caught\r\n");
    }
    
    
    bool charEncodeData[] = {1,0,1,0,0,1,1,0,0,1,1,0,0,1,1,0};
    char charEncodeExpected = 42;
    char charEncodeAns;
    Valid = ManchesterDecodeByte(charEncodeData, &charEncodeAns);
    
    if (!Valid)
    {
        pc.printf("Function detected error in format\r\n");
    }
    else if (charEncodeExpected != charEncodeAns)
    {
        pc.printf("TestManchester - decode - char - Failed\r\n");
        pc.printf("Expected: %d\t\tReceived: %d\r\n", 
        charEncodeExpected, charEncodeAns);
    }
    
    //--------------------TEST COMPLET -------------------------------//
    
    char charComplet = 158;
    bool tmpAns[16];
    char charCompletAns;
    
    ManchesterEncodeByte(charComplet, (bool *) tmpAns);
    Valid = ManchesterDecodeByte((bool *) tmpAns, &charCompletAns);
    
    if (!Valid)
    {
        pc.printf("Function detected error in format\r\n");   
    }
    if (charComplet != charCompletAns)
    {
        pc.printf("TestManchester - decode - complete - Failed\r\n");
        pc.printf("Expected: %d\t\tReceived: %d\r\n", 
        charComplet, charCompletAns);
    }
    
    pc.printf("TestManchester - End\r\n");
}