JGCtoGdT

Dependencies:   ConfigFile MODSERIAL_uVision Watchdog mbed-rtos mbed

main.cpp

Committer:
JavierGC
Date:
2013-05-05
Revision:
0:2e1b2d9fa0de

File content as of revision 0:2e1b2d9fa0de:

#include "mbed.h"
#include "MODSERIAL.h"
#include "rtos.h"
#include "Watchdog.h"
#include "ConfigFile.h"

Watchdog wd;

extern "C" void mbed_reset();

char InitialMessage[50];

DigitalOut ledCAN1(LED1);
DigitalOut ledCAN2(LED2);
DigitalOut led3(LED3);
DigitalOut ledPC(LED4);


time_t ctTime;
struct tm * timeinfo;

Ticker SpkTick;
Timer myT;


void LoadPCMail(char comm,  char *mess);

/************* Frequency ****************/
InterruptIn Freq1(p15);
InterruptIn Freq2(p16);
InterruptIn Freq3(p17);
Timer F1;
Timer F2;
Timer F3;

int Period1,Period2,Period3;

void Freq1_Meas(void)
{
    Period1=F1.read_us();
    F1.reset();
}
void Freq2_Meas(void)
{
    Period2=F2.read_us();
    F2.reset();
}
void Freq3_Meas(void)
{
    Period3=F3.read_us();
    F3.reset();
}
/************* End Frequency ************/

/************* PWM ****************/
PwmOut PwmO1(LED3);
/************* End PWM ************/

/************* CAN ***********************/
#define CAN_MaxMailElements 16
#define CANMessWait 1//ms
#define MessSizeCAN 128

typedef struct {
    char command;   /* command to execute */
    CANMessage mess;
} CAN_mail_t;
/************* CAN 1 *********************/
CAN can1(p9,p10);
int CAN1Freq=1000000;

Mail<CAN_mail_t, CAN_MaxMailElements> CAN1_mail;
int CAN1MailNum;

void LoadCAN1Mail(char command,  CANMessage mess) //para cargar mensajes de trabajo al proceso paralelo CAN1_thread_proc
{
    while(CAN1MailNum>=CAN_MaxMailElements) {
        Thread::wait(CANMessWait);
    }
    CAN_mail_t *mail = CAN1_mail.alloc();
    mail->command = command;
    mail->mess=mess;
    CAN1_mail.put(mail);
    CAN1MailNum++;
}

void messageFromCAN1()
{
    ledCAN1=true;
    CANMessage msg;
    can1.read(msg);
    LoadCAN1Mail(10,msg);
}

void CAN1_thread_proc(void const *args) //proceso paralelo de gestión CAN1
{
    char tmp[MessSizeCAN];
    while(true) {
        osEvent evt = CAN1_mail.get(osWaitForever);
        if (evt.status == osEventMail) {
            CAN_mail_t *mail = (CAN_mail_t*)evt.value.p;

            switch (mail->command) {
                case 0: //request Reset CAN
                    can1.reset();
                    LoadPCMail(1,"Reset CAN1");
                    break;
                case 1: //set frequency
                    can1.frequency(mail->mess.id);
                    LoadPCMail(1,"Set Frequency CAN1");
                    break;
                case 10: //Read from CAN
                    snprintf(tmp,MessSizeCAN,"ID=%i;TYPE=%i;FORMAT=%i;LEN=%d;DATA[0]=%u;DATA[1]=%u;DATA[2]=%u;DATA[3]=%u;DATA[4]=%u;DATA[5]=%u;DATA[6]=%u;DATA[7]=%u",mail->mess.id,mail->mess.type,mail->mess.format,mail->mess.len,mail->mess.data[0],mail->mess.data[1],mail->mess.data[2],mail->mess.data[3],mail->mess.data[4],mail->mess.data[5],mail->mess.data[6],mail->mess.data[7]);
                    LoadPCMail(2,tmp);
                    break;
                case 20: //Write to CAN
                    can1.write(mail->mess);
                    LoadPCMail(1,"Write to CAN1");
                    break;
                default: // request to send message from code
                    break;
            }
            CAN1_mail.free(mail);
            CAN1MailNum--;
            ledCAN1=false;
        }
    }
}
/************* END CAN 1 ****************/
/************* CAN 2 ********************/
CAN can2(p30,p29);
int CAN2Freq=1000000;

