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

Files at this revision

API Documentation at this revision

Comitter:
WiredHome
Date:
Sun Jul 15 15:15:18 2012 +0000
Commit message:
[mbed] converted /A_CANAdapter/CANUtilities/CANMessage

Changed in this revision

CANMessage.cpp Show annotated file Show diff for this revision Revisions of this file
CANMessage.h Show annotated file Show diff for this revision Revisions of this file
diff -r 000000000000 -r f0ce97992c5f CANMessage.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CANMessage.cpp	Sun Jul 15 15:15:18 2012 +0000
@@ -0,0 +1,134 @@
+/// @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"      // mbed <-> Visual Studio
+
+#include "FreeRunTimer.h"
+
+static FreeRunTimer timer;
+static bool timer_on;
+
+CANmsg::CANmsg() {
+    if (!timer_on) {
+        timer.start();
+        timer_on = true;
+    }
+    timestamp = timer.read_us();
+}
+
+CANmsg::CANmsg(CANCHANNEL_T _ch, CANDIR_T _dir, CANMessage _msg) {
+    if (!timer_on) {
+        timer.start();
+        timer_on = true;
+    }
+    timestamp = timer.read_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 = timer.read_us();        // set it to "now"
+    if (token)
+        timestamp = (uint32_t)(1000000 * atof(token));
+    return true;
+}
+
+void CANmsg::SetTimestamp() {
+    timestamp = (uint32_t)timer.read_us();
+}
+
+// 12345678901234567890123456789012345678901234567890123456789012345
+// r xtd 01 1CF00400 08 11 22 33 44 55 66 77 88 0    0 0012.123456
+void CANmsg::FormatCANMessage(char *buffer, int buflen) {
+    if (buflen >= 68) {    // 63+\r+\n+\0+2spare
+        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 %04u.%06u", Sec, uSec);
+    } else {
+        strcpy(buffer,"ERROR, buf too small");
+    }
+}
diff -r 000000000000 -r f0ce97992c5f CANMessage.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/CANMessage.h	Sun Jul 15 15:15:18 2012 +0000
@@ -0,0 +1,155 @@
+/// @file CANMessage.h 
+/// CANMessage is the primitive CAN message object. It supports creation,
+/// parsing, formatting, of messages.
+///
+/// @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
+///
+
+#ifndef CANMESSAGE_H
+#define CANMESSAGE_H
+#include "mbed.h"
+
+/// CAN direction, in the set {rcv, xmt}
+typedef enum {
+    rcv,
+    xmt
+} CANDIR_T;
+
+
+/// CAN Channel in the set {CH1, CH2} of CANCHANNELS
+typedef enum {
+    CH1,
+    CH2,
+    CANCHANNELS
+} CANCHANNEL_T;
+
+
+// CAN mode - active(acknowledge) or passive(monitor)
+//typedef enum {
+//    ACTIVE,
+//    PASSIVE
+//} CANMODE_T;
+
+
+/// A super CAN message object, which has additional capabilities
+///
+/// This object is derived from CANMessage, however it adds
+/// a timestamp and other useful methods.
+///
+class CANmsg : public CANMessage
+{
+public:
+    /// Constructor for a CANmsg object, which is a superclass of CANMessage
+    ///
+    /// The CANmsg object included additional information, including
+    /// direction, channel number, timestamp, and the ability to format
+    /// into ASCII
+    ///
+    CANmsg();
+    
+    /// Constructor for a CANmsg object, which is a superclass of CANMessage
+    ///
+    /// The CANmsg object included additional information, including
+    /// direction, channel number, timestamp, and the ability to format
+    /// into ASCII.
+    /// @param ch is the channel number (CH1, CH2)
+    /// @param dir is the direction (xmt, rcv)
+    /// @param msg is a CANMessage object from which to construct this object
+    ///
+    CANmsg(CANCHANNEL_T ch, CANDIR_T dir, CANMessage msg);
+    
+    /// Constructor for a CANmsg object, which is a superclass of CANMessage
+    /// 
+    /// The CANmsg object included additional information, including
+    /// direction, channel number, timestamp, and the ability to format
+    /// into ASCII.
+    /// This constructor creates a message from an ascii buffer with
+    /// the standard message format in it.
+    ///
+    /// @todo Improve the parser, it may not handle malformed input well
+    ///
+    /// @verbatim
+    /// t xtd 02 1CF00400 08 11 22 33 44 55 66 77 88 0   0 1234.567890
+    /// If the first letter is not 't' or 'r', transmit is assumed
+    ///   xtd 02 1CF00400 08 11 22 33 44 55 66 77 88 0   0 1234.567890
+    /// @endverbatim
+    ///
+    /// @param p is a pointer to a text string of the message contents,
+    ///        in the same format as what would be output with the 
+    ///        FormatCANMessage method.
+    ///
+    CANmsg(char *p);
+        
+    /// Destructor for the CANmsg object
+    ~CANmsg();
+    
+    /// Parse a text string into the CANmsg object, which is a superclass of CANMessage
+    ///
+    /// The CANmsg object included additional information, including
+    /// direction, channel number, timestamp, and the ability to format
+    /// into ASCII.
+    /// This constructor creates a message from an ascii buffer with
+    /// the standard message format in it.
+    ///
+    /// @todo Improve the parser, it may not handle malformed input well
+    ///
+    /// @verbatim
+    /// t xtd 02 1CF00400 08 11 22 33 44 55 66 77 88 0   0 1234.567890
+    /// If the first letter is not 't' or 'r', transmit is assumed
+    ///   xtd 02 1CF00400 08 11 22 33 44 55 66 77 88 0   0 1234.567890
+    /// @endverbatim
+    ///
+    /// @param p is a pointer to a text string of the message contents,
+    ///        in the same format as what would be output with the 
+    ///        FormatCANMessage method.
+    /// @returns true
+    ///
+    bool ParseCANMessage(char *p);
+
+    /// Formats this CAN message into a text buffer - which should be at least 70
+    ///
+    /// @todo buflen is currently ignored, which is unsafe
+    ///
+    /// @verbatim
+    /// t xtd 02 1CF00400 08 11 22 33 44 55 66 77 88 0   0 1234.567890
+    /// @endverbatim
+    ///
+    /// @param buffer is a pointer to the buffer to fill
+    /// @param buflen is the size of the buffer (minimum 70 recommended)
+    /// 
+    /// @returns nothing
+    void FormatCANMessage(char *buffer, int buflen);
+    
+    /// Overrides the timestamp in this message with the current time
+    void SetTimestamp();
+    
+    /// Gets the timestamp of this message
+    /// @returns time in microseconds
+    uint64_t GetTimestamp() { return timestamp; };
+    
+    /// direction of this CAN message - rcv or xmt
+    CANDIR_T dir;
+
+    /// channel number of this CAN message
+    CANCHANNEL_T ch;
+
+private:
+    /// internally held timestamp
+    uint64_t timestamp;
+    
+    // internally held mode
+    //CANMODE_T mode;
+};
+
+#endif // CANMESSAGE_H
\ No newline at end of file