Open OBC / e36obd

Dependents:   obdtest

DS2.cpp

Committer:
openobc
Date:
2011-05-20
Revision:
2:5a4b823759ac
Parent:
1:c935b1619b83

File content as of revision 2:5a4b823759ac:

#include "DS2.h"


DS2Packet::DS2Packet(int maxlength)
{
    has8BitAddr = 0;
    rawdata = (char*)malloc(maxlength);
    address = (unsigned short*)rawdata;
    length = rawdata + 2;
    data = rawdata + 3;
    checksum = rawdata + maxlength - 1;
    
    *length = 0;
}
    
DS2Packet::DS2Packet(int address, const char* data, int length)
{
    has8BitAddr = 0;
    rawdata = (char*)malloc(length + 4);
    this->address = (unsigned short*)rawdata;
    this->length = rawdata + 2;
    this->data = rawdata + 3;
    this->checksum = rawdata + 3 + length;
    
    rawdata[0] = address & 0xff;
    rawdata[1] = (address >> 8) & 0xff;
    rawdata[2] = length + 4;
    memcpy(rawdata + 3, data, length);
    
    updateChecksum();
}

DS2Packet::~DS2Packet()
{
    free(rawdata);
}

void DS2Packet::has8BitAddress(bool b)
{
    if(b && !has8BitAddr)
    {
        *address <<= 8;
        *length -= 1;
        rawdata += 1;
        updateChecksum();
    }
    else if(!b && has8BitAddr)
    {
        *address >>= 8;
        *length += 1;
        rawdata -= 1;
        updateChecksum();
    }
    has8BitAddr = b;
}

void DS2Packet::updateChecksum()
{
    *checksum = 0;
    for(int i = 0; i < *length - 1; i++)
        *checksum ^= rawdata[i];
}


DS2::DS2(Bus* KLine, Bus* LLine) :
    k(KLine), l(LLine)
{
    k->baud(9600);
    l->baud(9600);
    k->format(8, Serial::Even, 1);
    l->format(8, Serial::Even, 1);
}

DS2::~DS2()
{

}

int DS2::sendPacket(DS2Packet* packet, Bus* bus)
{
    dbg.printf("sent: ");
    for(int i = 0; i < packet->getLength(); i++)
    {
        dbg.printf("%02x ", packet->getRawData()[i]);
    }
    dbg.printf("on %s bus\r\n", (bus == k)? "k":"l");
    
    return bus->send(packet->getRawData(), packet->getLength());
}

//reads in a whole packet without verification; assumes the whole packet is in the uart buffer
DS2Packet* DS2::getPacket(Bus* bus)
{
    DS2Packet* packet = new DS2Packet(DS2_MTU);
    int count =  bus->get(packet->getRawData(), DS2_MTU);
    
    dbg.printf("received: ");
    for(int i = 0; i < count; i++)
        dbg.printf("%02x ", packet->getRawData()[i]);
    dbg.printf("on %s bus\r\n", (bus == k)? "k":"l");
    
    return packet;
}

DS2Packet* DS2::getPacket8(Bus* bus)
{
    DS2Packet* packet = new DS2Packet(DS2_MTU);
    packet->has8BitAddress(1);
    int count =  bus->get(packet->getRawData(), DS2_MTU);
    
    dbg.printf("received: ");
    for(int i = 0; i < count; i++)
        dbg.printf("%02x ", packet->getRawData()[i]);
    dbg.printf("on %s bus\r\n", (bus == k)? "k":"l");
    
    return packet;
}

//snoop k and l traffic and print it to dbg
//doesn't return
void DS2::snoop()
{
    dbg.printf("sniffing data on k and l\r\n");
    dbg.printf("k = <0x??>\r\nl = [0x??]\r\n");
    dbg.printf("begin INPA traffic now\r\n");
    int squelch = 0;
    while(1)
    {
        if(k->readable())
        {
            dbg.printf("<%02x>", k->getc());
            squelch = 10000;
        }
        else if(l->readable())
        {
            dbg.printf("[%02x]", l->getc());
            squelch = 10000;
        }
        else if(squelch)
        {
            if(!--squelch)
                dbg.printf("\r\n");
        }
    }
}

//try to query a module on the two different buses and with the two different packet types
void DS2::testModule(int address)
{
    //assemble an identification request packet
    DS2Packet *packet = new DS2Packet(address, DS2_IDENTIFY, sizeof(DS2_IDENTIFY));
    
    //try on k first
    dbg.printf("trying module with 16 bit address 0x%02x on k bus\r\n", packet->getAddress());
    sendPacket(packet, k);
    wait(0.5);
    if(k->readable()) //the module sent a reply
    {
        DS2Packet* reply = getPacket(k);
        dbg.printf("***received %i bytes from module at 0x%02x on k bus\r\n", reply->getLength(), reply->getAddress());
        delete reply;
        
    }

    //then try with 8 bit address
    packet->has8BitAddress(1);
    dbg.printf("trying module with  8 bit address 0x%02x on k bus\r\n", packet->getAddress());
    sendPacket(packet, k);
    wait(0.5);
    if(k->readable())
    {
        DS2Packet* reply = getPacket8(k);
        dbg.printf("***received %i bytes from module at 0x%02x on k bus\r\n", reply->getLength(), reply->getAddress());
        delete reply;
    }

    //now try on l
    packet->has8BitAddress(0);
    dbg.printf("trying module with 16 bit address 0x%02x on l bus\r\n", packet->getAddress());
    sendPacket(packet, l);
    wait(0.5);
    if(k->readable())
    {
        DS2Packet* reply = getPacket(k);
        dbg.printf("***received %i bytes from module at 0x%02x on k bus\r\n", reply->getLength(), reply->getAddress());
        delete reply;
    }
    
    //8 bit address again
    packet->has8BitAddress(1);
    dbg.printf("trying module with  8 bit address 0x%02x on l bus\r\n", packet->getAddress());
    sendPacket(packet, l);
    wait(0.5);
    if(k->readable())
    {
        DS2Packet* reply = getPacket8(k);
        reply->has8BitAddress(1);
        dbg.printf("***received %i bytes from module at 0x%02x on k bus\r\n", reply->getLength(), reply->getAddress());
        delete reply;
    }
  

    delete packet;
}

//if I knew of a module that was guaranteed to be the same in every car I'd test querying it here
bool DS2::test()
{
    return 1;
}