Making a BMW E90 instrument cluster alive for demonstration purposes

Dependencies:   mbed

Committer:
gume
Date:
Fri Mar 10 09:03:10 2017 +0000
Revision:
2:ef9a8a114395
Parent:
1:a582aeb10c32
Child:
3:4a4463380739
Better timing

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