asd

Dependencies:   mbed-rtos mbed RTC

main.cpp

Committer:
manl2003
Date:
2016-01-29
Revision:
3:1c077a1de3e5
Parent:
2:ebbca46b415f

File content as of revision 3:1c077a1de3e5:

//Laurent et Laurent
//manl2003 huol2102

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

//Pins
DigitalIn en_1(p27);
DigitalIn en_2(p28);
AnalogIn ea_1(p19);
AnalogIn ea_2(p20);
RawSerial pc(USBTX,USBRX);

//Mutex
Mutex mute;

//Compteurs
int tic_count = 0;
int tic_count_num1 = 0;
int FREQ_NUM_MS = 100;
int FREQ_ANAL_MS = 250;

//Constantes
#define FREQ_NUM_STAB_MS 50
        
#define SIGNAL_NUM 0x1
#define SIGNAL_ANALOG 0x2
#define SEUIL_ANAL 0xB999

//Timers
RtosTimer *ticker_num1 = NULL;
RtosTimer *ticker_num2 = NULL;
RtosTimer *ticker_analog1 = NULL;
RtosTimer *ticker_analog2 = NULL;

struct MailData
{
    //Structure permettant d'encapsuler toutes les données nécessaires à l'affichage
    void FillData(int _eventType, time_t _seconds)
    {
        eventType = _eventType;
        seconds = _seconds;    
    }
    int eventType;
    time_t seconds;
    void print()
    {
        char buffer[32];
        strftime(buffer, 32, "%I:%M %p\n", localtime(&seconds));
        switch(eventType)
        {
            case 0: pc.printf("Evenement detecte sur le premier canal numerique a %s.\r\n", buffer); break;
            case 1: pc.printf("Evenement detecte sur le deuxieme canal numerique a %s.\r\n", buffer); break;
            case 2: pc.printf("Evenement detecte sur le premier canal analogique a %s.\r\n", buffer); break;
            case 3: pc.printf("Evenement detecte sur le deuxieme canal analogique a %s.\r\n", buffer); break;
            
        }            
    }
};

//Mailbox
Mail<MailData, 16> mailBox;

struct num_args
{
    //Structure permettant d'encapsuler toutes les arguments pour un événement numérique
    num_args(DigitalIn *in_arg, int type_arg)
    {
        in = in_arg;
        type = type_arg;
    }
    int type;
    DigitalIn *in;    
};

struct analog_args
{
    //Structure permettant d'encapsuler toutes les arguments pour un événement analogique
    analog_args(AnalogIn *in_arg, int type_arg){
        in = in_arg;
        type = type_arg;
    }
    int type;
    AnalogIn* in;   
};

void collection(void const *args) {
    //Thread collecteur
    while (1) 
    {
        // attente et lecture d'un événement
        osEvent evt = mailBox.get();
        if (evt.status == osEventMail) 
        {
            mute.lock();
            // écriture de l'événement en sortie (port série)
            MailData *mail = (MailData*)evt.value.p;
            mail->print();
            mailBox.free(mail);
            mute.unlock();
        }
    }
}

void lecture_analog(void const *args) {
    //Lecture des événements analogues
    analog_args *analArgs = (analog_args*)args;
    bool premiereLectureDispo = false, deuxMoyennesPretes = false;
    uint16_t echantillonsAnal[5] = {0, 0, 0, 0, 0};
    int compteur = 0;
    int moyenneCourante = 0, moyennePrecedente = 0;
    while(1)
    {
        Thread::signal_wait(SIGNAL_ANALOG);
        // lecture des échantillons analogiques
        echantillonsAnal[compteur] = analArgs->in->read_u16();

        // calcul de la nouvelle moyenne courante
        if(premiereLectureDispo == true)
        {
            moyennePrecedente = moyenneCourante;
            moyenneCourante = 0;
            for(int i = 0; i < 5; i++)
            {
                moyenneCourante += echantillonsAnal[i];
            }
        }
        
        compteur++;
        if(compteur >= 5)
        {
            compteur = 0;
            premiereLectureDispo = true;
        }
        // génération éventuelle d'un événement
        if(!deuxMoyennesPretes)
        {
            deuxMoyennesPretes = true;
        }
        else if(abs(moyenneCourante - moyennePrecedente) > SEUIL_ANAL)
        {
            //On écrit dans la mailbox lorsqu'une variation excède le seuil
            mute.lock();
            MailData * mailData = mailBox.alloc();
            mailData->FillData(analArgs->type, time(NULL));
            mailBox.put(mailData);     
            mute.unlock();
        }
    }
}


