Libraries to support working with GMLAN - General Motors CAN BUS network in most of their vehicles between 2007-present day. Please note this is a work in progress and not guaranteed to be correct, use at your own risk! Read commit logs / subscribe to see what has been added, it's a work in progress after all ;)

Files at this revision

API Documentation at this revision

Comitter:
foxdie
Date:
Wed Apr 03 16:09:10 2013 +0000
Parent:
5:d0b067be6d44
Child:
7:5ec65e6e8095
Commit message:
Added wrapper for 11-bit requests

Changed in this revision

GMLAN.cpp Show annotated file Show diff for this revision Revisions of this file
GMLAN.h Show annotated file Show diff for this revision Revisions of this file
GMLAN_11bit.h Show annotated file Show diff for this revision Revisions of this file
--- a/GMLAN.cpp	Tue Mar 19 10:03:21 2013 +0000
+++ b/GMLAN.cpp	Wed Apr 03 16:09:10 2013 +0000
@@ -75,4 +75,98 @@
         return CANMessage(hdr.encode29bit(), datatochars, data.size(), CANData, CANExtended);
     else
         return CANMessage(arbitration, datatochars, data.size(), CANData, CANStandard);
+}
+
+GMLAN_11Bit_Request::GMLAN_11Bit_Request(int _id, vector<char> _request) {
+    id = _id;
+    request_data = _request;
+    tx_bytes = rx_bytes = 0;
+    tx_frame_counter = rx_frame_counter = 1;
+    const char _fp [8] = {0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA};
+    memcpy(frame_padding, _fp, 8);
+    request_state = GMLAN_STATE_READY_TO_SEND;
+}
+CANMessage GMLAN_11Bit_Request::getNextFrame(void) {
+    char datatochars [8];
+    memcpy(datatochars, frame_padding, 8);
+
+    if (request_data.size() < 8) {
+        // Unsegmented frame
+        datatochars[0] = (GMLAN_PCI_UNSEGMENTED << 4) | (request_data.size() & 0xF);
+        for (int i = 0; i < request_data.size(); i++) datatochars[i+1] = request_data[i];
+        request_state = GMLAN_STATE_AWAITING_REPLY;
+    } else if (tx_bytes == 0) {
+        // First segmented frame
+        datatochars[0] = (GMLAN_PCI_SEGMENTED << 4) | ((request_data.size() >> 8) & 0xF);
+        datatochars[1] = request_data.size() & 0xFF;
+        for (int i = 0; i < 6; i++) {
+            datatochars[i+2] = request_data[i];
+            tx_bytes++;
+        }
+        request_state = GMLAN_STATE_AWAITING_FC;
+    } else if (tx_bytes <= request_data.size()) {
+        // Additional segmented frame with data left to transmit
+        datatochars[0] = (GMLAN_PCI_ADDITIONAL << 4) | (tx_frame_counter & 0xF);
+        int old_tx_bytes = tx_bytes;
+        for (int i = old_tx_bytes; i < old_tx_bytes + 7; i++) {
+            if (i >= request_data.size()) break;
+            datatochars[(i+1)-old_tx_bytes] = request_data[i];
+            tx_bytes++;
+        }
+        tx_frame_counter++;
+        if (tx_frame_counter > 0xF) tx_frame_counter = 0x0;
+    }
+    
+    if (tx_bytes >= request_data.size()) request_state = GMLAN_STATE_AWAITING_REPLY;
+    
+    return CANMessage(id, datatochars, 8, CANData, CANStandard);
+}
+CANMessage GMLAN_11Bit_Request::getFlowControl(void) {
+    request_state = GMLAN_STATE_AWAITING_REPLY;
+    GMLAN_Message buffer = GMLAN_Message(0x0, id, 0x0, 0x30, 0x0, 0x0);
+    return buffer.generate();
+}
+void GMLAN_11Bit_Request::processFrame(CANMessage msg) {
+    if (((msg.id & 0xFF) == (id & 0xFF)) && (request_state == GMLAN_STATE_AWAITING_REPLY)) {
+        // Only handle requests we've instigated
+        char datatochars [8];
+        memcpy(datatochars, msg.data, 8);
+        
+        if (((datatochars[0] >> 4) & 0xF) == GMLAN_PCI_UNSEGMENTED) {
+            // Unsegmented frame
+            rx_bytes = datatochars[0] & 0xF;
+            if (datatochars[1] == GMLAN_SID_ERROR) {
+                // Error frame
+                if ((rx_bytes == 3) && (datatochars[3] == 0x78)) return; // "Still processing request" message, ignore this one
+                request_state = GMLAN_STATE_ERROR;
+            } else request_state = GMLAN_STATE_COMPLETED;
+            for (int i = 1; i < (rx_bytes+1); i++) response_data.push_back(datatochars[i]);
+        } else if (((datatochars[0] >> 4) & 0xF) == GMLAN_PCI_SEGMENTED) {
+            // First segmented frame
+            rx_bytes = datatochars[0] & 0xF;
+            rx_bytes = (rx_bytes << 8) | datatochars[1];
+            for (int i = 2; i < 8; i++) {
+                if ((i - 2) >= rx_bytes) {
+                    // Safety net for incorrectly formatted packets
+                    request_state = GMLAN_STATE_COMPLETED;
+                    return;
+                }
+                response_data.push_back(datatochars[i]);
+            }
+            request_state = GMLAN_STATE_SEND_FC;
+        } else if (((datatochars[0] >> 4) & 0xF) == GMLAN_PCI_ADDITIONAL) {
+            // Additional segmented frame
+            // TODO check for frame order
+            for (int i = 1; i < 8; i++) {
+                if (response_data.size() + 1 >= rx_bytes) {
+                    request_state = GMLAN_STATE_COMPLETED;
+                    return;
+                }
+                response_data.push_back(datatochars[i]);
+            }
+        } else if (((datatochars[0] >> 4) & 0xF) == GMLAN_PCI_FLOW_CONTROL) {
+            // Flow control frame
+            request_state = GMLAN_STATE_SEND_DATA;
+        }
+    }
 }
