f211

Dependencies:   mbed-dev1

Fork of OBD21121 by Surendar S

main.cpp

Committer:
takeuz
Date:
2017-04-29
Revision:
9:a3bdc9a71466
Parent:
8:cc3cb620c3bd
Child:
10:fe1b976a3f9c

File content as of revision 9:a3bdc9a71466:

#include "mbed.h"
#include "functions.h"

#define PID_REQUEST         0x7DF
#define PID_REPLY           0x7E8

#define CANSPEED_500      500000
#define CANSPEED_250      250000
#define CANSPEED_125      125000
#define sendDebugMessage  1
#define pushDebugData 1

const int canSpeeds[3]= {CANSPEED_125,CANSPEED_500,CANSPEED_250};
Serial serialPorts[2] = {Serial(P0_11,P0_13),Serial(P0_15,P0_14)};
Serial *kLineUART=NULL;
DigitalOut *klineWakeup=new DigitalOut(P0_28);
CAN canBus(P0_22, P0_23);

Ticker timeCounter;
Timer OBDTimer;
CANMessage can_MsgRx;
char kLineCmd[6]= {'\0','\0','\0','\0','\0','\0'};

void clearOBDCommand();
void flushBuffer();
void sendCommandToVehicle(char *_cmd);
void setKLineMsg(char *_cmd);
void flushBuffer();
void kLinekeepalive();
char tolower(unsigned char ch);
int findStringLength(char *_cmd);

int isPoweredupNow=1;
int interFace=1;
int debug=1;
int currentOBDProtocol=0;
const int protCan=1;
const int protkLine9141=2;
const int protkLine14230=3;
int canFrequency;
int cmd;
char can_msg[8];
char *incomingDataInInterFace;
const int incomingDataInInterFaceSize=256;
int incomingDataInInterFaceCounter=0;
char * incomingDataInOBD;
const int incomingDataInOBDSize=256;
int incomingDataInOBDCounter=0;
const int waitTimeForOBDComm=2000;
const int sleepTime=25000;
const int powerSaveTime=120;
int OBDCmdReceived=0;
int interfaceCmdReceived=0;
int lastOBDCmdRcvdTime=0;
int lastInterfaceCmdRcvdTime=0;
int KlineReadCount=0;
int isVehicleCommandProcessing=0;
int kLineCommandCount=0;
char kByte=0;

void readInterface()
{
    char c;
    while(serialPorts[interFace].readable()) {
        lastInterfaceCmdRcvdTime=0;
        c = serialPorts[interFace].getc();

        serialPorts[debug].putc(c);

        if(incomingDataInInterFaceCounter<incomingDataInInterFaceSize && c!='\r' && c!='\n') {
            incomingDataInInterFace[incomingDataInInterFaceCounter] = c;
        }
        incomingDataInInterFaceCounter++;

        if(c=='\r') {
            interfaceCmdReceived=1;
            serialPorts[debug].puts("nl\r\n");
        }

    }
}

void canReader()
{
    if (canBus.read(can_MsgRx)) {
        lastOBDCmdRcvdTime=0;
        if ((can_MsgRx.id == PID_REPLY)) {
            OBDCmdReceived=1;
            for (int i = 0; i < (int)can_MsgRx.len && currentOBDProtocol!=0; i++) {
                char c[2];
                sprintf(c, "%02X",can_MsgRx.data[i]);
                serialPorts[interFace].puts(c);
            }
        }
    }
}

void readKLine()
{
    char c;
    while(kLineUART->readable()) {
        c=kLineUART->getc();
        serialPorts[interFace].printf("%02x",c);
    }
}


void timeCounterFunction()
{
    lastInterfaceCmdRcvdTime++;
    lastOBDCmdRcvdTime++;
    KlineReadCount++;
    if(currentOBDProtocol==protkLine14230 && KlineReadCount>=3) {
        KlineReadCount=0;
        if(incomingDataInInterFaceCounter) {
            return;
        }
        kLinekeepalive();
    }

}