Mail<CAN_mail_t, CAN_MaxMailElements> CAN2_mail;
int CAN2MailNum;

void LoadCAN2Mail(char command,  CANMessage mess) //para cargar mensajes de trabajo al proceso paralelo CAN1_thread_proc
{
    while(CAN2MailNum>=CAN_MaxMailElements) {
        Thread::wait(CANMessWait);
    }
    CAN_mail_t *mail = CAN2_mail.alloc();
    mail->command = command;
    mail->mess=mess;
    CAN2_mail.put(mail);
    CAN2MailNum++;
}
void messageFromCAN2()
{
    ledCAN2=true;
    CANMessage msg;
    can2.read(msg);
    LoadCAN2Mail(10,msg);
}
void CAN2_thread_proc(void const *args) //proceso paralelo de gestión CAN1
{
    char tmp[MessSizeCAN];
    while(true) {
        osEvent evt = CAN2_mail.get(osWaitForever);
        if (evt.status == osEventMail) {
            CAN_mail_t *mail = (CAN_mail_t*)evt.value.p;

            switch (mail->command) {
                case 0: //request Reset CAN
                    can2.reset();
                    LoadPCMail(1,"Reset CAN2");
                    break;
                case 1: //set frequency
                    can2.frequency(mail->mess.id);
                    LoadPCMail(1,"Set Frequency CAN2");
                    break;
                case 10: //Read from CAN
                    snprintf(tmp,MessSizeCAN,"ID=%i;TYPE=%i;FORMAT=%i;LEN=%d;DATA[0]=%u;DATA[1]=%u;DATA[2]=%u;DATA[3]=%u;DATA[4]=%u;DATA[5]=%u;DATA[6]=%u;DATA[7]=%u",mail->mess.id,mail->mess.type,mail->mess.format,mail->mess.len,mail->mess.data[0],mail->mess.data[1],mail->mess.data[2],mail->mess.data[3],mail->mess.data[4],mail->mess.data[5],mail->mess.data[6],mail->mess.data[7]);
                    LoadPCMail(3,tmp);
                    break;
                case 20: //Write to CAN
                    can2.write(mail->mess);
                    LoadPCMail(1,"Write to CAN2");
                    break;
                default: // request to send message from code
                    break;
            }
            CAN2_mail.free(mail);
            CAN2MailNum--;
            ledCAN2=false;
        }
    }
}
/************* END CAN 2 ****************/
/************* END CAN ******************/

/************* RS232 PC ******************/
#define TxBuffer_NumMess 16
#define RxBuffer_NumMess 16
#define MessSizePC 128
#define TxBuffer TxBuffer_NumMess*MessSizePC
#define RxBuffer RxBuffer_NumMess*MessSizePC
#define PC_MaxMailElements 16
#define PCMessWait MessSizePC*10/9.6 //ms

MODSERIAL pc(USBTX, USBRX,TxBuffer,RxBuffer);
bool LOGPC;
int BaudRate;
double TxBufferWait;
char ChEnd;

typedef struct {
    char command;   /* command to execute */
    char message[MessSizePC];   /* arguments */
} PC_mail_t;

Mail<PC_mail_t, PC_MaxMailElements> PC_mail;
int PCMailNum;

void TLogSTR(char *Tstr)
{
    ctTime = time(NULL);
    timeinfo = localtime ( &ctTime );
    timeinfo->tm_hour=(timeinfo->tm_hour+1)%24;
    strftime (Tstr,MessSizePC,"%H:%M:%S",timeinfo);
}

