Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Ken_CAN_test.cpp
- Committer:
- kendunlop
- Date:
- 2022-07-11
- Revision:
- 13:e3a4abc461f4
- Parent:
- 12:e950feba910d
File content as of revision 13:e3a4abc461f4:
//This program was created by Ken 8th June 2022 to test the CAN output of a CAN Gateway. #define kMajorVersion 0 //Defines a major and minor version to be shown later in the program. #define kMinorVersion 5 #include "mbed.h" //Including mbed libraries. This should be all it needs to use the Mbed and CAN. #include <string> //This is needed to make text strings work #include <stdio.h> #include <ctype.h> //For 'is digit' condition #include <sstream> //This is used to convert an integer to hex #include <time.h> //To measure how long a process took? Includes clock_t and CLOCKS_PER_SEC RawSerial pc(USBTX, USBRX); // USB UART Terminal, tx, rx. Is needed for 'pc.printf' functions to work. // NOTE: Original pins for CAN Bus 1 are 9 and 10. CAN CanBus(p9, p10); //CANBus to use pins 9 and 10. This defines CanBus so other 'CanBus' lines will work. CAN CanBus2(p30, p29); //CANBus2 for recieving to use pins 30 and 29 (in that order!). CANMessage messageIn; //Define a CAN message to send CANMessage messageOut1; //Set messageOutText to a default message so it's defined. string messageOutText = ""; string messageOutTextWithSpaces = ""; string buttonPressMessageOutText = ""; string part = ""; int partincrement = 0; __int64 incrementer = 0; int CANCount = 0; int spamon = 0; int idspamon = 0; int idscheckedcount = 0; int spamcount = 0; int totalspamsever = 0; int spamstarttime = 0; int spamendtime = 0; int spamsecondstotal = 0; int spamspersecond = 0; int messagesinpersecond = 0; int vlistincrementer = 0; int idlistincrementer = 0; string spampreamble = "333"; int expected1 = 0; int expected2 = 0; unsigned char expected3 = 0; unsigned char expected4 = 0; unsigned char expected5 = 0; unsigned char expected6 = 0; unsigned char expected7 = 0; unsigned char expected8 = 0; unsigned char expected9 = 0; unsigned char expected10 = 0; int expectationwasfulfilled = -1; int expectationresolved = 1; int expectationtimer = 0; int shouldntcomein = 0; int goodnoreplies = 0; int goodnoreplystreak = 0; int goodnoreplystreakstartid = 0; int CANmatchstreak = 0; int CANmatchstreakstartID = 0; int unexpectedCANfails = 0; int unexpectedCANstreak = 0; int unexpectedCANstreakstartid = 0; int failsthistest = 0; int failsstreak = 0; int failsstreakstart = 0; int reportfailsindividually = 1; int noreplyfailsthistest = 0; int noreplystreak = 0; int noreplystreakstartid = 0; int mismatchfailsthistest = 0; int matchesthistest = 0; int addnewlinetonextmessage = 0; int checklaterbytes = 1; int aspamisgoing = 0; int CANpassthrough = 1; int speedspamison = 0; int messagesincount = 0; int messageinisneeded = 0; int idwasfound = 0; int columnidwasfound = 0; char c = NULL; int mbedCANbusspeed = 500 * 1000; int CANGatewayCANbusspeed = 500 * 1000; int listen = 1; int testwasaborted = 0; int customentry = 0; int normalkeypresses = 1; int tablesmode = 0; string customentrystring = ""; int hextotal = 0; int numberkeypressed = -1; //Array of IDs to translate can be overwritten with the 'copyarray'. //It's arranged in columns of IDs that are translated to the ID in the next column. //NOTE: Array must be a large enough size to contain all ID translations. int idsarray[2][8][10] = {}; //int copyarray[2][8][10] = {}; int arrayx = 2; int arrayy = 8; int arrayz = 10; int x = 0; int y = 0; int z = 0; int totalarraysize = 0; //A function to easily get the total of seconds a spam has taken int getspamsecondstotal(void) { //pc.printf("\r\nHere I'll get the spam seconds total!\r\n"); //pc.printf("Spam start/end time was %d / %d.\r\n", spamstarttime, spamendtime); int spamtickstotal = (spamendtime - spamstarttime); //pc.printf("Spam ticks total is %d.\r\n", spamtickstotal); //pc.printf("CLOCKS_PER_SEC are %d.\r\n", CLOCKS_PER_SEC); //pc.printf("Spamcount this test is %d.\r\n", spamcount); spamsecondstotal = ((spamendtime - spamstarttime) / CLOCKS_PER_SEC); //pc.printf("Spam seconds total is %d.\r\n", spamsecondstotal); spamspersecond = (10000 * spamcount); messagesinpersecond = (10000 * messagesincount); //pc.printf("Spams biggened x 10,000 is %d.\r\n", spamspersecond); spamspersecond = (spamspersecond / spamtickstotal); messagesinpersecond = (messagesinpersecond / spamtickstotal); //pc.printf("Spams per tick, still biggened, is %d.\r\n", spamspersecond); spamspersecond = (spamspersecond * CLOCKS_PER_SEC); messagesinpersecond = (messagesinpersecond * CLOCKS_PER_SEC); //pc.printf("Spams per second, still biggened, given %d ticks per second, is %d.\r\n", CLOCKS_PER_SEC, spamspersecond); spamspersecond = (spamspersecond / 10000); messagesinpersecond = (messagesinpersecond / 10000); //pc.printf("Spams per second, un-biggened, is %d.\r\n", spamspersecond); //pc.printf("\r\nSent %d messages for %d ticks (%d seconds) at %d ticks per second. Messages per second is %d.\r\n", spamcount, spamtickstotal, spamsecondstotal, CLOCKS_PER_SEC, spamspersecond); //Old version of the message if (speedspamison == 0) { if (aspamisgoing == 1) { pc.printf("\n"); } pc.printf("\rSent %d messages over %d seconds. Messages per second is %d.\r\n", spamcount, spamsecondstotal, spamspersecond); } return(spamsecondstotal, spamspersecond); } //A function to get table cells void dealwithtable(int copyarray) { for (int arrayprogress = 0; arrayprogress < totalarraysize; arrayprogress++) { x++; if (x >= arrayx) { x = 0; y++; } if (y >= arrayy) { y = 0; z++; } //int cellcontents = copyarray[x][y][z]; //pc.printf("Array progress is %d. Examining %d,%d,%d. It says '%d'.\r\n", arrayprogress, x, y, z, cellcontents); } } //Structure for CAN conversion pair, an ID and ID-plus-message, expressed in strings struct CANpair { string IDfrom; string IDmessageto; }; struct CANpair CANpairslist[32]; //This defines a list of CANpair string pairs, each with 'IDfrom' and 'IDmessageto'. //Structure for CAN conversion table struct CANconversion { int IDfrom; int IDto; int length; int Data [8]; }; struct CANconversion CANconversionlist[32]; //This defines a list of CANconversion structures, each with its own IDfrom, IDto, length, etc. (E.g.: 'CANconversionlist[0].IDfrom') int CANconversionlistheight = 32; //A function to reset the CAN pairs list so it can be re-written into void resetCANpairslist() { CANconversionlistheight = 0; for (int i = 0; i < 32; i++) { CANpairslist[i].IDfrom = ""; CANpairslist[i].IDmessageto = ""; //pc.printf("Emptying CANpairslist row %d.\r\n", i); } } //A function to deal with each CAN message part (e.g.: 301, 8, 01, 02...) void dealwithpart(void) { hextotal = 0; partincrement = partincrement + 1; //pc.printf("Dealing with part %d. (%s)\r\n", partincrement, part); //int partincrementb = 0; int textlength = part.length(); //int characterinc = 0; //pc.printf("That's %d characters long.\r\n", textlength); for (int i = 0; i < part.size(); i++) { //pc.printf("Examining character %d/%d.\r\n", (i+1), textlength); char individualcharacter = part.at(i); //pc.printf("That's '%c'.\r\n", individualcharacter); int numberized = 0; if(isdigit(individualcharacter)) { //pc.printf("That character is a digit.\r\n"); numberized = individualcharacter - '0'; //pc.printf("Numberized that's '%d'.\r\n", numberized); } else { //pc.printf("That character is NOT a digit.\r\n"); int asciivalue = toupper(individualcharacter); //pc.printf("Ascii value is %d.\r\n", asciivalue); numberized = asciivalue - 55; //pc.printf("Hex value is %d.\r\n", numberized); } //pc.printf("Eventual numberization is %d.\r\n", numberized); //pc.printf("Hex total is now %d.\r\n", hextotal); int powertoraise = part.size() - (i+1); //pc.printf("Must multiply by 16 to the power of %d.\r\n", powertoraise); int amounttoadd = numberized; //pc.printf("powertoraise is '%d'.\r\n", powertoraise); if (powertoraise == 1) { amounttoadd = numberized * 16; //pc.printf("Multiplying by 16.\r\n"); //pc.printf("powertoraise is '%d'.\r\n", powertoraise); } if (powertoraise == 2) { amounttoadd = numberized * 256; //pc.printf("Multiplying by 256.\r\n"); } //pc.printf("Amount to add is therefore %d.\r\n", amounttoadd); hextotal = hextotal + amounttoadd; //pc.printf("hextotal so far for this part is therefore %d.\r\n", hextotal); } //pc.printf("hextotal for whole part is therefore %d.\r\n", hextotal); //pc.printf("Need to convert that into true hex.\r\n"); std::stringstream sstream; sstream << std::hex << hextotal; //pc.printf("StringSteam says '%s'.\r\n", sstream.str()); if (partincrement == 1) { if (hextotal > 0xFFF) { hextotal = 0xFFF; } messageOut1.id = hextotal; expected1 = hextotal; if (customentry == 1) { idlistincrementer = hextotal; } //For IDs, check if the ID is represented in the idsarray. shouldntcomein = 0; if (mbedCANbusspeed != CANGatewayCANbusspeed) { shouldntcomein = 1; } idwasfound = 0; if (CANpassthrough == 0) { for(int i = 0; i <=CANconversionlistheight-1; i++) { if (CANconversionlist[i].IDfrom == expected1) { //pc.printf("ID was found in the array at %d.\r\n", i); idwasfound = 1; //pc.printf("IDwasfound is now '%d'.\r\n", idwasfound); columnidwasfound = i; int originalexpectedvalue = expected1; //Get string of hex code for original expected value (ID code found in array) std::stringstream sstream; sstream << std::hex << originalexpectedvalue; string tempstring = sstream.str(); //Get string of hex code for value to adjust to std::stringstream sstream2; sstream2 << std::hex << expected1; string tempstring2 = sstream2.str(); //pc.printf("\r\nFound message ID %s at 0,%d in idsarray! Will adjust expected value to %s.\r\n", tempstring, i, tempstring2); } } if (idwasfound == 0 and CANpassthrough == 0) { //pc.printf("CANpassthrough is %d.\r\n", CANpassthrough); shouldntcomein = 1; //pc.printf("ID of %d was never found, expecting it NOT to come in.\r\n", expected1); } if (shouldntcomein == 0 and unexpectedCANstreak > 0) //If data is expected to come in, this ends any unexpected-CAN streak. { if (aspamisgoing == 1) //Add a new line if it's in spam mode here to report new non-unexpected-CAN-streak stuff. { //pc.printf("\r\n(FrombreakingunexpectedCANstreak 2)\n"); pc.printf("\r\n\n"); } unexpectedCANstreak = 0; unexpectedCANstreakstartid = 0; } } } if (partincrement == 2) { messageOut1.len = hextotal; expected2 = hextotal; } if (partincrement >= 3) { messageOut1.data[partincrement-3] = hextotal; } if (partincrement == 3) { expected3 = hextotal; } if (partincrement == 4) { expected4 = hextotal; } if (partincrement == 5) { expected5 = hextotal; } if (partincrement == 6) { expected6 = hextotal; } if (partincrement == 7) { expected7 = hextotal; } if (partincrement == 8) { expected8 = hextotal; } if (partincrement == 9) { expected9 = hextotal; } if (partincrement == 10) { expected10 = hextotal; } //pc.printf("IDwasfound says '%d'.\r\n", idwasfound); if (idwasfound == 1 and partincrement == 10)//If the ID was found in the table earlier, use it as the basis for the expected values instead. { //pc.printf("ID was found in table earlier, setting expectations\r\n"); int i = columnidwasfound; expected1 = CANconversionlist[i].IDto; expected2 = CANconversionlist[i].length; expected3 = CANconversionlist[i].Data[0]; expected4 = CANconversionlist[i].Data[1]; expected5 = CANconversionlist[i].Data[2]; expected6 = CANconversionlist[i].Data[3]; expected7 = CANconversionlist[i].Data[4]; expected8 = CANconversionlist[i].Data[5]; expected9 = CANconversionlist[i].Data[6]; expected10 = CANconversionlist[i].Data[7]; } //pc.printf("Part %d complete.\r\n", partincrement); //pc.printf("--------------------------------------\r\n"); } //A function to go through each row in the string CAN pairs list and turn them into data for the CAN conversion list. void gothroughCANpairslist(void) { for (int i = 0; i < 30; i++) { string tempstringA = CANpairslist[i].IDfrom; string tempstringB = CANpairslist[i].IDmessageto; //pc.printf("Strings found are '%s' and '%s'.\r\n", tempstringA, tempstringB); //pc.printf("Will try to get an ID from out of '%s'.\r\n", tempstringA); if (tempstringA != "" and tempstringB != "")//Only get a number from the part if tempstring A and B have something in them. { CANconversionlistheight = i+1; partincrement = 0; part = tempstringA; dealwithpart(); //pc.printf("Hextotal obtained is %d.\r\n", hextotal); //pc.printf("partincrement is now %d.\r\n", partincrement); CANconversionlist[i].IDfrom = hextotal; partincrement = 0; part = tempstringB.substr(0,3); dealwithpart(); //pc.printf("Hextotal obtained is %d.\r\n", hextotal); CANconversionlist[i].IDto = hextotal; part = tempstringB.substr(4,1); dealwithpart(); //pc.printf("Hextotal obtained is %d.\r\n", hextotal); CANconversionlist[i].length = hextotal; part = tempstringB.substr(6,2); dealwithpart(); //pc.printf("Hextotal obtained is %d.\r\n", hextotal); CANconversionlist[i].Data [0] = hextotal; part = tempstringB.substr(9,2); dealwithpart(); //pc.printf("Hextotal obtained is %d.\r\n", hextotal); CANconversionlist[i].Data [1] = hextotal; part = tempstringB.substr(12,2); dealwithpart(); //pc.printf("Hextotal obtained is %d.\r\n", hextotal); CANconversionlist[i].Data [2] = hextotal; part = tempstringB.substr(15,2); dealwithpart(); //pc.printf("Hextotal obtained is %d.\r\n", hextotal); CANconversionlist[i].Data [3] = hextotal; part = tempstringB.substr(18,2); dealwithpart(); //pc.printf("Hextotal obtained is %d.\r\n", hextotal); CANconversionlist[i].Data [4] = hextotal; part = tempstringB.substr(21,2); dealwithpart(); //pc.printf("Hextotal obtained is %d.\r\n", hextotal); CANconversionlist[i].Data [5] = hextotal; part = tempstringB.substr(24,2); dealwithpart(); //pc.printf("Hextotal obtained is %d.\r\n", hextotal); CANconversionlist[i].Data [6] = hextotal; part = tempstringB.substr(27,2); dealwithpart(); //pc.printf("Hextotal obtained is %d.\r\n", hextotal); CANconversionlist[i].Data [7] = hextotal; } } } //A function to handle key presses in tables mode void tablesmodekeypress(void) { //pc.printf("Key press detected in tables mode!\r\n"); if (c >= 48 and c <= 57) { numberkeypressed = c - 48; pc.printf("That's a number key press.('%d')\r\n", numberkeypressed); resetCANpairslist(); if (numberkeypressed == 1) { CANpairslist[0].IDfrom = "301"; CANpairslist[0].IDmessageto = "301 8 08 00 00 00 00 00 00 00"; CANpairslist[1].IDfrom = "302"; CANpairslist[1].IDmessageto = "302 8 06 07 00 00 00 00 00 00"; CANpairslist[2].IDfrom = "303"; CANpairslist[2].IDmessageto = "303 8 00 00 00 00 00 00 00 00"; CANpairslist[3].IDfrom = "304"; CANpairslist[3].IDmessageto = "304 8 08 00 00 00 00 00 00 00"; CANpairslist[4].IDfrom = "305"; CANpairslist[4].IDmessageto = "305 8 08 00 00 00 00 00 00 00"; CANpairslist[5].IDfrom = "306"; CANpairslist[5].IDmessageto = "306 8 02 03 00 00 00 00 00 00"; CANpairslist[6].IDfrom = "307"; CANpairslist[6].IDmessageto = "307 8 06 07 08 00 00 00 00 00"; CANpairslist[7].IDfrom = "309"; CANpairslist[7].IDmessageto = "308 8 06 07 08 00 00 00 00 00"; } if (numberkeypressed == 2) { CANpairslist[0].IDfrom = "301"; CANpairslist[0].IDmessageto = "401 8 08 00 00 00 04 05 06 01"; CANpairslist[1].IDfrom = "302"; CANpairslist[1].IDmessageto = "402 8 04 05 06 07 06 07 08 00"; CANpairslist[2].IDfrom = "303"; CANpairslist[2].IDmessageto = "403 8 03 04 05 05 06 80 00 00"; CANpairslist[3].IDfrom = "304"; CANpairslist[3].IDmessageto = "404 8 04 05 06 07 06 07 08 00"; CANpairslist[4].IDfrom = "305"; CANpairslist[4].IDmessageto = "405 8 04 05 06 07 06 07 08 00"; CANpairslist[5].IDfrom = "306"; CANpairslist[5].IDmessageto = "406 8 02 03 00 00 00 00 00 00"; CANpairslist[6].IDfrom = "308"; CANpairslist[6].IDmessageto = "408 8 06 07 08 00 00 00 00 00"; CANpairslist[7].IDfrom = "309"; CANpairslist[7].IDmessageto = "409 8 06 07 08 00 00 00 00 00"; } if (numberkeypressed == 3) { CANpairslist[0].IDfrom = "317"; CANpairslist[0].IDmessageto = "40A 8 08 00 00 00 04 05 06 07"; CANpairslist[1].IDfrom = "318"; CANpairslist[1].IDmessageto = "409 8 08 00 00 00 04 05 06 07"; CANpairslist[2].IDfrom = "319"; CANpairslist[2].IDmessageto = "408 8 06 07 02 03 04 05 00 00"; CANpairslist[3].IDfrom = "31A"; CANpairslist[3].IDmessageto = "407 8 08 00 00 00 04 05 02 03"; CANpairslist[4].IDfrom = "31B"; CANpairslist[4].IDmessageto = "40C 8 04 05 06 07 02 03 08 00"; CANpairslist[5].IDfrom = "31C"; CANpairslist[5].IDmessageto = "40B 8 06 07 04 05 02 03 00 00"; CANpairslist[6].IDfrom = "31D"; CANpairslist[6].IDmessageto = "406 8 08 00 00 00 04 05 06 07"; CANpairslist[7].IDfrom = "31E"; CANpairslist[7].IDmessageto = "405 8 04 05 06 07 00 00 00 00"; CANpairslist[8].IDfrom = "324"; CANpairslist[8].IDmessageto = "403 8 06 07 08 07 00 00 00 00"; CANpairslist[9].IDfrom = "325"; CANpairslist[9].IDmessageto = "404 8 04 05 06 07 00 00 00 00"; CANpairslist[10].IDfrom = "329"; CANpairslist[10].IDmessageto = "402 8 08 00 00 00 04 05 06 07"; CANpairslist[11].IDfrom = "32A"; CANpairslist[11].IDmessageto = "401 8 04 05 02 03 06 05 00 00"; } gothroughCANpairslist(); pc.printf("CAN conversion list currently has %d rows:\r\n", CANconversionlistheight); int i = 0; while (i < CANconversionlistheight) { //pc.printf("Printing row %d: ", i+1); pc.printf("ID \033[1;37m%03X\033[0m will convert to: \033[1;30;47m%03X %01X %02X %02X %02X %02X %02X %02X %02X %02X\033[0m", CANconversionlist[i].IDfrom, CANconversionlist[i].IDto, CANconversionlist[i].length, CANconversionlist[i].Data[0], CANconversionlist[i].Data[1], CANconversionlist[i].Data[2], CANconversionlist[i].Data[3], CANconversionlist[i].Data[4], CANconversionlist[i].Data[5], CANconversionlist[i].Data[6], CANconversionlist[i].Data[7]); pc.printf("\r\n"); i++; } CANpassthrough = 0; pc.printf("CANpassthrough is now set to %d.\r\n", CANpassthrough); numberkeypressed = -1; } if (c == 27) { pc.printf("Leaving Expectation Table mode.\r\n"); normalkeypresses = 1; tablesmode = 0; } } //A function to report if baud rates differ void reportbaudrates(void) { if (mbedCANbusspeed != CANGatewayCANbusspeed) { pc.printf("Mbed baud rate (%d) is different from assumed CAN Gateway baud rate (%d), will expect no CAN.\r\n", (mbedCANbusspeed / 1000), (CANGatewayCANbusspeed / 1000)); } } //A function to handle when CAN-expectations are not fulfilled void expectationwasnotfulfilled(void) { //pc.printf("Expectation was not fulfilled for that message!\r\n"); } //A function to clear all test-related variables void resetCANbuses()//A quick method to reset both CAN buses conveniently { CanBus.reset(); // Clear any bus errors. Will this stop the 'cached' CAN sticking around? CanBus2.reset(); // Clear any bus errors. Will this stop the 'cached' CAN sticking around? } void resettest(void) { //pc.printf("Resetting test.\r\n"); listen = 1; failsthistest = 0; failsstreak = 0; failsstreakstart = 0; spamcount = 0; noreplyfailsthistest = 0; goodnoreplies = 0; goodnoreplystreak = 0; goodnoreplystreakstartid = 0; noreplystreak = 0; noreplystreakstartid = 0; CANmatchstreak = 0; CANmatchstreakstartID = 0; mismatchfailsthistest = 0; matchesthistest = 0; idscheckedcount = 0; unexpectedCANfails = 0; unexpectedCANstreak = 0; unexpectedCANstreakstartid = 0; messagesincount = 0; testwasaborted = 0; } //A function to add a carriage return in the output if the system has been writing out the CAN messages it sends. void addnewlineifneeded(void) { if (addnewlinetonextmessage == 1) { pc.printf("\r\n"); addnewlinetonextmessage = 0; } } void reportsentCAN() //A function to print out the CAN that was sent. Messages can only be positioned correctly once their results are known. { pc.printf("\033[1;33m\rSent out : %s \033[0m", messageOutTextWithSpaces); } //A function to end a test and report on findings. void endtest() { listen = 0; expectationresolved = 1; if (testwasaborted == 1) { pc.printf("\033[1;35mTest was aborted, results invalid.\033[0m\r\n"); pc.printf("\033[1;35m%d IDs sent out. %d failures found so far.\033[0m\r\n", spamcount, failsthistest); if (CANpassthrough == 0) { pc.printf("\033[1;35m%d expected non-replies found so far. \033[0m", goodnoreplies); } pc.printf("\033[1;35m%d CAN matches found so far.\033[0m\r\n", matchesthistest); } if (failsthistest == 0 and testwasaborted == 0) { pc.printf("\033[1;32mTest passed.\033[0m\r\n"); pc.printf("\033[1;32m%d IDs sent out. \033[0m", spamcount); pc.printf("\033[1;32m%d failures found.\033[0m\r\n", failsthistest); if (CANpassthrough == 0) { pc.printf("\033[1;32m%d expected non-replies found. \033[0m", goodnoreplies); } pc.printf("\033[1;32m%d CAN matches found.\033[0m\r\n", matchesthistest); } if (failsthistest > 0 and testwasaborted == 0) { pc.printf("\033[1;31mTest failed.\r\n%d failures found.\033[0m\r\n", failsthistest); pc.printf("\033[1;31m%d mismatch failures, %d 'no reply' failures, %d unexpected CAN messages.\033[0m\r\n", mismatchfailsthistest, noreplyfailsthistest, unexpectedCANfails); if (goodnoreplies > 0) { pc.printf("\033[1;31m%d expected non-replies occurred.\033[0m\r\n", goodnoreplies); } } pc.printf("-------------------------------------\r\n"); failsthistest = 0; normalkeypresses = 1; } //'End ID spam test' function so you can end it by reaching 2048 IDs or pressing 'Esc' while it's running void endidspamtest() { spamendtime = clock(); getspamsecondstotal();//Process the spam information idspamon = 0; aspamisgoing = 0; normalkeypresses = 0; addnewlinetonextmessage = 1; //addnewlineifneeded(); //pc.printf("Ending ID spam sequence. %d IDs checked total.\r\n", idscheckedcount); idlistincrementer = 0; endtest(); } void endspeedtest()//A different 'end' routine for speed tests. { //if (messagesincount == spamcount - 1)//If the messages in are only one less than messages out, adjust since it's probably just the test cancelling before getting that last message. //{ //pc.printf("messagesincount is only one less than spamcount, setting it.\r\n"); //messagesincount = spamcount; //} listen = 0; pc.printf("Ending CAN speed test.\r\n"); pc.printf("%d messages sent. ", spamcount); pc.printf("%d messages detected coming back in over %d seconds.\r\n", messagesincount, spamsecondstotal); int speedtestpercentage = ((messagesincount * 100)/spamcount); int speedtestpasslevel = 90; if (speedtestpercentage >= speedtestpasslevel) { //pc.printf("\033[1;32mTest pass: %d%% of messages detected back.\033[0m\r\n\n", speedtestpercentage); } else { //pc.printf("\033[1;31mTest fail: %d%% of messages detected back.\033[0m\r\n\n", speedtestpercentage); } speedtestpasslevel = (CANGatewayCANbusspeed / 1000) * 8; //The HD2 can do 80 channels at 100Hz, so 8,000 messages per second are required at top baud rate (1000kbit/s) if (CANGatewayCANbusspeed == mbedCANbusspeed) { if (messagesinpersecond >= speedtestpasslevel) { pc.printf("\033[1;32mTest pass: %d messages in per second. (%d required for pass at Gateway baud rate %d.)\033[0m\r\n", messagesinpersecond, speedtestpasslevel, CANGatewayCANbusspeed / 1000); } if (messagesinpersecond < speedtestpasslevel) { pc.printf("\033[1;31mTest fail: %d messages in per second. (%d required for pass at Gateway baud rate %d.)\033[0m\r\n", messagesinpersecond, speedtestpasslevel, CANGatewayCANbusspeed / 1000); } } if (CANGatewayCANbusspeed != mbedCANbusspeed) { pc.printf("\033[1;35mTest invalid: Mbed CAN bus baud rate (%d) does not match presumed CAN Gateway baud rate (%d).\033[0m\r\n", mbedCANbusspeed / 1000, CANGatewayCANbusspeed / 1000); } pc.printf("\n");//Add an extra new line so the whole baud rate test is separate from the rest of the text. } //A generic 'send CAN' function to send CAN with a standard message void sendCAN(void) { CanBus.write(messageOut1); //addnewlineifneeded(); if (aspamisgoing == 0) { //pc.printf("\r\n"); } expectationresolved = 0; //pc.printf("Expectationresolved now is %d.", expectationresolved); expectationtimer = 0; //addnewlinetonextmessage = 1; } //A function to get a coherent CAN message from one, uninterrupted string void getCANfrommessageOutText(void) { //pc.printf("messageOutText before space-removal is '%s'\r\n", messageOutText); messageOutTextWithSpaces = messageOutText; remove(messageOutText.begin(), messageOutText.end(), ' '); //Remove the spaces from the text to send out so it can be parsed. //pc.printf("After removing spaces, messageOutText is '%s'\r\n", messageOutText); string startofstring = messageOutText.substr(0,20); //Take the first 20 characters of the newly-formed string to get a spaceless CAN message. //pc.printf("String to parse is '%s'.\r\n", startofstring); expectationresolved = 0; if (expectationwasfulfilled == 0) { expectationwasnotfulfilled(); } if (expectationwasfulfilled == -1) { expectationwasfulfilled = 0; } expectationwasfulfilled = 0; partincrement = 0; if (mbedCANbusspeed != CANGatewayCANbusspeed) // If the two bus speeds don't match, note that CAN should not be expected to ocme in and report the issue. { shouldntcomein = 1; if (aspamisgoing == 0) { reportbaudrates(); } } part = startofstring.substr(0,3); dealwithpart(); part = startofstring.substr(3,1); dealwithpart(); part = startofstring.substr(4,2); dealwithpart(); part = startofstring.substr(6,2); dealwithpart(); part = startofstring.substr(8,2); dealwithpart(); part = startofstring.substr(10,2); dealwithpart(); part = startofstring.substr(12,2); dealwithpart(); part = startofstring.substr(14,2); dealwithpart(); part = startofstring.substr(16,2); dealwithpart(); part = startofstring.substr(18,2); dealwithpart(); } void displayhelp(void) { pc.printf("\033[1;32m---------------HELP---------------\r\n"); pc.printf("Ken_CAN_Test is a program designed by Ken Dunlop to test CAN on the CAN Gateway.\r\n"); pc.printf("The program is designed to send CAN, then test the response.\r\n"); pc.printf("Press 'z' to begin sending a series of incrementing messages. Press 'Esc' to finish the test.\r\n"); pc.printf("Press 'v' to send a message on all IDs (000 - 7FF). Press 'Esc' to abort the test.\r\n"); pc.printf("Use 'q', 'w', 'e', and 'r' to change the Mbed's CAN bus speed.\r\n"); pc.printf("Use 't', 'y', 'u', and 'i' to change the presumed CAN bus speed of the CAN Gateway.\r\n"); pc.printf("If the two CAN bus speeds are different, the program will expect to get no CAN messages back.\r\n"); pc.printf("Press 'a' to begin a baud rate test. This sends CAN messages quickly and measures how many come back.\r\n"); pc.printf("Press 'k' to enter Custom Entry mode. This allows you to enter an CAN ID manually and then send a CAN message.\r\n"); pc.printf("Press 'z' to begin sending incrementing CAN messages. The data in the message will increment by 1 each time.\r\n"); pc.printf("Press 'o' while sending incrementing messages to multiply the incrementation by 16. This shifts the number up one half-byte.\r\n"); pc.printf("Press 'k' to enter Custom Entry mode. This allows you to enter an CAN ID manually and then send a CAN message.\r\n"); pc.printf("Press 'm' to set up an expectation table. This changes what CAN the system expects back when sending certain CAN IDs.\r\n"); pc.printf("Press 'n' to cancel the expectation table and re-enter CAN passthrough mode. This will simply expect the same CAN back as was sent.\r\n"); pc.printf("Press the number keys from '1' to '0' to send various pre-defined CAN messages out.\r\n"); pc.printf("Press '?' to bring up this help screen!\r\n"); pc.printf("---------------------------------\033[0m\r\n"); } void printMessageOut (void) { //This function will print out whatever the CAN bus is sending out. Can't be used constantly as it sends '000 8 00 00 00 00 00 00 00 00' all the time. pc.printf("Message OUT: %03X %01X %02X %02X %02X %02X %02X %02X %02X %02X\r\n",messageOut1.id,messageOut1.len,messageOut1.data[0],messageOut1.data[1],messageOut1.data[2],messageOut1.data[3],messageOut1.data[4],messageOut1.data[5],messageOut1.data[6],messageOut1.data[7]); } void printMessageIn (void) { //This function will print out whatever the CAN bus is receiving. //addnewlineifneeded(); pc.printf("\033[0;36mMessage IN: %03X %01X %02X %02X %02X %02X %02X %02X %02X %02X\033[0m\r\n",messageIn.id,messageIn.len,messageIn.data[0],messageIn.data[1],messageIn.data[2],messageIn.data[3],messageIn.data[4],messageIn.data[5],messageIn.data[6],messageIn.data[7]); } //The 'main' function will run as soon as the program starts. int main() { pc.baud(115200); // serial port at 115200 CanBus.frequency(500 * 1000); // CAN bus at 500k CanBus2.frequency(500 * 1000); // CAN bus at 500k CanBus.reset(); // clear any bus errors CanBus2.reset(); // clear any bus errors //NOTE: Print messages must be below this line to work. pc.printf("\033[0m------------------------------------------\r\n"); pc.printf("Welcome to Ken CAN test.\r\n"); pc.printf("Setting CAN bus to 500k.\r\n"); pc.printf("Setting serial port to baud rate 115200.\r\n"); pc.printf("Using pins 9 and 10 for CANBus 1 (out) and 30 and 29 for CANBus 2 (in).\r\n"); pc.printf("Version %d.%d\r\n",kMajorVersion,kMinorVersion); pc.printf("Build date %s %s\r\n",__DATE__,__TIME__); pc.printf("\033[1;32mFor help, press '?'.\033[0m\r\n"); pc.printf("------------------------------------------\r\n"); //char c; //Check for button presses while (1) { if (expectationtimer < 100 and expectationresolved == 0) { if (expectationresolved == 0) { expectationtimer++; if (expectationtimer >= 2)//If expectation timer gets too high, the CAN reply is deemed not to have arrived. { if (CANmatchstreak > 0) //CAN not arriving breaks any CAN match streak { CANmatchstreak = 0; CANmatchstreakstartID = 0; if (aspamisgoing == 1) { pc.printf("\r\n\nFrombreakingCANmatchstreak");//Add a return into the terminal to show the old streak on a line by itself. } } if (goodnoreplystreak > 0 and shouldntcomein == 0) //A missing expected reply breaks any combos for expected no-replies { if (aspamisgoing == 1) { //pc.printf("\r\n(From breaking goodnoreplystreak)\n\r"); pc.printf("\r\n\n"); } goodnoreplystreak = 0; goodnoreplystreakstartid = 0; } // If data did not come in when it was expected... if (shouldntcomein == 0) { expectationwasfulfilled = 0; failsthistest++; noreplyfailsthistest++; if (aspamisgoing == 0) { noreplystreakstartid = idlistincrementer; } if (goodnoreplystreak > 0) { goodnoreplystreak = 0; if (aspamisgoing == 1) { pc.printf("(\r\n\n");//Add an extra line if breaking an 'as expected' no reply streak. } } if (failsstreak > 0) { if (aspamisgoing == 1) { pc.printf("\r\n\n");//Add an extra line if breaking a failure 'does not match expectation' streak } failsstreak = 0; failsstreakstart = 0; } if (aspamisgoing == 1) { if (noreplystreak == 0) { noreplystreakstartid = idlistincrementer; } noreplystreak++; } reportsentCAN();//Now that it's known the CAN has no reply, you can safely write out the sent CAN. (The needed line-returns have been added.) if (noreplystreakstartid != idlistincrementer) { pc.printf("\033[38;5;220mNo reply message detected for IDs %03X to %03X.\033[0m\r", noreplystreakstartid, idlistincrementer); } if (noreplystreakstartid == idlistincrementer) { pc.printf("\033[38;5;220mNo reply message detected for ID %03X.\033[0m\r", idlistincrementer); } if (aspamisgoing == 0) { pc.printf("\r\n\n"); //If it's not spamming, you can safely add a new line after the fail message. } } if (shouldntcomein == 1) { expectationwasfulfilled = 1; //Getting an expected non-reply breaks any unexpected reply streaks if (unexpectedCANstreak > 0) { if (aspamisgoing == 1) //Add a new line if it's in spam mode here to report new expected-non-message stuff. { //pc.printf("\r\n\n(FrombreakingunexpectedCANstreak)"); pc.printf("\r\n\n"); } unexpectedCANstreak = 0; unexpectedCANstreakstartid = 0; } //Getting an expected non-reply also breaks any unexpected non-reply streaks if (noreplystreak > 0) { if (aspamisgoing == 1) //Add a new line if it's in spam mode here to report new expected-non-message stuff. { //pc.printf("\r\n(From breaking noreplystreak)\n"); pc.printf("\r\n\n"); } noreplystreak = 0; noreplystreakstartid = 0; } // Also, getting an expected non-reply breaks any CAN-fail streaks if (failsstreak > 0 ) { if (aspamisgoing == 1) { //pc.printf("\r\n(From breaking CAN-mismatch streak)\n"); pc.printf("\r\n\n"); } failsstreak = 0; failsstreakstart = 0; } if (goodnoreplystreak == 0) //If there isn't yet a good no-reply streak, set the starting no-reply ID to this one { goodnoreplystreakstartid = idlistincrementer; if (CANmatchstreak > 0 and aspamisgoing == 1)//Also add an extra return for the breaking of the old CANmatchstreak if needed { CANmatchstreak = 0; pc.printf("(From breaking of CANmatchstreak)\r\n"); } } reportsentCAN();//Now that it's known the CAN has no reply, you can safely write out the sent CAN. (The needed line-returns have been added.) if (aspamisgoing == 0) { goodnoreplystreakstartid = idlistincrementer; } if (goodnoreplystreakstartid != idlistincrementer) { pc.printf("\033[0;32mNo reply message detected from %03X to %03X, as expected.\033[0m\r", goodnoreplystreakstartid, idlistincrementer); } if (goodnoreplystreakstartid == idlistincrementer) { pc.printf("\033[0;32mNo reply message detected for ID %03X, as expected.\033[0m\r", goodnoreplystreakstartid); } if (aspamisgoing == 0) { pc.printf("\r\n\n"); //If it's not spamming, you can safely add a new line after the fail message. } goodnoreplies++; goodnoreplystreak++; } expectationresolved = 1; //pc.printf("Expectation timer reached %d!\r\n", expectationtimer); expectationtimer = 0; if (idspamon == 1) { idscheckedcount++; idlistincrementer++; //Only add 1 to the idlist incrementer at the end so the first ID it sends is '000'. } if (customentry == 1) { pc.printf("Enter CAN ID to send: "); } } wait(0.01); } } if (pc.readable()) { c = tolower(pc.getc()); if (c != NULL) { //When the a key is pressed, define a CAN message and send it. //pc.printf("A key was pressed! (%c)\r\n", c); messageOutText = ""; buttonPressMessageOutText = ""; if (c == '1' and normalkeypresses == 1) { buttonPressMessageOutText = "301 8 01 02 03 04 05 06 07 08"; idlistincrementer = 0x301; } if (c == '2' and normalkeypresses == 1) { buttonPressMessageOutText = "302 8 01 02 03 04 05 06 07 08"; idlistincrementer = 0x302; } if (c == '3' and normalkeypresses == 1) { buttonPressMessageOutText = "303 8 01 02 03 04 05 06 07 08"; idlistincrementer = 0x303; } if (c == '4' and normalkeypresses == 1) { buttonPressMessageOutText = "304 8 01 02 03 04 05 06 07 08"; idlistincrementer = 0x304; } if (c == '5' and normalkeypresses == 1) { buttonPressMessageOutText = "305 8 01 02 03 04 05 06 07 08"; idlistincrementer = 0x305; } if (c == '6' and normalkeypresses == 1) { buttonPressMessageOutText = "306 8 01 02 03 04 05 06 07 08"; idlistincrementer = 0x306; } if (c == '7' and normalkeypresses == 1) { buttonPressMessageOutText = "307 8 01 02 03 04 05 06 07 08"; idlistincrementer = 0x307; } if (c == '8' and normalkeypresses == 1) { buttonPressMessageOutText = "308 8 01 02 03 04 05 06 07 08"; idlistincrementer = 0x308; } if (c == '9' and normalkeypresses == 1) { buttonPressMessageOutText = "309 8 01 02 03 04 05 06 07 08"; idlistincrementer = 0x309; } if (c == '0' and normalkeypresses == 1) { buttonPressMessageOutText = "7FF 8 FF FF FF FF FF FF FF FF";//NOTE: CAN IDs only go to 7FF, not FFF. idlistincrementer = 0x7FF; } if (c == 'a' and normalkeypresses == 1) { listen = 1; pc.printf("Starting baud rate speed test. Mbed at %d and CAN Gateway presumed %d. (Press 'Esc' to end.)\r\n", mbedCANbusspeed / 1000, CANGatewayCANbusspeed / 1000); pc.printf(""); resettest(); incrementer = 0x333; spamstarttime = clock(); speedspamison = 1; aspamisgoing = 1; normalkeypresses = 0; messageOut1.format = CANStandard; //Quickly define a convenient messageOut for the speed spam to use. messageOut1.id = 0x301; messageOut1.len = 8; messageOut1.data[0] = 0x06; messageOut1.data[1] = 0x3f; messageOut1.data[2] = 0xb2; messageOut1.data[3] = 0x29; messageOut1.data[4] = 0x19; messageOut1.data[5] = 0x97; messageOut1.data[6] = 0x67; messageOut1.data[7] = 0x37; pc.printf("Will send out '%03X %01X %02X %02X %02X %02X %02X %02X %02X %02X' as fast as possible.\r\n", messageOut1.id, messageOut1.len, messageOut1.data[0], messageOut1.data[1], messageOut1.data[2], messageOut1.data[3], messageOut1.data[4], messageOut1.data[5], messageOut1.data[6], messageOut1.data[7]); } if (c == 27 and speedspamison == 1)//Cancel speed spam mode { //pc.printf("\r\nEnding baud rate speed test mode from upper key press method.\r\n"); aspamisgoing = 0; normalkeypresses = 1; spamendtime = clock(); //endtest(); getspamsecondstotal(); endspeedtest(); speedspamison = 0; } if (buttonPressMessageOutText != "")//Centralized 'button press MessageOut' routine that applies to all button presses. { if (aspamisgoing == 0) { //addnewlineifneeded(); //resetCANbuses(); listen = 1; messageOutText = buttonPressMessageOutText; addnewlinetonextmessage = 1; checklaterbytes = 1;//Check all bytes for button-press messages. } buttonPressMessageOutText = ""; } if (c == '/' and normalkeypresses == 1) { displayhelp(); } if (c == '?' and normalkeypresses == 1) { displayhelp(); } if (c == 'q' and normalkeypresses == 1) { pc.printf("Changing Mbed CAN bus speed to 125.\r\n"); CanBus.frequency(125 * 1000); // CAN bus at 125k CanBus2.frequency(125 * 1000); // CAN bus at 125k mbedCANbusspeed = (125 * 1000); } if (c == 'w' and normalkeypresses == 1) { pc.printf("Changing Mbed CAN bus speed to 250.\r\n"); CanBus.frequency(250 * 1000); // CAN bus at 250k CanBus2.frequency(250 * 1000); // CAN bus at 250k mbedCANbusspeed = (250 * 1000); } if (c == 'e' and normalkeypresses == 1) { pc.printf("Changing Mbed CAN bus speed to 500.\r\n"); CanBus.frequency(500 * 1000); // CAN bus at 500k CanBus2.frequency(500 * 1000);// CAN bus at 500k mbedCANbusspeed = (500 * 1000); } if (c == 'r' and normalkeypresses == 1) { pc.printf("Changing Mbed CAN bus speed to 1000.\r\n"); CanBus.frequency(1000 * 1000); // CAN bus at 1000k CanBus2.frequency(1000 * 1000); // CAN bus at 1000k mbedCANbusspeed = (1000 * 1000); } if (c == 't' and normalkeypresses == 1) { CANGatewayCANbusspeed = (125 * 1000); pc.printf("CAN Gateway is now presumed to be at CAN bus speed %d.\r\n", CANGatewayCANbusspeed / 1000); } if (c == 'y' and normalkeypresses == 1) { CANGatewayCANbusspeed = (250 * 1000); pc.printf("CAN Gateway is now presumed to be at CAN bus speed %d.\r\n", CANGatewayCANbusspeed / 1000); } if (c == 'u' and normalkeypresses == 1) { CANGatewayCANbusspeed = (500 * 1000); pc.printf("CAN Gateway is now presumed to be at CAN bus speed %d.\r\n", CANGatewayCANbusspeed / 1000); } if (c == 'i' and normalkeypresses == 1) { CANGatewayCANbusspeed = (1000 * 1000); pc.printf("CAN Gateway is now presumed to be at CAN bus speed %d.\r\n", CANGatewayCANbusspeed / 1000); } if (c == 'k' and normalkeypresses == 1) { pc.printf("Will enter custom CAN entry mode. (Press 'Esc' to end.)\r\nEnter CAN ID to send: "); customentry = 1; normalkeypresses = 0; c = NULL; customentrystring = ""; } if (c == 27 and customentry == 1)//Pressing Esc ends Custom Entry mode { customentry = 0; normalkeypresses = 1; pc.printf("\r\nEnding custom entry mode.\r\n"); c = NULL; } if (c == 13 and customentry == 1 and customentrystring != "")//Pressing enter in Custom Entry mode tries to send a CAN message { pc.printf("\r\n"); //pc.printf("Will try to confirm CES ('%s').\r\n", customentrystring); if (customentrystring.length() < 3) { customentrystring = "0" + customentrystring; } if (customentrystring.length() < 3) { customentrystring = "0" + customentrystring; } checklaterbytes = 1; partincrement = 0; part = customentrystring; dealwithpart(); //pc.printf("Hextotal now says '%d'.\r\n", hextotal); if (hextotal > 0x7FF)//If the measured total is more than 0x7FF (the max ID), reduce it. { hextotal = 0x7FF; customentrystring = "7FF"; } if (hextotal < 0) // If the measured total is less than zero, make it zero instead. { hextotal = 0x000; customentrystring = "000"; } messageOutText = customentrystring + " 8 01 02 03 04 05 06 07 08"; customentrystring = ""; if (expectationresolved == 1 and messageOutText == "") { pc.printf("Enter CAN ID to send: "); } } if (c != NULL and customentry == 1 and expectationresolved == 1 and messageOutText == "") { //pc.printf("Custom entry detected! (%c)\r\n", c); if (c != '\r' and c != 8 and customentrystring.length() < 3) //Normal key presses add to the custom string. { customentrystring.push_back(toupper(c)); //pc.printf("Custom entry string now says '%s'.", customentrystring); } if (c == 8 and customentrystring.length() > 0) //Backspace (character 8) causes the text to go back one character. { pc.printf("\b "); customentrystring.erase(customentrystring.size()-1,1); } pc.printf("\rEnter CAN ID to send: %s", customentrystring); } if (c == 'n' and CANpassthrough == 0 and normalkeypresses == 1) { pc.printf("Starting CAN passthrough mode. Will expect to recieve the same CAN that is sent.\r\n"); CANpassthrough = 1; } if (c == 'm' and normalkeypresses == 1) //New menu to select multiple expectation tables { normalkeypresses = 0; //Go out of 'normal key presses' mode. pc.printf("Now entering Expectation Table mode. Press the number keys to activate different expectation tables.\r\n"); tablesmode = 1; } if (c != NULL and tablesmode == 1) { tablesmodekeypress(); } if (c == 'o' and idspamon == 0 and spamon == 1) { incrementer = (incrementer * 16); pc.printf("\n\rMultiplied Incrementer by 16. It's now %d.\r\n", incrementer); } if (c == 'i' and spamon == 1) { incrementer = incrementer + 16; std::stringstream sstream; sstream << std::hex << incrementer; string stringsofar = sstream.str(); //pc.printf("Incrementer is now %d.\r\n", incrementer); //pc.printf("StringStream says '%s'.\r\n", stringsofar); int length = stringsofar.length(); //pc.printf("Length is %d/16.\r\n", length); for (int i = 0; i < (16-length); i++) stringsofar = "0" + stringsofar; //pc.printf("stringsofar says '%s'.\r\n", stringsofar); //messageOutText = "305 8 " + stringsofar; //pc.printf("Will try to send '%s'.\r\n", messageOutText); } messageOut1.format = CANStandard; if (c == 'z' and normalkeypresses == 1) { resettest(); pc.printf("Starting spam sequence for ID %s. Press 'Esc' to end. Press 'o' to increase incrementer.\r\n", spampreamble); idlistincrementer = 0x333; reportbaudrates(); spamon = 1; aspamisgoing = 1; normalkeypresses = 0; checklaterbytes = 1; incrementer = 0; spamcount = 0; spamstarttime = clock(); //pc.printf("Spam start time is %d.\r\n", spamstarttime); } if (c == 27 and spamon == 1)//Cancel normal '333' incrementing spam mode { pc.printf("\r\n"); spamon = 2; aspamisgoing = 0; normalkeypresses = 1; spamendtime = clock(); getspamsecondstotal();//Process the spam information //pc.printf("Total spams ever are %d.\r\n", totalspamsever); endtest(); //pc.printf("-------------------------\r\n"); } if (c == 27 and idspamon == 1)//Cancel CAN ID spam mode { //pc.printf("Cancelling ID test mode.\r\n"); testwasaborted = 1; endidspamtest(); normalkeypresses = 1; } if (c == 'v' and normalkeypresses == 1) { resettest(); idspamon = 1; //Set the 'idspamon' integer to 1 so ID spam happens. aspamisgoing = 1; normalkeypresses = 0; checklaterbytes = 1; idlistincrementer = 0; pc.printf("Beginning check of all possible CAN IDs (000 - 7FF). Press 'Esc' to abort.\r\n"); reportbaudrates(); spamstarttime = clock(); //pc.printf("Spam started at clock time %d.\r\n", spamstarttime); if (checklaterbytes == 0) { pc.printf("Will only check CAN IDs, not later bytes.\r\n"); } if (checklaterbytes == 1) { pc.printf("Will check all bytes in each CAN message.\r\n"); } } if (messageOutText != "" and speedspamison == 0) { getCANfrommessageOutText(); sendCAN(); //CanBus.write(messageOut1); //CanBus2.write(messageOut1); if (spamon == 0 and idspamon == 0) { //printMessageOut(); } messageOutText = ""; } } } //If spam mode is on, spam an incrementing CAN message if (spamon == 1 and expectationresolved == 1) { spamcount ++; totalspamsever ++; incrementer ++; std::stringstream sstream; sstream << std::hex << incrementer; string stringsofar = sstream.str(); int length = stringsofar.length(); for (int i = 0; i < (16-length); i++) stringsofar = "0" + stringsofar; messageOutText = spampreamble + " 8 " + stringsofar; getCANfrommessageOutText(); sendCAN(); } if (idspamon == 1 and idlistincrementer >= 2048 and expectationresolved == 1) //If the spam value gets to 2048 (7FF), end the spam sequence. RL only go up to 7FF. { endidspamtest(); } if (idspamon == 1 and expectationresolved == 1) { spamcount++; std::stringstream sstream; sstream << std::hex << idlistincrementer; string idstring = ""; idstring = sstream.str(); //pc.printf("idstring says '%s'\r\n", idstring); if (idstring.length() < 3) { for (int i = 0; i < (4 - idstring.length()); i++) { idstring = "0" + idstring; } } //pc.printf("idstring now says '%s'\r\n", idstring); //pc.printf("%s\r\n", idstring); idstring = idstring + " 8 01 02 03 04 05 06 07 08"; //pc.printf("...and now idstring now says '%s'\r\n", idstring); messageOutText = idstring; getCANfrommessageOutText(); sendCAN(); //CanBus.write(messageOut1); //CanBus2.write(messageOut1); //pc.printf("ID list incrementer is now %d\r\n", idlistincrementer); wait(0.01);//ID spam at 100Hz } //Optional: mention any un-listened-to CAN messages. Having this stopped it from reading messages in when listen was on. //if (CanBus2.read(messageIn) and listen == 0) // { // pc.printf("(Un-listened-to CAN message came in.)\r\n"); // } //Check for CAN messages coming in if (CanBus2.read(messageIn) and listen == 1) { if (speedspamison == 1) { messagesincount++; //pc.printf("\033[0;36m Speed spam message IN: %03X %01X %02X %02X %02X %02X %02X %02X %02X %02X\033[0m\r\n",messageIn.id,messageIn.len,messageIn.data[0],messageIn.data[1],messageIn.data[2],messageIn.data[3],messageIn.data[4],messageIn.data[5],messageIn.data[6],messageIn.data[7]); } if (speedspamison == 0) { //pc.printf("\033[0;36mNormal message IN: %03X %01X %02X %02X %02X %02X %02X %02X %02X %02X\033[0m\r\n",messageIn.id,messageIn.len,messageIn.data[0],messageIn.data[1],messageIn.data[2],messageIn.data[3],messageIn.data[4],messageIn.data[5],messageIn.data[6],messageIn.data[7]); if (noreplystreak > 0) { noreplystreak = 0; noreplystreakstartid = 0; pc.printf("\r\n\n"); } if (goodnoreplystreak > 0) { goodnoreplystreak = 0; goodnoreplystreakstartid = 0; if (aspamisgoing == 1) { pc.printf("\r\n\n"); } } CANCount++; if (1 == 1)//Prepare to print out the message coming in { //Data shouldn't come in at all if 'shouldntcomein' is 1! //pc.printf("Wah! Unexpected CAN came in!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\r\n"); if (shouldntcomein == 1) { if (failsstreak > 0) { failsstreak = 0; failsstreakstart = 0; if (aspamisgoing == 1) { pc.printf("\n\n\r"); } } if (unexpectedCANstreak == 0)//If it's the start of a new unexpected-CAN streak, mark the starting ID. { unexpectedCANstreakstartid = idlistincrementer; } if (aspamisgoing == 0) { unexpectedCANstreakstartid = idlistincrementer; } reportsentCAN(); if (unexpectedCANstreakstartid != idlistincrementer) { pc.printf("\033[0;35mUnexpected data came in for IDs %03X to %03X!\033[0m", unexpectedCANstreakstartid, idlistincrementer); } if (unexpectedCANstreakstartid == idlistincrementer) { pc.printf("\033[0;35mUnexpected data came in for %03X!\033[0m", idlistincrementer); } failsthistest++; unexpectedCANfails++; unexpectedCANstreak++; } //Establish earlier whether it's a match in the 10 places int itsamatch = 1; if (expected1 != messageIn.id) {itsamatch = 0;} if (expected2 != messageIn.len and checklaterbytes >= 1) {itsamatch = 0;} if (expected3 != messageIn.data[0] and checklaterbytes >= 1) {itsamatch = 0;} if (expected4 != messageIn.data[1] and checklaterbytes >= 1) {itsamatch = 0;} if (expected5 != messageIn.data[2] and checklaterbytes >= 1) {itsamatch = 0;} if (expected6 != messageIn.data[3] and checklaterbytes >= 1) {itsamatch = 0;} if (expected7 != messageIn.data[4] and checklaterbytes >= 1) {itsamatch = 0;} if (expected8 != messageIn.data[5] and checklaterbytes >= 1) {itsamatch = 0;} if (expected9 != messageIn.data[6] and checklaterbytes >= 1) {itsamatch = 0;} if (expected10 != messageIn.data[7] and checklaterbytes >= 1) {itsamatch = 0;} if (itsamatch == 0 and shouldntcomein == 0) { if (goodnoreplystreak > 0) { goodnoreplystreak = 0; goodnoreplystreakstartid = 0; if (aspamisgoing == 1) { pc.printf("\r\n\n"); } } if (CANmatchstreak > 0) { CANmatchstreak = 0; CANmatchstreakstartID = 0; if (aspamisgoing == 1) { pc.printf("\r\n\n"); } } if (failsstreak == 0) { failsstreakstart = idlistincrementer; } failsstreak++; if (aspamisgoing == 0) { failsstreakstart = idlistincrementer; } reportsentCAN(); //Report sent CAN before any 'does not match...' messages if (failsstreakstart == idlistincrementer) { pc.printf("\033[0;31mData for ID %03X does not match expectation!\033[0m", idlistincrementer); } if (failsstreakstart != idlistincrementer) { pc.printf("\033[0;31mData for IDs %03X to %03X does not match expectation!\033[0m", failsstreakstart, idlistincrementer); } } //Decide if a message in will need to be printed ('Message received was:...') messageinisneeded = 0; if (aspamisgoing == 0) {messageinisneeded = 1;} if (itsamatch == 0 and shouldntcomein == 0 and reportfailsindividually == 1) {messageinisneeded = 1;} // If a message in is destined to be printed, reset the failsstreak if needed if (messageinisneeded == 1 and failsstreak > 0) { failsstreak = 0; failsstreakstart = 0; } // Once it's known whether the data matches expectation, set the match streak if (itsamatch == 1 and shouldntcomein == 0) { if (failsstreak > 0) { failsstreak = 0; failsstreakstart = 0; if (aspamisgoing == 1) { pc.printf("\r\n\n"); } } if (CANmatchstreak == 0) { CANmatchstreakstartID = idlistincrementer; } CANmatchstreak++; } if (itsamatch == 0 and CANmatchstreak > 0) //If it's NOT a match, break any CANmatchstreak { CANmatchstreak = 0; CANmatchstreakstartID = 0; } // Print needed message reportsentCAN(); if (messageinisneeded == 0) //If a message in is NOT needed, simply report what the CAN is doing on the same line. { if (itsamatch == 1 and CANmatchstreakstartID == idlistincrementer and CANmatchstreak > 0) { pc.printf("\033[0;32mCAN matches expected values on ID %03X.\033[0m", idlistincrementer); } if (itsamatch == 1 and CANmatchstreakstartID != idlistincrementer and CANmatchstreak > 0) { pc.printf("\033[0;32mCAN matches expected values from IDs %03X to %03X.\033[0m", CANmatchstreakstartID, idlistincrementer); } } if (messageinisneeded == 1) //Only if message in is needed do you need to look at printing each part of the message { pc.printf("\r\nMessage received was: "); if (expected1 != messageIn.id) { //pc.printf("\r\nID of %d does NOT match %d.\r\n", messageIn.id, expected1); pc.printf("\033[1;31m%03X\033[0m ", messageIn.id);//Show the ID in red if it doesn't match. } if (expected1 == messageIn.id) { pc.printf("\033[1;32m%03X\033[0m ", messageIn.id);//Show the ID in green if it matches. } if (expected2 != messageIn.len and checklaterbytes >= 1) { //pc.printf("Length of %d does NOT match %d.\r\n", messageIn.len, expected2); pc.printf("\033[1;31m%01X\033[0m ", messageIn.len); } else { pc.printf("\033[1;32m%01X\033[0m ", messageIn.len); } if (expected3 != messageIn.data[0] and checklaterbytes >= 1) { //pc.printf("Data 0 of %d does NOT match %d.\r\n", messageIn.data[0], expected3); pc.printf("\033[1;31m%02X\033[0m ", messageIn.data[0]); } else { pc.printf("\033[1;32m%02X\033[0m ", messageIn.data[0]); } if (expected4 != messageIn.data[1] and checklaterbytes >= 1) { //pc.printf("Data 1 of %d does NOT match %d.\r\n", messageIn.data[1], expected4); pc.printf("\033[1;31m%02X\033[0m ", messageIn.data[1]); } else { pc.printf("\033[1;32m%02X\033[0m ", messageIn.data[1]); } if (expected5 != messageIn.data[2] and checklaterbytes >= 1) { //pc.printf("Data 2 of %d does NOT match %d.\r\n", messageIn.data[2], expected5); pc.printf("\033[1;31m%02X\033[0m ", messageIn.data[2]); } else { pc.printf("\033[1;32m%02X\033[0m ", messageIn.data[2]); } if (expected6 != messageIn.data[3] and checklaterbytes >= 1) { //pc.printf("Data 3 of %d does NOT match %d.\r\n", messageIn.data[3], expected6); pc.printf("\033[1;31m%02X\033[0m ", messageIn.data[3]); } else { pc.printf("\033[1;32m%02X\033[0m ", messageIn.data[3]); } if (expected7 != messageIn.data[4] and checklaterbytes >= 1) { //pc.printf("Data 4 of %d does NOT match %d.\r\n", messageIn.data[4], expected7); pc.printf("\033[1;31m%02X\033[0m ", messageIn.data[4]); } else { pc.printf("\033[1;32m%02X\033[0m ", messageIn.data[4]); } if (expected8 != messageIn.data[5] and checklaterbytes >= 1) { //pc.printf("Data 5 of %d does NOT match %d.\r\n", messageIn.data[5], expected8); pc.printf("\033[1;31m%02X\033[0m ", messageIn.data[5]); } else { pc.printf("\033[1;32m%02X\033[0m ", messageIn.data[5]); } if (expected9 != messageIn.data[6] and checklaterbytes >= 1) { //pc.printf("Data 6 of %d does NOT match %d.\r\n", messageIn.data[6], expected9); pc.printf("\033[1;31m%02X\033[0m ", messageIn.data[6]); } else { pc.printf("\033[1;32m%02X\033[0m ", messageIn.data[6]); } if (expected10 != messageIn.data[7] and checklaterbytes >= 1) { //pc.printf("Data 7 of %d does NOT match %d.\r\n", messageIn.data[7], expected10); pc.printf("\033[1;31m%02X\033[0m ", messageIn.data[7]); } else { pc.printf("\033[1;32m%02X\033[0m ", messageIn.data[7]); } if (messageinisneeded == 1) { //pc.printf("\r\n(Aftersentoutmessage)"); pc.printf("\r\n");//Add a return and a new line after the 'Sent out' message is finished if it's not spam mode. } } if (itsamatch == 0) { mismatchfailsthistest++; if (aspamisgoing == 1) { //pc.printf("\r\n(ToseparateMRWfromDNM)"); //Having a new line here separated 'message received was:...' from 'Does NOT match...' too much. } if (messageinisneeded == 1) { pc.printf("Does NOT match : %03X %01X %02X %02X %02X %02X %02X %02X %02X %02X\r", expected1, expected2, expected3, expected4, expected5, expected6, expected7, expected8, expected9, expected10); //pc.printf("Check later bytes is %d.\r\n", checklaterbytes); if (messageinisneeded == 1 and aspamisgoing == 0) { pc.printf("\n\n"); } if (messageinisneeded == 1 and aspamisgoing == 1) { pc.printf("\n\n"); } } failsthistest++; //Add 1 to failsthistest to mark the fail expectationwasfulfilled = 0; expectationresolved = 1; } if (itsamatch == 1) { expectationwasfulfilled = 1; expectationresolved = 1; matchesthistest++; //If it's a match, write out a 'Matches expectation...' message if (messageinisneeded == 1) { pc.printf("Matches expectation : %03X %01X %02X %02X %02X %02X %02X %02X %02X %02X\r", expected1, expected2, expected3, expected4, expected5, expected6, expected7, expected8, expected9, expected10); if (aspamisgoing == 0) { pc.printf("\n\n"); } } } } if (idspamon == 1) { idscheckedcount++; idlistincrementer++; //Only add 1 to the idlist incrementer at the end so the first ID it sends is '000'. } if (customentry == 1) { pc.printf("Enter CAN ID to send: "); } } //If speed-spam is on, spam a CAN message as fast as possible. } if (speedspamison == 1) { //sendCAN(); CanBus.write(messageOut1); spamcount++; //pc.printf("\rSent %d '%03X %01X %02X %02X %02X %02X %02X %02X %02X %02X' messages...", spamcount, messageOut1.id, messageOut1.len, messageOut1.data[0], messageOut1.data[1], messageOut1.data[2], messageOut1.data[3], messageOut1.data[4], messageOut1.data[5], messageOut1.data[6], messageOut1.data[7]); //Pressing 'Esc' switches off speed spam mode wait(0.00001); } } }