summaryrefslogtreecommitdiffstats
path: root/Master/Real-Time Systems/mki/src/mki.cpp
blob: 1438679688028d06c742f4cb46c5f38e0212c650 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
//============================================================================
// Name:
//   mki.cpp
//
// Summary:
//   A pretty simple class for controlling the parts
//   we can on the mercedes-combi-instrument
//
// Created on:
//   Okt 1, 2010
//
// Author:
//   Christian Steiger
//============================================================================

#include "mki.h"

// constructor
mki::mki()
{
	// set data
	m_alert = 0;

	// clean up structs
	memset(&m_can_id_200, 0, sizeof(m_can_id_200));
	memset(&m_can_id_208, 0, sizeof(m_can_id_208));
	memset(&m_can_id_210, 0, sizeof(m_can_id_210));
	memset(&m_can_id_308, 0, sizeof(m_can_id_308));
	memset(&m_can_id_312, 0, sizeof(m_can_id_312));
	memset(&m_can_id_550, 0, sizeof(m_can_id_550));
	memset(&m_can_id_608, 0, sizeof(m_can_id_608));

	// set message ids
	m_can_id_200.can_id = 0x200;
	m_can_id_208.can_id = 0x208;
	m_can_id_210.can_id = 0x210;
	m_can_id_308.can_id = 0x308;
	m_can_id_312.can_id = 0x312;
	m_can_id_550.can_id = 0x550;
	m_can_id_608.can_id = 0x608;

	// set message length
	m_can_id_200.can_dlc = 8;
	m_can_id_208.can_dlc = 8;
	m_can_id_210.can_dlc = 8;
	m_can_id_308.can_dlc = 8;
	m_can_id_312.can_dlc = 8;
	m_can_id_550.can_dlc = 8;
	m_can_id_608.can_dlc = 8;
}

// destructor
mki::~mki()
{

}


//============================================================================
// Summary:
//   Connects to an socket can interface.
// Parameters:
//   [in] interface - name of the can interface, e.g. can0, vcan0
//   [out] 0 on success, -1 on failure, sets errno.
//============================================================================
int mki::connect( const char* const interface )
{
	return m_can.connect( interface );

}

//============================================================================
// Summary:
//   Enables some of the available lamps in the cockpit.
//
//   Possible values are:
//      MKI_ABS, MKI_ESP, MKI_ENGINE, MKI_WARN,
//      MKI_WARN_BLINK, MKI_FUEL_LOW
//      MKI_HANDBRAKE will cause alarm beep when Mph > 0
//
//   Combine them via logical OR to enable more than one at the same time.
//   Each call will reset the lamp status, so a setLamps(0) will disable all.
//
// Parameters:
//   [in] lamps - bitmask which contains the lamps to activate.
//============================================================================
void mki::setLamps( const unsigned int lamps )
{
	// erase the used bytes to make things easier
	m_can_id_200.data[0] = 0;
	m_can_id_308.data[3] = 0;

	// activate handbrake lamp. can cause alarm beep when moving
	if ( lamps & MKI_HANDBRAKE )
		m_can_id_200.data[0] |= 0x02;

	// activate abs lamp
	if ( lamps & MKI_ABS )
		m_can_id_200.data[0] |= 0x04;

	// activate esp lamp
	if ( lamps & MKI_ESP )
		m_can_id_200.data[0] |= 0x08;

	// activate warning triangle
	if ( lamps & MKI_WARN )
		m_can_id_200.data[0] |= 0x10;

	// activate warning triangle and let it blink. ignores MKI_WARN.
	if ( lamps & MKI_WARN_BLINK )
		m_can_id_200.data[0] |= 0x20;

	// activate fuel low lamp
	if ( lamps & MKI_FUEL_LOW )
		m_can_id_308.data[3] |= 0x01;

	// activate engine lamp
	if ( lamps & MKI_ENGINE )
		m_can_id_308.data[3] |= 0x02;

}

void mki::setLampsOff( void )
{
	// erase the used bytes to make things easier
	m_can_id_200.data[0] = 0;
	m_can_id_308.data[3] = 0;

	// activate handbrake lamp. can cause alarm beep when moving

		m_can_id_200.data[0] |= 0x00;


}





//============================================================================
// Summary:
//   Sets the Rpm.
// Parameters:
//   [in] rpm - the rpm to be set, only values between 0 and 7000 make sense.
//============================================================================
void mki::setRpm( const unsigned short rpm )
{
	// dont allow values higher than 7000, or you may not see anyhting
	const unsigned short int rpm_ = (rpm > 7000) ? 7000 : rpm;

	// convert the rpm for the message bytes
	const unsigned short int hbyte = rpm_ / 250;
	const unsigned short int lbyte = rpm_ - (hbyte *  250);

	// set variables
	m_can_id_308.data[1] = hbyte;
	m_can_id_308.data[2] = lbyte;
}