void LoadPCMail(char comm,  char *mess) //para cargar mensajes de trabajo al proceso paralelo ComPC_thread_proc
{
    while(PCMailNum>=PC_MaxMailElements) {
        Thread::wait(PCMessWait);
    }
    if(comm!=1 || LOGPC) {
        PC_mail_t *mail = PC_mail.alloc();
        mail->command = comm;
        snprintf(mail->message,MessSizePC,"%s",mess);
        PC_mail.put(mail);
        PCMailNum++;
    }
}

void messageFromPC(MODSERIAL_IRQ_INFO *q) //trabajo solicitado desde PC
{
    ledPC=true;
    MODSERIAL *sys = q->serial;
    char temp[MessSizePC];

    int i=sys->move(temp,MessSizePC,ChEnd);
    if (temp[i-2]=='\r') {
        i-=2;
    } else {
        i-=1;
    }
    temp[i]=0;
    LoadPCMail(0,temp);
}

int ComPC_Write(char *mess) //sólo para usarse en ComPC_thread_proc
{
    int i=strlen(mess);
    if(i>0) {
        while((TxBuffer-pc.txBufferGetCount())<i) {
            Thread::wait(TxBufferWait);
        }
        return pc.printf(mess);
    }
    return 0;
}

void ComPC_thread_proc(void const *args) //proceso paralelo de gestión PC: tareas solicitadas y envío a PC
{

    while(true) {
        osEvent evt = PC_mail.get(osWaitForever);
        if (evt.status == osEventMail) {
            PC_mail_t *mail = (PC_mail_t*)evt.value.p;

            char mess[MessSizePC];
            char Tstr[20];
            TLogSTR(Tstr);
            switch (mail->command) {
                case 0: //request from PC
                    CANMessage CanMess;
                    switch (mail->message[0]) {
                        case 'T':
                            float seconds;
                            sscanf(&mail->message[1],"%f",&seconds);
                            set_time((double)seconds);
                            time_t ctTime;
                            ctTime = time(NULL);
                            snprintf(mess,MessSizePC,"%s",ctime(&ctTime));
                            LoadPCMail(1,mess);
                            break;
                        case 'C': //CAN
                            switch (mail->message[1]) {
                                case '1': //CAN1, Send from PC a Message to CAN1
                                    switch (mail->message[2]) {
                                        case 'R': //reset CAN
                                            LoadCAN1Mail(0,CanMess);
                                            snprintf (mess,MessSizePC,"ACK(%s):%s\r\n",Tstr, mail->message);
                                            break;
                                        case 'F': //set Frequency CAN
                                            sscanf(&mail->message[3],"%i",&CanMess.id);
                                            LoadCAN1Mail(1,CanMess);
                                            snprintf (mess,MessSizePC,"ACK(%s):%s\r\n",Tstr, mail->message);
                                            break;
                                        case 'W': //Write CAN
                                            sscanf(&mail->message[3],"%i;%i;%i;%u;%u;%u;%u;%u;%u;%u;%u;%u",&CanMess.id,&CanMess.type,&CanMess.format,&CanMess.len,&CanMess.data[0],&CanMess.data[1],&CanMess.data[2],&CanMess.data[3],&CanMess.data[4],&CanMess.data[5],&CanMess.data[6],&CanMess.data[7]);
                                            LoadCAN1Mail(20,CanMess);
                                            snprintf (mess,MessSizePC,"ACK(%s):%s\r\n",Tstr, mail->message);
                                            break;
                                        default:
                                            snprintf (mess,MessSizePC,"NAK(%s):%s\r\n",Tstr, mail->message);
                                            break;
                                    }
                                    break;
                                case '2': //CAN2, Send from PC a Message to CAN2
                                    switch (mail->message[2]) {
                                        case 'R': //reset CAN
                                            LoadCAN2Mail(0,CanMess);
                                            snprintf (mess,MessSizePC,"ACK(%s):%s\r\n",Tstr, mail->message);
                                            break;
                                        case 'F': //set Frequency CAN
                                            sscanf(&mail->message[3],"%i",&CanMess.id);
                                            LoadCAN2Mail(1,CanMess);
                                            snprintf (mess,MessSizePC,"ACK(%s):%s\r\n",Tstr, mail->message);
                                            break;
                                        case 'W': //Write CAN
                                            sscanf(&mail->message[3],"%i;%i;%i;%u;%u;%u;%u;%u;%u;%u;%u;%u",&CanMess.id,&CanMess.type,&CanMess.format,&CanMess.len,&CanMess.data[0],&CanMess.data[1],&CanMess.data[2],&CanMess.data[3],&CanMess.data[4],&CanMess.data[5],&CanMess.data[6],&CanMess.data[7]);
                                            LoadCAN2Mail(20,CanMess);
                                            snprintf (mess,MessSizePC,"ACK(%s):%s\r\n",Tstr, mail->message);
                                            break;
                                        default:
                                            snprintf (mess,MessSizePC,"NAK(%s):%s\r\n",Tstr, mail->message);
                                            break;
                                    }
                                    break;
                                default:
                                    snprintf (mess,MessSizePC,"NAK(%s):%s\r\n",Tstr, mail->message);
                                    break;
                            }
                            break;
                        case 'F': //Frequencies
                            switch (mail->message[1]) {
                                case '1': //Freq1, Get Freq11
                                    snprintf(mess,MessSizePC,"F1= %i usec\r\n",Period1);
                                    break;
                                case '2': //Freq2, Get Freq2
                                    snprintf(mess,MessSizePC,"F2= %i usec\r\n",Period2);
                                    break;
                                case '3': //Freq3, Get Freq3
                                    snprintf(mess,MessSizePC,"F3= %i usec\r\n",Period3);
                                    break;
                                default:
                                    snprintf (mess,MessSizePC,"NAK(%s):%s\r\n",Tstr, mail->message);
                                    break;
                            }
                            break;
                        case 'P':
                            float duty=0;
                            int periodus=0;
                            switch (mail->message[1]) {
                                case '1':
                                    sscanf(&mail->message[2],"%f;%i",&duty,&periodus);
                                    PwmO1.write(duty);
                                    PwmO1.period_us(periodus);
                                    snprintf (mess,MessSizePC,"ACK(%s):%s\r\n",Tstr, mail->message);
                                    break;
                                default:
                                    snprintf (mess,MessSizePC,"NAK(%s):%s\r\n",Tstr, mail->message);
                                    break;
                            }
                            break;
                        case 'R':
                            if(strcmp(mail->message,"REBOOT")==0) {
                                mbed_reset();//wd.Configure(2.0);
                            } else {
                                snprintf (mess,MessSizePC,"NAK(%s):%s\r\n",Tstr, mail->message);
                            }
                            break;
                        case 'r':
                            if(strcmp(mail->message,"reboot")==0) {
                                mbed_reset();//wd.Configure(2.0);
                            } else {
                                snprintf (mess,MessSizePC,"NAK(%s):%s\r\n",Tstr, mail->message);
                            }
                            break;
                        default:
                            snprintf (mess,MessSizePC,"NAK(%s):%s\r\n",Tstr, mail->message);
                            break;
                    }
                    break;
                case 1: //Send LOG to PC
                    if(LOGPC) {
                        snprintf(mess,MessSizePC,"LOG(%s):%s\r\n",Tstr ,mail->message);
                    } else {
                        mess[0]=0;
                    }
                    break;
                case 2: //Send to PC a Message from CAN1
                    snprintf(mess,MessSizePC,"CAN1:%s\r\n",mail->message);
                    break;
                case 3: //Send to PC a Message from CAN2
                    snprintf(mess,MessSizePC,"CAN2:%s\r\n",mail->message);
                    break;
                default:
                    break;
            }
            PC_mail.free(mail);
            PCMailNum--;
            ledPC=false;
            ComPC_Write(mess);
        }
    }
}
/************* END RS232 PC **************/

