SLCAN/CAN-USB implementation for mbed targets

Dependencies:   USBDevice mbed

Files at this revision

API Documentation at this revision

Comitter:
devanlai
Date:
Sat Feb 04 09:49:57 2017 +0000
Parent:
2:1327e61cc56b
Commit message:
Send z/Z response as expected for T/t/R/r commands.; Add minimal support for F/M/m/s commands for compatibility

Changed in this revision

main.cpp Show annotated file Show diff for this revision Revisions of this file
slcan.cpp Show annotated file Show diff for this revision Revisions of this file
slcan.h Show annotated file Show diff for this revision Revisions of this file
--- a/main.cpp	Thu Jun 09 06:29:08 2016 +0000
+++ b/main.cpp	Sat Feb 04 09:49:57 2017 +0000
@@ -11,20 +11,14 @@
 USBSerial virtualUART(VID, PID, VERSION, false);
 USBSLCAN slcan(virtualUART, can1);
 
-/*
-Serial hwUART(USBTX, USBRX);
-SerialSLCAN slcan(hwUART, can1);
-*/
+//Serial hwUART(USBTX, USBRX);
+//SerialSLCAN slcan(hwUART, can1);
 
 Timer timer;
 DigitalOut led(LED1);
 DigitalOut led2(LED2);
 
 int main() {
-    can1.mode(CAN::Reset);
-    //can1.frequency(500000);
-    //can1.mode(CAN::Silent);
-    
     virtualUART.connect(false);
     //hwUART.baud(115200);
 
@@ -42,7 +36,6 @@
             virtualUART.connect(false);
         }
         
-        
         if (active) {
             timer.reset();
             timer.start();
--- a/slcan.cpp	Thu Jun 09 06:29:08 2016 +0000
+++ b/slcan.cpp	Sat Feb 04 09:49:57 2017 +0000
@@ -148,14 +148,24 @@
 }
 
 size_t SLCANBase::commandResponseLength(const char* command) {
-    if (command[0] == 'N') {
-        return 6;
-    } else if (command[0] == 'V') {
-        return 6;
-    } else if (command[0] == 'v') {
-        return 4;
-    } else {
-        return 1;
+    switch (command[0]) {
+        case 'N':
+        case 'V': {
+            return 6;
+        }
+        case 'v':
+        case 'F': {
+            return 4;
+        }
+        case 'T':
+        case 't':
+        case 'R':
+        case 'r': {
+            return 2;
+        }
+        default: {
+            return 1;
+        }
     }
 }
 
@@ -168,10 +178,14 @@
     switch (command[0]) {
         // Configuration commands
         case 'S':
+        case 's':
         case 'O':
         case 'L':
         case 'l':
-        case 'C': {
+        case 'C':
+        case 'Z':
+        case 'M':
+        case 'm': {
             success = execConfigCommand(command);
             break;
         }
@@ -180,7 +194,7 @@
         case 'T':
         case 'r':
         case 'R': {
-            success = execTransmitCommand(command);
+            success = execTransmitCommand(command, response);
             break;
         }
         // Diagnostic commands
@@ -188,6 +202,7 @@
         case 'v':
         case 'N':
         case 'W':
+        case 'F':
             success = execDiagnosticCommand(command, response);
             break;
         default: {
@@ -204,9 +219,19 @@
     size_t len = strlen(command);
     
     // Validate command length
-    if (len != 1 && command[0] != 'S') {
-        return false;
-    } else if (command[0] == 'S' && len != 2) {
+    if (command[0] == 'M' || command[0] == 'm') {
+        if (len != 9) {
+            return false;
+        }
+    } else if (command[0] == 's') {
+        if (!((len == 5) || (len == 7))) {
+            return false;
+        }
+    } else if (command[0] == 'S' || command[0] == 'Z') {
+        if (len != 2) {
+            return false;
+        }
+    } else if (len != 1) {
         return false;
     }
 
@@ -249,6 +274,22 @@
             success = setMode(CAN::Reset);
             break;
         }
+        case 's': {
+            // TODO: implement direct BTR control
+            success = true;
+            break;
+        }
+        case 'M':
+        case 'm': {
+            // TODO: implement filtering
+            success = true;
+            break;
+        }
+        case 'Z': {
+            // TODO: implement timestamping
+            success = true;
+            break;
+        }
         default: {
             success = false;
             break;
@@ -258,13 +299,14 @@
     return success;
 }
 
-bool SLCANBase::execTransmitCommand(const char* command) {
+bool SLCANBase::execTransmitCommand(const char* command, char* response) {
     bool success = false;
 
     size_t len = strlen(command);
 
     bool validMessage = false;
     CANMessage msg;
+
     if (command[0] == 't' || command[0] == 'T') {
         msg.type = CANData;
         msg.format = (command[0] == 't') ? CANStandard : CANExtended;
@@ -290,8 +332,15 @@
             }
         }
     }
-
+    
     if (validMessage) {
+        if (command[0] == 'T' || command[0] == 'R') {
+            response[0] = 'Z';
+            response[1] = '\0';
+        } else if (command[0] == 't' || command[0] == 'r') {
+            response[0] = 'z';
+            response[1] = '\0';
+        }
         success = transmitMessage(msg);
     }
 
@@ -354,6 +403,14 @@
             response[index] = '\0';
             break;
         }
+        case 'F': {
+            success = true;
+            uint8_t status = 0x00;
+            response[0] = 'F';
+            response[1] = format_nibble(status >> 4);
+            response[2] = format_nibble(status >> 0);
+            response[3] = '\0';
+        }
         case 'W': {
             // Just swallow the MCP2515 register write command
             success = true;
@@ -388,7 +445,7 @@
 }
 
 bool USBSLCAN::transmitMessage(CANMessage& msg) {
-    return (can.write(msg) == 1);    
+    return (can.write(msg) == 1);
 }
 
 bool USBSLCAN::getNextCANMessage(CANMessage& msg) {
--- a/slcan.h	Thu Jun 09 06:29:08 2016 +0000
+++ b/slcan.h	Sat Feb 04 09:49:57 2017 +0000
@@ -33,7 +33,7 @@
     
 private:
     bool execConfigCommand(const char* command);
-    bool execTransmitCommand(const char* command);
+    bool execTransmitCommand(const char* command, char* response);
     bool execDiagnosticCommand(const char *command, char* response);
 };