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 ;)
GMLAN.cpp
00001 /* 00002 GMLAN.cpp - Source file for GMLAN Library 00003 00004 GMLAN is a Controller Area Network Bus used in General Motors vehicles from 00005 roughly 2007-onwards. Its purpose is to allow various Electronic Control Units 00006 (aka ECUs) within a modern vehicle to share information and enact procedures. 00007 00008 An example of this would be communication between the HU (Head unit) and the 00009 DIC (Dashboard Information Cluster), when you adjust the volume up / down, this 00010 is reported to the cluster to be displayed. 00011 00012 It is the function of this library to "crack open" this world to allow anyone 00013 with only as little as a few hours of C++ programming under their belt to get 00014 started in what can sometimes seem a daunting world. 00015 00016 Jason Gaunt, 18th Feb 2013 00017 */ 00018 00019 #include "mbed.h" 00020 #include "GMLAN.h" 00021 #include <vector> 00022 00023 void CANHeader::decode(int _header) { 00024 if (_header < 0x800) 00025 { 00026 // 11-bit header 00027 arbitrationID = (_header >> 0) & 0x7FF; 00028 } else { 00029 // 29-bit header 00030 priorityID = (_header >> 26) & 0x7; 00031 arbitrationID = (_header >> 13) & 0x1FFF; 00032 senderID = (_header >> 0) & 0x1FFF; 00033 } 00034 } 00035 int CANHeader::encode29bit(void) { 00036 long int buffer = 0; 00037 buffer = (buffer << 3) | 0x0; // 3 bit padding 00038 buffer = (buffer << 3) | priorityID; 00039 buffer = (buffer << 13) | arbitrationID; 00040 buffer = (buffer << 13) | senderID; 00041 return buffer; 00042 } 00043 int CANHeader::encode11bit(void) { 00044 short int buffer = 0; 00045 buffer = (buffer << 5) | 0x0; // 5 bit padding 00046 buffer = (buffer << 11) | arbitrationID; 00047 return buffer; 00048 } 00049 00050 00051 GMLAN_Message::GMLAN_Message(int _priority, int _arbitration, int _sender, 00052 int _b0, int _b1, int _b2, int _b3, int _b4, int _b5, int _b6, int _b7) { 00053 priority = _priority; 00054 arbitration = _arbitration; 00055 sender = _sender; 00056 if (_b0 != -1) data.push_back(_b0); 00057 if (_b1 != -1) data.push_back(_b1); 00058 if (_b2 != -1) data.push_back(_b2); 00059 if (_b3 != -1) data.push_back(_b3); 00060 if (_b4 != -1) data.push_back(_b4); 00061 if (_b5 != -1) data.push_back(_b5); 00062 if (_b6 != -1) data.push_back(_b6); 00063 if (_b7 != -1) data.push_back(_b7); 00064 } 00065 CANMessage GMLAN_Message::generate(void) { 00066 CANHeader hdr; 00067 hdr.priority(priority); 00068 hdr.arbitration(arbitration); 00069 hdr.sender(sender); 00070 00071 char datatochars [data.size()]; 00072 for (int i = 0; i < data.size(); i++) datatochars[i] = data[i]; 00073 00074 if (sender > 0x0) 00075 return CANMessage(hdr.encode29bit(), datatochars, data.size(), CANData, CANExtended); 00076 else 00077 return CANMessage(arbitration, datatochars, data.size(), CANData, CANStandard); 00078 } 00079 00080 GMLAN_11Bit_Request::GMLAN_11Bit_Request(int _id, vector<char> _request, bool _await_response, bool _handle_flowcontrol) { 00081 id = _id; 00082 request_data = _request; 00083 await_response = _await_response; 00084 handle_flowcontrol = _handle_flowcontrol; 00085 tx_bytes = rx_bytes = 0; 00086 tx_frame_counter = rx_frame_counter = 1; 00087 const char _fp [8] = {0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA}; 00088 memcpy(frame_padding, _fp, 8); 00089 request_state = GMLAN_STATE_READY_TO_SEND; 00090 } 00091 CANMessage GMLAN_11Bit_Request::getNextFrame(void) { 00092 char datatochars [8]; 00093 memcpy(datatochars, frame_padding, 8); 00094 00095 if (handle_flowcontrol == true) { 00096 // Only run this section if we need flow control 00097 if (request_data.size() < 8) { 00098 // Unsegmented frame 00099 datatochars[0] = (GMLAN_PCI_UNSEGMENTED << 4) | (request_data.size() & 0xF); 00100 for (int i = 0; i < request_data.size(); i++) { 00101 datatochars[i+1] = request_data[i]; 00102 tx_bytes++; 00103 } 00104 request_state = GMLAN_STATE_AWAITING_REPLY; 00105 } else if (tx_bytes == 0) { 00106 // First segmented frame 00107 datatochars[0] = (GMLAN_PCI_SEGMENTED << 4) | ((request_data.size() >> 8) & 0xF); 00108 datatochars[1] = request_data.size() & 0xFF; 00109 for (int i = 0; i < 6; i++) { 00110 datatochars[i+2] = request_data[i]; 00111 tx_bytes++; 00112 } 00113 request_state = GMLAN_STATE_AWAITING_FC; 00114 } else if (tx_bytes <= request_data.size()) { 00115 // Additional segmented frame with data left to transmit 00116 datatochars[0] = (GMLAN_PCI_ADDITIONAL << 4) | (tx_frame_counter & 0xF); 00117 int old_tx_bytes = tx_bytes; 00118 for (int i = old_tx_bytes; i < old_tx_bytes + 7; i++) { 00119 if (i >= request_data.size()) break; 00120 datatochars[(i+1)-old_tx_bytes] = request_data[i]; 00121 tx_bytes++; 00122 } 00123 tx_frame_counter++; 00124 if (tx_frame_counter > 0xF) tx_frame_counter = 0x0; 00125 } 00126 if (tx_bytes >= request_data.size()) { 00127 if (await_response == true) request_state = GMLAN_STATE_AWAITING_REPLY; 00128 else request_state = GMLAN_STATE_COMPLETED; 00129 } 00130 } else { 00131 // No flow control required, build the frames without parsing but make sure we don't overshoot 8 bytes 00132 for (int i = 0; i < request_data.size(); i++) { 00133 if (i < 8) { 00134 datatochars[i] = request_data[i]; 00135 tx_bytes++; 00136 } 00137 else break; 00138 } 00139 if (await_response == true) request_state = GMLAN_STATE_AWAITING_REPLY; 00140 else request_state = GMLAN_STATE_COMPLETED; 00141 } 00142 00143 return CANMessage(id, datatochars, 8, CANData, CANStandard); 00144 } 00145 CANMessage GMLAN_11Bit_Request::getFlowControl(void) { 00146 request_state = GMLAN_STATE_AWAITING_REPLY; 00147 GMLAN_Message buffer = GMLAN_Message(0x0, id, 0x0, 0x30, 0x0, 0x0); 00148 return buffer.generate(); 00149 } 00150 void GMLAN_11Bit_Request::processFrame(CANMessage msg) { 00151 if (((msg.id & 0xFF) == (id & 0xFF)) && 00152 ((request_state == GMLAN_STATE_AWAITING_REPLY) || (request_state == GMLAN_STATE_AWAITING_FC)) 00153 ) { 00154 // Only handle requests we've instigated 00155 char datatochars [8]; 00156 memcpy(datatochars, msg.data, 8); 00157 00158 if (((datatochars[0] >> 4) & 0xF) == GMLAN_PCI_UNSEGMENTED) { 00159 // Unsegmented frame 00160 rx_bytes = (datatochars[0] & 0xF); 00161 if (datatochars[1] == GMLAN_SID_ERROR) { 00162 // Error frame 00163 if ((rx_bytes == 3) && (datatochars[3] == 0x78)) return; // "Still processing request" message, ignore this one 00164 request_state = GMLAN_STATE_ERROR; 00165 } else request_state = GMLAN_STATE_COMPLETED; 00166 for (int i = 1; i < (rx_bytes+1); i++) response_data.push_back(datatochars[i]); 00167 } else if (((datatochars[0] >> 4) & 0xF) == GMLAN_PCI_SEGMENTED) { 00168 // First segmented frame 00169 rx_bytes = (datatochars[0] & 0xF); 00170 rx_bytes = (rx_bytes << 8) | datatochars[1]; 00171 for (int i = 2; i < 8; i++) { 00172 if ((i - 2) >= rx_bytes) { 00173 // Safety net for incorrectly formatted packets 00174 request_state = GMLAN_STATE_COMPLETED; 00175 return; 00176 } 00177 response_data.push_back(datatochars[i]); 00178 } 00179 request_state = GMLAN_STATE_SEND_FC; 00180 } else if (((datatochars[0] >> 4) & 0xF) == GMLAN_PCI_ADDITIONAL) { 00181 // Additional segmented frame 00182 // TODO check for frame order 00183 for (int i = 1; i < 8; i++) { 00184 if (response_data.size() >= rx_bytes) { 00185 request_state = GMLAN_STATE_COMPLETED; 00186 return; 00187 } 00188 response_data.push_back(datatochars[i]); 00189 } 00190 if (response_data.size() >= rx_bytes) { 00191 request_state = GMLAN_STATE_COMPLETED; 00192 return; 00193 } 00194 } else if (((datatochars[0] >> 4) & 0xF) == GMLAN_PCI_FLOW_CONTROL) { 00195 // Flow control frame 00196 request_state = GMLAN_STATE_SEND_DATA; 00197 } 00198 } 00199 }
Generated on Tue Jul 12 2022 23:00:10 by 1.7.2