void GetConfig()
{

#define CfgNumParam 6
#define CfgSizeParam 50

    pc.format(8,Serial::Even,1);
    pc.baud(115200);
    ConfigFile cfg;
    LocalFileSystem local("local");

    int i;
    char value[CfgNumParam][CfgSizeParam];
    char CfgK[CfgNumParam][CfgSizeParam]= {"InitialMessage","BaudRate","ChEnd","LOGPC","CAN1Freq","CAN2Freq"};

    pc.printf("\r\n* * *\r\n* * *\r\n");

    if (!cfg.read("/local/config.cfg")) {
        error("\r\nFailure to read a configuration file");
    }
    char Tstr[10];
    for (i=0; i<CfgNumParam; i++) {
        if (cfg.getValue(CfgK[i], &value[i][0], sizeof(value[i]))) {
            TLogSTR(Tstr);
            pc.printf("CFG_Param(%s): '%s'='%s'\r\n", Tstr,CfgK[i], value[i]);
        } else {
            error("Failure Reading '%s'\r\n", CfgK[i]);
        }
    }
    strcpy(InitialMessage,value[0]);
    BaudRate=atoi(value[1]);
    ChEnd=(char)atoi(value[2]);
    LOGPC=(bool)atoi(value[3]);
    CAN1Freq=atoi(value[4]);
    CAN2Freq=atoi(value[5]);

    TxBufferWait= 10000*MessSizePC/BaudRate;

    pc.printf("* * *\r\n* * *\r\n");

    while(!pc.txBufferEmpty()) {
        Thread::wait(100);
    };
}

