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@3:c2a26d9d689b, 2019-09-20 (annotated)
- Committer:
- WiredHome
- Date:
- Fri Sep 20 21:56:43 2019 +0000
- Revision:
- 3:c2a26d9d689b
- Parent:
- 2:4307b498b508
- Child:
- 4:4ba6856f7b4f
Clean up CANMessage implementation.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
WiredHome | 0:f0ce97992c5f | 1 | /// @file CANMessage.h |
WiredHome | 0:f0ce97992c5f | 2 | /// This is the basic CAN message, and supports construction of, formatting and decoding. |
WiredHome | 0:f0ce97992c5f | 3 | /// |
WiredHome | 0:f0ce97992c5f | 4 | /// @version 1.0 |
WiredHome | 0:f0ce97992c5f | 5 | /// |
WiredHome | 0:f0ce97992c5f | 6 | /// @note Copyright &copr; 2011 by Smartware Computing, all rights reserved. |
WiredHome | 0:f0ce97992c5f | 7 | /// Individuals may use this application for evaluation or non-commercial |
WiredHome | 0:f0ce97992c5f | 8 | /// purposes. Within this restriction, changes may be made to this application |
WiredHome | 0:f0ce97992c5f | 9 | /// as long as this copyright notice is retained. The user shall make |
WiredHome | 0:f0ce97992c5f | 10 | /// clear that their work is a derived work, and not the original. |
WiredHome | 0:f0ce97992c5f | 11 | /// Users of this application and sources accept this application "as is" and |
WiredHome | 0:f0ce97992c5f | 12 | /// shall hold harmless Smartware Computing, for any undesired results while |
WiredHome | 0:f0ce97992c5f | 13 | /// using this application - whether real or imagined. |
WiredHome | 0:f0ce97992c5f | 14 | /// |
WiredHome | 0:f0ce97992c5f | 15 | /// @author David Smart, Smartware Computing |
WiredHome | 0:f0ce97992c5f | 16 | /// |
WiredHome | 0:f0ce97992c5f | 17 | /// @note |
WiredHome | 0:f0ce97992c5f | 18 | /// Version History |
WiredHome | 0:f0ce97992c5f | 19 | /// 20110724 |
WiredHome | 0:f0ce97992c5f | 20 | /// \li Extending timestamp to 64 bits |
WiredHome | 0:f0ce97992c5f | 21 | /// |
WiredHome | 0:f0ce97992c5f | 22 | #include <mbed.h> |
WiredHome | 1:c56577ae52df | 23 | |
WiredHome | 0:f0ce97992c5f | 24 | #include "CANMessage.h" |
WiredHome | 1:c56577ae52df | 25 | #include "Utilities.h" // missing functions... |
WiredHome | 1:c56577ae52df | 26 | |
WiredHome | 1:c56577ae52df | 27 | static Timer timer; |
WiredHome | 1:c56577ae52df | 28 | static bool timer_on; |
WiredHome | 0:f0ce97992c5f | 29 | |
WiredHome | 1:c56577ae52df | 30 | static char mytolower(char a) { |
WiredHome | 1:c56577ae52df | 31 | if (a >= 'A' && a <= 'Z') |
WiredHome | 1:c56577ae52df | 32 | return (a - 'A' + 'a'); |
WiredHome | 1:c56577ae52df | 33 | else |
WiredHome | 1:c56577ae52df | 34 | return a; |
WiredHome | 1:c56577ae52df | 35 | } |
WiredHome | 1:c56577ae52df | 36 | |
WiredHome | 1:c56577ae52df | 37 | static int mystrnicmp(const char *l, const char *r, size_t n) { |
WiredHome | 1:c56577ae52df | 38 | int result = 0; |
WiredHome | 0:f0ce97992c5f | 39 | |
WiredHome | 1:c56577ae52df | 40 | if (n != 0) { |
WiredHome | 1:c56577ae52df | 41 | do { |
WiredHome | 1:c56577ae52df | 42 | result = mytolower(*l++) - mytolower(*r++); |
WiredHome | 1:c56577ae52df | 43 | } while ((result == 0) && (*l != '\0') && (--n > 0)); |
WiredHome | 1:c56577ae52df | 44 | } |
WiredHome | 1:c56577ae52df | 45 | if (result < -1) |
WiredHome | 1:c56577ae52df | 46 | result = -1; |
WiredHome | 1:c56577ae52df | 47 | else if (result > 1) |
WiredHome | 1:c56577ae52df | 48 | result = 1; |
WiredHome | 1:c56577ae52df | 49 | return result; |
WiredHome | 1:c56577ae52df | 50 | } |
WiredHome | 0:f0ce97992c5f | 51 | |
WiredHome | 0:f0ce97992c5f | 52 | CANmsg::CANmsg() { |
WiredHome | 0:f0ce97992c5f | 53 | if (!timer_on) { |
WiredHome | 0:f0ce97992c5f | 54 | timer.start(); |
WiredHome | 0:f0ce97992c5f | 55 | timer_on = true; |
WiredHome | 0:f0ce97992c5f | 56 | } |
WiredHome | 2:4307b498b508 | 57 | timestamp = timer.read_high_resolution_us(); |
WiredHome | 0:f0ce97992c5f | 58 | } |
WiredHome | 0:f0ce97992c5f | 59 | |
WiredHome | 0:f0ce97992c5f | 60 | CANmsg::CANmsg(CANCHANNEL_T _ch, CANDIR_T _dir, CANMessage _msg) { |
WiredHome | 0:f0ce97992c5f | 61 | if (!timer_on) { |
WiredHome | 0:f0ce97992c5f | 62 | timer.start(); |
WiredHome | 0:f0ce97992c5f | 63 | timer_on = true; |
WiredHome | 0:f0ce97992c5f | 64 | } |
WiredHome | 2:4307b498b508 | 65 | timestamp = timer.read_high_resolution_us(); |
WiredHome | 0:f0ce97992c5f | 66 | ch = _ch; |
WiredHome | 0:f0ce97992c5f | 67 | dir = _dir; |
WiredHome | 0:f0ce97992c5f | 68 | id = _msg.id; |
WiredHome | 0:f0ce97992c5f | 69 | len = _msg.len; |
WiredHome | 0:f0ce97992c5f | 70 | for (int i=0; i<len; i++) |
WiredHome | 0:f0ce97992c5f | 71 | data[i] = _msg.data[i]; |
WiredHome | 0:f0ce97992c5f | 72 | format = _msg.format; |
WiredHome | 0:f0ce97992c5f | 73 | type = _msg.type; |
WiredHome | 0:f0ce97992c5f | 74 | } |
WiredHome | 0:f0ce97992c5f | 75 | |
WiredHome | 0:f0ce97992c5f | 76 | // 0 1 2 3 4 5---------------------| 6 7 8 |
WiredHome | 0:f0ce97992c5f | 77 | // t xtd 02 1CF00400 08 11 22 33 44 55 66 77 88 0 0 1234.567890 |
WiredHome | 0:f0ce97992c5f | 78 | // If the first letter is not 't'ransmit or 'r'eceive, transmit is |
WiredHome | 0:f0ce97992c5f | 79 | // assumed |
WiredHome | 0:f0ce97992c5f | 80 | // xtd 02 1CF00400 08 11 22 33 44 55 66 77 88 0 0 1234.567890 |
WiredHome | 0:f0ce97992c5f | 81 | CANmsg::CANmsg(char *p) { |
WiredHome | 0:f0ce97992c5f | 82 | if (!timer_on) { |
WiredHome | 0:f0ce97992c5f | 83 | timer.start(); |
WiredHome | 0:f0ce97992c5f | 84 | timer_on = true; |
WiredHome | 0:f0ce97992c5f | 85 | } |
WiredHome | 0:f0ce97992c5f | 86 | ParseCANMessage(p); |
WiredHome | 0:f0ce97992c5f | 87 | } |
WiredHome | 0:f0ce97992c5f | 88 | |
WiredHome | 0:f0ce97992c5f | 89 | CANmsg::~CANmsg() { |
WiredHome | 0:f0ce97992c5f | 90 | } |
WiredHome | 0:f0ce97992c5f | 91 | |
WiredHome | 0:f0ce97992c5f | 92 | bool CANmsg::ParseCANMessage(char *p) { |
WiredHome | 0:f0ce97992c5f | 93 | //int state = 0; |
WiredHome | 0:f0ce97992c5f | 94 | //printf("\r\nParseCANMessage(%s)\r\n",p); |
WiredHome | 0:f0ce97992c5f | 95 | char *token; |
WiredHome | 0:f0ce97992c5f | 96 | char *search = " ,\t"; // any of these is a separator |
WiredHome | 0:f0ce97992c5f | 97 | token = strtok(p, search); // might now point to 't'|'r', or 'xtd'|'nrm' |
WiredHome | 0:f0ce97992c5f | 98 | if (*token == 'r') |
WiredHome | 0:f0ce97992c5f | 99 | dir = rcv; |
WiredHome | 0:f0ce97992c5f | 100 | else |
WiredHome | 0:f0ce97992c5f | 101 | dir = xmt; |
WiredHome | 0:f0ce97992c5f | 102 | if (*token == 't' || *token == 'r') // transmit or receive |
WiredHome | 0:f0ce97992c5f | 103 | token = strtok(NULL, search); // advance past 't'|'r' |
WiredHome | 0:f0ce97992c5f | 104 | if (mystrnicmp(token,"xtd",3) == 0) |
WiredHome | 0:f0ce97992c5f | 105 | format = CANExtended; |
WiredHome | 0:f0ce97992c5f | 106 | else if (mystrnicmp(token, "nrm", 3) == 0) |
WiredHome | 0:f0ce97992c5f | 107 | format = CANStandard; |
WiredHome | 0:f0ce97992c5f | 108 | token = strtok(NULL, search); |
WiredHome | 0:f0ce97992c5f | 109 | ch = (CANCHANNEL_T)(atoi(token) - 1); |
WiredHome | 0:f0ce97992c5f | 110 | token = strtok(NULL, search); |
WiredHome | 0:f0ce97992c5f | 111 | id = hextoul(token); |
WiredHome | 0:f0ce97992c5f | 112 | token = strtok(NULL, search); |
WiredHome | 0:f0ce97992c5f | 113 | len = hextoul(token); |
WiredHome | 0:f0ce97992c5f | 114 | for (int i=0; i<len; i++) { |
WiredHome | 0:f0ce97992c5f | 115 | token = strtok(NULL, search); |
WiredHome | 0:f0ce97992c5f | 116 | data[i] = (char)hextoul(token); |
WiredHome | 0:f0ce97992c5f | 117 | } |
WiredHome | 0:f0ce97992c5f | 118 | token = strtok(NULL, search); |
WiredHome | 0:f0ce97992c5f | 119 | // fixedZero = atoi(token) |
WiredHome | 0:f0ce97992c5f | 120 | token = strtok(NULL, search); |
WiredHome | 0:f0ce97992c5f | 121 | // lostMessages = atoi(token); |
WiredHome | 0:f0ce97992c5f | 122 | token = strtok(NULL, search); |
WiredHome | 2:4307b498b508 | 123 | timestamp = timer.read_high_resolution_us(); // set it to "now" |
WiredHome | 0:f0ce97992c5f | 124 | if (token) |
WiredHome | 0:f0ce97992c5f | 125 | timestamp = (uint32_t)(1000000 * atof(token)); |
WiredHome | 0:f0ce97992c5f | 126 | return true; |
WiredHome | 0:f0ce97992c5f | 127 | } |
WiredHome | 0:f0ce97992c5f | 128 | |
WiredHome | 0:f0ce97992c5f | 129 | void CANmsg::SetTimestamp() { |
WiredHome | 2:4307b498b508 | 130 | timestamp = (uint32_t)timer.read_high_resolution_us(); |
WiredHome | 0:f0ce97992c5f | 131 | } |
WiredHome | 0:f0ce97992c5f | 132 | |
WiredHome | 0:f0ce97992c5f | 133 | // 12345678901234567890123456789012345678901234567890123456789012345 |
WiredHome | 1:c56577ae52df | 134 | // r xtd 01 1CF00400 08 11 22 33 44 55 66 77 88 0 0 12.123456 |
WiredHome | 0:f0ce97992c5f | 135 | void CANmsg::FormatCANMessage(char *buffer, int buflen) { |
WiredHome | 0:f0ce97992c5f | 136 | if (buflen >= 68) { // 63+\r+\n+\0+2spare |
WiredHome | 3:c2a26d9d689b | 137 | if (format >= 128) { |
WiredHome | 3:c2a26d9d689b | 138 | sprintf(buffer, "%c %s %02d %8s %02X ", |
WiredHome | 3:c2a26d9d689b | 139 | (dir == xmt ) ? 't' : 'r', |
WiredHome | 3:c2a26d9d689b | 140 | "ERR", |
WiredHome | 3:c2a26d9d689b | 141 | ch + 1, |
WiredHome | 3:c2a26d9d689b | 142 | (format == 128) ? "active" : "passive", |
WiredHome | 3:c2a26d9d689b | 143 | 8); |
WiredHome | 3:c2a26d9d689b | 144 | for (int d=0; d<8; d++) { |
WiredHome | 3:c2a26d9d689b | 145 | sprintf(buffer + strlen(buffer), "%02X ", 0); |
WiredHome | 3:c2a26d9d689b | 146 | } |
WiredHome | 3:c2a26d9d689b | 147 | } else { |
WiredHome | 3:c2a26d9d689b | 148 | sprintf(buffer, "%c %s %02d %08X %02X ", |
WiredHome | 3:c2a26d9d689b | 149 | (dir == xmt ) ? 't' : 'r', |
WiredHome | 3:c2a26d9d689b | 150 | (format == CANExtended) ? "xtd" : "nrm", |
WiredHome | 3:c2a26d9d689b | 151 | ch + 1, |
WiredHome | 3:c2a26d9d689b | 152 | id, |
WiredHome | 3:c2a26d9d689b | 153 | len); |
WiredHome | 3:c2a26d9d689b | 154 | for (int d=0; d<8; d++) { |
WiredHome | 3:c2a26d9d689b | 155 | if (d < len) |
WiredHome | 3:c2a26d9d689b | 156 | sprintf(buffer + strlen(buffer), "%02X ", data[d]); |
WiredHome | 3:c2a26d9d689b | 157 | else |
WiredHome | 3:c2a26d9d689b | 158 | strcat(buffer, " "); |
WiredHome | 3:c2a26d9d689b | 159 | } |
WiredHome | 0:f0ce97992c5f | 160 | } |
WiredHome | 0:f0ce97992c5f | 161 | uint32_t uSec = timestamp % 1000000; // integer math is faster than float |
WiredHome | 0:f0ce97992c5f | 162 | uint32_t Sec = timestamp / 1000000; |
WiredHome | 1:c56577ae52df | 163 | sprintf(buffer + strlen(buffer), "0 0 %6u.%06u", Sec, uSec); |
WiredHome | 0:f0ce97992c5f | 164 | } else { |
WiredHome | 0:f0ce97992c5f | 165 | strcpy(buffer,"ERROR, buf too small"); |
WiredHome | 0:f0ce97992c5f | 166 | } |
WiredHome | 0:f0ce97992c5f | 167 | } |