int main()
{
    serialPorts[interFace].baud(9600);
    serialPorts[debug].puts("f2119\r\n");
    incomingDataInInterFace=(char *)malloc(incomingDataInInterFaceSize*sizeof(char));
    incomingDataInOBD=(char *)malloc(incomingDataInOBDSize*sizeof(char));
    *klineWakeup=0;

    clearMemoryLocation(incomingDataInInterFace,incomingDataInInterFaceSize);
    clearMemoryLocation(incomingDataInOBD,incomingDataInOBDSize);
    wait_ms(300);
    timeCounter.attach(&timeCounterFunction, 1.0);
    serialPorts[interFace].attach(&readInterface);
    serialPorts[interFace].puts("TU211 v1.0\r\n");
    while(1) {
        if(interfaceCmdReceived && checkForLocalInterfaceCommand()) {
            serialPorts[debug].puts("Going to clear UART data\r\n");
            clearInterfaceCommand();
            serialPorts[debug].puts("UART data cleared\r\n");
        }
        if(currentOBDProtocol==0 && isPoweredupNow) {
            isPoweredupNow=0;
#if sendDebugMessage
            serialPorts[debug].puts("Going to figure protocol\r\n");
#endif
            serialPorts[debug].puts("Searching...\r\n");
            checkCommunicationProtocol();
            if(!currentOBDProtocol) {
#if sendDebugMessage
                serialPorts[debug].puts("!Unknownprotocol\r\n");
#endif
            } else if(currentOBDProtocol==protCan) {
#if sendDebugMessage
                serialPorts[debug].puts("can Protocol\r\n");
#endif
                serialPorts[interFace].puts("OK\r\n");
            } else if(currentOBDProtocol==protkLine14230) {
#if sendDebugMessage
                serialPorts[debug].puts("Kline Protocol\r\n");
#endif
            }
        }
        if(interfaceCmdReceived && checkForLocalInterfaceCommand()) {
            serialPorts[debug].puts("Going to clear UART data\r\n");
            clearInterfaceCommand();
            serialPorts[debug].puts("UART data cleared\r\n");
        }
        if(interfaceCmdReceived && currentOBDProtocol) {
            serialPorts[debug].puts("Going to process user command\r\n");
            clearOBDCommand();
            if(currentOBDProtocol==protCan) {
                processUserCommand();
            } else if(currentOBDProtocol==protkLine14230) {
                while(isVehicleCommandProcessing);
                flushBuffer();
                /*kLineUART->attach(NULL);
                kLineUART->attach(&readKLine);*/
                sendCommandToVehicle(incomingDataInInterFace);
                wait_ms(500);
                serialPorts[debug].printf("\r\n");
            } else {
                clearInterfaceCommand();
                serialPorts[interFace].puts("?\r\n");
#if sendDebugMessage
                serialPorts[debug].puts("?\r\n");
#endif
            }
        } else if(interfaceCmdReceived) {
            clearInterfaceCommand();
            serialPorts[interFace].puts("?\r\n");
#if sendDebugMessage
            serialPorts[debug].puts("?\r\n");
#endif
        }
        sleepProcess();
        /*if(lastOBDCmdRcvdTime> powerSaveTime && lastInterfaceCmdRcvdTime> powerSaveTime ) {
            powerSaveMode();
        } else {
            sleepProcess();
        }*/
    }
}
void checkCommunicationProtocol()
{
    /* #if sendDebugMessage
     serialPorts[debug].puts("check Communication protocal ENT\r\n");
    #endif*/
    int i=0;
    do {
#if sendDebugMessage
        serialPorts[debug].puts("CanBusCheck\r\n");
#endif
        canBus.reset();
        canBus.frequency(canSpeeds[i]);
        canBus.attach(NULL);
        canBus.attach(&canReader);
        OBDTimer.reset();
        OBDTimer.start();
        OBDCmdReceived=0;
        setCanMessage("010D");
        if (canBus.write(CANMessage(PID_REQUEST, can_msg, 8))) {
            /*#if sendDebugMessage
                       serialPorts[debug].printf("OBDTIMER:%d\r\n",OBDTimer.read_ms());
            #endif*/
            while(OBDTimer.read_ms() < waitTimeForOBDComm) {
                if(OBDCmdReceived) {
                    currentOBDProtocol=protCan;
                    canFrequency=i;
                    break;
                }
            }
        }
        wait_ms(200);
        i++;
    } while(i<3 && canFrequency==0);
    OBDTimer.stop();
    canBus.attach(NULL);
    if(!currentOBDProtocol) {
        //Kline interface check
        initializeKLine();
    }
#if sendDebugMessage
    serialPorts[debug].puts("check Communication protocal EXT\r\n");
#endif
}
void clearMemoryLocation( char *base, int _size)
{
    for(int forCount=0; forCount<_size; forCount++) {
        base[forCount]='\0';
    }
}
void setCanMessage(char* _cmd)
{
    serialPorts[debug].puts("user Command :");
    serialPorts[debug].puts(_cmd);
    serialPorts[debug].puts("\r\n");
    int len=findStringLength(_cmd)/2;
    char _mode[2]="";
    for(int i=0; i<2; i++) {
        _mode[i]=_cmd[i];
    }
    int mode=strtol(_mode,NULL, 16);
    cmd=strtol((_cmd+2),NULL, 16);
    can_msg[0] = len;
    can_msg[1] = mode;
    can_msg[2] = cmd;
    can_msg[3] = 0;
    can_msg[4] = 0;
    can_msg[5] = 0;
    can_msg[6] = 0;
    can_msg[7] = 0;
}
void processUserCommand()
{
    OBDTimer.reset();
    setCanMessage(incomingDataInInterFace);
    OBDTimer.start();
    OBDCmdReceived=0;
    canBus.attach(NULL);
    canBus.attach(&canReader);
    if (canBus.write(CANMessage(PID_REQUEST, can_msg, 8))) {
        while(OBDTimer.read_ms() < waitTimeForOBDComm) {
            if(OBDCmdReceived) {
                clearInterfaceCommand();
                break;
            }
        }
    }
    OBDTimer.stop();
    if(!OBDCmdReceived) {
        clearInterfaceCommand();
        serialPorts[interFace].puts("?");
    }
    serialPorts[interFace].puts("\r\n");
}
void sleepProcess()
{

#if pushDebugData
    serialPorts[debug].puts("SPe\r\n");
#endif
    OBDTimer.reset();
    OBDTimer.start();
    while(OBDTimer.read_ms()<sleepTime && !interfaceCmdReceived) {
        wait_ms(50);
    }
    OBDTimer.stop();
}