void lecture_num(void const *args) {
    // lecture des échantillons numériques
    num_args *numArgs = (num_args*)args;
    bool lectureDebut;
    while (1)
    {
        Thread::signal_wait(SIGNAL_NUM);
        lectureDebut = numArgs->in->read();
        wait_ms(FREQ_NUM_STAB_MS);
        if(lectureDebut != numArgs->in->read())
        {
            //On écrit dans la mailbox lorsqu'un événement numérique est détecté
            mute.lock();
            MailData * mailData = mailBox.alloc();
            mailData->FillData(numArgs->type, time(NULL));
            mailBox.put(mailData);
            mute.unlock();
        }
        if (numArgs->type == 0)
        {
            tic_count_num1++;
        }
    }
}

void signaleur_num(void const *args){
    //Fonction qui envoie periodiquement un signal aux threads numériques
    Thread* signaled_thread = (Thread*)args;
    signaled_thread->signal_set(SIGNAL_NUM);
}

void signaleur_analog(void const *args){
    //Fonction qui envoie periodiquement un signal aux threads analogiques
    Thread* signaled_thread = (Thread*)args;
    signaled_thread->signal_set(SIGNAL_ANALOG);
}

    
    
void starttickers()
{
    ticker_num1->start(FREQ_NUM_MS);
    ticker_num2->start(FREQ_NUM_MS);
    ticker_analog1->start(FREQ_ANAL_MS);
    ticker_analog2->start(FREQ_ANAL_MS);
    pc.printf("Tickers started \n\r");
}
    
void restartTickers()
{
    ticker_num1->stop();
    ticker_num2->stop();
    ticker_analog1->stop();
    ticker_analog2->stop();
    ticker_num1->start(FREQ_NUM_MS);
    ticker_num2->start(FREQ_NUM_MS);
    ticker_analog1->start(FREQ_ANAL_MS);
    ticker_analog2->start(FREQ_ANAL_MS);
}

void tictoc()
{
    //Fonction servant a vérifier et corriger l'écart entre la RTC et la CPU clock
    int tic_diff;
    tic_count++;
    if (tic_count == 10)
    {
        if (!(99 < tic_count_num1 < 101))
        {
            tic_diff = 100-tic_count_num1;
            FREQ_NUM_MS += tic_diff;
            FREQ_ANAL_MS += tic_diff;
            restartTickers();
             pc.printf("Modif: %i %i", FREQ_NUM_MS, FREQ_ANAL_MS);
        }
        pc.printf("RTC Tic count: %i, Real Tic count: %i\r\n", tic_count, tic_count_num1);
        tic_count = 0;
        tic_count_num1 = 0;
    }
}

int main() {
    en_1.mode(PullUp);
    en_2.mode(PullUp);
    
    pc.printf("Depart\r\n");
    
    
    //Création des specs des threads
    num_args argsNum1(&en_1, 0);
    num_args argsNum2(&en_2, 1);
    analog_args argsAnalog1(&ea_1, 2);
    analog_args argsAnalog2(&ea_2, 3);
    
    //Créations des threads
    Thread num1(lecture_num, &argsNum1);
    Thread num2(lecture_num, &argsNum2);
    Thread analog1(lecture_analog, &argsAnalog1);
    Thread analog2(lecture_analog, &argsAnalog2);
    Thread collecteur(collection);
    
    //Initialisation des tickers
    RtosTimer temp_ticker_num1(signaleur_num, osTimerPeriodic, &num1);
    ticker_num1 = &temp_ticker_num1;
    RtosTimer temp_ticker_num2(signaleur_num, osTimerPeriodic, &num2);
    ticker_num2 = &temp_ticker_num2;
    RtosTimer temp_ticker_analog1(signaleur_analog, osTimerPeriodic, &analog1);
    ticker_analog1 = &temp_ticker_analog1;
    RtosTimer temp_ticker_analog2(signaleur_analog, osTimerPeriodic, &analog2);
    ticker_analog2 = &temp_ticker_analog2;
    
    // initialisation du RTC
    set_time(1453667014);
    
    //Lancement des tickers
    starttickers();
    
    RTC::attach(&tictoc, RTC::Second);

    
    while(1);
}