A simple CAN adapter that supports two channels of CAN on the mbed. Configurable speed, monitor mode, statistics and send/receive via the USB serial port to a PC (or terminal program set for 921.6 kbaud)

Dependencies:   CommandProcessor Watchdog mbed

Committer:
WiredHome
Date:
Mon Apr 11 11:32:05 2011 +0000
Revision:
0:ea85c59ec672
Child:
1:6b831d0c058c

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
WiredHome 0:ea85c59ec672 1 /// CANadapter is a simple program that permits monitoring as well as transmitting
WiredHome 0:ea85c59ec672 2 /// on both CAN buses that the mbed supports. It communicates to either the user or
WiredHome 0:ea85c59ec672 3 /// a PC hosted program via the USB Serial port.
WiredHome 0:ea85c59ec672 4 ///
WiredHome 0:ea85c59ec672 5 /// For robustness, there is a small CommandProcessor, which permits setting
WiredHome 0:ea85c59ec672 6 /// CAN interface metrics, reviewing statistics, and sending messages.
WiredHome 0:ea85c59ec672 7 ///
WiredHome 0:ea85c59ec672 8 /// There is also a watchdog, which will keep the system running and recover
WiredHome 0:ea85c59ec672 9 /// if there was a problem.
WiredHome 0:ea85c59ec672 10 ///
WiredHome 0:ea85c59ec672 11 /// @note Copyright &copr; 2011 by Smartware Computing, all rights reserved.
WiredHome 0:ea85c59ec672 12 /// Individuals may use this application for evaluation or non-commercial
WiredHome 0:ea85c59ec672 13 /// purposes. Within this restriction, changes may be made to this application
WiredHome 0:ea85c59ec672 14 /// as long as this copyright notice is retained. The user shall make
WiredHome 0:ea85c59ec672 15 /// clear that their work is a derived work, and not the original.
WiredHome 0:ea85c59ec672 16 /// Users of this application and sources accept this application "as is" and
WiredHome 0:ea85c59ec672 17 /// shall hold harmless Smartware Computing, for any undesired results while
WiredHome 0:ea85c59ec672 18 /// using this application - whether real or imagined.
WiredHome 0:ea85c59ec672 19 /// @author David Smart, Smartware Computing
WiredHome 0:ea85c59ec672 20 ///
WiredHome 0:ea85c59ec672 21 #include "mbed.h"
WiredHome 0:ea85c59ec672 22 #include "Watchdog.h"
WiredHome 0:ea85c59ec672 23 #include "CommandProcessor.h"
WiredHome 0:ea85c59ec672 24 #include "CANUtilities.h"
WiredHome 0:ea85c59ec672 25 #include "CANQueue.h"
WiredHome 0:ea85c59ec672 26 #include "vs_string.h" // helpers that normalize between compilers for string functions
WiredHome 0:ea85c59ec672 27
WiredHome 0:ea85c59ec672 28 extern "C" void mbed_reset();
WiredHome 0:ea85c59ec672 29
WiredHome 0:ea85c59ec672 30 Serial pc(USBTX, USBRX); ///!< Used as the console for interactively reporting progress
WiredHome 0:ea85c59ec672 31 DigitalOut myled(LED4); /// LED sign of life
WiredHome 0:ea85c59ec672 32
WiredHome 0:ea85c59ec672 33 Watchdog wd;
WiredHome 0:ea85c59ec672 34
WiredHome 0:ea85c59ec672 35 //Ticker ticker; // for automated sending of messages during development
WiredHome 0:ea85c59ec672 36
WiredHome 0:ea85c59ec672 37 //Timer timestamp;
WiredHome 0:ea85c59ec672 38 CAN can1(p9, p10); // bind CAN1 to the hardware
WiredHome 0:ea85c59ec672 39 CAN can2(p30, p29); // bind CAN2 to the hardware
WiredHome 0:ea85c59ec672 40 Timeout t1; // create a timeout mechanism for can1
WiredHome 0:ea85c59ec672 41 Timeout t2; // create a timeout mechanism for can2
WiredHome 0:ea85c59ec672 42 void c1off(); // extinquish the can1 activity indicator
WiredHome 0:ea85c59ec672 43 void c2off(); // extinquish the can2 activity indicator
WiredHome 0:ea85c59ec672 44
WiredHome 0:ea85c59ec672 45 struct {
WiredHome 0:ea85c59ec672 46 CAN *can;
WiredHome 0:ea85c59ec672 47 Timeout *flash;
WiredHome 0:ea85c59ec672 48 DigitalOut led;
WiredHome 0:ea85c59ec672 49 void (*off)(void);
WiredHome 0:ea85c59ec672 50 bool active;
WiredHome 0:ea85c59ec672 51 int bitrate;
WiredHome 0:ea85c59ec672 52 uint32_t txCounter;
WiredHome 0:ea85c59ec672 53 uint32_t rxCounter;
WiredHome 0:ea85c59ec672 54 } can[] = {
WiredHome 0:ea85c59ec672 55 {&can1, &t1, LED1, c1off, false, 250000, 0, 0},
WiredHome 0:ea85c59ec672 56 {&can2, &t2, LED2, c2off, false, 250000, 0, 0}
WiredHome 0:ea85c59ec672 57 };
WiredHome 0:ea85c59ec672 58
WiredHome 0:ea85c59ec672 59 CANQueue inQueue(10);
WiredHome 0:ea85c59ec672 60
WiredHome 0:ea85c59ec672 61 bool CANTransmitMsg(CANmsg msg);
WiredHome 0:ea85c59ec672 62
WiredHome 0:ea85c59ec672 63 RUNRESULT_T CANconfig(char *p);
WiredHome 0:ea85c59ec672 64 const CMD_T CANconfigCmd = {"CANconfig", "Configure [channel mode speed], ? for more", CANconfig, visible};
WiredHome 0:ea85c59ec672 65 RUNRESULT_T CANmessage(char *p);
WiredHome 0:ea85c59ec672 66 const CMD_T CANmessageCmd = {"CANmessage", "Shows the CAN message format", CANmessage, visible};
WiredHome 0:ea85c59ec672 67 RUNRESULT_T CANtransmit(char *p);
WiredHome 0:ea85c59ec672 68 const CMD_T CANtransmitCmd = {"t", "transmit a CAN message (see CANmessage format)", CANtransmit, visible};
WiredHome 0:ea85c59ec672 69 RUNRESULT_T CANstatistics(char *p);
WiredHome 0:ea85c59ec672 70 const CMD_T CANstatisticsCmd = {"CANstats", "Shows the CAN statistics", CANstatistics, visible};
WiredHome 0:ea85c59ec672 71 RUNRESULT_T CANreset(char *p);
WiredHome 0:ea85c59ec672 72 const CMD_T CANresetCmd = {"CANreset", "Reset CAN channel [0|1|*]", CANreset, visible};
WiredHome 0:ea85c59ec672 73 RUNRESULT_T Free(char *p);
WiredHome 0:ea85c59ec672 74 const CMD_T FreeCmd = {"Free", "Shows the free memory in bytes", Free, visible};
WiredHome 0:ea85c59ec672 75 RUNRESULT_T Reboot(char *p);
WiredHome 0:ea85c59ec672 76 const CMD_T RebootCmd = {"Reboot", "Causes a near immediate reboot", Reboot, visible};
WiredHome 0:ea85c59ec672 77
WiredHome 0:ea85c59ec672 78 RUNRESULT_T Reboot(char *p) {
WiredHome 0:ea85c59ec672 79 (void)p;
WiredHome 0:ea85c59ec672 80 pc.printf(" now...\r\n");
WiredHome 0:ea85c59ec672 81 wait(0.5);
WiredHome 0:ea85c59ec672 82 mbed_reset();
WiredHome 0:ea85c59ec672 83 return runok;
WiredHome 0:ea85c59ec672 84 }
WiredHome 0:ea85c59ec672 85
WiredHome 0:ea85c59ec672 86 RUNRESULT_T Free(char *p) {
WiredHome 0:ea85c59ec672 87 (void)p;
WiredHome 0:ea85c59ec672 88 uint32_t max = 100000;
WiredHome 0:ea85c59ec672 89 uint32_t x = max / 2;
WiredHome 0:ea85c59ec672 90 uint32_t min = 0;
WiredHome 0:ea85c59ec672 91
WiredHome 0:ea85c59ec672 92 while (min < max-1) {
WiredHome 0:ea85c59ec672 93 void * p = malloc(x);
WiredHome 0:ea85c59ec672 94 if (p) {
WiredHome 0:ea85c59ec672 95 free(p);
WiredHome 0:ea85c59ec672 96 min = x;
WiredHome 0:ea85c59ec672 97 } else {
WiredHome 0:ea85c59ec672 98 max = x;
WiredHome 0:ea85c59ec672 99 }
WiredHome 0:ea85c59ec672 100 x = (max + min)/2;
WiredHome 0:ea85c59ec672 101 }
WiredHome 0:ea85c59ec672 102 pc.printf("\r\n%u bytes free\r\n", x);
WiredHome 0:ea85c59ec672 103 return runok;
WiredHome 0:ea85c59ec672 104 }
WiredHome 0:ea85c59ec672 105
WiredHome 0:ea85c59ec672 106
WiredHome 0:ea85c59ec672 107 RUNRESULT_T CANconfig(char *p) {
WiredHome 0:ea85c59ec672 108 int ch, mode, bitrate;
WiredHome 0:ea85c59ec672 109 char *token;
WiredHome 0:ea85c59ec672 110 char *search = " ,\t";
WiredHome 0:ea85c59ec672 111
WiredHome 0:ea85c59ec672 112 token = strtok(p, search);
WiredHome 0:ea85c59ec672 113 ch = atoi(token);
WiredHome 0:ea85c59ec672 114 token = strtok(NULL, search);
WiredHome 0:ea85c59ec672 115 if (mystrnicmp(token, "monitor", 7) == 0)
WiredHome 0:ea85c59ec672 116 mode = 0;
WiredHome 0:ea85c59ec672 117 else if (mystrnicmp(token, "0", 1) == 0)
WiredHome 0:ea85c59ec672 118 mode = 0;
WiredHome 0:ea85c59ec672 119 else if (mystrnicmp(token, "active", 7) == 0)
WiredHome 0:ea85c59ec672 120 mode = 1;
WiredHome 0:ea85c59ec672 121 else if (mystrnicmp(token, "1", 1) == 0)
WiredHome 0:ea85c59ec672 122 mode = 1;
WiredHome 0:ea85c59ec672 123 else
WiredHome 0:ea85c59ec672 124 mode = -1;
WiredHome 0:ea85c59ec672 125 token = strtok(NULL, search);
WiredHome 0:ea85c59ec672 126 bitrate = atoi(token);
WiredHome 0:ea85c59ec672 127
WiredHome 0:ea85c59ec672 128 if (ch >=1 && ch <= 2 && mode != -1 && bitrate > 1000 && bitrate <= 1000000) {
WiredHome 0:ea85c59ec672 129 can[ch-1].can->monitor(mode);
WiredHome 0:ea85c59ec672 130 can[ch-1].can->frequency(bitrate);
WiredHome 0:ea85c59ec672 131 pc.printf("\r\n");
WiredHome 0:ea85c59ec672 132 } else {
WiredHome 0:ea85c59ec672 133 pc.printf("\r\n CANconfig [channel mode bits/sec]\r\n"
WiredHome 0:ea85c59ec672 134 " channel = 1 or 2\r\n"
WiredHome 0:ea85c59ec672 135 " mode = 0|monitor|1|active\r\n"
WiredHome 0:ea85c59ec672 136 " speed = baud rate (e.g. 10000, 250000, 500000, etc.)\r\n"
WiredHome 0:ea85c59ec672 137 "");
WiredHome 0:ea85c59ec672 138 }
WiredHome 0:ea85c59ec672 139 return runok;
WiredHome 0:ea85c59ec672 140 }
WiredHome 0:ea85c59ec672 141
WiredHome 0:ea85c59ec672 142 RUNRESULT_T CANreset(char *p) {
WiredHome 0:ea85c59ec672 143 if (*p == '1' || *p == '*')
WiredHome 0:ea85c59ec672 144 can[CH1].can->reset();
WiredHome 0:ea85c59ec672 145 if (*p == '2' || *p == '*')
WiredHome 0:ea85c59ec672 146 can[CH2].can->reset();
WiredHome 0:ea85c59ec672 147 pc.printf("\r\n");
WiredHome 0:ea85c59ec672 148 return runok;
WiredHome 0:ea85c59ec672 149 }
WiredHome 0:ea85c59ec672 150
WiredHome 0:ea85c59ec672 151
WiredHome 0:ea85c59ec672 152 RUNRESULT_T CANmessage(char *p) {
WiredHome 0:ea85c59ec672 153 pc.printf( "\r\n// CAN Message Format\r\n"
WiredHome 0:ea85c59ec672 154 "//\r\n"
WiredHome 0:ea85c59ec672 155 "// +--- 'r'eceive or 't'ransmit\r\n"
WiredHome 0:ea85c59ec672 156 "// | +--- 'nrm' 11 bit identifier, 'xtd' 29 bit identifier\r\n"
WiredHome 0:ea85c59ec672 157 "// | | +--- channel '1' to '2'\r\n"
WiredHome 0:ea85c59ec672 158 "// | | | +--- identifier in hex\r\n"
WiredHome 0:ea85c59ec672 159 "// | | | | +--- dlc is data length control from 0 to 8\r\n"
WiredHome 0:ea85c59ec672 160 "// | | | | | +--- data bytes 1 to 8\r\n"
WiredHome 0:ea85c59ec672 161 "// | | | | | | [Below not required to send\r\n"
WiredHome 0:ea85c59ec672 162 "// | | | | | | +--- fixed zero\r\n"
WiredHome 0:ea85c59ec672 163 "// | | | | | | | +--- err count\r\n"
WiredHome 0:ea85c59ec672 164 "// | | | | | | | | +--- timestamp\r\n"
WiredHome 0:ea85c59ec672 165 "// | | | | | | | | |\r\n"
WiredHome 0:ea85c59ec672 166 "// _ ___ __ ________ __ _______________________ _ ___ ___________\r\n"
WiredHome 0:ea85c59ec672 167 "// r xtd 02 1CF00400 08 11 22 33 44 55 66 77 88 0 0 1234.567890\r\n"
WiredHome 0:ea85c59ec672 168 "// t xtd 01 18EAFF03 03 EE EE 00 0 0 1235.654321\r\n"
WiredHome 0:ea85c59ec672 169 "// 12345678901234567890123456789012345678901234567890123456789012\r\n");
WiredHome 0:ea85c59ec672 170 return runok;
WiredHome 0:ea85c59ec672 171 }
WiredHome 0:ea85c59ec672 172
WiredHome 0:ea85c59ec672 173 RUNRESULT_T CANtransmit(char *p) {
WiredHome 0:ea85c59ec672 174 if (*p) {
WiredHome 0:ea85c59ec672 175 CANmsg msg(p);
WiredHome 0:ea85c59ec672 176 if (msg.dir == xmt)
WiredHome 0:ea85c59ec672 177 CANTransmitMsg(msg);
WiredHome 0:ea85c59ec672 178 pc.printf("\r\n");
WiredHome 0:ea85c59ec672 179 } else {
WiredHome 0:ea85c59ec672 180 pc.printf( "\r\n't'ransmit a CAN message in the message format\r\n");
WiredHome 0:ea85c59ec672 181 }
WiredHome 0:ea85c59ec672 182 return runok;
WiredHome 0:ea85c59ec672 183 }
WiredHome 0:ea85c59ec672 184
WiredHome 0:ea85c59ec672 185 RUNRESULT_T CANstatistics(char *p) {
WiredHome 0:ea85c59ec672 186 pc.printf("\r\n ch mode bitrate rxCount rxErrors txCount txErrors\r\n");
WiredHome 0:ea85c59ec672 187 for (int i=0; i<CANCHANNELS; i++)
WiredHome 0:ea85c59ec672 188 pc.printf(" %2u %7s %8u %7u %8u %7u %8u\r\n",
WiredHome 0:ea85c59ec672 189 i+1,
WiredHome 0:ea85c59ec672 190 can[i].active ? "active" : "monitor",
WiredHome 0:ea85c59ec672 191 can[i].bitrate,
WiredHome 0:ea85c59ec672 192 can[i].rxCounter,
WiredHome 0:ea85c59ec672 193 can[i].can->rderror(),
WiredHome 0:ea85c59ec672 194 can[i].txCounter,
WiredHome 0:ea85c59ec672 195 can[i].can->tderror()
WiredHome 0:ea85c59ec672 196 );
WiredHome 0:ea85c59ec672 197 return runok;
WiredHome 0:ea85c59ec672 198 }
WiredHome 0:ea85c59ec672 199
WiredHome 0:ea85c59ec672 200
WiredHome 0:ea85c59ec672 201
WiredHome 0:ea85c59ec672 202
WiredHome 0:ea85c59ec672 203 int mReadable() {
WiredHome 0:ea85c59ec672 204 return pc.readable();
WiredHome 0:ea85c59ec672 205 }
WiredHome 0:ea85c59ec672 206 int mGetCh() {
WiredHome 0:ea85c59ec672 207 return pc.getc();
WiredHome 0:ea85c59ec672 208 }
WiredHome 0:ea85c59ec672 209 int mPutCh(int a) {
WiredHome 0:ea85c59ec672 210 return pc.putc(a);
WiredHome 0:ea85c59ec672 211 }
WiredHome 0:ea85c59ec672 212 int mPutS(const char * s) {
WiredHome 0:ea85c59ec672 213 return pc.printf("%s\r\n", s);
WiredHome 0:ea85c59ec672 214 }
WiredHome 0:ea85c59ec672 215
WiredHome 0:ea85c59ec672 216 void c1off() {
WiredHome 0:ea85c59ec672 217 can[CH1].led = false;
WiredHome 0:ea85c59ec672 218 }
WiredHome 0:ea85c59ec672 219 void c2off() {
WiredHome 0:ea85c59ec672 220 can[CH2].led = false;
WiredHome 0:ea85c59ec672 221 }
WiredHome 0:ea85c59ec672 222
WiredHome 0:ea85c59ec672 223 void canreceive(CANCHANNEL_T ch) {
WiredHome 0:ea85c59ec672 224 CANMessage msg;
WiredHome 0:ea85c59ec672 225
WiredHome 0:ea85c59ec672 226 if (can[ch].can->read(msg)) {
WiredHome 0:ea85c59ec672 227 CANmsg _msg(ch, rcv, msg);
WiredHome 0:ea85c59ec672 228
WiredHome 0:ea85c59ec672 229 inQueue.Enqueue(_msg);
WiredHome 0:ea85c59ec672 230 can[ch].rxCounter++;
WiredHome 0:ea85c59ec672 231 can[ch].led = true;
WiredHome 0:ea85c59ec672 232 can[ch].flash->attach(can[ch].off, 0.02);
WiredHome 0:ea85c59ec672 233 }
WiredHome 0:ea85c59ec672 234 }
WiredHome 0:ea85c59ec672 235
WiredHome 0:ea85c59ec672 236
WiredHome 0:ea85c59ec672 237 void can1rcv() {
WiredHome 0:ea85c59ec672 238 canreceive(CH1);
WiredHome 0:ea85c59ec672 239 }
WiredHome 0:ea85c59ec672 240 void can2rcv() {
WiredHome 0:ea85c59ec672 241 canreceive(CH2);
WiredHome 0:ea85c59ec672 242 }
WiredHome 0:ea85c59ec672 243
WiredHome 0:ea85c59ec672 244 bool CANTransmitMsg(CANmsg msg) {
WiredHome 0:ea85c59ec672 245 if (msg.dir == xmt) {
WiredHome 0:ea85c59ec672 246 if (can[msg.ch].can->write(CANMessage(msg.id, (char *)&msg.data, msg.len, CANData, msg.format)))
WiredHome 0:ea85c59ec672 247 return true;
WiredHome 0:ea85c59ec672 248 }
WiredHome 0:ea85c59ec672 249 return false;
WiredHome 0:ea85c59ec672 250 }
WiredHome 0:ea85c59ec672 251
WiredHome 0:ea85c59ec672 252 void cantransmit(int ch) {
WiredHome 0:ea85c59ec672 253 char byte = (char)can[ch].txCounter;
WiredHome 0:ea85c59ec672 254
WiredHome 0:ea85c59ec672 255 if (can[ch].can->write(CANMessage(1337, &byte, 1))) {
WiredHome 0:ea85c59ec672 256 can[ch].txCounter++;
WiredHome 0:ea85c59ec672 257 }
WiredHome 0:ea85c59ec672 258 }
WiredHome 0:ea85c59ec672 259
WiredHome 0:ea85c59ec672 260 void can1send() {
WiredHome 0:ea85c59ec672 261 cantransmit(1);
WiredHome 0:ea85c59ec672 262 }
WiredHome 0:ea85c59ec672 263 void can2send() {
WiredHome 0:ea85c59ec672 264 cantransmit(2);
WiredHome 0:ea85c59ec672 265 }
WiredHome 0:ea85c59ec672 266
WiredHome 0:ea85c59ec672 267
WiredHome 0:ea85c59ec672 268
WiredHome 0:ea85c59ec672 269 int main(int argc, char* argv[]) {
WiredHome 0:ea85c59ec672 270 CMDP_T * cp = GetCommandProcessor();
WiredHome 0:ea85c59ec672 271 RUNRESULT_T cp_state;
WiredHome 0:ea85c59ec672 272
WiredHome 0:ea85c59ec672 273 pc.baud(921600);
WiredHome 0:ea85c59ec672 274 if (wd.WatchdogCausedReset())
WiredHome 0:ea85c59ec672 275 pc.printf("Watchdog caused reset. WD is now rearmed\r\n");
WiredHome 0:ea85c59ec672 276 wd.Configure(2.0); // sets the timeout interval pretty short
WiredHome 0:ea85c59ec672 277
WiredHome 0:ea85c59ec672 278 // Set up the Command Processor interface
WiredHome 0:ea85c59ec672 279 cp->Init(
WiredHome 0:ea85c59ec672 280 0xFFFF, // Everything is enabled
WiredHome 0:ea85c59ec672 281 TRUE, // Case Insensitive
WiredHome 0:ea85c59ec672 282 TRUE, // Echo on
WiredHome 0:ea85c59ec672 283 50, // Command Buffer length
WiredHome 0:ea85c59ec672 284 mReadable, // User provided API (kbhit())
WiredHome 0:ea85c59ec672 285 mGetCh, // User provided API
WiredHome 0:ea85c59ec672 286 mPutCh, // User provided API
WiredHome 0:ea85c59ec672 287 mPutS); // User provided API
WiredHome 0:ea85c59ec672 288 cp->Add(&CANconfigCmd);
WiredHome 0:ea85c59ec672 289 cp->Add(&CANmessageCmd);
WiredHome 0:ea85c59ec672 290 cp->Add(&CANtransmitCmd);
WiredHome 0:ea85c59ec672 291 cp->Add(&CANstatisticsCmd);
WiredHome 0:ea85c59ec672 292 cp->Add(&CANresetCmd);
WiredHome 0:ea85c59ec672 293 cp->Add(&FreeCmd);
WiredHome 0:ea85c59ec672 294 cp->Add(&RebootCmd);
WiredHome 0:ea85c59ec672 295
WiredHome 0:ea85c59ec672 296 can2.attach(can2rcv);
WiredHome 0:ea85c59ec672 297 can1.attach(can1rcv);
WiredHome 0:ea85c59ec672 298 can[CH1].can->monitor(false); // make them active on the network or tx errors result
WiredHome 0:ea85c59ec672 299 can[CH2].can->monitor(false);
WiredHome 0:ea85c59ec672 300
WiredHome 0:ea85c59ec672 301 // This just sends a message every now and again
WiredHome 0:ea85c59ec672 302 //ticker.attach(&can1send, 1);
WiredHome 0:ea85c59ec672 303
WiredHome 0:ea85c59ec672 304 // Do nothing to waste time in here...
WiredHome 0:ea85c59ec672 305 do {
WiredHome 0:ea85c59ec672 306 myled = !myled; // activity indicator
WiredHome 0:ea85c59ec672 307
WiredHome 0:ea85c59ec672 308 wd.Service(); // service the dog
WiredHome 0:ea85c59ec672 309 cp_state = cp->Run(); // user interactions on the console interface
WiredHome 0:ea85c59ec672 310
WiredHome 0:ea85c59ec672 311 while (inQueue.QueueCount()) { // If we handle messages badly, could watchdog in here
WiredHome 0:ea85c59ec672 312 CANmsg msg;
WiredHome 0:ea85c59ec672 313
WiredHome 0:ea85c59ec672 314 if (inQueue.Dequeue(&msg)) {
WiredHome 0:ea85c59ec672 315 char buf[100];
WiredHome 0:ea85c59ec672 316 msg.FormatCANMessage(buf, sizeof(buf));
WiredHome 0:ea85c59ec672 317 pc.printf("%s\r\n", buf);
WiredHome 0:ea85c59ec672 318 // To test, just enable the following, which tosses the ball back and forth
WiredHome 0:ea85c59ec672 319 //wait(0.2);
WiredHome 0:ea85c59ec672 320 //msg.dir = xmt; // What we received, we reflect back
WiredHome 0:ea85c59ec672 321 //CANTransmitMsg(msg);
WiredHome 0:ea85c59ec672 322 }
WiredHome 0:ea85c59ec672 323 }
WiredHome 0:ea85c59ec672 324 } while (cp_state == runok);
WiredHome 0:ea85c59ec672 325 cp->End();
WiredHome 0:ea85c59ec672 326 return 0;
WiredHome 0:ea85c59ec672 327 }
WiredHome 0:ea85c59ec672 328
WiredHome 0:ea85c59ec672 329