void powerSaveMode()
{
#if pushDebugData
    serialPorts[debug].puts("PowerSaveOn\r\n");
#endif
    wait(20);
#if pushDebugData
    serialPorts[debug].puts("PowerSaveOff\r\n");
#endif
}
int checkForLocalInterfaceCommand()
{
    serialPorts[debug].puts("CommandDETECTED\r\n");
    int i=0;
    while(incomingDataInInterFace[i]!='\0'){
        incomingDataInInterFace[i]=tolower(incomingDataInInterFace[i]);
        i++;
    }
    char temp[2]= {incomingDataInInterFace[0],incomingDataInInterFace[1]};
    if(strcmp(temp,"at")!=0) {
        serialPorts[debug].puts("Not Local Command\r\n");
        return 0;
    }
    if(strcmp(incomingDataInInterFace,"atz")==0) {
        LPC_SYSCON->SYSAHBCLKCTRL1 |= (1<<7);
        LPC_SWM->PINASSIGN0 = 0xffffffffUL;
    LPC_SWM->PINASSIGN1 = 0xffffffffUL;
    LPC_SWM->PINASSIGN2 = 0xffffffffUL;
    LPC_SWM->PINASSIGN3 = 0xffffffffUL;
    LPC_SWM->PINASSIGN4 = 0xffffffffUL;
    LPC_SWM->PINASSIGN5 = 0xffffffffUL;
    LPC_SWM->PINASSIGN8 = 0xffffffffUL;
        LPC_SYSCON->SYSAHBCLKCTRL1 |= (0<<7);
        NVIC_SystemReset();
    }
    if(strcmp(incomingDataInInterFace,"atrv")==0) {
        serialPorts[interFace].puts("12.1V\r\n");
        clearMemoryLocation(incomingDataInInterFace,incomingDataInInterFaceSize);
        return 1;
    }
    serialPorts[interFace].puts("?\r\n");
    return 2;
}
void sendResponseToInterface()
{
    serialPorts[interFace].puts(incomingDataInOBD);
    serialPorts[interFace].puts("\r\n");
}