//============================================================================
// Summary:
//   Sets the Mph.
// Parameters:
//   [in] mph - the mph to be set, only values between 0 and 160 make sense.
//============================================================================
void mki::setMph( const unsigned char mph )
{
	// calculate low and high byte
	unsigned short int hbyte = mph / 10;
	unsigned short int lbyte = (mph - (hbyte * 10)) * 25;

	// filter high byte, since bit 6 and 7 make the hbyte value invalid
	hbyte &= 0x3F;

	// set address 0x200 properties
	m_can_id_200.data[2] = hbyte;
	m_can_id_200.data[3] = lbyte;
	m_can_id_200.data[4] = hbyte;
	m_can_id_200.data[5] = lbyte;

	// set address 0x208 properties
	m_can_id_208.data[4] = hbyte;
	m_can_id_208.data[5] = lbyte;
	m_can_id_208.data[6] = hbyte;
	m_can_id_208.data[7] = lbyte;

}


//============================================================================
// Summary:
//   Sets the cooling water temperature.
//   Just give the value you want to see in degree, e.g. setCWTemp(85).
//   Only values between 40 and 130 make sense, everything else
//   wont be displayed due to display limitatios.
//
// Parameters:
//   [in] temp - the temperature to be set.
//============================================================================
void mki::setCWTemp( const unsigned char temp )
{
	// we need to add an offset of 40 to show the temperature 1:1,
	// since the display wont show anything when we reach 0xFF,
	// we will simply limit the value to the highest possible setting.
	m_can_id_608.data[0] = ((temp + 40) > 176) ? 176 : temp + 40;
}


//============================================================================
// Summary:
//   Sets the properties of the limit mode which is shown in the lcd-display.
//
//   Possible values are:
//     MKI_LIMIT       = activates a big limit view in the lcd-display,
//                       if no changes are made it will switch back and forth
//                       between the main and limit display for a short while,
//                       and then stays in the main mode.
//     MKI_LIMIT_TEXT  = activates a small limit text in the main display mode.
//     MKI_PERMANENT   = make the MKI_LIMIT view permanently visible.
//     MKI_EXCEED      = alarm beep and "exceeded" message in the limit view.
//     MKI_WINTER_TYRE = switches "limit" text to "winter tyre limit".
//     MKI_MPH_BLINK   = let the mph value blink.
//     MKI_NO_MPH      = show --- instad of the mph value.
//
//   The mph value shown there can be controlled with setLimitMph(mph);
//
// Parameters:
//   [in] flags - a bitmask which control the different modes.
//============================================================================
void mki::setDisplay( const unsigned int flags )
{

	// just kill the data content except for byte 7
	// makes life much easier for us in this function
	unsigned short int i;
	for (i = 0; i < 7; i++)
		m_can_id_210.data[i] = 0;

	// enable limit display
	if ( flags & MKI_LIMIT )
		m_can_id_210.data[5] |= 0x01;

	// set permanent limit display
	if ( flags & MKI_PERMANENT )
		m_can_id_210.data[3] = 0x80;

	// shall the mph value blink?
	if ( flags & MKI_MPH_BLINK )
		m_can_id_210.data[5] |= 0x02;

	// --- instead of mph value?
	if ( flags & MKI_NO_MPH )
		m_can_id_210.data[5] |= 0x08;

	// enable winter tyre message instad of limit
	if ( flags & MKI_NO_MPH )
		m_can_id_210.data[5] |= 0x08;

	// exceed warning with alarm sound
	if ( flags & MKI_EXCEED )
		m_can_id_210.data[4] |= 0x01;

	// exceed warning with alarm sound
	if ( flags & MKI_LIMIT_TEXT )
		m_can_id_210.data[4] |= 0x08;

}


//============================================================================
// Summary:
//   Sets the Mph you see in the limit display if you activate
//   it via setDisplay(MKI_LIMIT) or setDisplay(MKI_LIMIT_TEXT).
// Parameters:
//   [in] mph - the mph to be set, a value between 0 and 255.
//============================================================================
void mki::setDisplayMph( const unsigned char mph )
{
	// just copy the value
	m_can_id_210.data[7] = mph;

}


