CANMessage is the primitive CAN message object. It supports creation, parsing, formatting of messages. Can be easily integrated with CANPort and CANQueue libraries.
Revision 0:f0ce97992c5f, committed 2012-07-15
- 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