CANMessage is the primitive CAN message object. It supports creation, parsing, formatting of messages. Can be easily integrated with CANPort and CANQueue libraries.

CANMessage.cpp

Committer:
WiredHome
Date:
2019-10-23
Revision:
4:4ba6856f7b4f
Parent:
3:c2a26d9d689b

File content as of revision 4:4ba6856f7b4f:

/// @file CANMessage.h
/// This is the basic CAN message, and supports construction of, formatting and decoding.
///
/// @version 1.0
///
/// @note Copyright &copr; 2011 by Smartware Computing, all rights reserved.
///     Individuals may use this application for evaluation or non-commercial
///     purposes. Within this restriction, changes may be made to this application
///     as long as this copyright notice is retained. The user shall make
///     clear that their work is a derived work, and not the original.
///     Users of this application and sources accept this application "as is" and
///     shall hold harmless Smartware Computing, for any undesired results while
///     using this application - whether real or imagined.
///
/// @author David Smart, Smartware Computing
///
/// @note
/// Version History
/// 20110724
/// \li Extending timestamp to 64 bits
///
#include <mbed.h>

#include "CANMessage.h"
#include "Utilities.h"      // missing functions...

static Timer timer;
static bool timer_on;

static char mytolower(char a) {
    if (a >= 'A' && a <= 'Z')
        return (a - 'A' + 'a');
    else
        return a;
}

static int mystrnicmp(const char *l, const char *r, size_t n) {
    int result = 0;

    if (n != 0) {
        do {
            result = mytolower(*l++) - mytolower(*r++);
        } while ((result == 0) && (*l != '\0') && (--n > 0));
    }
    if (result < -1)
        result = -1;
    else if (result > 1)
        result = 1;
    return result;
}

CANmsg::CANmsg() {
    if (!timer_on) {
        timer.start();
        timer_on = true;
    }
    timestamp = (uint32_t)timer.read_us(); // read_high_resolution_us();
}

CANmsg::CANmsg(CANCHANNEL_T _ch, CANDIR_T _dir, CANMessage _msg) {
    if (!timer_on) {
        timer.start();
        timer_on = true;
    }
    timestamp = (uint32_t)timer.read_us(); // read_high_resolution_us();
    ch = _ch;
    dir = _dir;
    id = _msg.id;
    len = _msg.len;
    for (int i=0; i<len; i++)
        data[i] = _msg.data[i];
    format = _msg.format;
    type = _msg.type;
}

//        0 1   2  3        4  5---------------------| 6   7 8
//        t xtd 02 1CF00400 08 11 22 33 44 55 66 77 88 0   0 1234.567890
//        If the first letter is not 't'ransmit or 'r'eceive, transmit is
//          assumed
//        xtd 02 1CF00400 08 11 22 33 44 55 66 77 88 0   0 1234.567890
CANmsg::CANmsg(char *p) {
    if (!timer_on) {
        timer.start();
        timer_on = true;
    }
    ParseCANMessage(p);
}

CANmsg::~CANmsg() {
}

bool CANmsg::ParseCANMessage(char *p) {
    //int state = 0;
    //printf("\r\nParseCANMessage(%s)\r\n",p);
    char *token;
    char *search = " ,\t";  // any of these is a separator
    token = strtok(p, search);  // might now point to 't'|'r', or 'xtd'|'nrm'
    if (*token == 'r')
        dir = rcv;
    else
        dir = xmt;
    if (*token == 't' || *token == 'r') // transmit or receive
        token = strtok(NULL, search);    // advance past 't'|'r'
    if (mystrnicmp(token,"xtd",3) == 0)
        format = CANExtended;
    else if (mystrnicmp(token, "nrm", 3) == 0)
        format = CANStandard;
    token = strtok(NULL, search);
    ch = (CANCHANNEL_T)(atoi(token) - 1);
    token = strtok(NULL, search);
    id = hextoul(token);
    token = strtok(NULL, search);
    len = hextoul(token);
    for (int i=0; i<len; i++) {
        token = strtok(NULL, search);
        data[i] = (char)hextoul(token);
    }
    token = strtok(NULL, search);
    // fixedZero = atoi(token)
    token = strtok(NULL, search);
    // lostMessages = atoi(token);
    token = strtok(NULL, search);
    timestamp = (uint32_t)timer.read_us(); // read_high_resolution_us();        // set it to "now"
    if (token)
        timestamp = (uint32_t)(1000000 * atof(token));
    return true;
}

void CANmsg::SetTimestamp() {
    timestamp = (uint32_t)timer.read_us(); // read_high_resolution_us();
}

// 12345678901234567890123456789012345678901234567890123456789012345
// r xtd 01 1CF00400 08 11 22 33 44 55 66 77 88 0    0     12.123456
void CANmsg::FormatCANMessage(char *buffer, int buflen) {
    if (buflen >= 68) {    // 63+\r+\n+\0+2spare
        if (format >= 128) {
            sprintf(buffer, "%c %s %02d %8s %02X ",
                    (dir == xmt ) ? 't' : 'r',
                    "ERR",
                    ch + 1,
                    (format == 128) ? "active" : "passive",
                    8);
            for (int d=0; d<8; d++) {
                sprintf(buffer + strlen(buffer), "%02X ", 0);
            }
        } else {
            sprintf(buffer, "%c %s %02d %08X %02X ",
                    (dir == xmt ) ? 't' : 'r',
                    (format == CANExtended) ? "xtd" : "nrm",
                    ch + 1,
                    id,
                    len);
            for (int d=0; d<8; d++) {
                if (d < len)
                    sprintf(buffer + strlen(buffer), "%02X ", data[d]);
                else
                    strcat(buffer, "   ");
            }
        }
        uint32_t uSec = timestamp % 1000000;    // integer math is faster than float
        uint32_t Sec = timestamp / 1000000;
        sprintf(buffer + strlen(buffer), "0   0 %6u.%06u", Sec, uSec);
    } else {
        strcpy(buffer,"ERROR, buf too small");
    }
}