//============================================================================
// Summary:
//   Sets an alert message. Possible alerts are:
//
//     MKI_OIL_LOW        = shows "engine oil level, stop. ENGINE OFF!" alert.
//     MKI_TIRE_PRESSURE  = shows "tire pressure low, check tires".
//     MKI_TIRE_DEFECT    = shows "tire pressure low, caution tire defect!".
//
//   The alerts can be combined via logical OR, in this case it will
//   alert beep once for every error and then switch back and forth
//   between the enabled alerts, MKI_TIRE_DEFECT however overrides
//   MKI_TIRE_PRESSURE, so you wont see it after setting MKI_TIRE_DEFECT.
//
//   To deactivate the alerts just call setAlert(0).
//   It can also take a second or two until the alert gets active.
//
// Parameters:
//   [in] alert - see the description above.
//============================================================================
void mki::setAlert( const unsigned int alert )
{
	// we have a alert
	if (alert)
	{
		// set the appropiate variable so
		// sendData() will send the 0x550 message
		m_alert = 1;

		// kill byte to make things easier
		m_can_id_550.data[0] = 0;

		// tire pressure low alert
		if ( alert & MKI_TIRE_PRESSURE )
			m_can_id_550.data[0] |= 0x10;

		// tire defect alert
		if ( alert & MKI_TIRE_DEFECT )
			m_can_id_550.data[0] |= 0x20;

	}
	else
	{
		// unset the appropiate variable so
		// sendData() wont send the 0x550 message
		m_alert = 0;
	}
}


//============================================================================
// Summary:
//   Sends all the messages the display needs to function.
//   You need to call this command every 50ms or so to keep
//   everything working, best use a while-loop like this:
//
//   while (1) { mki_object.sendData(); usleep(50000); }
//
//   It may be tedious, but makes usage a bit easier, and you can decide
//   on your own how to implement it (let it run in a seperate pthread or so).
//
//   Be aware that the function itself sleeps a good time to prevent
//   write buffer overflows, together its roughly 50ms,
//   60ms if you enabled alerts.
//
// Parameters:
//   none
//============================================================================
// TODO mki::sendData() - Implement error handling to make it more solid.
void mki::sendData(void)
{

	// sleep 10ms between the messages to prevent
	// write buffer error that will happen otherwise.
	m_can.writeMsg(&m_can_id_200);
	usleep(1000);

	m_can.writeMsg(&m_can_id_208);
	usleep(1000);

	m_can.writeMsg(&m_can_id_210);
	usleep(1000);

	m_can.writeMsg(&m_can_id_308);
	usleep(1000);

	m_can.writeMsg(&m_can_id_312);
	usleep(1000);

	m_can.writeMsg(&m_can_id_608);
	usleep(1000);

	// Only write 550 if we have alerts
	if (m_alert) {
		m_can.writeMsg(&m_can_id_550);
		usleep(1000);
	}

}

//============================================================================
// Summary:
//   Sets the Kmh.
//   Works the same wike like setMph(), the Kmh will be converted
//   into Mph and then shown on the display.
//
// Parameters:
//   [in] mph - the mph to be set, only values between 0 and 255 make sense.
//============================================================================
void mki::setKmh ( const unsigned char kmh )
{
	// convert bewteen kmh and mph
	// and call the appropiate function
	setMph( (char)(kmh * 0.6f) );
}


//============================================================================
// Summary:
//   Sets the Kmh for the limit modes.
//   Works the same wike like setDisplayMph(), the Kmh will be converted
//   into Mph and then shown on the display if you used
//   setDisplay(MKI_LIMIT) or setDisplay(MKI_LIMIT_TEXT).
//
// Parameters:
//   [in] mph - the mph to be set, only values between 0 and 255 make sense.
//============================================================================
void mki::setDisplayKmh ( const unsigned char kmh )
{
	// convert bewteen kmh and mph
	// and call the appropiate function
	setMph( (char)(kmh * 0.6f) );
}


//============================================================================
// Summary:
//   Gives back a pointer to the CanIO class that is used to connect
//   to the can interface. Allows you to set some properties like
//   hideErrors() or Loopback. Be cautious with it, the mki-class isnt
//   really prepared for some of the errors you could cause with it.
//
// Parameters:
//   [out] mph - the mph to be set, only values between 0 and 255 make sense.
//============================================================================
// TODO mki::getInterface - Try to optimize the class in a way that allows us to remove this function.
// At the moment the error handling is pretty bad, so you will get spammed with error messages or
// gibberisch when you try to send and the interface isnt up for example, so this needs work.
CanIO* mki::getInterface(void)
{
	// return the reference
	return &m_can;
}