This package contains a simple test of tests for various elements of the SmartBoard hardware, which is a simple baseboard designed for easy embedding. It is able to run both a semi-automatic test suite as well as allow interactive testing.

Dependencies:   EthernetNetIf NTPClient_NetServices mbed

This program is most of what you need to test your SmartBoard baseboard hardware. It provides a means to test the following:

  • Two channels of CAN (with a loopback cable)
  • RS-232 Ports
  • Analog inputs
  • PWM outputs
  • Ethernet port
  • Real time clock
  • micro SD
  • USB Host port
Revision:
1:586392c0e935
Parent:
0:5db287f0060b
Child:
2:02e7d896824f
--- a/SmartBoard_Tester.cpp	Sun Jan 16 18:30:14 2011 +0000
+++ b/SmartBoard_Tester.cpp	Mon Jan 24 00:41:01 2011 +0000
@@ -24,6 +24,7 @@
 void PWM_Tests(void);
 void AnalogIn_Tests(void);
 void RTC_Tests(void);
+void RTC_Set(void);
 void MicroSD_Tests(void);
 void RS_232_Tests(void);
 void CAN_Tests(void);
@@ -50,7 +51,7 @@
     switch (i) {
         default:
         case '?':
-            pc.printf("Commands:\r\nx"
+            pc.printf("Commands:\r\n"
                       "  L   LED_Tests();\r\n"
                       "  P   PWM_Tests(); // note interaction between LEDs and PWMs\r\n"
                       "  A   AnalogIn_Tests();\r\n"
@@ -77,6 +78,9 @@
         case 'R':
             RTC_Tests();
             break;
+        case 'r':
+            RTC_Set();
+            break;
         case 'M':
             MicroSD_Tests();
             break;
@@ -113,14 +117,14 @@
     bool init = true;                   ///< init is slightly different
     bool interactive = false;           ///< track when in interactive mode
     int test = 0;                       ///< which test to run
-    char TestList[] = "XLPARMSCEU";     ///< list of valid test commands
+    char TestList[] = "XLPARrMSCEU";    ///< list of valid test commands AUTOTESTS are uppercase
 
     while (1) {
         if (pc.readable() || init) {
             pc.printf("\r\n\r\n");
             pc.printf("SmartBoard Hardware Tester\r\n");
             pc.printf("  SmartBoard Hardware    v0.05\r\n");
-            pc.printf("  SmartBoard Software    v0.07\r\n");
+            pc.printf("  SmartBoard Software    v0.09\r\n");
             pc.printf("\r\n");
             pc.printf("                      [USB]       [Eth/USB]    \r\n");
             pc.printf(" +---------------+------------+---+-------+---+\r\n");
@@ -287,7 +291,7 @@
     const int oldTime = 1256729737;
 
     printf("RTC Test:\r\n");
-    ShowTime(0, -6, 0);
+    ShowTime(tzOffsetHr, tzOffsetMin);
     x = time(NULL);         // Save the time before the test
     printf("    Saving current time(%d)\r\n", x);
 
@@ -299,11 +303,94 @@
         wait(1.0);
     }
     set_time(x + time(NULL) - 1256729737);          // Approximately restored
-    ShowTime(0, -6, 0);
+    ShowTime(tzOffsetHr, tzOffsetMin);
     wait(1.0);
-    ShowTime(0, -6, 0);
+    ShowTime(tzOffsetHr, tzOffsetMin);
+}
+
+/// GetNumber will get from the user a number using the
+/// specified number of digits.
+///
+/// They can enter a number from 0 to 10^(digits-1)
+///
+/// @param digits is the number of digits to enter
+/// @param pValue is a pointer to where to store the result
+/// @returns true if a number was entered
+/// @returns false if they entered a non-digit
+///
+int GetNumber(int digits, int * pValue) {
+    int tempValue = 0;
+    int i;
+
+    while (digits--) {
+        i = pc.getc();
+        if (i == ' ') i = '0';      // special case for leading blank
+        if (i >= '0' && i <= '9') {
+            pc.putc(i);
+            tempValue = tempValue * 10 + (i - '0');
+        } else
+            return false;
+    }
+    *pValue = tempValue;
+    return true;
 }
 
+/// RTC_Set will interactively set the Real Time Clock
+///
+/// It will allow you to enter the date and time information
+/// and then create a timestamp. After this, it will set
+/// the RTC to that timestamp.
+///
+void RTC_Set(void) {
+    time_t seconds = time(NULL);
+    struct tm *t = localtime(&seconds);
+    int i;
+
+    printf("RTC Set:\r\n");
+    ShowTime(seconds, tzOffsetHr, tzOffsetMin);
+    printf("    Enter the time MM/DD/YYYY HH:MM:SS\r\n");
+    while (1) {
+        printf("                 > ");
+        if (GetNumber(2, &t->tm_mon)) {
+            pc.putc('/');
+            if (!GetNumber(2, &t->tm_mday))
+                continue;
+            pc.putc('/');
+            if (!GetNumber(4, &t->tm_year))
+                continue;
+        } else {
+            pc.printf("%02d/%02d/%04d", t->tm_mon+1, t->tm_mday, t->tm_year+1900);
+        }
+        pc.putc(' ');
+        if (!GetNumber(2, &t->tm_hour)) {
+            pc.printf("%02d:%02d:%02d\r\n", t->tm_hour, t->tm_min, t->tm_sec);
+            break;          // they can bail here
+        }
+        pc.putc(':');
+        if (!GetNumber(2, &t->tm_min))
+            continue;
+        pc.putc(':');
+        if (!GetNumber(2, &t->tm_sec))
+            continue;
+        else {
+            t->tm_mon--; // 1-12 => 0-11
+            t->tm_year -= 1900;
+            t->tm_hour -= tzOffsetHr;
+            t->tm_min -= tzOffsetMin;
+            pc.printf("\r\n");
+            // convert to timestamp and display (1256729737)
+            time_t seconds = mktime(t);
+            set_time(seconds);
+            break;
+        }
+    }
+    for (i=0; i<5; i++) {
+        ShowTime(tzOffsetHr, tzOffsetMin);
+        wait(1.0);
+    }
+}
+
+
 /// Ethernet_Tests will attempt to test the Ethernet interface
 ///
 /// It will connect to the network - if possible, then it will
@@ -340,34 +427,54 @@
     }
 }
 
+/// isPrint tests the passed in character for being 'printable'
+///
+/// It will evaluate the character on a simple ASCII range of
+/// characters 0 to 127.
+///
+/// @param i is the character to test
+/// @returns true if the character is in the printable set (including <space>)
+/// @returns false if the character is not printable (may be control code or extended character)
+///
+bool isPrint(char i) {
+    if (i >= ' ' && i <= '~')
+        return true;
+    else
+        return false;
+}
+
 /// MicroSD_Tests attempts to access and write a file on the micro SD card
 ///
 /// It will mount the file system, then attempt to write a simple
 /// file on the micro SD card.
 ///
 void MicroSD_Tests(void) {
-    SDFileSystem sd(p5, p6, p7, p8, "sd"); // the pinout on the mbed Cool Components workshop board
+    SDFileSystem sd(p5, p6, p7, p8, "ud"); // the pinout on the mbed Cool Components workshop board
+    DigitalIn cardIn(p11);
     FILE *fp;
     char buffer[50];
 
     printf("SD File System Tests:\r\n");
-    mkdir("/sd/mydir", 0777);
-    fp = fopen("/sd/mydir/sdtest.txt", "w");
-    if (fp == NULL) {
-        printf("    Could not open file for write\r\n");
-    } else {
-        fprintf(fp, "Write a message to the micro SD card!");
-        fclose(fp);
-        printf("    Closed file.\r\n");
-        fp = fopen("/sd/mydir/sdtest.txt", "r");
-        if (fp) {
-            printf("    Reading file back.\r\n");
-            if (fgets(buffer, sizeof(buffer), fp)) {
-                if (strlen(buffer) > 2)
-                    buffer[strlen(buffer)-2] = '\0';    // chomp the <LF>
-                printf("    Read: {%s}\r\n", buffer);
+    printf("    Card Detection: %s\r\n", (cardIn) ? "in" : "out");
+    if (cardIn) {
+        mkdir("/ud/testDir", 0777);
+        fp = fopen("/ud/testDir/sdtest.txt", "w");
+        if (fp == NULL) {
+            printf("    Could not open file for write\r\n");
+        } else {
+            fprintf(fp, "Write a message to the micro SD card!\n");
+            fclose(fp);
+            printf("    Closed file.\r\n");
+            fp = fopen("/ud/testDir/sdtest.txt", "r");
+            if (fp) {
+                printf("    Reading file back.\r\n");
+                if (fgets(buffer, sizeof(buffer), fp)) {
+                    while (strlen(buffer) > 0 && !isPrint(buffer[strlen(buffer)-1]))
+                        buffer[strlen(buffer)-1] = '\0';    // chomp the <LF>
+                    printf("    Read: {%s}\r\n", buffer);
+                }
+                fclose(fp);
             }
-            fclose(fp);
         }
     }
     printf("    test complete!\r\n");
@@ -404,6 +511,51 @@
     }
 }
 
+
+/// FormatMicroseconds will format a number of microseconds int ascii seconds.
+///
+/// It will support formatting the number with decimal and thousands
+/// separators.
+///
+/// @param value to format
+/// @returns the formatted string
+///
+char * FormatMicroseconds(int value) {
+    static char result[15] = "";
+    int uSec = value % 1000000;
+    int Sec = value / 1000000;
+    
+    if (Sec > 1000)
+        sprintf(result, "%3i,%3i.%06i", Sec/1000, Sec%1000, uSec);
+    else
+        sprintf(result, "%7i.%06i", Sec, uSec);
+    return result;
+}
+
+
+/// ShowCANMessage will print to the console as specified
+///
+/// This format is used in other tools, and is not explained
+/// here except in the code.
+///
+/// @param tx indicates it is a transmit message when non-zero, receive otherwise
+/// @param ch is the communication channel of this message
+/// @msg is the CAN message to be shown
+/// @uSec is the timestamp in microseconds
+/// @returns nothing
+///
+void ShowCANMessage(int tx, int ch, CANMessage msg, int uSec) {
+    pc.printf("%c %s %d %08X %02X ", (tx) ? 't' : 'r', (msg.format == CANExtended) ? "xtd" : "nrm", ch, msg.id, msg.len);
+    for (int d=0; d<8; d++) {
+        if (d < msg.len)
+            pc.printf("%02X ", msg.data[d]);
+        else
+            pc.printf("   ");
+    }
+    pc.printf("0   0 %s\r\n", FormatMicroseconds(uSec));
+}
+
+
 /// CAN_Tests will send some packets on one CAN port and expect them on the other
 ///
 /// It will attempt to send 10 messages on one port and expect that
@@ -416,21 +568,39 @@
     CAN can2(p30, p29);
     char Txcounter = 0;
     char Rxcounter = 0;
-    CANMessage msg;
+    CANMessage tMsg;
+    CANMessage rMsg;
+    Timer timer;
     int i;
 
-    printf("CAN Tests:\r\n");
-    for (i=0; i<10; i++) {
-        if (can1.write(CANMessage(1337, &Txcounter, 1))) {
+    pc.printf("CAN Tests:\r\n");
+    i = can1.frequency(250000);
+    pc.printf("    can1 frequency set: %i\r\n", i);
+    i = can2.frequency(250000);
+    pc.printf("    can2 frequency set: %i\r\n", i);
+    timer.start();
+    for (i=0; i<25; i++) {  // gets a few more passes to receive the messages
+
+        for (int x=0; x<8; x++)
+            tMsg.data[x] = (char)(rand());
+        tMsg.data[0] = Txcounter;
+        tMsg.id = rand();
+        tMsg.len = rand() % 9;
+        tMsg.type = CANData;
+        tMsg.format  = (rand() & 1) ? CANExtended : CANStandard;
+
+        if (Txcounter < 10 && can1.write(tMsg)) {
+            pc.printf("    ");
+            ShowCANMessage(1, 1, tMsg, timer.read_us());
             Txcounter++;
-            printf("    Message sent: %d\r\n", Txcounter);
-            wait(0.05);
+            //wait(0.05);
         }
-        if (can2.read(msg)) {
-            printf("    Message received: %d\r\n", msg.data[0]);
+        if (can2.read(rMsg)) {
             Rxcounter++;
+            pc.printf("    ");
+            ShowCANMessage(0, 2, rMsg, timer.read_us());
         }
-        wait(0.2);
+        wait(0.005);
     }
     if (Txcounter == Rxcounter)
         printf("    passed.\r\n");