summaryrefslogtreecommitdiffstats
path: root/Master/Real-Time Systems/mki/src
diff options
context:
space:
mode:
authorSven Eisenhauer <sven@sven-eisenhauer.net>2023-11-10 15:11:48 +0100
committerSven Eisenhauer <sven@sven-eisenhauer.net>2023-11-10 15:11:48 +0100
commit33613a85afc4b1481367fbe92a17ee59c240250b (patch)
tree670b842326116b376b505ec2263878912fca97e2 /Master/Real-Time Systems/mki/src
downloadStudium-master.tar.gz
Studium-master.tar.bz2
add new repoHEADmaster
Diffstat (limited to 'Master/Real-Time Systems/mki/src')
-rw-r--r--Master/Real-Time Systems/mki/src/libcanio.cpp680
-rw-r--r--Master/Real-Time Systems/mki/src/libcanio.h81
-rw-r--r--Master/Real-Time Systems/mki/src/mki.cpp439
-rw-r--r--Master/Real-Time Systems/mki/src/mki.h86
4 files changed, 1286 insertions, 0 deletions
diff --git a/Master/Real-Time Systems/mki/src/libcanio.cpp b/Master/Real-Time Systems/mki/src/libcanio.cpp
new file mode 100644
index 0000000..52cf12c
--- /dev/null
+++ b/Master/Real-Time Systems/mki/src/libcanio.cpp
@@ -0,0 +1,680 @@
+//============================================================================
+// Name:
+// libcanio.cpp
+//
+// Summary:
+// A pretty simple library for the SocketCan layer, which trys to make
+// the communication with the interfaces a bit easier, thus saving the
+// tedious research time needed to get things up and running.
+//
+// Created on:
+// Sep 24, 2010
+//
+// Author:
+// Christian Steiger
+//============================================================================
+
+// TODO CanIO interface - Read me first!
+// As you can see there are a lot of "placeholder routine" TODOs in this file,
+// normally filters can be set per setsocketopt, but not during runtime.
+// Well, it was mentioned on the following page that this is possible...
+// http://www.brownhat.org/docs/socketcan/llcf-api.html
+// ...but i wasnt yet able to find the one command to do it,
+// and my time for this project is rapidly running out. So the current
+// filter implementation is a crude one in software that needs to be
+// replaced with the real thing. Comments and function types already 'fit'
+// more or less, so changes on the class interface shouldnt be neccesary.
+
+// Includes
+#include "libcanio.h"
+
+// Constructor
+CanIO::CanIO()
+{
+ // set default variables
+ m_socket = 0;
+ m_print_errors = 1;
+ m_filter = 0;
+ m_filter_size = 0;
+ m_filter_active = 0;
+}
+
+// Destructor
+CanIO::~CanIO()
+{
+ // properly close the socket
+ disconnect();
+}
+
+//============================================================================
+// 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 CanIO::connect(const char* const interface)
+{
+ // disconnect if theres already an socket present
+ if (m_socket)
+ disconnect();
+
+ // create needed variables
+ struct sockaddr_can addr;
+ struct ifreq ifr;
+ int ret;
+
+ // create a socket handler
+ m_socket = socket(PF_CAN, SOCK_RAW, CAN_RAW);
+
+ // invalid socket_handler?
+ if (m_socket < 0)
+ {
+ // print error message if wanted
+ if (m_print_errors)
+ perror("CanIO::connect, socket");
+
+ // return the result
+ return m_socket;
+ }
+
+ // copy the name of the wanted interface into the ifreq struct
+ strcpy(ifr.ifr_name, interface);
+
+ // and get the interface index via ioctl for further operations
+ ret = ioctl(m_socket, SIOCGIFINDEX, &ifr);
+
+ // check for errors
+ if (ret < 0)
+ {
+ // prints errno message if wanted
+ if (m_print_errors)
+ perror("CanIO::connect, ioctl");
+
+ // close socket
+ disconnect();
+
+ // return the result
+ return ret;
+ }
+
+ if (m_filter_active)
+ setsockopt(
+ m_socket,
+ SOL_CAN_RAW,
+ CAN_RAW_FILTER,
+ m_filter,
+ m_filter_size * sizeof(can_filter)
+ );
+
+ // copy the info we got from the ioctl call
+ addr.can_ifindex = ifr.ifr_ifindex;
+
+ // set the protocol/implementation we want to use
+ addr.can_family = AF_CAN;
+
+ // bind the socket to the device
+ ret = bind(m_socket, (struct sockaddr *)&addr, sizeof(addr));
+
+ // check for errors and prints errno message if wanted
+ if (ret < 0)
+ {
+ // print errormessage if wanted
+ if (m_print_errors)
+ perror("CanIO::connect, bind");
+
+ // close socket
+ disconnect();
+ }
+
+ // return the result
+ return ret;
+}
+
+//============================================================================
+// Summary:
+// Disconnects from a socket can interface
+// Parameters:
+// [out] 0 on success, -1 on failure, sets errno.
+//============================================================================
+int CanIO::disconnect(void)
+{
+ // just abort if there isnt a socket
+ if (!m_socket)
+ return 0;
+
+ // close socket connection
+ int ret = close(m_socket);
+
+ // set m_socket to 0
+ m_socket = 0;
+
+ // check for errors and prints errno message if wanted
+ if (ret < 0 && m_print_errors)
+ perror("CanIO::disconnect, close");
+
+ // return the result
+ return ret;
+}
+
+//============================================================================
+// Summary:
+// Reads a can message from the device. The read ist blocking,
+// if there arent new messages it will wait until one is available!
+// Parameters:
+// [in] frame - pointer to a can_frame where the message data is stored.
+// take a look in /usr/include/linux/can.h for more details.
+// The message type is also in the can_id field, use the masks
+// CAN_EFF_FLAG, CAN_RTR_FLAG and CAN_ERR_FLAG to determine it.
+// [in] timestamp - a pointer to a timeval struct, contains sec and usec.
+// [out] 0 on success, -1 on failure (sets errno), -2 on incomplete frames.
+//============================================================================
+ssize_t CanIO::readMsg(can_frame* frame, timeval* timestamp)
+{
+ // detect nullpointer
+ if (!frame)
+ {
+ // set errno, invalid argument
+ errno = EINVAL;
+
+ // print error message if wanted
+ if (m_print_errors)
+ perror("CanIO::readMsg");
+
+ // return the failure
+ return -1;
+ }
+
+ // create temporary variables
+ ssize_t nbytes;
+
+ // look at the placeholder comment below
+ readmsg_loop:
+
+ // read a can message from the bus
+ nbytes = read(m_socket, frame, sizeof(can_frame));
+
+ // check for errors
+ if (nbytes < 0)
+ {
+ // print errno message if wanted
+ if (m_print_errors)
+ perror("CanIO::readMsg, read");
+
+ // return the result
+ return nbytes;
+ }
+
+ // check for a complete frame
+ // note: we cant fetch missing bytes, each read, even with a byte length of 1,
+ // will get the starting bytes of a new message instead of the missing ones.
+ if (nbytes < (signed int)sizeof(can_frame))
+ {
+ // print error message if wanted
+ if (m_print_errors)
+ fprintf(stderr, "CanIO::readMsg, read: incomplete CAN frame.\n");
+
+ // returns -2 for error indication
+ return -2;
+ }
+
+ // check if a timestamp is wanted
+ if ( timestamp )
+ {
+ // misuse the nbyte variable to get ioctls result
+ nbytes = ioctl(m_socket, SIOCGSTAMP, timestamp);
+
+ // was there an error?
+ if (nbytes < 0)
+ {
+ // print error if wanted
+ if (m_print_errors)
+ perror("CanIO::readMsg, ioctl");
+
+ // returns the result
+ return nbytes;
+ }
+ }
+
+ // TODO CanIO::ReadMsg - Placeholder, remove this part when you rewrite the filter functions.
+ // Its a simple goto command, ugly, but saves code. Dont forget to remove the mark above too.
+ if (m_filter_active > 0)
+ while(!isVisible(frame->can_id))
+ goto readmsg_loop;
+
+ // everything ok, return 0
+ return 0;
+}
+
+
+//============================================================================
+// Summary:
+// Trys to write a can message to the device.
+// Parameters:
+// [in] frame - pointer to a can_frame struct which contains the message_data.
+// [in] frame - pointer to a can_frame struct where the message data is stored.
+// take a look in /usr/include/linux/can.h for more details.
+// The message type is also in the can_id field, use the flags
+// CAN_EFF_FLAG, CAN_RTR_FLAG and CAN_ERR_FLAG to set it.
+// [out] 0 on success, -1 on failure, sets errno.
+//============================================================================
+ssize_t CanIO::writeMsg(const can_frame* const frame)
+{
+ // detect nullpointer
+ if (!frame)
+ {
+ // set errno, invalid argument
+ errno = EINVAL;
+
+ // print error message if wanted
+ if (m_print_errors)
+ perror("CanIO::writeMsg");
+
+ // return the failure
+ return -1;
+ }
+
+ // try to write to the device and return the result
+ int ret = write(m_socket, frame, sizeof(struct can_frame));
+
+ // check for errors and prints errno message if wanted
+ if (ret < 0 && m_print_errors)
+ perror("CanIO::writeMsg, write");
+
+ // return the result
+ return ret;
+}
+
+//============================================================================
+// Summary:
+// Dont print error messages on stderr.
+// Useful if you do want to to the errorhandling yourself.
+// Parameters:
+// none
+//============================================================================
+void CanIO::hideErrors(void)
+{
+ m_print_errors = 0;
+}
+
+//============================================================================
+// Summary:
+// Print error messages on stderr.
+// Useful for debugging purposes, enabled per default.
+// Parameters:
+// none
+//============================================================================
+void CanIO::showErrors(void)
+{
+ m_print_errors = 1;
+}
+
+
+//============================================================================
+// Summary:
+// The driver is able to generate error frames which can be passed to the
+// application in the same way like other can messages,
+// This command enables this feature.
+// Parameters:
+// [in] mask - The errors are divided in different error classes which
+// can be filtered with the appropiate masks.
+// To get every error just ignore this argument, otherwise
+// set the masks for the errors you would like to see.
+// Take a look at /usr/include/linux/can/error.h for masks.
+// [out] 0 on success, -1 on failure, sets errno.
+//============================================================================
+int CanIO::showCanErrors(const can_err_mask_t err_mask)
+{
+ // create temporary variables
+ can_err_mask_t mask = err_mask;
+
+ // check the mask value
+ if (!mask)
+ mask = CAN_ERR_MASK;
+
+ // return the results of setsockopt
+ int ret = setsockopt(
+ m_socket,
+ SOL_CAN_RAW,
+ CAN_RAW_ERR_FILTER,
+ &mask,
+ sizeof(mask)
+ );
+
+ // check for errors and prints errno message if wanted
+ if (ret < 0 && m_print_errors)
+ perror("CanIO::showCanErrors, setsockopt");
+
+ // return the result
+ return ret;
+
+}
+
+//============================================================================
+// Summary:
+// The driver can generate error frames which can be passed to the
+// application in the same way like other can messages,
+// this command disables this feature (default).
+// Parameters:
+// [out] 0 on success, -1 on failure, sets errno.
+//============================================================================
+int CanIO::hideCanErrors(void)
+{
+ // set the mask to zero
+ can_err_mask_t mask = 0;
+
+ // return the results of setsockopt
+ int ret = setsockopt(
+ m_socket,
+ SOL_CAN_RAW,
+ CAN_RAW_ERR_FILTER,
+ &mask,
+ sizeof(mask)
+ );
+
+ // check for errors and prints errno message if wanted
+ if (ret < 0 && m_print_errors)
+ perror("CanIO::hideCanErrors, setsockopt");
+
+ // return the result
+ return ret;
+}
+
+//============================================================================
+// Summary:
+// TODO CanIO::enableLoopBack() - Describe me!
+// Parameters:
+// [out] 0 on success, -1 on failure, sets errno.
+//============================================================================
+int CanIO::enableLoopBack(void)
+{
+ // create temporary variables
+ const int loopback = 1;
+ int ret;
+
+ // set the loopback state
+ ret = setsockopt(
+ m_socket,
+ SOL_CAN_RAW,
+ CAN_RAW_LOOPBACK,
+ &loopback,
+ sizeof(loopback)
+ );
+
+ // check for errors and prints errno message if wanted
+ if (ret < 0 && m_print_errors)
+ perror("CanIO::enableLoopBack, setsockopt");
+
+ // return the result
+ return ret;
+}
+
+//============================================================================
+// Summary:
+// TODO CanIO::disableLoopBack() - Describe me!
+// Parameters:
+// [out] 0 on success, -1 on failure, sets errno.
+//============================================================================
+int CanIO::disableLoopBack(void)
+{
+ // create temporary variables
+ const int loopback = 0;
+ int ret;
+
+ // set the loopback state
+ ret = setsockopt(
+ m_socket,
+ SOL_CAN_RAW,
+ CAN_RAW_LOOPBACK,
+ &loopback,
+ sizeof(loopback)
+ );
+
+ // check for errors and prints errno message if wanted
+ if (ret < 0 && m_print_errors)
+ perror("CanIO::disableLoopBack, setsockopt");
+
+ // return the result
+ return ret;
+}
+
+
+//============================================================================
+// Summary:
+// TODO CanIO::enableRecvOwnMsgs() - Describe me!
+// Parameters:
+// [out] 0 on success, -1 on failure, sets errno.
+//============================================================================
+int CanIO::enableRecvOwnMsgs(void)
+{
+ // create temporary variables
+ const int recv_own_msgs = 1;
+ int ret;
+
+ // set the loopback state
+ ret = setsockopt(
+ m_socket,
+ SOL_CAN_RAW,
+ CAN_RAW_RECV_OWN_MSGS,
+ &recv_own_msgs,
+ sizeof(recv_own_msgs)
+ );
+
+ // check for errors and prints errno message if wanted
+ if (ret < 0 && m_print_errors)
+ perror("CanIO::enableRecvOwnMsgs, setsockopt");
+
+ // return the result
+ return ret;
+}
+
+//============================================================================
+// Summary:
+// TODO CanIO::disableRecvOwnMsgs() - Describe me!
+// Parameters:
+// [out] 0 on success, -1 on failure, sets errno.
+//============================================================================
+int CanIO::disableRecvOwnMsgs(void)
+{
+ // create temporary variables
+ const int recv_own_msgs = 0;
+ int ret;
+
+ // set the loopback state
+ ret = setsockopt(
+ m_socket,
+ SOL_CAN_RAW,
+ CAN_RAW_RECV_OWN_MSGS,
+ &recv_own_msgs,
+ sizeof(recv_own_msgs)
+ );
+
+ // check for errors and prints errno message if wanted
+ if (ret < 0 && m_print_errors)
+ perror("CanIO::disableRecvOwnMsgs, setsockopt");
+
+ // return the result
+ return ret;
+}
+
+//============================================================================
+// Summary:
+// Adds a custom can id filter
+// Parameters:
+// [in] rfilter - Points to an can_filter struct which contains the filter.
+// [in] size - The size of the rfilter.
+// [out] 0 on success, -1 on failure, sets errno.
+//
+// Filter example:
+// This shows messages with an id between 0x200 and 0x2FF:
+// rfilter.can_id = 0x200;
+// rfilter.can_mask = 0xF00;
+//
+// While this hides messages with in id between 0x200 and 0x2FF:
+// rfilter.can_id = 0x200 | CAN_INV_FILTER;
+// rfilter.can_mask = 0xF00;
+//
+// More filters can be combined like this:
+// rfilter[0].can_id = 0x00001234; // exactly this EFF frame
+// rfilter[0].can_mask = CAN_EFF_MASK;
+// rfilter[1].can_id = 0x234; // exactly this SFF frame
+// rfilter[1].can_mask = CAN_SFF_MASK;
+//============================================================================
+// TODO CanIO::addFilter() - Placeholder routine, rewrite for setsockopt.
+int CanIO::addFilter(const can_filter* const filter, const unsigned int size)
+{
+ // detect nullpointer and wrong size
+ if (!filter || size < sizeof(can_filter))
+ {
+ // set errno, invalid argument
+ errno = EINVAL;
+
+ // print error message if wanted
+ if (m_print_errors)
+ perror("CanIO::addFilter");
+
+ // return the failure
+ return -1;
+ }
+
+ // calculate the arraysize
+ unsigned int arraysize = (size / sizeof(can_filter));
+
+ // if there arnt already rules defined
+ if (!m_filter)
+ {
+ // create a new array of pointers to can_filter
+ m_filter = new can_filter[arraysize];
+
+ // just copy the data
+ memcpy(m_filter, filter, size);
+
+ // set the new arraysize
+ m_filter_size = arraysize;
+ }
+
+ // if there are already rules, extend the set
+ else
+ {
+ // copy the pointer from the old array
+ can_filter *temp = m_filter;
+
+ // create a new one, with the size of the two rulesets
+ m_filter = new can_filter[ arraysize + m_filter_size ];
+
+ // copy the old one
+ memcpy(m_filter, temp, m_filter_size * sizeof(can_filter));
+
+ // copy the new one after the end of the old one
+ memcpy(m_filter + m_filter_size, filter, size);
+
+ // set the new filter size
+ m_filter_size += arraysize;
+
+ // delete the content of the old pointer
+ delete temp;
+ }
+
+ // enable the filter
+ if (!m_filter_active)
+ m_filter_active = 1;
+
+ // everything okay
+ return 0;
+}
+
+//============================================================================
+// Summary:
+// Enables the filter, put already stored filter rules back to work.
+// addFilter does this automatically, use disableFilter to prevent it.
+// Parameters:
+// [out] 0 on success, -1 on failure, sets errno.
+//============================================================================
+// TODO CanIO:enableFilter() - Placeholder routine, rewrite for setsockopt.
+int CanIO::enableFilter(void)
+{
+ // sets filter activity
+ m_filter_active = 1;
+
+ // placeholder for setsockopt returns
+ return 0;
+}
+
+//============================================================================
+// Summary:
+// Disables the Filter, but keep the filter rules in the background.
+// Stays disabled until you call enableFilter, regardless of addFilter calls.
+// Parameters:
+// [out] 0 on success, -1 on failure, sets errno.
+//============================================================================
+// TODO CanIO:disableFilter() - Placeholder routine, rewrite for setsockopt.
+int CanIO::disableFilter(void)
+{
+ // sets filter activity
+ m_filter_active = -1;
+
+ // placeholder for setsockopt returns
+ return 0;
+}
+
+//============================================================================
+// Summary:
+// Simply resets the filter.
+// Parameters:
+// [out] 0 on success, -1 on failure, sets errno.
+//============================================================================
+// TODO CanIO::clearFilter() - Placeholder routine, rewrite for setsockopt.
+int CanIO::clearFilter(void)
+{
+ // reset filter size
+ m_filter_size = 0;
+
+ // delete only when there is a pointer
+ if (m_filter)
+ delete m_filter;
+
+ // Everything okay
+ return 0;
+}
+
+//============================================================================
+// Summary:
+// Checks if the given can id is visible or not.
+// Dont use this function, it will be obsolete when
+// the filter functions get a better implementation
+// Parameters:
+// [in] id - The can id
+// [out] True or false, depending on visibility
+//============================================================================
+// TODO CanIO::isVisible() - Placeholder help routine, remove it when you rewrite the filter functions.
+char CanIO::isVisible(const unsigned int id)
+{
+ // declare variables
+ short unsigned int i;
+ char visible = 0;
+
+ // go through the filter rules
+ for (i = 0; i < m_filter_size; i++)
+ {
+ // make things much easier to read,
+ // gcc -O2 will take hopefully care of it
+ const unsigned int rule = (m_filter + i)->can_mask & (m_filter + i)->can_id;
+ const unsigned int input = (m_filter + i)->can_mask & id;
+
+ // inverted filter?
+ if ((m_filter + i)->can_id & CAN_INV_FILTER)
+ {
+ if (rule != input)
+ return 1;
+ }
+ else
+ {
+ if (rule == input)
+ return 1;
+ }
+ }
+ // Everything okay
+ return visible;
+}
+
+
diff --git a/Master/Real-Time Systems/mki/src/libcanio.h b/Master/Real-Time Systems/mki/src/libcanio.h
new file mode 100644
index 0000000..8f57b14
--- /dev/null
+++ b/Master/Real-Time Systems/mki/src/libcanio.h
@@ -0,0 +1,81 @@
+//============================================================================
+// Name:
+// libcanio.h
+//
+// Summary:
+// A pretty simple interface to the SocketCan layer,
+// which trys to make the communication with the can interfaces easier.
+//
+// Created on:
+// Sep 24, 2010
+//
+// Author:
+// Christian Steiger
+//============================================================================
+
+#ifndef LIBCANIO_H_
+#define LIBCANIO_H_
+
+#include <cstdio>
+#include <cstdlib>
+#include <cstring>
+#include <cerrno>
+
+#include <unistd.h>
+#include <net/if.h>
+#include <sys/time.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <linux/can.h>
+#include <linux/can/raw.h>
+#include <linux/can/error.h>
+
+class CanIO
+{
+ public:
+ // constructor and destructor
+ CanIO();
+ virtual ~CanIO();
+
+ // connect and disconnect
+ int connect(const char* const interface = "can0");
+ int disconnect(void);
+
+ // read and write messages
+ ssize_t readMsg(can_frame* frame, timeval* timestamp = 0);
+ ssize_t writeMsg(const can_frame* const frame);
+
+ // socketcan options
+ int showCanErrors(const can_err_mask_t err_mask = 0);
+ int hideCanErrors(void);
+ int enableLoopBack(void);
+ int disableLoopBack(void);
+ int enableRecvOwnMsgs(void);
+ int disableRecvOwnMsgs(void);
+
+ // filter functions
+ int addFilter(const can_filter* const filter, const unsigned int size);
+ int enableFilter(void);
+ int disableFilter(void);
+ int clearFilter(void);
+
+ // debugging help
+ void hideErrors(void);
+ void showErrors(void);
+
+ protected:
+ // class members
+ int m_socket;
+ char m_print_errors;
+ char m_filter_active;
+ can_filter* m_filter;
+ unsigned short int m_filter_size;
+
+ private:
+ // dont use this function, it will be obsolete when
+ // the filter functions get a better implementation
+ char isVisible(const unsigned int id);
+
+};
+
+#endif
diff --git a/Master/Real-Time Systems/mki/src/mki.cpp b/Master/Real-Time Systems/mki/src/mki.cpp
new file mode 100644
index 0000000..1438679
--- /dev/null
+++ b/Master/Real-Time Systems/mki/src/mki.cpp
@@ -0,0 +1,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;
+}
+
+
diff --git a/Master/Real-Time Systems/mki/src/mki.h b/Master/Real-Time Systems/mki/src/mki.h
new file mode 100644
index 0000000..f2ef77b
--- /dev/null
+++ b/Master/Real-Time Systems/mki/src/mki.h
@@ -0,0 +1,86 @@
+//============================================================================
+// Name:
+// mki.h
+//
+// Summary:
+// A pretty simple class for controlling the parts
+// we can on the mercedes-combi-instrument
+//
+// Created on:
+// Okt 1, 2010
+//
+// Author:
+// Christian Steiger
+//============================================================================
+
+// includes
+#include "libcanio.h"
+
+// defines to make things easier, take a look at mkp.cpp
+// to see what they are doing exactly.
+
+// lamps on the display (mki::setLamps())
+#define NONE 0x00
+#define MKI_ABS 0x01
+#define MKI_ESP 0x02
+#define MKI_HANDBRAKE 0x04
+#define MKI_ENGINE 0x08
+#define MKI_WARN 0x10
+#define MKI_WARN_BLINK 0x20
+#define MKI_FUEL_LOW 0x40
+
+// lcd display options (mki::setDisplay())
+#define MKI_LIMIT 0x01
+#define MKI_LIMIT_TEXT 0x02
+#define MKI_PERMANENT 0x04
+#define MKI_EXCEED 0x08
+#define MKI_WINTER_TYRE 0x10
+#define MKI_MPH_BLINK 0x10
+#define MKI_NO_MPH 0x20
+
+// warnings (mki::setAlert())
+#define MKI_OIL_LOW 0x01
+#define MKI_TIRE_PRESSURE 0x02
+#define MKI_TIRE_DEFECT 0x04
+
+
+// class definition
+class mki
+{
+ public:
+ // constructor and destructor
+ mki();
+ ~mki();
+
+ // various methods, see mki.cpp for descriptions
+ int connect( const char* const interface );
+ void setLamps( const unsigned int lamps);
+ void setLampsOff(void);
+ void setRpm( const unsigned short rpm );
+ void setMph( const unsigned char mph );
+ void setCWTemp( const unsigned char temp );
+ void setDisplayMph( const unsigned char mph );
+ void setDisplay( const unsigned int flags );
+ void setAlert( const unsigned int problem );
+
+ void sendData(void);
+
+ void setKmh ( const unsigned char kmh );
+ void setDisplayKmh ( const unsigned char kmh );
+
+ // dont rely to heavily on this, it should be removed asap.
+ CanIO* getInterface(void);
+
+ protected:
+ // class members
+ CanIO m_can;
+ unsigned char m_alert;
+
+ can_frame m_can_id_200;
+ can_frame m_can_id_208;
+ can_frame m_can_id_210;
+ can_frame m_can_id_308;
+ can_frame m_can_id_312;
+ can_frame m_can_id_550;
+ can_frame m_can_id_608;
+};