void clearInterfaceCommand()
{
    incomingDataInInterFaceCounter=0;
    interfaceCmdReceived=0;
    clearMemoryLocation(incomingDataInInterFace,incomingDataInInterFaceSize);
}

void clearOBDCommand()
{
    clearMemoryLocation(incomingDataInOBD,incomingDataInOBDSize);
    incomingDataInOBDCounter=0;
    OBDCmdReceived=0;
}
int findStringLength(char *_cmd)
{
    int i=0;
    for(i=0; _cmd[i]!='\0'; ++i);
    return i;
}
int initializeKLine()
{
#if sendDebugMessage
    serialPorts[debug].puts("K-Line Check\r\n");
#endif
    *klineWakeup=1;
    wait_ms(300);
    *klineWakeup=0;
    wait_ms(25);
    *klineWakeup=1;
    wait_ms(25);
    delete klineWakeup;
    kLineUART=new Serial(P0_28,P0_27);
    kLineUART->baud(10400);
    kLineUART->attach(&readKLine);
    uint8_t crc=0;
    crc=crc+0xC1;
    crc=crc+0x33;
    crc=crc+0xF1;
    crc=crc+0x81;
    kLineUART->putc(0xC1);
    kLineUART->putc(0x33);
    kLineUART->putc(0xF1);
    kLineUART->putc(0x81);
    kLineUART->putc(crc);
    wait(1);
    //have to check K-line Response
    currentOBDProtocol=protkLine14230; // have to remove this line
    return 0;
}

void setKLineMsg(char *_cmd)
{
    for(int i=3; i<6; i++) {
        kLineCmd[i]='\0';
    }
    int len=findStringLength(_cmd)/2;
    char _mode[2]="";
    uint8_t crc=0;
    if(len==1) {
        crc=crc+0xC1;
        kLineCmd[0]=0xC1;
        crc=crc+0x33;
        kLineCmd[1]=(0x33);
        crc=crc+0xF1;
        kLineCmd[2]=(0xF1);
        crc=crc+strtol((_cmd),NULL, 16);
        kLineCmd[3]=(strtol((_cmd),NULL, 16));
        kLineCmd[4]=(crc);
    } else if(len==2) {
        crc=crc+0xC2;
        kLineCmd[0]=(0xC2);
        crc=crc+0x33;
        kLineCmd[1]=(0x33);
        crc=crc+0xF1;
        kLineCmd[2]=(0xF1);
        for(int i=0; i<2; i++) {
            _mode[i]=_cmd[i];
        }
        crc=crc+strtol(_mode,NULL, 16);
        kLineCmd[3]=(strtol(_mode,NULL, 16));
        crc=crc+(strtol((_cmd+2),NULL, 16));
        kLineCmd[4]=(strtol((_cmd+2),NULL, 16));
        kLineCmd[5]=(crc);
    }
}

void sendCommandToVehicle(char *_cmd)
{
    isVehicleCommandProcessing=1;
    setKLineMsg(_cmd);
    for(kLineCommandCount=0; kLineCommandCount<6; kLineCommandCount++) {
        if(kLineCmd[kLineCommandCount]=='\0') {
            break;
        }
        kLineUART->putc(kLineCmd[kLineCommandCount]);
    }
    wait_ms(500);
    //have to check given and received commands are same.
    //if it is same we have to read the response else just fush buffer and send the command again
    clearInterfaceCommand();
    isVehicleCommandProcessing=0;
}

void flushBuffer()
{
    while(kLineUART->readable()) {
        kLineUART->getc();
    }
}
void kLinekeepalive()
{
    kLineUART->putc(0xc1);
    kLineUART->putc(0x33);
    kLineUART->putc(0xf1);
    kLineUART->putc(0x3e);
    kLineUART->putc(0x23);
}
char tolower(unsigned char ch) {
    if (ch >= 'A' && ch <= 'Z')
        ch = 'a' + (ch - 'A');
    return ch;
 }