\ No newline at end of file
--- a/GMLAN.h	Tue Mar 19 10:03:21 2013 +0000
+++ b/GMLAN.h	Wed Apr 03 16:09:10 2013 +0000
@@ -96,4 +96,38 @@
         CANMessage generate(void);
 };
 
+class GMLAN_11Bit_Request {
+    /*
+    Class to allow easier handling of sending and receiving 11-bit messages
+    */
+    private:
+        vector<char> request_data, response_data;
+        int id, request_state;
+        int tx_frame_counter, tx_bytes;
+        int rx_frame_counter, rx_bytes;
+        
+        char frame_padding [8];
+    
+    public:
+        // (Main function) Create message and send it
+        GMLAN_11Bit_Request(int _id, vector<char> _request);
+        
+        // Process each frame to transmit and flow control frame if needed
+        CANMessage getNextFrame(void);
+        CANMessage getFlowControl(void);
+        // Process each received frame
+        void processFrame(CANMessage msg);
+        
+        // Handle starting and flow control
+        void start(void) { request_state = GMLAN_STATE_SEND_DATA; }
+        void continueFlow(void) { request_state = GMLAN_STATE_SEND_DATA; }
+        
+        // Return request_state to confirm status
+        int getState(void) { return request_state; }
+        // Return ID
+        int getID(void) { return id; }
+        // Return response
+        vector<char> getResponse(void) { return response_data; }
+};
+
 #endif
\ No newline at end of file
--- a/GMLAN_11bit.h	Tue Mar 19 10:03:21 2013 +0000
+++ b/GMLAN_11bit.h	Wed Apr 03 16:09:10 2013 +0000
@@ -19,6 +19,7 @@
 #ifndef GMLAN_11BIT_H
 #define GMLAN_11BIT_H
 
+// CAN IDs
 #define GMLAN_INITIAL_WAKE_UP_REQUEST   0x100
 #define GMLAN_REQUEST_TO_ALL_NODES  0x101
 #define GMLAN_DIAGNOSTIC_REQUEST    0x102
@@ -49,4 +50,42 @@
 #define GMLAN_ECM_TO_EXTERNAL_OBD_TEST_EQUIPMENT    0x7E8
 #define GMLAN_SPECIFIC_OBD_COMPLIANT_ECU_TO_EXTERNAL_OBD_TEST_EQUIPMENT 0x7E9
 
+// PCI byte
+#define GMLAN_PCI_UNSEGMENTED       0x0
+#define GMLAN_PCI_SEGMENTED         0x1
+#define GMLAN_PCI_ADDITIONAL        0x2
+#define GMLAN_PCI_FLOW_CONTROL      0x3
+
+// Service ID byte
+#define GMLAN_SID_CLEAR_DTC         0x4
+#define GMLAN_SID_START_DIAG        0x10
+#define GMLAN_SID_REQ_FAIL_RECS     0x12
+#define GMLAN_SID_REQ_DID           0x1A
+#define GMLAN_SID_RES_NORM_OP       0x20
+#define GMLAN_SID_REQ_PID           0x22
+#define GMLAN_SID_READ_ADDR         0x23
+#define GMLAN_SID_REQ_SEC_ACCESS    0x27
+#define GMLAN_SID_DSBL_NORM_OP      0x28
+#define GMLAN_SID_DEF_DPID_MSG      0x2C
+#define GMLAN_SID_DEF_PID_BY_ADDR   0x2D
+#define GMLAN_SID_DL_REQ            0x34
+#define GMLAN_SID_DATA_TRANS        0x36
+#define GMLAN_SID_WRITE_DID         0x3B
+#define GMLAN_SID_TESTER_PRESENT    0x3E
+#define GMLAN_SID_ERROR             0x7F
+#define GMLAN_SID_REQ_PROG_STATE    0xA2
+#define GMLAN_SID_PROG_MODE         0xA5
+#define GMLAN_SID_READ_DTC          0xA9
+#define GMLAN_SID_REQ_DPID          0xAA
+#define GMLAN_SID_REQ_CONTROL       0xAE
+
+// States of request
+#define GMLAN_STATE_READY_TO_SEND   0x0
+#define GMLAN_STATE_SEND_DATA       0x1
+#define GMLAN_STATE_AWAITING_FC     0x2
+#define GMLAN_STATE_AWAITING_REPLY  0x3
+#define GMLAN_STATE_SEND_FC         0x4
+#define GMLAN_STATE_COMPLETED       0x5
+#define GMLAN_STATE_ERROR           0x6
+
 #endif
\ No newline at end of file