int main()
{

    //char tempMessPC[MessSizePC];
    PCMailNum=0;
    GetConfig();

    // ************ PC ^^^^^^^^^^^^^
    pc.baud(BaudRate);
    Thread ComPC_thread (ComPC_thread_proc,NULL,osPriorityBelowNormal);
    pc.attach(&messageFromPC, MODSERIAL::RxAutoDetect);
    pc.autoDetectChar(ChEnd);

    // ************ PC_end ^^^^^^^^^^^^^

    LoadPCMail(1,"");
    LoadPCMail(1,"");
    LoadPCMail(1,"");
    LoadPCMail(1,"*****************************");
    LoadPCMail(1,InitialMessage);
    LoadPCMail(1,"*****************************");
    LoadPCMail(1,"");
    LoadPCMail(1,"");
    LoadPCMail(1,"");

    // ************ CAN1 ^^^^^^^^^^^
    Thread CAN1_thread (CAN1_thread_proc,NULL,osPriorityNormal);
    can1.frequency(CAN1Freq);
    can1.attach(&messageFromCAN1);
    // ************ CAN1_end ^^^^^^^

    // ************ CAN2 ^^^^^^^^^^^
    Thread CAN2_thread (CAN2_thread_proc,NULL,osPriorityNormal);
    can2.frequency(CAN2Freq);
    can2.attach(&messageFromCAN2);
    // ************ CAN2_end ^^^^^^^

    // ************ WD *************
    wd.WatchdogCausedReset();
    wd.Configure(5.0);
    // ************ WD_end *********

    // ************ Interrupts Freqs
    F1.start();
    F2.start();
    F3.start();
    Period1=0;
    Period2=0;
    Period3=0;

    Freq1.rise(Freq1_Meas);
    Freq2.rise(Freq2_Meas);
    Freq3.rise(Freq3_Meas);

    // ************ End Interrupts Freqs

    while(true) {
        //Thread::wait(osWaitForever);
        wd.Service();
        Thread::wait(1000);
    }
}