Making a BMW E90 instrument cluster alive for demonstration purposes

Dependencies:   mbed

Committer:
gume
Date:
Sat Mar 11 10:03:52 2017 +0000
Revision:
3:4a4463380739
Parent:
2:ef9a8a114395
Initial Speed module (not yet working); Fuel data

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gume 0:830e074c92d5 1 #include "mbed.h"
gume 0:830e074c92d5 2 #include "T15Msg.h"
gume 3:4a4463380739 3 #include "SpeedMsg.h"
gume 0:830e074c92d5 4
gume 2:ef9a8a114395 5 Timer timer100;
gume 2:ef9a8a114395 6 Timer timer200;
gume 0:830e074c92d5 7
gume 1:a582aeb10c32 8 Serial pc(USBTX, USBRX);
gume 0:830e074c92d5 9 DigitalOut led1(PA_5);
gume 0:830e074c92d5 10 CAN can1(PB_8, PB_9); // rd, td Transmitter
gume 3:4a4463380739 11
gume 0:830e074c92d5 12 T15Msg t15;
gume 3:4a4463380739 13 SpeedMsg speed;
gume 0:830e074c92d5 14
gume 2:ef9a8a114395 15 int fuel1 = 0x4F04;
gume 2:ef9a8a114395 16 int fuel2 = 0x2312;
gume 2:ef9a8a114395 17
gume 2:ef9a8a114395 18 char absCtr = 0;
gume 2:ef9a8a114395 19 unsigned char airBagCtr = 0;
gume 2:ef9a8a114395 20 char ctr100 = 0;
gume 2:ef9a8a114395 21
gume 0:830e074c92d5 22 /*
gume 0:830e074c92d5 23 0x130 (CAS) T15 signal, 100 ms
gume 0:830e074c92d5 24 0x1B4 (Kombi) OUT? Speed status, 100 ms
gume 0:830e074c92d5 25 */
gume 0:830e074c92d5 26
gume 1:a582aeb10c32 27
gume 0:830e074c92d5 28 void sendT15() {
gume 1:a582aeb10c32 29 if (!t15.sendMessage(&can1)) {
gume 1:a582aeb10c32 30 pc.printf("Cannot send T15!\n");
gume 1:a582aeb10c32 31 }
gume 0:830e074c92d5 32 /*
gume 0:830e074c92d5 33 char data_130 [] = { 0x45, 0x42, 0x8F, 0xE2, 0xFE };
gume 0:830e074c92d5 34 char data_130 [] = { 0x45, 0x40, 0x21, 0x8F, 0x00 };
gume 0:830e074c92d5 35 */
gume 0:830e074c92d5 36 }
gume 0:830e074c92d5 37
gume 2:ef9a8a114395 38 void sendABSCtr() {
gume 2:ef9a8a114395 39
gume 2:ef9a8a114395 40 char data[2];
gume 2:ef9a8a114395 41 absCtr++;
gume 2:ef9a8a114395 42 if (absCtr == 0x0f) absCtr = 0;
gume 2:ef9a8a114395 43 data[0] = 0xf0 | absCtr;
gume 2:ef9a8a114395 44 data[1] = 0xff;
gume 2:ef9a8a114395 45 if (!can1.write(CANMessage(0x0C0, data, 2))) {
gume 2:ef9a8a114395 46 pc.printf("Cannot send ABS counter!\n");
gume 2:ef9a8a114395 47 }
gume 2:ef9a8a114395 48 }
gume 2:ef9a8a114395 49
gume 2:ef9a8a114395 50 void sendAirBagCtr() {
gume 2:ef9a8a114395 51
gume 2:ef9a8a114395 52 char data[2];
gume 2:ef9a8a114395 53 airBagCtr++;
gume 2:ef9a8a114395 54 if (airBagCtr == 0xff) airBagCtr = 0;
gume 2:ef9a8a114395 55 data[0] = airBagCtr;
gume 2:ef9a8a114395 56 data[1] = 0xff;
gume 2:ef9a8a114395 57 if (!can1.write(CANMessage(0x0D7, data, 2))) {
gume 2:ef9a8a114395 58 pc.printf("Cannot send AirBag counter!\n");
gume 2:ef9a8a114395 59 }
gume 1:a582aeb10c32 60 }
gume 1:a582aeb10c32 61
gume 0:830e074c92d5 62 void sendLight(char mode) {
gume 0:830e074c92d5 63
gume 0:830e074c92d5 64 /*
gume 0:830e074c92d5 65 // Light
gume 0:830e074c92d5 66 CAN ID-----DATA
gume 0:830e074c92d5 67 ===== ----====
gume 0:830e074c92d5 68 21A-------00 20 F7 OFF
gume 0:830e074c92d5 69 21A-------04 22 F7 Parking light / angel eyes
gume 0:830e074c92d5 70 21A-------05 22 F7 Light on
gume 0:830e074c92d5 71 */
gume 0:830e074c92d5 72
gume 0:830e074c92d5 73 char *data;
gume 0:830e074c92d5 74 char data_21A_0 [] = { 0x00, 0x20, 0xF7 };
gume 0:830e074c92d5 75 char data_21A_1 [] = { 0x04, 0x22, 0xF7 };
gume 0:830e074c92d5 76 char data_21A_2 [] = { 0x05, 0x22, 0xF7 };
gume 0:830e074c92d5 77
gume 0:830e074c92d5 78 switch (mode) {
gume 0:830e074c92d5 79 case 1:
gume 0:830e074c92d5 80 data = data_21A_1;
gume 0:830e074c92d5 81 break;
gume 0:830e074c92d5 82 case 2:
gume 0:830e074c92d5 83 data = data_21A_2;
gume 0:830e074c92d5 84 break;
gume 0:830e074c92d5 85 default:
gume 0:830e074c92d5 86 data = data_21A_0;
gume 0:830e074c92d5 87 break;
gume 0:830e074c92d5 88 }
gume 0:830e074c92d5 89 if (can1.write(CANMessage(0x21A, data, 3))) {
gume 1:a582aeb10c32 90 pc.printf("Light sent %d\n", mode);
gume 0:830e074c92d5 91 }
gume 0:830e074c92d5 92 }
gume 0:830e074c92d5 93
gume 0:830e074c92d5 94 //Ignition status
gume 0:830e074c92d5 95 /*
gume 0:830e074c92d5 96 0[7]: engine runinng
gume 0:830e074c92d5 97 1[7]: ignition || engine running
gume 0:830e074c92d5 98 2[7]: ignition || engine running
gume 0:830e074c92d5 99 2[654312]: 111111
gume 0:830e074c92d5 100 3: 0x50
gume 0:830e074c92d5 101 4-7: 0xff
gume 0:830e074c92d5 102 */
gume 0:830e074c92d5 103
gume 0:830e074c92d5 104 /*
gume 0:830e074c92d5 105 // Ignition
gume 0:830e074c92d5 106 char data_26E [] = { 0x40, 0x40, 0x4F, 0x50, 0xFF, 0xFF, 0xFF, 0xFF };
gume 0:830e074c92d5 107 if(can1.write(CANMessage(0x26E, data_26E, 8))) {
gume 0:830e074c92d5 108 printf("Ignition sent \n");
gume 0:830e074c92d5 109 }
gume 0:830e074c92d5 110 */
gume 0:830e074c92d5 111
gume 0:830e074c92d5 112 /*
gume 0:830e074c92d5 113 // RPM
gume 0:830e074c92d5 114 char data_0A5 [] = { 0xCD, 0xD5, 0xEC, 0xC7, 0x7E, 0x34, 0x0C, 0xF1 };
gume 0:830e074c92d5 115 if(can1.write(CANMessage(0x0A5, data_0A5, 8))) {
gume 0:830e074c92d5 116 printf("RPM sent \n");
gume 0:830e074c92d5 117 }
gume 0:830e074c92d5 118 */
gume 0:830e074c92d5 119
gume 0:830e074c92d5 120 /*
gume 0:830e074c92d5 121 // Speed
gume 0:830e074c92d5 122 char data_1A6 [] = { 0x13, 0x4D, 0x46, 0x4D, 0x33, 0x4D, 0xD0, 0xFF };
gume 0:830e074c92d5 123 if(can1.write(CANMessage(0x1A6, data_1A6, 8))) {
gume 0:830e074c92d5 124 printf("Speed sent \n");
gume 0:830e074c92d5 125 }
gume 0:830e074c92d5 126 */
gume 0:830e074c92d5 127
gume 0:830e074c92d5 128 /*
gume 0:830e074c92d5 129 // Door
gume 0:830e074c92d5 130 char data_2FC [] = { 0x81, 0x01, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
gume 0:830e074c92d5 131 if(can1.write(CANMessage(0x2FC, data_2FC, 7))) {
gume 0:830e074c92d5 132 printf("Door sent \n");
gume 0:830e074c92d5 133 }
gume 0:830e074c92d5 134 */
gume 0:830e074c92d5 135
gume 0:830e074c92d5 136 /*
gume 0:830e074c92d5 137 // HB
gume 0:830e074c92d5 138 char data_34F [] = { 0xFE, 0xFF };
gume 0:830e074c92d5 139 //data_34F[0] = counter;
gume 0:830e074c92d5 140 if(can1.write(CANMessage(0x34F, data_34F, 2))) {
gume 0:830e074c92d5 141 printf("HB sent \n");
gume 0:830e074c92d5 142 }
gume 0:830e074c92d5 143 */
gume 0:830e074c92d5 144
gume 2:ef9a8a114395 145 void sendFuel() {
gume 2:ef9a8a114395 146
gume 2:ef9a8a114395 147 char data[5];
gume 2:ef9a8a114395 148 data[0] = fuel1 / 256;
gume 2:ef9a8a114395 149 data[1] = fuel1 & 0xff;
gume 2:ef9a8a114395 150 data[2] = fuel2 / 256;
gume 2:ef9a8a114395 151 data[3] = fuel2 & 0xff;
gume 2:ef9a8a114395 152 data[4] = 0;
gume 2:ef9a8a114395 153
gume 2:ef9a8a114395 154 if(!can1.write(CANMessage(0x349, data, 5))) {
gume 2:ef9a8a114395 155 printf("Cannot send fuel!\r\n");
gume 0:830e074c92d5 156 }
gume 2:ef9a8a114395 157 }
gume 2:ef9a8a114395 158
gume 2:ef9a8a114395 159 void canLoop() {
gume 2:ef9a8a114395 160
gume 2:ef9a8a114395 161 if (timer100.read_ms() > 100) {
gume 2:ef9a8a114395 162 sendT15();
gume 3:4a4463380739 163 speed.sendMessage(&can1);
gume 2:ef9a8a114395 164
gume 2:ef9a8a114395 165 timer100.reset();
gume 2:ef9a8a114395 166 led1 = !led1;
gume 2:ef9a8a114395 167 }
gume 2:ef9a8a114395 168
gume 2:ef9a8a114395 169 if (timer200.read_ms() > 200) {
gume 2:ef9a8a114395 170 sendABSCtr();
gume 2:ef9a8a114395 171 sendAirBagCtr();
gume 2:ef9a8a114395 172 sendFuel();
gume 2:ef9a8a114395 173
gume 2:ef9a8a114395 174 timer200.reset();
gume 2:ef9a8a114395 175 }
gume 2:ef9a8a114395 176 }
gume 2:ef9a8a114395 177
gume 0:830e074c92d5 178
gume 1:a582aeb10c32 179 bool sendMessage(int id, char *data, int len) {
gume 1:a582aeb10c32 180
gume 2:ef9a8a114395 181 pc.printf("Sending message: %01X%02X (%d), ", id >> 8, id & 0xff, id);
gume 1:a582aeb10c32 182 for (int i = 0; i < len; i++) pc.printf("%02X ", data[i]);
gume 1:a582aeb10c32 183 pc.printf("\r\n");
gume 1:a582aeb10c32 184
gume 1:a582aeb10c32 185 return can1.write(CANMessage(id, data, len));
gume 1:a582aeb10c32 186 }
gume 1:a582aeb10c32 187
gume 2:ef9a8a114395 188 int readHex(char *hexstr, uint8_t *data, int len) {
gume 2:ef9a8a114395 189
gume 2:ef9a8a114395 190 int i = 0, l = 0;
gume 2:ef9a8a114395 191 char hexnums[128];
gume 2:ef9a8a114395 192
gume 2:ef9a8a114395 193 while (i < len) {
gume 2:ef9a8a114395 194 char h = hexstr[i++];
gume 2:ef9a8a114395 195 if ((h < '0' || h > 'F') || (h > '9' && h < 'A')) continue;
gume 2:ef9a8a114395 196 if (h >= 'A') hexnums[l++] = 10 + (h - 'A');
gume 2:ef9a8a114395 197 else hexnums[l++] = h - '0';
gume 2:ef9a8a114395 198 }
gume 2:ef9a8a114395 199 hexnums[l] = 0; // Extra 0 for uneven pairs
gume 2:ef9a8a114395 200 i = 0;
gume 2:ef9a8a114395 201 while (i < (l+1) / 2) {
gume 2:ef9a8a114395 202 data[i] = (hexnums[i * 2] << 4) | hexnums[i * 2 + 1];
gume 2:ef9a8a114395 203 i++;
gume 2:ef9a8a114395 204 }
gume 2:ef9a8a114395 205 return (l+1) / 2;
gume 2:ef9a8a114395 206
gume 2:ef9a8a114395 207 }
gume 1:a582aeb10c32 208
gume 0:830e074c92d5 209 //**********The main program*********************
gume 1:a582aeb10c32 210
gume 1:a582aeb10c32 211 void doCommand(char *command) {
gume 1:a582aeb10c32 212
gume 1:a582aeb10c32 213 pc.printf("Command: %s\r\n", command);
gume 1:a582aeb10c32 214 for (int j = 0;;j++) {
gume 1:a582aeb10c32 215 pc.printf("%02x ", command[j]);
gume 1:a582aeb10c32 216 if (command[j] == 0) break;
gume 1:a582aeb10c32 217 }
gume 1:a582aeb10c32 218 pc.printf("\r\n");
gume 1:a582aeb10c32 219
gume 1:a582aeb10c32 220 if (strcmp(command, "START") == 0) {
gume 1:a582aeb10c32 221 pc.printf("Start\r\n");
gume 1:a582aeb10c32 222 t15.start();
gume 3:4a4463380739 223 speed.setSpeed(0x13, 0x4d, 0x46, 0x4d, 0x33, 0x4d);
gume 1:a582aeb10c32 224 }
gume 1:a582aeb10c32 225
gume 1:a582aeb10c32 226 else if (strcmp(command, "STOP") == 0) {
gume 1:a582aeb10c32 227 pc.printf("Stop\n");
gume 3:4a4463380739 228 speed.setSpeed(0x0, 0x0, 0x0, 0x0, 0x0, 0x0);
gume 1:a582aeb10c32 229 t15.stop();
gume 1:a582aeb10c32 230 }
gume 1:a582aeb10c32 231
gume 1:a582aeb10c32 232 else if (command[0] == 'L') {
gume 1:a582aeb10c32 233 int mode = command[1] - '0';
gume 1:a582aeb10c32 234 sendLight(mode);
gume 1:a582aeb10c32 235 }
gume 1:a582aeb10c32 236
gume 1:a582aeb10c32 237 else if (command[0] == 'M') {
gume 2:ef9a8a114395 238 uint8_t hexid[4];
gume 2:ef9a8a114395 239 uint8_t canmsg[8];
gume 2:ef9a8a114395 240 int idlen;
gume 2:ef9a8a114395 241
gume 2:ef9a8a114395 242 if (strchr(command + 1, ' ')) idlen = strchr(command + 1, ' ') - (command + 1);
gume 2:ef9a8a114395 243 else return;
gume 2:ef9a8a114395 244 readHex(command + 1, hexid, idlen);
gume 2:ef9a8a114395 245 int id = hexid[0] * 256 + hexid[1];
gume 2:ef9a8a114395 246 int l = readHex(command + 1 + idlen, canmsg, strlen(command + 1 + idlen));
gume 1:a582aeb10c32 247
gume 2:ef9a8a114395 248 sendMessage(id, (char*) canmsg, l);
gume 2:ef9a8a114395 249 }
gume 2:ef9a8a114395 250
gume 2:ef9a8a114395 251 else if (command[0] == 'F') {
gume 2:ef9a8a114395 252 uint8_t hexfuel[4];
gume 2:ef9a8a114395 253
gume 2:ef9a8a114395 254 int l = readHex(command + 1, hexfuel, strlen(command + 1));
gume 2:ef9a8a114395 255 fuel1 = hexfuel[0] * 256 + hexfuel[1];
gume 2:ef9a8a114395 256 if (l>2) fuel2 = hexfuel[2] * 256 + hexfuel[3];
gume 2:ef9a8a114395 257
gume 2:ef9a8a114395 258 pc.printf("Set fuel to %02x%02x : %02x%02x.\r\n", fuel1 / 256, fuel1 & 0xff, fuel2 / 256, fuel2 & 0xff);
gume 1:a582aeb10c32 259 }
gume 1:a582aeb10c32 260 }
gume 1:a582aeb10c32 261
gume 0:830e074c92d5 262 int main() {
gume 0:830e074c92d5 263
gume 1:a582aeb10c32 264 pc.baud(115200);
gume 0:830e074c92d5 265 can1.frequency(100000);
gume 2:ef9a8a114395 266
gume 2:ef9a8a114395 267 timer100.start();
gume 2:ef9a8a114395 268 timer200.start();
gume 2:ef9a8a114395 269
gume 2:ef9a8a114395 270 pc.printf("CAN hacking started\r\n");
gume 1:a582aeb10c32 271
gume 1:a582aeb10c32 272 char buffer[128];
gume 1:a582aeb10c32 273 int bufferlen = 0;
gume 0:830e074c92d5 274
gume 1:a582aeb10c32 275 while (1) {
gume 2:ef9a8a114395 276
gume 2:ef9a8a114395 277 canLoop();
gume 2:ef9a8a114395 278
gume 1:a582aeb10c32 279 if (pc.readable()) {
gume 1:a582aeb10c32 280 char c = pc.getc();
gume 1:a582aeb10c32 281 pc.putc(c); // Local ECHO
gume 1:a582aeb10c32 282 if (c == '\r') {
gume 1:a582aeb10c32 283 buffer[bufferlen] = 0;
gume 1:a582aeb10c32 284 doCommand(buffer);
gume 1:a582aeb10c32 285 bufferlen = 0;
gume 1:a582aeb10c32 286 } else {
gume 1:a582aeb10c32 287 buffer[bufferlen++] = c;
gume 1:a582aeb10c32 288 }
gume 1:a582aeb10c32 289 }
gume 1:a582aeb10c32 290 }
gume 1:a582aeb10c32 291
gume 0:830e074c92d5 292 }