Communicate with IAI Robotnet linear actuators

Dependents:   IAILinearActuators

linactbuf.cpp

Committer:
henryeherman
Date:
2014-02-24
Revision:
0:de88dc2515d3

File content as of revision 0:de88dc2515d3:

#include <linactbuf.h>


namespace IAI {

LinActBuf::LinActBuf() {
    reset();
}

void LinActBuf::push(unsigned char value) {
    len++;
    *ptr = value;
    ptr++;
}

void LinActBuf::pushRx(unsigned char value) {
    rxlen++;
    *rxptr = value;
    rxptr++;
}

void LinActBuf::reset() {
    len = 0;
    ptr = buf;
    buf[0] = GWADDR;
    resetRx();
}


void LinActBuf::resetRx() {
    rxlen = 0;
    exprxlen = 0;
    rxptr = rxbuf;
    rxbuf[0] = 0;
    rxmsgptr = 0;
    datalen = 0;
}

void LinActBuf::copy(LinActBuf *other) {
    for(int i=0;i<other->len;i++) {
        buf[i] = other->buf[i];
    }
}

unsigned int LinActBuf::crc_update(unsigned int crc, unsigned char a) {
    crc ^= a;
    //printf("CRC^=a:0x%x, a=%x\r\n", crc, a);
    for(int i=0;i<8;i++) {
        if(crc & 1) {
            crc = (crc >> 1) ^ 0xA001;
        } else {
            crc = crc >> 1;
        }
    }
    //printf("return CRC: 0x%x\r\n", crc);
    return crc;
}

void LinActBuf::calc_crc() {

    unsigned short crc = 0xffff;

    for(int i=0;i<len;i++) {
        crc = crc_update(crc, buf[i]);
    }

    if (len+2 > LINACT_BUFLEN) {
        // this is an error so log it
        LINBUFERR("tried to write beyond buffer length\n");
        return;
    }
    //printf("0x%04x\r\n", crc);
    buf[len] = (crc & 0xff);
    buf[len+1] = ((crc & 0xff00) >> 8);
    len=len+2;
}

char * LinActBuf::as_string() {
    strbuf[0]='\0';
    char tmpbuf[4] = "";
    for(int i=0;i<len;i++) {
        sprintf(tmpbuf, "%02X", (unsigned char)buf[i]);

        strcat(strbuf,tmpbuf);
        //printf("%d:%s\r\n",i, tmpbuf);
    }
    return strbuf;
}

char * LinActBuf::rx_as_string() {
    rxstrbuf[0]='\0';
    char tmpbuf[4] = "";
    for(int i=0;i<len;i++) {
        sprintf(tmpbuf, "%02X", (unsigned char)buf[i]);

        strcat(rxstrbuf,tmpbuf);
        //printf("%d:%s\r\n",i, tmpbuf);
    }
    return rxstrbuf;
}

void LinActBuf::readRegsisterStr(unsigned short startreg, unsigned short count) {
    buf[GWADDRPOS] = GWADDR;
    buf[CMDPOS] = LINACT_READ_MULTI;
    buf[2] = (unsigned char)((startreg & 0xFF00) >> 8);
    buf[3] = (unsigned char)(startreg & 0x00FF);
    buf[4] = (unsigned char)((count & 0xFF00) >> 8);
    buf[5] = (unsigned char)(count & 0x00FF);
    len = 6;
    calc_crc();

    // See page 151
    // Header + crc + 2*numreg
    datalen = 2 * count;
    exprxlen = 5 + datalen; // Len in bytes

    rxmsgptr = rxbuf + 3;
}

void LinActBuf::writeRegisterStr(unsigned short reg, unsigned short value) {
    buf[GWADDRPOS] = GWADDR;
    buf[CMDPOS] = LINACT_WRITE;
    buf[2] = (unsigned char)((reg & 0xFF00) >> 8);
    buf[3] = (unsigned char)(reg & 0x00FF);
    buf[4] = (unsigned char)((value & 0xFF00) >>8);
    buf[5] = (unsigned char)(value & 0x00FF);
    len = 6;
    calc_crc();
    rxmsgptr = 0;
    // See Page 163 for expected len
    exprxlen = 8; //Len in bytes
}

void LinActBuf::writeMultiRegisterStr(unsigned short reg,
    unsigned short reglen, unsigned char * data, unsigned char dlen) {

    buf[GWADDRPOS] = GWADDR;
    buf[CMDPOS] = LINACT_WRITE_MULTI;
    buf[2] = (unsigned char)((reg & 0xFF00) >> 8);
    buf[3] = (unsigned char)(reg & 0x00FF);
    buf[4] = (unsigned char)((reglen & 0xFF00) >> 8);
    buf[5] = (unsigned char)(reglen & 0x00FF);
    buf[6] = dlen;


    for(int i=0;i<dlen;i++) {
        buf[7+i] = data[i];
    }
    len = dlen+7;
    calc_crc();

    // See page 180
    exprxlen = 8; // Len in bytes
    rxmsgptr = 0;
}


unsigned char * LinActBuf::rxdata() {
    return rxmsgptr;
}

unsigned int LinActBuf::rxdatalen() {
    return datalen;
}

// Check the checksum
int LinActBuf::rxvalidate() {

    if(rxlen != exprxlen)
        return RXMSGLENERR;

    switch(buf[CMDPOS]) {
        case LINACT_WRITE:
            if((buf[len-1] == rxbuf[rxlen-1]) &&
                    (buf[len-2] == rxbuf[rxlen-2]))
                return RXWRCRCOK;
        case LINACT_WRITE_MULTI:
            if(checkrxcrc())
                return RXMULWRCRCOK;
        case LINACT_READ_MULTI:
            if(checkrxcrc())
                return RXREADCRCOK;
        default:
            break;
    }
    return RXINVALIDCRCERR;
}

int LinActBuf::checkrxcrc() {
    unsigned short crc = 0xffff;

    if (rxlen < 2)
        return 0;

    // Check all bytes but last 2
    for(int i=0;i<(rxlen-2);i++) {
        crc = crc_update(crc, rxbuf[i]);
    }

    if(rxbuf[rxlen-2] == (crc & 0xff) &&
    rxbuf[rxlen-1] == ((crc & 0xff00) >> 8))
        return 1;
    LINBUFDBG("Expected CRC 0x%04X\r\n", crc);
    return 0;
}


} // End IAI Namespace