Program the control the fischertechnik robo interface or intelligent interface via tcp socket or via a java gui.

Dependencies:   mbed ConfigFile

Revision:
0:7f26f0680202
Child:
1:2c9d412ad471
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libft.c	Fri Dec 31 14:01:14 2010 +0000
@@ -0,0 +1,2802 @@
+//this file was adapted by Ad for use in the mbed environment
+//currently all USB functionality has been disabled, this may change in the future
+//the comport functionality has been adapted to the mbed serial class
+//threads and semphores were replaced by other primitives
+//as a consequence also the ftlib.h was adapted
+
+/** @file
+ *
+ * Copyright (C) 2007 Erik Andresen erik@vontaene.de
+ *
+ * Open Source version of the fischertechnik ROBO Interface Library for Unix like systems
+ *
+ * Communication is done through a "transfer area" this is constantly updated.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+/**
+ * \example example.c
+ *
+ * \mainpage libft Index Page
+ *
+ * \section intro_sec Introduction
+ *
+ * libft is an Open Source version of the fischertechnik ROBO Interface Library for Unix like systems
+ *
+ * The goal is to create a library that is fully compatible with the ftlib by knobloch eletronic.
+ *
+ * This library should work on any systems supported by libusb, like Linux, BSD and Mac OS X and is released
+ * under the GNU Lesser General Public License (LGPL)
+ *
+ * Included is the helper program "ftuploader" which allows you to upload programs to the Robo Interface.\n
+ * Running ftuploader --help should give you an idea how to use it.\n
+ * Also included is an Interface Diagnose utility. See section Interface Diagnose
+ *
+ * \section dl_sec Download
+ * Current Version: 0.4.3
+ *
+ * See http://defiant.homedns.org/~erik/ft/libft/files/ \n
+ * Download Latest version: http://defiant.homedns.org/~erik/ft/libft/files/libft-current.tar.gz
+ *
+ * \section req_sec Requirements
+ * - libusb - http://libusb.sourceforge.net/
+ * - cmake at least version 2.4 - http://cmake.org
+ * - pthreads (Should be included with every modern posix compatible OS)
+ *
+ *
+ * \section apidoc_sec API Documentation
+ * \see libft.c
+ *
+ * \section install_sec Installation
+ *
+ * \subsection step1 Step 1: Compiling
+ *
+ * Type
+ * - cmake .
+ * - make
+ * \subsection step2 Step 2: Installation
+ * Type
+ * - make install
+ *
+ * After installing you should run
+ * - ldconfig
+ *
+ * to make the library known to your system. Make sure that /etc/ld.so.conf is configured to include /usr/local/li
+ *
+ * To install the diagnose utility type
+ * - make diag
+ *
+ * Debian packages are available. Please read http://vontaene.de/apt/README.txt.\n
+ * You can install them with apt-get install libft0 libft-doc libft-python libft-diag
+ *
+ * \subsection step3 Step 3: udev
+ * When running udev you might want to copy the file fischertechnik.rules from the udev folder to /etc/udev/rules.d/ to get the correct permissions.\n
+ * Udev then needs a reload with
+ * - udevcontrol reload_rules
+ *
+ * You will now need to replug your device.
+ *
+ * \subsection step4 Step 4: Create Documentation\n
+ * Type\n
+ * - make doc\n
+ * to create the html API documentation.
+ *
+ * \subsection step5 Step 5: Python
+ * A Python interface to this library is available, see the python folder for details.\n
+ * Type\n
+ * make python\n
+ *
+ * in the python/ -folder to install the python module.
+ * Use pydoc to read its documentation:
+ * - pydoc robointerface in the shell
+ * - help(robointerface) from the python interpreter
+ *
+ * \section diag_sec Interface Diagnose
+ * You can find it in the folder diag/.\n
+ * It requires the python module (see above) and PyQT4. You can launch it by running "sh ftdiagnose"
+ * \image html diag1.png
+ *
+ * \section author_sec Author
+ * Erik Andresen - erik@vontaene.de
+ *
+ * Please contact me for bugs or any suggestions
+ *
+ * Homepage of libft: http://defiant.homedns.org/~erik/ft/libft/
+ *
+ *
+ * \section changes_sec Changes
+ *
+ * - 0.4.3:    - Bug fix: Extension digital inputs at RoboRF
+ *        - ftdiagnose: Display connection status
+ *        - Added functions: (not in Knobloch lib):
+ *            - IsFtInterfaceConnected()
+ *        - Python added functions:
+ *            - IsConnected()
+ * - 0.4.2:    - Python support to open the interface by serial
+ *        - Some Bug fixes
+ *         - Added functions: (not in Knobloch lib)
+ *             - SetRealSerial()
+ * - 0.4.1:
+ *           - Added support to change the RF address.
+ *         - Added functions: (not in Knobloch lib)
+ *             - SetRFMode()
+ *             - GetRFMode()
+ *         - Added support for functions:
+ *             - GetFtManufacturerStrg()
+ *             - GetFtShortNameStrg()
+ *             - GetFtLongNameStrg()
+ *             - GetFtLibErrorString()
+ *         - Some minor Bug fixes
+ * - 0.4:
+ *           - Hopefully support for more then one Robo Interface attached to an RF Link.
+ *             - InitFtUsbDeviceList() will now also count the number of Robo Interfaces attached to an RF Link
+ *         - Added support for the ft distance sensor
+ *         - Added functions:
+ *             - GetFtDeviceTypeString() (not in Knobloch lib)
+ *         - Added support for functions:
+ *             - SetFtDistanceSensorMode()
+ *         - Python added functions:
+ *             - GetNumFtUsbDevices()
+ *             - RoboInterface.GetDeviceTypeString()
+ *             - GetD1()
+ *             - GetD2()
+ *         - Added ft Diagnose utility.
+ * - 0.3:
+ *           - added (overwrite) --target option to the ftuploader
+ *         - included some documentation
+ *         - minor fixes
+ *         - enhanced python layer
+ *         - support for RF Module
+ * - 0.2.1:
+ *           - fixed Analog/Voltage Sensor calculations
+ * - 0.2:
+ *           - added udev file
+ *         - experimental support for uploading to the interface (usb only)
+ *         - included program ftuploader
+ *         - add support for functions:
+ *             - DownloadFtProgram()
+ *             - StartFtProgram()
+ *             - StopFtProgram()
+ *             - DeleteFtProgram()
+ *             - SetFtProgramActiv()
+ *             - GetFtProgramName()
+ *             - GetFtStatus()
+ *             - GetFtFirmware()
+ *             - GetFtFirmwareStrg()
+ *             - GetFtSerialNr()
+ *             - GetFtSerialNrStrg()
+ *
+ *
+ * \section porting_sec Porting your program from the Knobloch Windows Library
+ * When porting your program from the Knobloch Library for Microsoft Windows operation systems please note the following:
+ * - The name of this library is libft, not ftlib (the Knobloch original) to follow the UNIX naming scheme
+ * - Types like DWORD are replaced with their logical ANSI-C counterparts, like
+ *   -# DWORD - long int
+ *   -# LPCSTR - char *
+ *   -# LPVOID - void *
+ *   -# BYTE - unsigned char
+ *   -# USHORT - unsigned short int
+ *   -# UINT - unsigned int
+ *   -# UCHAR - unsigned char
+ * - The Windows Notifications stuff will probably never be supported.
+ * - Some return codes might be different, so if something is going wrong, check this manual.
+ *
+ */
+#define MBED
+#define NOTNOW
+#define SPLITTRANSFER
+
+#ifdef MBED
+#include "mbed.h"
+#define usleep(x)    wait_us(x)
+#define sleep(x)    wait(x)
+#define LIBFT_VERSION_MAJOR 1
+#define LIBFT_VERSION_MINOR 0
+#define LIBFT_VERSION_PATCH 0
+extern Serial viaUsb;
+#else
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <termios.h>
+#include <fcntl.h>
+#endif
+#ifdef USE_USB
+#include <usb.h>
+#else
+//some dummy USB stuff
+#endif
+#ifdef USE_DOWNLOAD
+#include "crc.h"
+#endif
+#include "ftlib.h"
+
+/** \cond doxygen ignore start */
+#define VERSION_MAJOR LIBFT_VERSION_MAJOR
+#define VERSION_MINOR LIBFT_VERSION_MINOR
+#define VERSION_PATCH LIBFT_VERSION_PATCH
+#define FT_VENDOR_ID 0x146a
+#define ROBO_IF_PRODUCT_ID 0x1
+#define EXT_IF_PRODUCT_ID 0x2
+#define RF_DATA_LINK_PRODUCT_ID 0x3
+#define ABF_IF_COMPLETE 0x8b // 0xf2
+#define INTERFACE_QUERY_TIME 10000 // &#65533;s == 5ms
+#define INTERFACE_QUERY_TIME_SERIAL 10000
+#define FT_ENDPOINT_INTERRUPT_IN 0x81
+#define FT_ENDPOINT_INTERRUPT_OUT 0x1
+#define FT_ENDPOINT_BULK_IN 0x82
+#define FT_ENDPOINT_BULK_OUT 0x2
+#define FT_RF_ENDPOINT_INTERRUPT_IN 0x82
+#define FT_RF_ENDPOINT_INTERRUPT_OUT 0x2
+#define FT_USB_TIMEOUT 1000
+#define FT_USB_TIMEOUT_LONG 10000
+
+#ifdef MBED
+#define BAUDRATE_II 9600
+#define BAUDRATE_RI 38400
+#else
+#define BAUDRATE_II B9600
+#define BAUDRATE_RI B38400
+#endif
+#define PROGRAM_UPLOAD_PACKET_SIZE 128
+
+#ifndef MIN
+#define MIN(a, b) ( (a)<=(b) ? (a) : (b) )
+#endif
+/** \endcond doxygen ignore end */
+
+
+/**
+ * \brief Returns lib version
+ *
+ *  Returns the library version.
+ *
+ *  @return version as Major Minor Patch
+ */
+long int GetLibVersion() {
+    return VERSION_MAJOR<<16 | VERSION_MINOR<<8 | VERSION_PATCH;
+}
+
+
+/**
+ * \brief Returns lib version
+ *
+ * Returns the library version.
+ * The allocated space should be freed with free() later.
+ *
+ * @return Pointer to a string with the serial
+ */
+char *GetLibVersionStrg() {
+    long int ver = GetLibVersion();
+    char *s = (char *)malloc(16);
+    int byte1 = ver & 0xff;
+    int byte2 = (ver & 0xff00) >> 8;
+    int byte3 = (ver & 0xff0000) >> 16;
+
+    snprintf(s, 16, "%d.%02d.%02d", byte3, byte2, byte1);
+
+    return s;
+}
+
+
+/**
+ * \brief Library initialization (dummy)
+ *
+ * Dummy for compatibility. Only used in original library.
+ * @return Always FTLIB_ERR_SUCCESS
+ */
+long int InitFtLib() {
+    return FTLIB_ERR_SUCCESS;
+}
+
+
+/**
+ * \brief Initiates and scans the USB bus
+ *
+ * This function has to be called before any other USB action.
+ * It will set up USB basic variables and then scan the USB bus.
+ *
+ * @return Always FTLIB_ERR_SUCCESS. Not able to fail.
+ */
+long int InitFtUsbDeviceList() {
+#ifdef USE_USB
+    usb_init();
+    usb_find_busses();
+    usb_find_devices();
+#endif
+    return FTLIB_ERR_SUCCESS;
+}
+
+
+/** \cond doxygen ignore start */
+static unsigned int GetNumFtDevicesFromRF(struct usb_device *dev) {
+    unsigned int iNum = 0;
+#ifdef USE_USB
+    usb_dev_handle *device;
+    int ret;
+    unsigned char buffer[35] = { 0 };
+    int i;
+
+    device = usb_open(dev);
+
+    for (i=1; i<9; i++) {
+        ret = usb_control_msg(device, 0xc0, 0x52, i<<8 | 0x05, 0, buffer, 35, FT_USB_TIMEOUT);
+        if (ret < 0) fprintf(stderr, "Error sending control msg 0xC0 0x52\n");
+        else if (buffer[0] == 0xfa && buffer[1] == 0) iNum++; // buffer[1] == 0xff => no device
+    }
+
+    usb_close(device);
+#endif
+    return iNum;
+}
+
+
+static unsigned int GetNthFtDeviceFromRF(struct usb_device *dev, int iNum) {
+    int ret=0;
+#ifdef USE_USB
+    usb_dev_handle *device;
+    unsigned char buffer[35] = { 0 };
+    int i;
+
+    device = usb_open(dev);
+
+    for (i=1; i<9, iNum>0; i++) {
+        ret = usb_control_msg(device, 0xc0, 0x52, i<<8 | 0x05, 0, buffer, 35, FT_USB_TIMEOUT);
+        if (ret < 0) fprintf(stderr, "Error sending control msg 0xC0 0x52\n");
+        else if (buffer[0] == 0xfa && buffer[1] == 0) iNum--; // buffer[1] == 0xff => no device
+
+        ret = i;
+    }
+
+    usb_close(device);
+#endif
+    return ret;
+}
+
+
+static int GetFtDeviceFromRFWithSerial(struct usb_device *dev, long int dwSN) {
+#ifdef USE_USB
+    usb_dev_handle *device;
+    int ret;
+    unsigned char buffer[35] = { 0 };
+    int i;
+    long int serial;
+
+    device = usb_open(dev);
+
+    for (i=1; i<9; i++) {
+        ret = usb_control_msg(device, 0xc0, 0x52, i<<8 | 0x05, 0, buffer, 35, FT_USB_TIMEOUT);
+        if (ret < 0) fprintf(stderr, "Error sending control msg 0xC0 0x52\n");
+        else if (buffer[0] == 0xfa && buffer[1] == 0) { // buffer[1] == 0xff => no device
+            serial = buffer[6]<<24 | buffer[5]<<16 | buffer[4]<<8 | buffer[3];
+
+            if (serial == dwSN) {
+                return i;
+            }
+        }
+    }
+
+    usb_close(device);
+#endif
+    return 0;
+}
+/** \endcond doxygen ignore end */
+
+
+/**
+ * \brief Get the count of found ft Interfaces over USB.
+ *
+ * If we find a Robo RF Data Link we will count the devices attached to it instead
+ *
+ * @return Number of ft Interface devices on the USB bus found.
+ */
+unsigned int GetNumFtUsbDevice() {
+    unsigned int iNum = 0;
+#ifdef USE_USB
+    struct usb_device *dev;
+    struct usb_bus *busses;
+    struct usb_bus *bus;
+    busses = usb_get_busses();
+
+    for (bus = busses; bus; bus = bus->next) {
+        for (dev = bus->devices; dev; dev = dev->next) {
+            if (dev->descriptor.idVendor == FT_VENDOR_ID) {
+                if (dev->descriptor.idProduct == RF_DATA_LINK_PRODUCT_ID) {
+                    iNum+=GetNumFtDevicesFromRF(dev);
+                }
+                iNum++;
+            }
+        }
+    }
+#endif
+    return iNum;
+}
+
+
+/** \cond doxygen ignore start */
+static int FtproductIDToInterfaceID(int iProductID) {
+    switch (iProductID) {
+        case ROBO_IF_PRODUCT_ID:
+            return FT_ROBO_IF_USB;
+        case EXT_IF_PRODUCT_ID:
+            return FT_ROBO_IO_EXTENSION;
+        case RF_DATA_LINK_PRODUCT_ID:
+            return FT_ROBO_RF_DATA_LINK;
+    }
+
+    return 0;
+}
+
+
+static int FtInterfaceIDToProductID(int InterfaceID) {
+    switch (InterfaceID) {
+        case FT_ROBO_IF_USB:
+            return ROBO_IF_PRODUCT_ID;
+        case FT_ROBO_IO_EXTENSION:
+            return EXT_IF_PRODUCT_ID;
+        case FT_ROBO_RF_DATA_LINK:
+            return RF_DATA_LINK_PRODUCT_ID;
+    }
+
+    return 0;
+}
+/** \endcond doxygen ignore end */
+
+
+/**
+ * \brief Gets the handle to a ft USB device.
+ *
+ * Get the handle for the ft USB device with this number.
+ * Passing just 0 as argument will use the first device found.
+ *
+ * Count the interfaces with GetNumFtUsbDevice()
+ *
+ * @see GetNumFtUsbDevice()
+ * @param Num selected Interface. If unsure try 0.
+ * @return The ft device or NULL if error
+ */
+FT_HANDLE GetFtUsbDeviceHandle(unsigned char Num) {
+#ifdef USE_USB
+    struct usb_device *dev;
+    struct usb_bus *busses;
+    struct usb_bus *bus;
+    int i=0;
+    FT_HANDLE ret;
+    int count_ri_at_rf;
+    busses = usb_get_busses();
+
+    for (bus = busses; bus; bus = bus->next) {
+        for (dev = bus->devices; dev; dev = dev->next) {
+            if (dev->descriptor.idVendor == FT_VENDOR_ID) {
+                if (dev->descriptor.idProduct == RF_DATA_LINK_PRODUCT_ID) {
+                    count_ri_at_rf = GetNumFtDevicesFromRF(dev);
+                    i+=count_ri_at_rf;
+                }
+                if (i >= Num) { // '>=' because any RF will add more then 1 to the count
+                    ret = (FT_HANDLE) malloc (sizeof(struct ft_handle_devices));
+                    if (ret == NULL) {
+                        perror("GetFtUsbDeviceHandle malloc");
+                        return NULL;
+                    }
+                    ret->device = NULL;
+                    ret->dev = dev;
+                    ret->sdev = 0;
+                    ret->type = FtproductIDToInterfaceID(dev->descriptor.idProduct);
+                    sem_init(&ret->lock, 0, 1);
+                    memset(&ret->transfer_area, 0, sizeof(struct _FT_TRANSFER_AREA));
+                    ret->transfer_area.TransferAktiv = 0;
+                    ret->query_time = INTERFACE_QUERY_TIME;
+                    ret->transfer_area.RfModulNr = -1;
+                    ret->interface_connected = 0;
+
+                    if (dev->descriptor.idProduct == RF_DATA_LINK_PRODUCT_ID) {
+                        ret->transfer_area.RfModulNr = GetNthFtDeviceFromRF(dev, Num);
+                        if (ret->transfer_area.RfModulNr == 0) // user has chosen the RF Modul, so choose the first Interface at RF for the user
+                            ret->transfer_area.RfModulNr = GetNthFtDeviceFromRF(dev, 1);
+                        else
+                            ret->type = FT_ROBO_IF_OVER_RF;
+                    }
+
+                    return ret;
+                }
+                i++;
+            }
+        }
+    }
+#endif
+    return NULL;
+}
+
+
+/**
+ * \brief Gets the handle to a ft USB device with a specific serial number.
+ *
+ * Get the handle for the ft USB device with this number.
+ * Serial is 1 for most devices, unless explicitly changed in the device.
+ * Second argument can be FT_AUTO_TYPE.
+ *
+ * @param dwSN Serial of the USB Device
+ * @param dwTyp Type of the USB Device: FT_AUTO_TYPE, FT_ROBO_IF_USB, FT_ROBO_IO_EXTENSION, FT_ROBO_IF_OVER_RF or FT_ROBO_RF_DATA_LINK
+ * @return The ft device or NULL on error
+ */
+FT_HANDLE GetFtUsbDeviceHandleSerialNr(long int dwSN, long int dwTyp) {
+#ifdef USE_USB
+    int i;
+    FT_HANDLE ret;
+    for (i=0; i < GetNumFtUsbDevice(); i++) {
+        ret = GetFtUsbDeviceHandle(i);
+        OpenFtUsbDevice(ret);
+
+        if ((dwTyp == FT_AUTO_TYPE || ret->type == dwTyp) && GetFtSerialNr(ret) == dwSN) {
+            CloseFtDevice(ret);
+            return ret;
+        }
+
+        CloseFtDevice(ret);
+    }
+#endif
+    return NULL;
+}
+
+
+//blocking
+int read(Serial *d, unsigned char *ptr, int n) {
+    for (int i = 0; i< n; i++) {
+        ptr[i] = d->getc();
+    }
+    return n;
+}
+int read(Serial *stream, unsigned char *buf, int n, int timeout_ms) {
+    Timer t;
+    t.start();
+    int i = 0;
+    while (t.read_ms() < timeout_ms && i < n) {
+        if (stream->readable())
+            buf[i++] = stream->getc();
+    }
+    return i;
+}
+
+//blocking
+int write(Serial *d, unsigned char *ptr, int n) {
+    for (int i = 0; i< n; i++) {
+        d->putc(ptr[i]);
+    }
+    return n;
+}
+int write(Serial *d, unsigned char *ptr, int n, int timeout_ms) {
+    Timer t;
+    t.start();
+    int i = 0;
+    while (t.read_ms() < timeout_ms && i < n) {
+        if (d->writeable())
+            d->putc(ptr[i++]);
+    }
+    return i;
+}
+
+//non-blocking
+int ft_handle_devices::write() {
+    windex = 0;
+    //sdev->attach(this, &ft_handle_devices::writeByte, Serial::TxIrq);//could be moved to FtThreadInit
+    //sdev->attach(this, &ft_handle_devices::readByte, Serial::RxIrq);
+    writeByte(); //write the first byte, callback will take care of the rest
+    return num_write;
+}
+void ft_handle_devices::writeByte() {
+    if (windex < num_write) {
+        sdev->putc(out[windex++]);
+        if (windex == num_write)
+            rindex = 0;
+    }
+}
+void ft_handle_devices::readByte() {
+    if (rindex < num_read) {
+        in[rindex++] = sdev->getc();
+        if (rindex == num_read) {
+            //sdev->attach(0,Serial::RxIrq);//could be moved to FtThreadFinish
+            //sdev->attach(0,Serial::TxIrq);
+            FtThreadEnd();
+        }
+    }
+}
+/**
+ * \brief Gets the handle to a ft serial device.
+ *
+ * Get the handle for the ft Serial device at the selected serial port.
+ *
+ * @param sDevice filename of your serial device, like /dev/ttyS0.
+ * @param dwTyp Interface type. FT_INTELLIGENT_IF, FT_INTELLIGENT_IF_SLAVE or FT_ROBO_IF_COM.
+ * @param dwZyklus Cycle to retrieve analog values (only II). Try 10.
+ * @return The ft device or NULL if error.
+ */
+FT_HANDLE OpenFtCommDevice(char *sDevice, long int dwTyp, long int dwZyklus) {//makes a (blocking) comm request to the interface
+    FT_HANDLE ret;
+    unsigned char in[5];
+    unsigned char on[] = " ft-Robo-ON-V1";
+    on[0] = 0xA1;
+#ifdef MBED
+    Serial *dev;
+    switch (sDevice[3]) {
+        case '1':
+            dev = new Serial(p9, p10);
+            break;
+        case '2':
+            dev = new Serial(p13, p14);
+            break;
+        case '3':
+            dev = new Serial(p28, p27);
+            break;
+//      default:  dev = new Serial(p9, p10); break;
+        default:
+            dev = &viaUsb;
+            break;
+    }
+    ret = new ft_handle_devices;
+#else
+    long int dev;
+    if ((dev = open(sDevice, O_RDWR | O_NOCTTY)) < 0) {
+        perror("OpenFtCommDevice open");
+        return NULL;
+    }
+
+    if ((ret = (FT_HANDLE) malloc (sizeof(struct ft_handle_devices))) == NULL) {
+        perror("GetFtUsbDeviceHandle malloc");
+        return NULL;
+    }
+    ret->device = NULL;
+    ret->dev = NULL;
+#endif
+    ret->type = dwTyp;
+    memset(&ret->transfer_area, 0, sizeof(struct _FT_TRANSFER_AREA));
+    ret->transfer_area.TransferAktiv = 0;
+    ret->analogcycle = dwZyklus/2.0+0.5;
+    ret->query_time = INTERFACE_QUERY_TIME_SERIAL;
+    ret->transfer_area.RfModulNr = -1;
+    ret->interface_connected = 0;
+#ifdef MBED
+    ret->lock = 1; //init the semaphore
+    if (dev != &viaUsb) {
+        if (dwTyp == FT_INTELLIGENT_IF || dwTyp == FT_INTELLIGENT_IF_SLAVE || dwTyp == FT_ROBO_IF_IIM)
+            dev->baud(BAUDRATE_II);
+        else // dwTyp == FT_ROBO_IF_COM
+            dev->baud(BAUDRATE_RI);
+    }
+    ret->sdev = dev;
+    if (dwTyp == FT_INTELLIGENT_IF) ret->transfer_area.BusModules = 1;
+    else if (dwTyp == FT_INTELLIGENT_IF_SLAVE) ret->transfer_area.BusModules = 2;
+    printf("about to send '%s'\n", on);
+    if (dwTyp == FT_ROBO_IF_COM) {
+        int sent = write(dev, on, strlen((const char*)on), 100/*ms*/);
+//        int sent = dev->printf("%s", on);
+        printf("sent %d bytes to COM\n", sent);
+        if (sent == strlen((const char*)on)) {
+            if (read(dev, in, 5, 1000/*ms*/) == 5) {              //   if (dev->scanf("%5c", in) == 1) { does not work, could have to do with NUL chars or needs a lookahead char
+                printf("%02X: interface version: %d.%d.%d.%d\n", in[0], in[4], in[3], in[2], in[1]);
+                if ((in[0] ^ on[0]) ==  0x0FFU) {
+                    printf("opening of %s OK\n", sDevice);
+                } else {
+                    printf("return code is %02X but should be %02X\n", in[0], ~on[0]&0xFF);
+                    delete ret;
+                    return NULL;
+                }
+            } else {
+                printf("read did not return 5\n");
+                delete ret;
+                return NULL;
+            }
+        } else {
+            printf("only %d chars were sent i.o %d\n", sent, strlen((const char*)on));
+            delete ret;
+            return NULL;
+        }
+    }
+    //printf("OpenFtCommDevice: Error communicating with serial\n");
+    //delete ret;
+    //return NULL;
+//}
+#else
+    sem_init(&ret->lock, 0, 1);
+    tcgetattr(dev, &ret->saveioset); /* save current modem settings */
+    bzero(&ret->newioset, sizeof(struct termios));
+    ret->newioset.c_cflag = CS8 | CLOCAL | CREAD;
+    if (dwTyp == FT_INTELLIGENT_IF || dwTyp == FT_INTELLIGENT_IF_SLAVE || dwTyp == FT_ROBO_IF_IIM)
+        ret->newioset.c_cflag |= BAUDRATE_II;
+    else // dwTyp == FT_ROBO_IF_COM
+        ret->newioset.c_cflag |= BAUDRATE_RI;
+    ret->newioset.c_oflag = 0;
+    ret->newioset.c_lflag = 0;
+    ret->newioset.c_cc[VTIME] = 1;
+    ret->newioset.c_cc[VMIN] = 0;
+    tcflush(dev, TCIFLUSH);
+    tcsetattr(dev, TCSANOW, &ret->newioset);
+    ret->sdev = dev;
+    if (dwTyp == FT_INTELLIGENT_IF) ret->transfer_area.BusModules = 1;
+    else if (dwTyp == FT_INTELLIGENT_IF_SLAVE) ret->transfer_area.BusModules = 2;
+
+    if (dwTyp == FT_ROBO_IF_COM && ((write(dev, &on, 14)) != 14 || (read(dev, &in, 5)) != 5 || in[0] != 0x5E)) {
+        fprintf(stderr, "OpenFtCommDevice: Error communicating with serial\n");
+        free(ret);
+        return NULL;
+    }
+#endif
+    return ret;
+}
+
+
+/**
+ * \brief Returns type of the interface
+ *
+ * This function will return the type of the interface that is behind the handle.
+ *
+ * @param hFt Handle of the device
+ * @return NO_FT_DEVICE, FT_INTELLIGENT_IF, FT_INTELLIGENT_IF_SLAVE, FT_ROBO_IF_COM, FT_ROBO_IF_USB, FT_ROBO_IF_IIM, FT_ROBO_IF_OVER_RF, FT_ROBO_IO_EXTENSION or FT_ROBO_RF_DATA_LINK
+ */
+long int GetFtDeviceTyp(FT_HANDLE hFt) {
+    if (hFt == NULL) {
+        fprintf(stderr, "GetFtDeviceTyp: No such device\n");
+        return NO_FT_DEVICE;
+    }
+
+    return hFt->type;
+}
+
+
+/**
+ * \brief Returns a string that identifies the interface with human words
+ *
+ * This function will give you a human readable string like "Robo Interface" you can work with.
+ *
+ * @param hFt Handle of the device
+ * @param dest Buffer we can write the string to
+ * @param len Maximum length of this buffer
+ * @return FTLIB_ERR_SUCCESS or a failure
+ */
+long int GetFtDeviceTypeString(FT_HANDLE hFt, char *dest, int len) {
+    // Todo: Maybe let usb query the string from the device?
+    if (hFt == NULL) {
+        fprintf(stderr, "GetFtDeviceTyp: No such device\n");
+        return NO_FT_DEVICE;
+    }
+
+    switch (GetFtDeviceTyp(hFt)) {
+        case FT_INTELLIGENT_IF:
+            strncpy(dest, "Intelligent Interface", len);
+            break;
+        case FT_INTELLIGENT_IF_SLAVE:
+            strncpy(dest, "Intelligent Interface with slave", len);
+            break;
+        case FT_ROBO_IF_IIM:
+            strncpy(dest, "Robo Interface II mode", len);
+            break;
+        case FT_ROBO_IF_COM:
+            strncpy(dest, "Robo Interface over serial", len);
+            break;
+        case FT_ROBO_IF_USB:
+            strncpy(dest, "Robo Interface over USB", len);
+            break;
+        case FT_ROBO_IO_EXTENSION:
+            strncpy(dest, "Robo IO Extension", len);
+            break;
+        case FT_ROBO_RF_DATA_LINK:
+            strncpy(dest, "Robo RF Datalink", len);
+            break;
+        case FT_ROBO_IF_OVER_RF:
+            strncpy(dest, "Robo Interface over RF Datalink", len);
+            break;
+        default:
+            strncpy(dest, "Unknown", len);
+    }
+
+    return FTLIB_ERR_SUCCESS;
+}
+
+
+
+/**
+ * \brief Opens this USB device.
+ *
+ * This function will try to open the ft USB device that belongs to the ft handle hFt.
+ * You can get the ft handle with GetFtUsbDeviceHandle() or GetFtUsbDeviceHandleSerialNr().
+ *
+ * @see GetFtUsbDeviceHandle()
+ * @see GetFtUsbDeviceHandleSerialNr()
+ * @param hFt ft USB Device to open
+ * @return Number >= 0 on success, < 0 on error
+ */
+long int OpenFtUsbDevice(FT_HANDLE hFt) {
+#ifdef USE_USB
+    long int ret;
+
+    if (hFt == NULL) {
+        fprintf(stderr, "OpenFtUsbDevice: No such device\n");
+        return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
+    }
+    hFt->device = usb_open(hFt->dev);
+    ret = usb_claim_interface(hFt->device, 0);
+    if (ret < 0) perror("usb_claim_interface");
+
+    return ret;
+#else
+    return FTLIB_ERR_NOT_SUPPORTED;
+#endif
+}
+
+
+/**
+ * \brief Close the ft Device
+ *
+ * This function will close the ft Device and free its memory.
+ *
+ * @param hFt Handle of the Device to close.
+ * @return A number < 0 on error.
+ */
+long int CloseFtDevice(FT_HANDLE hFt) {//sends a comm request
+    int ret = 0;
+    unsigned char off = 0xA2;
+    unsigned char in[1];
+    unsigned char buf[1];
+
+    if (hFt == NULL) {
+        fprintf(stderr, "CloseFtDevice: No such device\n");
+        return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
+    }
+
+    while (hFt->transfer_area.TransferAktiv != 0) {
+        fprintf(stderr, "Transfer area still active\n");
+        sleep(1);
+    }
+
+    switch (hFt->type) {
+            // usb
+#ifdef USE_USB
+        case FT_ROBO_RF_DATA_LINK:
+        case FT_ROBO_IF_OVER_RF:
+        case FT_ROBO_IF_USB:
+        case FT_ROBO_IO_EXTENSION:
+            ret = usb_release_interface(hFt->device, 0);
+            if (ret < 0) {
+                fprintf(stderr, "CloseFtDevice(): Error in usb_release_interface()\n");
+                break;
+            }
+            ret = usb_close(hFt->device);
+            break;
+#endif
+            // serial
+#ifdef MBED
+        case FT_ROBO_IF_COM:
+            if (write(hFt->sdev, &off, 1) != 1 || read(hFt->sdev, in, 1) != 1 || (in[0]^off != 0xFF)) {
+                fprintf(stderr, "CloseFtDevice: Error communicating with serial\n");
+            }
+        case FT_ROBO_IF_IIM:
+        case FT_INTELLIGENT_IF:
+        case FT_INTELLIGENT_IF_SLAVE:
+            delete hFt->sdev;
+            ret = 0;
+            break;
+#else
+        case FT_ROBO_IF_COM:
+            if ((write(hFt->sdev, &off, 1)) != 1 || (read(hFt->sdev, &in, 1)) != 1 || in[0] != 0x5D) {
+                fprintf(stderr, "CloseFtDevice: Error communicating with serial\n");
+            }
+        case FT_ROBO_IF_IIM:
+        case FT_INTELLIGENT_IF:
+        case FT_INTELLIGENT_IF_SLAVE:
+            tcsetattr(hFt->sdev, TCSANOW, &hFt->saveioset);
+            ret = close(hFt->sdev);
+            break;
+#endif
+    }
+#ifdef MBED
+    delete hFt;
+#else
+    free(hFt);
+#endif
+    hFt = NULL;
+    return ret;
+}
+
+
+/**
+ * \brief Library deinitialization (dummy)
+ *
+ * Dummy for compatibility. Only used in original library.
+ * @return Always FTLIB_ERR_SUCCESS
+ */
+long int CloseFtLib() {
+    return FTLIB_ERR_SUCCESS;
+}
+
+
+/**
+ * \brief Check for Library initialization (dummy)
+ *
+ * Dummy for compatibility. Only used in original library.
+ * @return Always FTLIB_ERR_LIB_IS_INITIALIZED since initialization is ignored in this version
+ */
+long int IsFtLibInit() {
+    return FTLIB_ERR_LIB_IS_INITIALIZED;
+}
+
+bool test_and_set(int& s) {
+    bool tmp;
+    __disable_irq();
+    if (tmp = s>0)
+        s--;
+    __enable_irq();
+    return tmp;
+}
+
+void increment(int& s) {
+    __disable_irq();
+    s++;
+    __enable_irq();
+}
+#ifdef SPLITTRANSFER
+
+//version for mbed with split functionality
+
+void ft_handle_devices::FtThreadInit() {//setup buffers for this type of interface
+    FT_TRANSFER_AREA *area = &transfer_area;
+    num_write = ABF_IF_COMPLETE_NUM_WRITE;
+    num_read = ABF_IF_COMPLETE_NUM_READ;
+    usb_endpoint_write = FT_ENDPOINT_INTERRUPT_OUT;
+    usb_endpoint_read = FT_ENDPOINT_INTERRUPT_IN;
+    cycle=0;
+
+    out[0] = ABF_IF_COMPLETE;
+    area->TransferAktiv = 1;
+    sdev->attach(this, &ft_handle_devices::writeByte, Serial::TxIrq);
+    sdev->attach(this, &ft_handle_devices::readByte, Serial::RxIrq);
+    busy = false;
+
+    switch (type) {
+        case FT_ROBO_IF_COM:
+            out[0] = 0xf2;
+            num_write = 17;
+            num_read = 21;
+            break;
+        case FT_INTELLIGENT_IF:
+            num_write = 2;
+            break;
+        case FT_INTELLIGENT_IF_SLAVE:
+            num_write = 3;
+            break;
+#ifdef USE_USB
+        case FT_ROBO_IO_EXTENSION:
+            out[0] = 0xf2;
+            num_write = 6;
+            num_read = 6;
+            break;
+        case FT_ROBO_IF_OVER_RF:
+        case FT_ROBO_RF_DATA_LINK:
+            usb_endpoint_write = FT_RF_ENDPOINT_INTERRUPT_OUT;
+            usb_endpoint_read = FT_RF_ENDPOINT_INTERRUPT_IN;
+
+            // init RF
+            // 0x102 == first RF
+            // 0x202 == 2nd RF
+            // ...
+            //ret = usb_control_msg(hFt->device, 0xc0, 0xfb, 0x102, 0x1, in, 2, FT_USB_TIMEOUT);
+            ret = usb_control_msg(hFt->device, 0xc0, 0xfb, hFt->transfer_area.RfModulNr << 8 | 0x02, 0x1, in, 2, FT_USB_TIMEOUT);
+            if (ret != 2) {
+                fprintf(stderr, "%d FtThread: Error initiating RF Module!\n");
+                area->TransferAktiv = 0;
+            }
+            break;
+#endif
+    }
+}
+
+extern int trigger_interface;
+
+bool ft_handle_devices::guardedFtThreadBegin() {//called every 10ms by the main loop to issue a request, should be non-blocking, guarded by busy flag to avoid multiple pending requests
+//viaUsb.putc('.');
+    __disable_irq();
+    if (busy) {
+        if (trigger_interface > 10) { //interface has not responded within 10 slots or response was missed
+            putc('?',stderr);
+            busy = false; //release the busy flag to reenable the request-reply process
+        }
+        __enable_irq();
+        return false; //skip the timeslot when previous was not yet handled
+    }
+    busy = true;
+    __enable_irq();
+    FtThreadBegin();//here the request is sent to the interface
+    return true;
+}
+
+void ft_handle_devices::FtThreadTrigger() {
+        trigger_interface++;//this is polled by the main loop
+    //printf("%d ", trigger_interface);
+}
+
+//here the real data exchange starts
+void ft_handle_devices::FtThreadBegin() {//called every 10ms to issue a request, should be non-blocking
+    int ii_speed = 0;
+    FT_TRANSFER_AREA *area = &transfer_area;
+    if (!test_and_set(lock)) {//return when transferarea is in use
+        busy = false; //release the mutex, otherwise the thread effectively stops
+        return;//return because there is no point in sending a nonsense request, alternatively the lock can be ignored in which case the data may be inconsistent
+    }
+    out[1] = area->M_Main;
+    out[2] = (area->MPWM_Main[0] & 0x7) | (area->MPWM_Main[1]<<3 & 0x38) | (area->MPWM_Main[2]<<6 & 0xC0);
+    out[3] = (area->MPWM_Main[2] & 0x1) | (area->MPWM_Main[3]<<1 & 0xE) | (area->MPWM_Main[4]<<4 & 0x70) | (area->MPWM_Main[5]<<7 & 0x80);
+    out[4] = (area->MPWM_Main[5] & 0x3) | (area->MPWM_Main[6]<<2 & 0x1C) | (area->MPWM_Main[7]<<5 & 0xE0);
+    out[5] = area->M_Sub1;
+    out[6] = (area->MPWM_Sub1[0] & 0x7) | (area->MPWM_Sub1[1]<<3 & 0x38) | (area->MPWM_Sub1[2]<<6 & 0xC0);
+    out[7] = (area->MPWM_Sub1[2] & 0x1) | (area->MPWM_Sub1[3]<<1 & 0xE) | (area->MPWM_Sub1[4]<<4 & 0x70) | (area->MPWM_Sub1[5]<<7 & 0x80);
+    out[8] = (area->MPWM_Sub1[5] & 0x3) | (area->MPWM_Sub1[6]<<2 & 0x1C) | (area->MPWM_Sub1[7]<<5 & 0xE0);
+    out[9] = area->M_Sub2;
+    out[10] = (area->MPWM_Sub2[0] & 0x7) | (area->MPWM_Sub2[1]<<3 & 0x38) | (area->MPWM_Sub2[2]<<6 & 0xC0);
+    out[11] = (area->MPWM_Sub2[2] & 0x1) | (area->MPWM_Sub2[3]<<1 & 0xE) | (area->MPWM_Sub2[4]<<4 & 0x70) | (area->MPWM_Sub2[5]<<7 & 0x80);
+    out[12] = (area->MPWM_Sub2[5] & 0x3) | (area->MPWM_Sub2[6]<<2 & 0x1C) | (area->MPWM_Sub2[7]<<5 & 0xE0);
+    out[13] = area->M_Sub3;
+    out[14] = (area->MPWM_Sub3[0] & 0x7) | (area->MPWM_Sub3[1]<<3 & 0x38) | (area->MPWM_Sub3[2]<<6 & 0xC0);
+    out[15] = (area->MPWM_Sub3[2] & 0x1) | (area->MPWM_Sub3[3]<<1 & 0xE) | (area->MPWM_Sub3[4]<<4 & 0x70) | (area->MPWM_Sub3[5]<<7 & 0x80);
+    out[16] = (area->MPWM_Sub3[5] & 0x3) | (area->MPWM_Sub3[6]<<2 & 0x1C) | (area->MPWM_Sub3[7]<<5 & 0xE0);
+    out[17]    = 0;
+    out[18]    = 0;
+    out[19]    = 0;
+    out[20]    = 0;
+    out[21]    = 0;
+    out[22]    = 0;
+    out[23]    = 0;
+    out[24]    = 0;
+    out[25]    = 0;
+    out[26]    = 0;
+    out[27]    = 0;
+    out[28]    = 0;
+    out[29]    = 0;
+    out[30]    = 0;
+    out[31]    = 0;
+
+    // For the II we need to simulate different speeds here
+    if (type == FT_INTELLIGENT_IF || type == FT_INTELLIGENT_IF_SLAVE) {
+        int iCurMotor;
+        for (iCurMotor = 0; iCurMotor < 7; iCurMotor++) {
+            if (area->MPWM_Main[iCurMotor] < ii_speed) out[1] &= ~(1 << iCurMotor);
+            if (area->MPWM_Sub1[iCurMotor] < ii_speed) out[5] &= ~(1 << iCurMotor);
+        }
+
+        ii_speed++;
+        if (ii_speed > 7) ii_speed = 0;
+    }
+
+    if (type == FT_INTELLIGENT_IF) {
+        cycle++;
+        num_read = 1;
+        out[0] = 0xC1;
+        if (cycle % 20) { // EX
+            out[0] = 0xC5;
+            num_read = 3;
+        } else if (cycle % 10) { // EY
+            out[0] = 0xC9;
+            num_read = 3;
+        }
+    } else if (type == FT_INTELLIGENT_IF_SLAVE) {
+        cycle++;
+        num_read = 2;
+        out[0] = 0xC2;
+        out[2] = out[5];
+        if (cycle % 20) { // EX
+            out[0] = 0xC6;
+            num_read = 4;
+        } else if (cycle % 10) { // EY
+            out[0] = 0xCA;
+            num_read = 4;
+        }
+    }
+//viaUsb.putc('-');
+    increment(lock);//release the lock on shared memeory
+    int ret = 0;
+    switch (type) {//send the request
+#ifdef USE_USB
+        case FT_ROBO_IF_USB:
+        case FT_ROBO_IO_EXTENSION:
+        case FT_ROBO_IF_OVER_RF:
+        case FT_ROBO_RF_DATA_LINK:
+            ret = usb_interrupt_write(hFt->device, usb_endpoint_write, out, num_write, FT_USB_TIMEOUT);
+            break;
+#endif
+        case FT_ROBO_IF_COM:
+        case FT_INTELLIGENT_IF:
+        case FT_INTELLIGENT_IF_SLAVE:
+            // ret = write(sdev, out, num_write);
+            //sdev->dmaSend(out, num_write);
+            ret = write();//start the transfer of the 'out' buffer, when complete the read_callback will receive the reply and when the reply is complete FtThreadEnd will be called
+//                viaUsb.putc(';');
+            break;
+    }
+    if (ret != num_write) {
+        interface_connected = 0;
+        fprintf(stderr, "FtThread: Error writing to the Interface...exiting!\n");
+    }
+}
+
+void ft_handle_devices::FtThreadEnd() {//called by the receiver/dma callback when the reply is complete
+    int ret = 0;
+    FT_TRANSFER_AREA *area = &transfer_area;
+    switch (type) { //receive the reply
+#ifdef USE_USB
+        case FT_ROBO_IF_USB:
+        case FT_ROBO_IO_EXTENSION:
+        case FT_ROBO_IF_OVER_RF:
+        case FT_ROBO_RF_DATA_LINK:
+            ret = usb_interrupt_read(hFt->device, usb_endpoint_read, in, num_read, FT_USB_TIMEOUT);
+            break;
+#endif
+        case FT_ROBO_IF_COM:
+        case FT_INTELLIGENT_IF:
+        case FT_INTELLIGENT_IF_SLAVE:
+//            ret = read(sdev, in, num_read);
+            ret = num_read;
+//                viaUsb.putc('/');
+            break;
+    }
+    if (ret != num_read) {
+        interface_connected = 0;
+        fprintf(stderr, "FtThread: Error reading from the Interface\n");
+        return;
+    }
+
+    if (!test_and_set(lock)) {//skip when busy
+        busy = false;
+        return;
+    }
+    area->ChangeEg = area->E_Main != in[0] || area->E_Sub1 != in[1] || area->E_Sub2 != in[2] || area->E_Sub3 != in[3];
+    area->E_Main = in[0];
+    area->E_Sub1 = in[1];
+    area->E_Sub2 = in[2];
+    area->E_Sub3 = in[3];
+    area->ChangeAn = 1; //assume that analog always changes (noise)
+    area->AX = in[4];
+    area->AY = in[5];
+    area->A1 = in[6];
+    area->A2 = in[7];
+    area->AX |= (in[8] & 0x3) << 8;
+    area->AY |= (in[8] & 0xC) << 6;
+    area->A1 |= (in[8] & 0x30) << 4;
+    area->A2 |= (in[8] & 0xC0) << 2;
+    area->AZ = in[9];
+    area->D1 = in[10];
+    area->D2 = in[11];
+    area->AV = in[12];
+    area->AZ |= (in[13] & 0x3) << 8;
+    area->D1 |= (in[13] & 0xC) << 6;
+    area->D2 |= (in[13] & 0x30) << 4;
+    area->AV |= (in[13] & 0xC0) << 2;
+    if (area->IRKeys != in[14])
+        area->ChangeIr = 1;
+    area->IRKeys = in[14];
+    area->BusModules = in[15];
+    // 16
+    area->AXS1 = in[17];
+    area->AXS2 = in[18];
+    area->AXS3 = in[19];
+    area->AXS1 |= (in[20] & 0x3) << 8;
+    area->AXS2 |= (in[20] & 0xC) << 6;
+    area->AXS3 |= (in[20] & 0x30) << 4;
+    // 21
+    area->AVS1 = in[22];
+    area->AVS2 = in[23];
+    area->AVS3 = in[24];
+    area->AVS1 |= (in[25] & 0x3) << 8;
+    area->AVS2 |= (in[25] & 0xC) << 6;
+    area->AVS3 |= (in[25] & 0x30) << 4;
+    // 26...42
+    if (type == FT_INTELLIGENT_IF) {
+        if (cycle % analogcycle) { // EX
+            area->AX = in[1] & (8<<in[2]);
+        } else if (cycle % (2*analogcycle)) { // EY
+            area->AY = in[1] & (8<<in[2]);
+        }
+    } else if (type == FT_INTELLIGENT_IF_SLAVE) {
+        if (cycle % analogcycle) { // EX
+            area->AX = in[1] & (8<<in[2]);
+        } else if (cycle % (2*analogcycle)) { // EY
+            area->AY = in[1] & (8<<in[2]);
+        }
+    }
+    increment(lock);
+    interface_connected = 1;
+    if (ne.NotificationCallback) {
+//        printf("%02X\r", transfer_area.E_Main);
+        (*ne.NotificationCallback)(ne.Context);
+    }
+    busy = false;
+}
+
+void ft_handle_devices::FtThreadFinish() {//called by StopFtTransferArea
+#ifdef USE_USB
+    if (hFt->type == FT_ROBO_IF_OVER_RF || hFt->type == FT_ROBO_RF_DATA_LINK) {
+        ret = usb_control_msg(hFt->device, 0xc0, 0x21, hFt->transfer_area.RfModulNr << 8, 0, in, 1, FT_USB_TIMEOUT);
+        if (ret != 1 || in[0] != 0xd7) {
+            fprintf(stderr, "Error uninitiating RF Module!\n");
+        }
+    }
+#endif
+#ifdef MBED
+    sdev->attach(0,Serial::RxIrq);
+    sdev->attach(0,Serial::TxIrq);
+#endif
+    transfer_area.TransferAktiv = 0;
+}
+
+void ft_handle_devices::FtThread() {
+//    ::FtThread(this);
+//    printf("%02X\r", transfer_area.E_Main);
+//    viaUsb.putc('.');
+}
+
+#endif
+
+/**
+ * \brief reset outputs
+ *
+ * Will clear all outputs.
+ *
+ * @return Always FTLIB_ERR_SUCCESS
+ */
+long int ResetFtTransfer(FT_HANDLE hFt) {
+    FT_TRANSFER_AREA *area = &hFt->transfer_area;
+
+    area->M_Main = 0;
+    area->M_Sub1 = 0;
+    area->M_Sub2 = 0;
+    area->M_Sub3 = 0;
+
+    return FTLIB_ERR_SUCCESS;
+}
+
+
+/**
+ * \brief Starts the communication thread.
+ *
+ * This function is needed to start the communication with the interface in passive mode.
+ * Get the handle with GetFtUsbDeviceHandle(), GetFtUsbDeviceHandleSerialNr() or OpenFtCommDevice().
+ *
+ * @see GetFtUsbDeviceHandle()
+ * @see GetFtUsbDeviceHandleSerialNr()
+ * @see OpenFtCommDevice()
+ * @param hFt Handle of the interface.
+ * @param ignored The second argument is ignored in this version.
+ * @return Everything except FTLIB_ERR_SUCCESS indicates an error.
+ */
+long int StartFtTransferArea(FT_HANDLE hFt, NOTIFICATION_EVENTS* ev) {
+    int ret;
+
+    if (hFt == NULL) {
+        fprintf(stderr, "StartFtTransferArea: No such device\n");
+        return NO_FT_DEVICE;
+    }
+    if (ev)
+        hFt->ne = *ev; //copy the entire struct
+    else
+        memset(&hFt->ne, 0, sizeof(NOTIFICATION_EVENTS));
+#ifdef MBED
+//at least for serial devices another solution must be found. A normal request/reply uses the entire 10 ms, this is OK but the CPU should not wait for it
+//either a buffer or a DMA scheme must be used to free CPU time, this means that at the beginning of the time slot the req. buffer is prepared and
+//handed over to IRQ/USB, the reply is gathered in a buffer and when complete the transfer area is updated.
+    hFt->t = new Ticker;
+    //printf("ticker created\n");
+    hFt->FtThreadInit();//setup buffers and serial handlers
+    //hFt->t->attach_us(hFt, &ft_handle_devices::FtThreadBegin, INTERFACE_QUERY_TIME);
+    hFt->t->attach_us(hFt, &ft_handle_devices::FtThreadTrigger, INTERFACE_QUERY_TIME);//FtThreadTrigger just sets a global variable that is polled by the main loop, which subsequently calls guardedFtThreadBegin
+    printf("thread attached\n");
+    ret = 0;
+#else
+    ret = pthread_create(&hFt->t, NULL, (void *)FtThread, hFt);
+#endif
+    usleep(INTERFACE_QUERY_TIME*10);
+    if (ret != 0) {
+        perror("StartFtTransferArea pthread_create");
+        return ret;
+    }
+
+    return FTLIB_ERR_SUCCESS;
+}
+
+
+/**
+ * \brief Starts the communication thread.
+ *
+ * Since notification are ignored in this version, will just call StartFtTransferArea().
+ *
+ * @see StartFtTransferArea()
+ */
+long int StartFtTransferAreaWithCommunication(FT_HANDLE hFt, NOTIFICATION_EVENTS* ignored) {
+    return StartFtTransferArea(hFt, ignored);
+}
+
+
+/**
+ * \brief Get the transfer area
+ *
+ * This function will return a pointer to the transfer area of the given handle.
+ *
+ * @param hFt Handle of the device.
+ * @return transfer area or NULL on error.
+ */
+FT_TRANSFER_AREA* GetFtTransferAreaAddress(FT_HANDLE hFt) {
+    if (hFt == NULL) {
+        fprintf(stderr, "GetFtTransferAreaAddress: No such device\n");
+        return NULL;
+    }
+    return &hFt->transfer_area;
+}
+
+
+/**
+ * \brief Stops the communication thread.
+ * \warning Will block a few microseconds until thread stopped.
+ *
+ * This function will stop the communication thread.
+ *
+ * @see StartFtTransferArea()
+ * @param hFt Handle of the Interface.
+ * @return Everything except FTLIB_ERR_SUCCESS indicates an error.
+ */
+long int StopFtTransferArea(FT_HANDLE hFt) {
+    int ret;
+
+    if (hFt == NULL) {
+        fprintf(stderr, "StopFtTransferArea: No such device\n");
+        return NO_FT_DEVICE;
+    }
+
+#ifdef MBED
+    hFt->t->detach();
+    delete hFt->t;
+    hFt->FtThreadFinish();
+#else
+    usleep(INTERFACE_QUERY_TIME*10); // wait to make sure the last command is send to the interface
+    if (hFt->transfer_area.TransferAktiv == 1) {
+        hFt->transfer_area.TransferAktiv = 2; // cleaner then pthread_cancel()
+    }
+    if ((ret = pthread_join(hFt->t, NULL)) != 0) return ret;
+#endif
+    return FTLIB_ERR_SUCCESS;
+}
+
+
+/**
+ * \brief check if transfer is active.
+ *
+ * Check if we are currently communicating with the device.
+ *
+ * @param hFt Handle of the Interface.
+ * @return FTLIB_ERR_THREAD_IS_RUNNING or FTLIB_ERR_THREAD_NOT_RUNNING
+ */
+long int IsFtTransferActiv(FT_HANDLE hFt) {
+    if (hFt == NULL) {
+        fprintf(stderr, "StopFtTransferArea: No such device\n");
+        return NO_FT_DEVICE;
+    }
+
+    if (hFt->transfer_area.TransferAktiv) return FTLIB_ERR_THREAD_IS_RUNNING;
+
+    return FTLIB_ERR_THREAD_NOT_RUNNING;
+}
+
+
+#ifdef USE_DOWNLOAD
+/**
+ * \brief Upload a program to the interface
+ *
+ * Upload (download from the perspective of the interface) a program to the interface.
+ *
+ * @param hFt Handle of the Interface
+ * @param dwMemBlock Destination 0 (Flash 1), 1 (Flash 2) or 2 (Ram)
+ * @param pbArray Pointer to the program to upload
+ * @param dwSize Size of the program to upload
+ * @param dwParameter 1 to Autostart this program, else 0.
+ * @param pbName Name of the program to upload
+ * @param dwNameLen Length of the name
+ * @return FTLIB_ERR_SUCCESS if you got lucky
+ */
+long int DownloadFtProgram(FT_HANDLE hFt, long int dwMemBlock, unsigned char *pbArray, long int dwSize, long int dwParameter, unsigned char *pbName, long int dwNameLen) {
+    int ret;
+    unsigned char buffer[128];
+    long int i;
+    crc_t crc;
+    int memblockarg;
+
+    if (hFt == NULL) {
+        fprintf(stderr, "DownloadFtProgram: No such device\n");
+        return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
+    } else if (hFt->type != FT_ROBO_IF_USB) {
+        fprintf(stderr, "DownloadFtProgram: Sorry, I can only handle the Robo Interface over USB at this time.\n");
+        return FTLIB_ERR_NOT_SUPPORTED;
+    }
+
+    switch (dwMemBlock) {
+        case 0x0:    // flash 1
+            memblockarg = 0x100;
+            if (dwParameter == 1) memblockarg += 0x100;
+            break;
+        case 0x1:    // flash 2
+            memblockarg = 0x101;
+            if (dwParameter == 1) fprintf(stderr, "Warning: Autostart for flash 2 not supported\n");
+            break;
+        case 0x2:    // ram
+            memblockarg = 0x102;
+            if (dwParameter == 1) fprintf(stderr, "Warning: Autostart for RAM not supported\n");
+            break;
+        case 0xf0:    // firmware A
+            memblockarg = 0xf200;
+            break;
+        case 0xf1:    // firmware B
+            memblockarg = 0xf201;
+            break;
+        default:
+            fprintf(stderr, "Unknown Memblock Target\n");
+            return FTLIB_ERR_DOWNLOAD_WRONG_MEM_BLOCK;
+    }
+
+    // init upload
+    ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x20, 0, buffer, 1, FT_USB_TIMEOUT_LONG);
+    if (ret < 0) {
+        fprintf(stderr, "Error sending control msg 0xC0 0xF0\n");
+        return ret;
+    }
+    if (buffer[0] != 1) {
+        fprintf(stderr, "Error uploading Program: Return value for 0xC0 0xF0 is 0x%x\n", buffer[0]);
+        return FTLIB_ERR_DOWNLOAD;
+    }
+
+    // write name
+    memset(buffer, 0, 128); // clean buffer
+    if (pbName != NULL)
+        strncpy(buffer, pbName, MIN(dwNameLen, 80)); // copy to buffer, so we not change the original content
+    ret = usb_control_msg(hFt->device, 0x40, 0x10, memblockarg, dwSize/PROGRAM_UPLOAD_PACKET_SIZE, buffer, 80, FT_USB_TIMEOUT_LONG);
+    if (ret < 0) {
+        fprintf(stderr, "Error sending control msg 0x40 0x10\n");
+        return ret;
+    }
+
+    // check
+    ret = usb_control_msg(hFt->device, 0xC0, 0x20, 0x0, 0x0, buffer, 1, FT_USB_TIMEOUT_LONG);
+    if (ret < 0) {
+        fprintf(stderr, "Error sending control ms 0xC0 0x20g\n");
+        return ret;
+    }
+    if (buffer[0] != dwMemBlock || (buffer[0] == 0 && memblockarg == 0xf200) || (buffer[0] == 1 && memblockarg == 0xf201)) {
+        fprintf(stderr, "Upload Error: Target mismatch\n");
+    }
+
+    // write the data
+    for (i=0; dwSize >= PROGRAM_UPLOAD_PACKET_SIZE; i++, dwSize -= PROGRAM_UPLOAD_PACKET_SIZE) {
+        memset(buffer, 0, 128); // clean buffer
+        memcpy(buffer, pbArray + (i*PROGRAM_UPLOAD_PACKET_SIZE), MIN(dwSize, PROGRAM_UPLOAD_PACKET_SIZE)); // make sure we not change the original content
+
+        crc = crc_init();
+        crc = crc_update(crc, buffer, PROGRAM_UPLOAD_PACKET_SIZE);
+        crc = crc_finalize(crc);
+
+        // write 128 byte
+        /*printf("CRC: 0x%x\n", crc);
+        printf("Paket: 0x%x\n", i+1);
+        for(k=0; k<128; k++) {
+            printf("0x%x ", buffer[k]);
+            if ((k+1) % 16 == 0 && k != 0) printf("\n");
+        }
+        printf("\n");*/
+        ret = usb_control_msg(hFt->device, 0x40, 0x11, i+1, crc, buffer, PROGRAM_UPLOAD_PACKET_SIZE, FT_USB_TIMEOUT_LONG);
+        if (ret < 0) {
+            fprintf(stderr, "Error sending control msg 0x40 0x11 0x%x\n", i+1);
+            return ret;
+        }
+
+        // check
+        ret = usb_control_msg(hFt->device, 0xC0, 0x20, 0x0, 0x0, buffer, 1, FT_USB_TIMEOUT_LONG);
+        if (ret < 0) {
+            fprintf(stderr, "Error sending control msg 0xC0 0x20\n");
+            return ret;
+        }
+        if (buffer[0] != 1) {
+            fprintf(stderr, "Error uploading Program: Return value for 0xC0, 0x20 is 0x%x\n", buffer[0]);
+            return FTLIB_ERR_DOWNLOAD;
+        }
+    }
+
+    return FTLIB_ERR_SUCCESS;
+}
+
+
+/**
+ * \brief Start a program
+ *
+ * Will start a program that has been Successfully uploaded to the interface.
+ *
+ * @param hFt Handle of the Interface
+ * @param dwMemBlock Destination 0 (Flash 1), 1 (Flash 2) or 2 (Ram)
+ * @return FTLIB_ERR_SUCCESS or FTLIB_ERR_IF_NO_PROGRAM
+ */
+long int StartFtProgram(FT_HANDLE hFt, long int dwMemBlock) {
+    int ret;
+    unsigned char buffer[2];
+
+    if (hFt == NULL) {
+        fprintf(stderr, "StartFtProgram: No such device\n");
+        return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
+    }
+
+    switch (hFt->type) {
+        case FT_ROBO_IF_USB:
+            // note: serial documentation says 0xf4 here, sniffer says 0x12
+            ret = usb_control_msg(hFt->device, 0xc0, 0x12, dwMemBlock, 0, buffer, 1, FT_USB_TIMEOUT_LONG);
+            if (ret < 0) {
+                fprintf(stderr, "Error sending control msg 0xC0 0xF4\n");
+                return ret;
+            }
+            if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
+            else return FTLIB_ERR_IF_NO_PROGRAM;
+            break;
+        case FT_ROBO_IF_COM:
+            buffer[0] = 0xf4;
+            buffer[1] = dwMemBlock;
+            if ((write(hFt->sdev, &buffer, 2)) != 2 || (read(hFt->sdev, &buffer, 1)) != 1) {
+                return FTLIB_ERR_IF_NO_PROGRAM;
+            }
+            if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
+            else return FTLIB_ERR_IF_NO_PROGRAM;
+            break;
+    }
+
+    return FTLIB_ERR_NOT_SUPPORTED;
+}
+
+
+/**
+ * \brief Stop a program
+ *
+ * Will stop the current running program that has been uploaded to the interface.
+ *
+ * @param hFt Handle of the Interface
+ * @return FTLIB_ERR_SUCCESS or FTLIB_ERR_IF_NO_PROGRAM
+ */
+long int StopFtProgram(FT_HANDLE hFt) {
+    int ret;
+    unsigned char buffer[1];
+
+    if (hFt == NULL) {
+        fprintf(stderr, "StopFtProgram: No such device\n");
+        return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
+    }
+
+    switch (hFt->type) {
+        case FT_ROBO_IF_USB:
+            // note: serial documentation says 0xf8 here, sniffer says 0x13
+            ret = usb_control_msg(hFt->device, 0xc0, 0x13, 0, 0, buffer, 1, FT_USB_TIMEOUT_LONG);
+            if (ret < 0) {
+                fprintf(stderr, "Error sending control msg 0xC0 0x13\n");
+                return ret;
+            }
+
+            if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
+            else return FTLIB_ERR_IF_NO_PROGRAM;
+            break;
+        case FT_ROBO_IF_COM:
+            buffer[0] = 0xf8;
+            if ((write(hFt->sdev, &buffer, 1)) != 1 || (read(hFt->sdev, &buffer, 1)) != 1) {
+                return FTLIB_ERR_IF_NO_PROGRAM;
+            }
+            if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
+            else return FTLIB_ERR_IF_NO_PROGRAM;
+            break;
+    }
+
+    return FTLIB_ERR_NOT_SUPPORTED;
+}
+
+
+/**
+ * \brief Delete a program
+ *
+ * Will delete a program that has been uploaded to the interface.
+ *
+ * @param hFt Handle of the Interface
+ * @param dwMemBlock Destination 0 (Flash 1), 1 (Flash 2) or 2 (Ram)
+ * @return FTLIB_ERR_SUCCESS or FTLIB_ERR_IF_NO_PROGRAM
+ */
+long int DeleteFtProgram(FT_HANDLE hFt, long int dwMemBlock) {
+    int ret;
+    unsigned char buffer[2];
+
+    if (hFt == NULL) {
+        fprintf(stderr, "DeleteFtProgram: No such device\n");
+        return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
+    }
+
+    switch (hFt->type) {
+        case FT_ROBO_IF_USB:
+            ret = usb_control_msg(hFt->device, 0xc0, 0xf5, dwMemBlock, 0, buffer, 1, FT_USB_TIMEOUT_LONG);
+            if (ret < 0) {
+                fprintf(stderr, "Error sending control msg 0xC0 0xF5\n");
+                return ret;
+            }
+
+            if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
+            else return FTLIB_ERR_IF_NO_PROGRAM;
+            break;
+        case FT_ROBO_IF_COM:
+            buffer[0] = 0xf5;
+            buffer[1] = dwMemBlock;
+            if ((write(hFt->sdev, &buffer, 2)) != 2 || (read(hFt->sdev, &buffer, 1)) != 1) {
+                return FTLIB_ERR_IF_NO_PROGRAM;
+            }
+            if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
+            else return FTLIB_ERR_IF_NO_PROGRAM;
+            break;
+    }
+
+    return FTLIB_ERR_NOT_SUPPORTED;
+}
+
+
+/**
+ * \brief Activate a program
+ *
+ * Will activate a program that has been uploaded to the interface.
+ *
+ * @param hFt Handle of the Interface
+ * @param dwMemBlock Destination 0 (Flash 1) or 1 (Flash 2)
+ * @return FTLIB_ERR_SUCCESS or FTLIB_ERR_IF_NO_PROGRAM
+ */
+long int SetFtProgramActiv(FT_HANDLE hFt, long int dwMemBlock) {
+    int ret;
+    unsigned char buffer[1];
+
+    if (hFt == NULL) {
+        fprintf(stderr, "SetFtProgramActiv: No such device\n");
+        return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
+    }
+
+    switch (hFt->type) {
+        case FT_ROBO_IF_USB:
+            ret = usb_control_msg(hFt->device, 0xc0, 0xf9, dwMemBlock, 0, buffer, 1, FT_USB_TIMEOUT_LONG);
+            if (ret < 0) {
+                fprintf(stderr, "Error sending control msg 0xC0 0xf9\n");
+                return ret;
+            }
+
+            if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
+            else return FTLIB_ERR_IF_NO_PROGRAM;
+            break;
+        case FT_ROBO_IF_COM:
+            buffer[0] = 0xf9;
+            buffer[1] = dwMemBlock;
+            if ((write(hFt->sdev, &buffer, 2)) != 2 || (read(hFt->sdev, &buffer, 1)) != 1) {
+                return FTLIB_ERR_IF_NO_PROGRAM;
+            }
+            if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS;
+            else return FTLIB_ERR_IF_NO_PROGRAM;
+            break;
+    }
+
+    return FTLIB_ERR_NOT_SUPPORTED;
+}
+
+
+/**
+ * \brief Get the name of a program
+ *
+ * Will write the name of a program that has been uploaded to the interface to a given area.
+ *
+ * @param hFt Handle of the Interface
+ * @param dwMemBlock Destination 0 (Flash 1), 1 (Flash 2) or 2 (Ram)
+ * @param pName Pointer to the area where we can store the name
+ * @param dwSize Size of the area to store the name to
+ * @return FTLIB_ERR_SUCCESS or FTLIB_ERR_IF_NO_PROGRAM
+ */
+long int GetFtProgramName(FT_HANDLE hFt, long int dwMemBlock, long int dwSize, void *pName) {
+    int ret;
+    unsigned char buffer[dwSize+1];
+
+    if (hFt == NULL) {
+        fprintf(stderr, "GetFtProgramName: No such device\n");
+        return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
+    }
+
+    switch (hFt->type) {
+        case FT_ROBO_IF_USB:
+            ret = usb_control_msg(hFt->device, 0xc0, 0xfa, dwMemBlock, 0, buffer, dwSize + 1, FT_USB_TIMEOUT_LONG);
+            if (ret < 0) {
+                fprintf(stderr, "Error sending control msg 0xC0 0xFA\n");
+                return ret;
+            }
+            memcpy(pName, buffer+1, ret-1);
+
+            if (buffer[0] == 0x1) return FTLIB_ERR_SUCCESS;
+            if (buffer[0] == 0xf3) return FTLIB_ERR_IF_NO_PROGRAM;
+            return buffer[1];
+            break;
+        case FT_ROBO_IF_COM:
+            buffer[0] = 0xfa;
+            buffer[1] = dwMemBlock;
+            if ((write(hFt->sdev, &buffer, 2)) != 2 || (ret = read(hFt->sdev, &buffer, dwSize+1)) < 0 || buffer[0] != 0x01) {
+                return FTLIB_ERR_IF_NO_PROGRAM;
+            }
+            memcpy(pName, buffer+1, ret-1);
+            if (buffer[0] == 0x1) return FTLIB_ERR_SUCCESS;
+            break;
+    }
+
+    return FTLIB_ERR_NOT_SUPPORTED;
+}
+
+
+/**
+ * \brief Checks if a program is running
+ *
+ * Checks if a program is currently running.
+ *
+ * @param hFt Handle of the Interface
+ * @param num Area where we can store the number of the running program.
+ * @return 1 if a program is running, else 0
+ */
+int GetFtStatus(FT_HANDLE hFt, int *num) {
+    int ret;
+    unsigned char buffer[3];
+
+    if (hFt == NULL) {
+        fprintf(stderr, "GetFtStatus: No such device\n");
+        return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
+    }
+
+    switch (hFt->type) {
+        case FT_ROBO_IF_USB:
+            // test replace 0xf0 with 0x50
+            ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x3, 0, buffer, 3, FT_USB_TIMEOUT);
+            if (ret < 0) {
+                fprintf(stderr, "Error sending control msg 0xC0 0xF0\n");
+                return ret;
+            }
+            ret = buffer[1];
+            *num = buffer[2];
+            break;
+        case FT_ROBO_IF_COM:
+            buffer[0] = 0xf0;
+            buffer[1] = 0x3;
+            if ((write(hFt->sdev, &buffer, 2)) != 2 || (ret = read(hFt->sdev, &buffer, 3)) < 0 || buffer[0] != 0xfc) {
+                return ret;
+            }
+            ret = buffer[1];
+            *num = buffer[2];
+            break;
+        default:
+            return FTLIB_ERR_NOT_SUPPORTED;
+    }
+
+    return ret;
+}
+#endif //USE_DOWNLOAD
+
+/**
+ * \brief Get the firmware number of this interface.
+ *
+ * Returns the firmware number of the interface squashed into a single int.
+ *
+ * @param hFt Handle of the Interface
+ * @return Firmware number as int byte4 | byte3 | byte2 | byte1, 0 on error.
+ */
+long int GetFtFirmware(FT_HANDLE hFt) {//makes a blocking comm request
+    int ret;
+    unsigned char buffer[35] = { 0 };
+    long int firmware = 0;
+
+    if (hFt == NULL) {
+        fprintf(stderr, "GetFtFirmware: No such device\n");
+        return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
+    }
+
+
+    switch (hFt->type) {
+        case FT_INTELLIGENT_IF:
+        case FT_INTELLIGENT_IF_SLAVE:
+            return 0;
+            break;
+#ifdef USE_USB
+        case FT_ROBO_IF_USB:
+        case FT_ROBO_IO_EXTENSION:
+        case FT_ROBO_RF_DATA_LINK:
+            ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x1, 0, buffer, 5, FT_USB_TIMEOUT);
+            if (ret < 0) {
+                fprintf(stderr, "Error sending control msg 0xC0 0xF0\n");
+                return 0;
+            }
+            firmware = buffer[1] | buffer[2]<<8 | buffer[3]<<16 | buffer[4]<<24;
+            break;
+        case FT_ROBO_IF_OVER_RF:
+            ret = usb_control_msg(hFt->device, 0xc0, 0x52, hFt->transfer_area.RfModulNr<<8 | 0x05, 0, buffer, 35, FT_USB_TIMEOUT);
+            if (ret < 0) {
+                fprintf(stderr, "Error sending control msg 0xC0 0x52\n");
+                return 0;
+            }
+            if (buffer[0] == 0xfa && buffer[1] == 0) { // buffer[1] == 0xff => no device
+                firmware = buffer[23]<<24 | buffer[22]<<16 | buffer[21]<<8 | buffer[20];
+            }
+            break;
+#endif
+        case FT_ROBO_IF_COM:
+            buffer[0] = 0xf0;
+            buffer[1] = 0x01;
+#ifdef MBED
+//printf("requesting FW\n");
+            //ret = hFt->sdev->printf("%2c", buffer);
+            ret = write(hFt->sdev, buffer, 2);
+//            printf("request was sent %d\n", ret);
+#else
+            ret = write(hFt->sdev, &buffer, 2);
+#endif
+            if (ret != 2) {
+                fprintf(stderr, "Error writing msg 0xF0 0x01\n");
+                return 0;
+            }
+#ifdef MBED
+            //ret = hFt->sdev->scanf("%5c", buffer)==1 ? 5 : 0 ;
+            ret = read(hFt->sdev, buffer, 5);
+#else
+            ret = read(hFt->sdev, &buffer, 5);
+#endif
+            if (ret != 5) {
+                fprintf(stderr, "Error reading msg 0xF0 0x01\n");
+                return 0;
+            }
+            firmware = buffer[1] | buffer[2]<<8 | buffer[3]<<16 | buffer[4]<<24;
+//            printf("fw: %ld\n", firmware);
+            break;
+        default:
+            return FTLIB_ERR_NOT_SUPPORTED;
+    }
+
+    return firmware;
+}
+
+
+/**
+ * \brief Get the firmware number of this interface.
+ *
+ * Returns the firmware number of the interface with this handle.
+ * The allocated space should be freed with free() later.
+ *
+ * @param hFt Handle of the Interface
+ * @return Pointer to a string with the firmware
+ */
+char *GetFtFirmwareStrg(FT_HANDLE hFt) {
+    long int ifw = GetFtFirmware(hFt);
+    char *s = (char *)malloc(16);
+    int byte1 = ifw & 0xff;
+    int byte2 = (ifw & 0xff00) >> 8;
+    int byte3 = (ifw & 0xff0000) >> 16;
+    int byte4 = (ifw & 0xff000000) >> 24;
+
+    snprintf(s, 16, "%d.%02d.%02d.%02d", byte4, byte3, byte2, byte1);
+
+    return s;
+}
+
+
+#ifndef NOTNOW
+/**
+ * \brief Get the serial number of this interface.
+ *
+ * Returns the serial number of the interface squashed into a single int.
+ *
+ * @param hFt Handle of the Interface
+ * @return Serial number as int byte4 | byte3 | byte2 | byte1, 0 on error.
+ */
+long int GetFtSerialNr(FT_HANDLE hFt) {
+    int ret;
+    unsigned char buffer[35] = { 0 };
+    long int serial = 0;
+
+    if (hFt == NULL) {
+        fprintf(stderr, "GetFtSerialNr: No such device\n");
+        return  FTLIB_ERR_PORT_NUMBER_IS_NULL;
+    }
+
+
+    switch (hFt->type) {
+        case FT_INTELLIGENT_IF:
+        case FT_INTELLIGENT_IF_SLAVE:
+            return 0;
+            break;
+        case FT_ROBO_IF_USB:
+            ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x2, 0, buffer, 5, FT_USB_TIMEOUT);
+            if (ret < 0) {
+                fprintf(stderr, "Error sending control msg 0xC0 0xF0\n");
+                return 0;
+            }
+            serial = buffer[1] + buffer[2]*100 + buffer[3]*10000 + buffer[4]*1000000;
+            break;
+        case FT_ROBO_IO_EXTENSION:
+            ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x2, 0, buffer, 14, FT_USB_TIMEOUT);
+            if (ret < 0) {
+                fprintf(stderr, "Error sending control msg 0xC0 0xF0\n");
+                return 0;
+            }
+            serial = buffer[1] + buffer[2]*100 + buffer[3]*10000 + buffer[4]*1000000;
+            break;
+        case FT_ROBO_RF_DATA_LINK:
+            ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x2, 0, buffer, 14, FT_USB_TIMEOUT);
+            if (ret < 0) {
+                fprintf(stderr, "Error sending control msg 0xC0 0x52\n");
+                return 0;
+            }
+            serial = buffer[1] + buffer[2]*100 + buffer[3]*10000 + buffer[4]*1000000;
+            break;
+        case FT_ROBO_IF_OVER_RF:
+            ret = usb_control_msg(hFt->device, 0xc0, 0x52, hFt->transfer_area.RfModulNr<<8 | 0x05, 0, buffer, 35, FT_USB_TIMEOUT);
+            if (ret < 0) {
+                fprintf(stderr, "Error sending control msg 0xC0 0x52\n");
+                return 0;
+            }
+            if (buffer[0] == 0xfa && buffer[1] == 0) { // buffer[1] == 0xff => no device
+                serial = buffer[6]*1000000 + buffer[5]*10000 + buffer[4]*100 + buffer[3];
+            }
+            break;
+        case FT_ROBO_IF_COM:
+            buffer[0] = 0xf0;
+            buffer[1] = 0x02;
+            ret = write(hFt->sdev, &buffer, 2);
+            if (ret != 2) {
+                fprintf(stderr, "Error writing msg 0xF0 0x02\n");
+                return 0;
+            }
+            ret = read(hFt->sdev, &buffer, 5);
+            if (ret != 5) {
+                fprintf(stderr, "Error reading msg 0xF0 0x02\n");
+                return 0;
+            }
+            serial = buffer[1] + buffer[2]*100 + buffer[3]*10000 + buffer[4]*1000000;
+            break;
+        default:
+            return FTLIB_ERR_NOT_SUPPORTED;
+    }
+
+    return serial;
+}
+
+
+/**
+ * \brief Get the serial number of this interface.
+ *
+ * Returns the serial number of the interface with this handle.
+ * The allocated space should be freed with free() later.
+ *
+ * @param hFt Handle of the Interface
+ * @return Pointer to a string with the serial
+ */
+char *GetFtSerialNrStrg(FT_HANDLE hFt) {
+    long int ifw = GetFtSerialNr(hFt);
+    char *s = (char *)malloc(16);
+    int byte1, byte2, byte3, byte4;
+
+    byte1 = ifw % 100;
+    ifw /= 100;
+    byte2 = ifw % 100;
+    ifw /= 100;
+    byte3 = ifw % 100;
+    ifw /= 100;
+    byte4 = ifw % 100;
+    ifw /= 100;
+
+    snprintf(s, 16, "%d.%02d.%02d.%02d", byte4, byte3, byte2, byte1);
+
+    return s;
+}
+
+
+/**
+ * \brief Close all ft devices
+ *
+ * Dummy. Can't be supported. Only used in original library.
+ *
+ * @return Always FTLIB_ERR_NOT_SUPPORTED
+ */
+long int CloseAllFtDevices() {
+    return FTLIB_ERR_NOT_SUPPORTED;
+}
+
+
+/**
+ * \brief Set the inputs D1 and D2 to distance oder voltage measuring
+ *
+ * This function allows to enable the inputs D1 and D2 to measure distances.
+ * Must be called before StartFtTransferArea()
+ *
+ * Note by Hardware Vendor:
+ * "Since the operating mode of the D1 / D2 inputs can be set by means of software, we recommend that no
+ * voltage be supplied 'directly' to these connections in order to avoid damage to the interface during software
+ * errors. Since the inputs are highly resistive, a resistance of approximately 200 Ohm - 470 Ohm should be
+ * directly connected to the D1 / D2 socket (series connection). We recommend to connect the voltage range to
+ * be measured 'behind' it."
+ *
+ * @param hFt Handle of the Interface
+ * @param dwMode Set mode to IF_DS_INPUT_VOLTAGE (measure voltage) or IF_DS_INPUT_DISTANCE (measure distance)
+ * @param dwTol1 Range of tolerance for D1. Try IF_DS_INPUT_TOL_STD (20).
+ * @param dwTol2 Range of tolerance for D2. Try IF_DS_INPUT_TOL_STD (20).
+ * @param dwLevel1 Threshold for D1. Try 100.
+ * @param dwLevel2 Threshold for D2. Try 100.
+ * @param dwRepeat1 Repition value for D1. Try IF_DS_INPUT_REP_STD (3).
+ * @param dwRepeat2 Repition value for D2. Try IF_DS_INPUT_REP_STD (3).
+ * @return FTLIB_ERR_SUCCESS on success
+ */
+long int SetFtDistanceSensorMode(FT_HANDLE hFt, long int dwMode, long int dwTol1, long int dwTol2, long int dwLevel1, long int dwLevel2, long int dwRepeat1, long int dwRepeat2) {
+    int ret;
+    unsigned char buffer[] =  {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; // 34
+    int i;
+
+    buffer[1] = dwTol1;
+    buffer[2] = dwTol2;
+    buffer[3] = dwLevel1;
+    buffer[4] = dwLevel1>>8;
+    buffer[5] = dwLevel2;
+    buffer[6] = dwLevel2>>8;
+    buffer[7] = dwRepeat1;
+    buffer[8] = dwRepeat2;
+
+    if (hFt == NULL) {
+        fprintf(stderr, "GetFtFirmware: No such device\n");
+        return FTLIB_ERR_PORT_NUMBER_IS_NULL;
+    }
+
+    switch (hFt->type) {
+        case FT_ROBO_IF_USB:
+            ret = usb_control_msg(hFt->device, 0x40, 0xf1, 0x1, dwMode, buffer+1, 8, FT_USB_TIMEOUT);
+            if (ret != 8) {
+                fprintf(stderr, "Error sending control msg 0x40 0xf1\n");
+                return ret;
+            }
+            break;
+        case FT_ROBO_RF_DATA_LINK:
+        case FT_ROBO_IF_OVER_RF:
+            ret = usb_control_msg(hFt->device, 0x40, 0x53, hFt->transfer_area.RfModulNr<<8 | 0x01, 0, buffer, 34, FT_USB_TIMEOUT);
+            if (ret != 34) {
+                fprintf(stderr, "Error sending control msg 0x40 0x53\n");
+                return ret;
+            }
+            break;
+        case FT_ROBO_IF_COM:
+            // move data in array for two bytes
+            for (i=10; i>=3; i--) {
+                buffer[i] = buffer[i-2];
+            }
+            buffer[0] = 0xf1;
+            buffer[1] = 0x01;
+            buffer[2] = dwMode;
+            if ((write(hFt->sdev, &buffer, 11)) != 11 || (read(hFt->sdev, &buffer, 1)) != 1 || buffer[0] != 0x01) {
+                fprintf(stderr, "SetFtDistanceSensorMode: Error communicating with serial\n");
+                return buffer[0];
+            }
+            break;
+        default:
+            return FTLIB_ERR_NOT_SUPPORTED;
+    }
+
+    usleep(100000); // wait before continue, else it doesn't always work
+
+    return FTLIB_ERR_SUCCESS;
+}
+
+
+/**
+ * \brief Sets the frequency and call sign for a Robo Interface or RF Data Link.
+ *
+ * Sets the frequency and call sign which allows to control multiple Interfaces at one RF Data Link.
+ * The value won't be lost on power failure.
+ *
+ * @param hFt Handle of the Interface
+ * @param frequency to use. May be between 2 and 80.
+ * @param callSign call sign for this Interface. May be between 1 and 8. (ignored for the RF Data Link)
+ * @return FTLIB_ERR_SUCCESS on success
+ */
+long int SetRFMode(FT_HANDLE hFt, long int frequency, long int callSign) {
+    int ret;
+    unsigned char buffer[5];
+
+    if (hFt == NULL) {
+        fprintf(stderr, "GetFtFirmware: No such device\n");
+        return FTLIB_ERR_PORT_NUMBER_IS_NULL;
+    } else if (frequency < 2 || frequency > 80) {
+        return FTLIB_ERR_INVALID_PARAM;
+    } else if (callSign > 8) {
+        return FTLIB_ERR_INVALID_PARAM;
+    }
+
+    switch (hFt->type) {
+        case FT_ROBO_RF_DATA_LINK:
+            ret = usb_control_msg(hFt->device, 0xc0, 0xfb, 1, frequency, buffer, 2, FT_USB_TIMEOUT);
+            if (ret != 2 || buffer[0] != 0xfe || buffer[1] != 0) {
+                fprintf(stderr, "Error sending control msg 0xc0 0xfb\n");
+                return ret;
+            }
+            break;
+        case FT_ROBO_IF_USB:
+            // not or-ing 1 to frequency seems to disable the modul
+            ret = usb_control_msg(hFt->device, 0xc0, 0xfb, (callSign<<8) | 1, (1<<8) | frequency, buffer, 2, FT_USB_TIMEOUT);
+            if (ret != 2 || buffer[0] != 0xfe || buffer[1] != 0) {
+                fprintf(stderr, "Error sending control msg 0xc0 0xfb\n");
+                return ret;
+            }
+            break;
+        case FT_ROBO_IF_COM:
+            buffer[0] = 0xfb;
+            buffer[1] = 0x1;
+            buffer[2] = 0x7f;
+            buffer[3] = frequency;
+            buffer[4] = callSign;
+            if ((write(hFt->sdev, &buffer, 5)) != 5 || (ret = read(hFt->sdev, &buffer, 2)) != 2 || buffer[0] != 0xfe) {
+                fprintf(stderr, "SetRFMode: Error communicating with serial\n");
+                return ret;
+            }
+            break;
+        default:
+            return FTLIB_ERR_NOT_SUPPORTED;
+    }
+
+    return FTLIB_ERR_SUCCESS;
+}
+
+
+/**
+ * \brief Gets the frequency and call sign of a Robo Interface or RF Data Link.
+ *
+ * Sets the frequency and call sign which allows to control multiple Interfaces at one RF Data Link.
+ *
+ * @param hFt Handle of the Interface
+ * @param frequency Points to a place to store the frequency.
+ * @param callSign Points to a place to store the callSign. (Value will be 0 for the RF Data Link)
+ * @return FTLIB_ERR_SUCCESS on success
+ */
+long int GetRFMode(FT_HANDLE hFt, long int *frequency, long int *callSign) {
+    int ret;
+    unsigned char buffer[8];
+
+    if (hFt == NULL) {
+        fprintf(stderr, "GetFtFirmware: No such device\n");
+        return FTLIB_ERR_PORT_NUMBER_IS_NULL;
+    }
+
+    switch (hFt->type) {
+        case FT_ROBO_IF_USB:
+        case FT_ROBO_RF_DATA_LINK:
+            ret = usb_control_msg(hFt->device, 0xc0, 0xfb, 0x81, 0, buffer, 8, FT_USB_TIMEOUT);
+            if (ret != 8) {
+                fprintf(stderr, "Error sending control msg 0xc0 0xfb\n");
+                return ret;
+            }
+            *frequency = buffer[6];
+            *callSign = buffer[7];
+            break;
+        case FT_ROBO_IF_COM:
+            buffer[0] = 0xfb;
+            buffer[1] = 0x81;
+            if ((write(hFt->sdev, &buffer, 2)) != 2 || (ret = read(hFt->sdev, &buffer, 8)) != 8 || buffer[0] != 0x7e) {
+                fprintf(stderr, "GetRFMode: Error communicating with serial\n");
+                return ret;
+            }
+            *frequency = buffer[6];
+            *callSign = buffer[7];
+            break;
+        default:
+            return FTLIB_ERR_NOT_SUPPORTED;
+    }
+
+    return FTLIB_ERR_SUCCESS;
+}
+
+
+/**
+ * \brief Switches between the real serial and 0001 of a device.
+ *
+ * Every ft Interface is shipped with 0001 as serial.
+ * Nevertheless each has its own serial which can be activated.
+ *
+ * @param hFt Handle of the Interface
+ * @param bOn 0 to use 0001, else the real serial
+ * @return FTLIB_ERR_SUCCESS on success
+ */
+long int SetRealSerial(FT_HANDLE hFt, unsigned char bOn) {
+    int ret;
+    // on: 2 0xd2 0x3a
+    // off: 1 0x81 0x6f
+    // RF: 2 d8 77 vs 1 8b 22
+    // Whats the number?
+    // SetSerial(hFt, 5386);
+    unsigned char buffer[16] = {0xaf, 0x83, 0x55, 0xa1, 1, 0, 0, 0, 1, 0x81, 0x6f, 0, 0, 0, 0, 0};
+
+    if (hFt == NULL) {
+        fprintf(stderr, "GetFtFirmware: No such device\n");
+        return FTLIB_ERR_PORT_NUMBER_IS_NULL;
+    }
+
+    switch (hFt->type) {
+        case FT_ROBO_IF_USB:
+            if (bOn) {
+                buffer[8] = 2;
+                buffer[9] = 0xd2;
+                buffer[10] = 0x3a;
+            } else {
+                buffer[8] = 1;
+                buffer[9] = 0x81;
+                buffer[10] = 0x6f;
+            }
+            ret = usb_control_msg(hFt->device, 0x40, 0xaf, 0x83, 0, buffer, 16, 200000);
+            if (ret != 16) {
+                fprintf(stderr, "Error sending control msg 0x40 0xaf\n");
+                return ret;
+            }
+            break;
+        case FT_ROBO_IF_OVER_RF:
+            if (bOn) {
+                buffer[8] = 2;
+                buffer[9] = 0xd8;
+                buffer[10] = 0x77;
+            } else {
+                buffer[8] = 1;
+                buffer[9] = 0x8b;
+                buffer[10] = 0x22;
+            }
+            ret = usb_control_msg(hFt->device, 0x40, 0xaf, 0x83, 0, buffer, 16, 200000);
+            if (ret != 16) {
+                fprintf(stderr, "Error sending control msg 0x40 0xaf\n");
+                return ret;
+            }
+            break;
+        case FT_ROBO_IO_EXTENSION:
+            if (bOn) {
+                buffer[8] = 2;
+                buffer[9] = 0x5f;
+                buffer[10] = 0x28;
+            } else {
+                buffer[8] = 1;
+                buffer[9] = 0x0c;
+                buffer[10] = 0x7d;
+            }
+            ret = usb_control_msg(hFt->device, 0x40, 0xaf, 0x83, 0, buffer, 16, 200000);
+            if (ret != 16) {
+                fprintf(stderr, "Error sending control msg 0x40 0xaf\n");
+                return ret;
+            }
+            break;
+        case FT_ROBO_IF_COM:
+            if ((write(hFt->sdev, &buffer, 16)) != 16 || (ret = read(hFt->sdev, &buffer, 2)) != 2 || buffer[0] != 0x7c) {
+                fprintf(stderr, "SetRealSerial: Error communicating with serial\n");
+                return ret;
+            }
+            break;
+        default:
+            return FTLIB_ERR_NOT_SUPPORTED;
+    }
+
+    return FTLIB_ERR_SUCCESS;
+}
+
+
+
+/**
+ * @brief Gets the Manufacturer of the Interface
+ *
+ * Will return the Manufacturer of a fischertechnik USB device.
+ * The allocated space should be freed with free() later.
+ *
+ * @param hFt Handle of the Interface
+ * @return Pointer to the string with the name
+ */
+char *GetFtManufacturerStrg(FT_HANDLE hFt) {
+    char *buffer = (char *)malloc(128);
+    memset(buffer, '\0', 128);
+
+    if (hFt == NULL) {
+        fprintf(stderr, "GetFtFirmware: No such device\n");
+    }
+
+    switch (hFt->type) {
+        case FT_ROBO_IF_USB:
+        case FT_ROBO_RF_DATA_LINK:
+        case FT_ROBO_IF_OVER_RF:
+            usb_get_string_simple(hFt->device, 1, buffer, 128);
+            break;
+    }
+
+    return buffer;
+}
+
+
+/**
+ * @brief Gets the short name of the Interface
+ *
+ * Will return the short name of a fischertechnik USB device.
+ * The allocated space should be freed with free() later.
+ *
+ * @param hFt Handle of the Interface
+ * @return Pointer to the string with the name
+ */
+char *GetFtShortNameStrg(FT_HANDLE hFt) {
+    char *buffer = (char *)malloc(128);
+    memset(buffer, '\0', 128);
+
+    if (hFt == NULL) {
+        fprintf(stderr, "GetFtFirmware: No such device\n");
+    }
+
+    switch (hFt->type) {
+        case FT_ROBO_IF_USB:
+        case FT_ROBO_RF_DATA_LINK:
+        case FT_ROBO_IF_OVER_RF:
+            usb_get_string_simple(hFt->device, 5, buffer, 128);
+            break;
+    }
+
+    return buffer;
+}
+
+
+/**
+ * @brief Gets the long name of the Interface
+ *
+ * Will return the long name of a fischertechnik USB device.
+ * The allocated space should be freed with free() later.
+ *
+ * @param hFt Handle of the Interface
+ * @return Pointer to the string with the name
+ */
+char *GetFtLongNameStrg(FT_HANDLE hFt) {
+    char *buffer = (char *)malloc(128);
+    memset(buffer, '\0', 128);
+
+    if (hFt == NULL) {
+        fprintf(stderr, "GetFtFirmware: No such device\n");
+    }
+
+    switch (hFt->type) {
+        case FT_ROBO_IF_USB:
+        case FT_ROBO_RF_DATA_LINK:
+        case FT_ROBO_IF_OVER_RF:
+            usb_get_string_simple(hFt->device, 2, buffer, 128);
+            break;
+    }
+
+    return buffer;
+}
+#endif //NOTNOW
+
+/**
+ * @brief Tells if we successfuly got a connection to the Interface
+ *
+ * @param hFt Handle of the Interface
+ * @return 0 if the Interface is not connected
+ */
+char IsFtInterfaceConnected(FT_HANDLE hFt) {
+    return hFt->interface_connected;
+}
+
+
+/**
+ * @brief Gets the description of an error
+ *
+ * Will return a description of an error.
+ * The allocated space should be freed with free() later.
+ *
+ * The return value is the constant as string if parameter dwTyp is 0,
+ * else a verbose description of the error.
+ *
+ * @param dwErrorCode Error Code
+ * @param dwTyp Type of the return value (see description)
+ * @return Pointer to a string (see description)
+ */
+char *GetFtLibErrorString(long int dwErrorCode, long int dwTyp) {
+    char *buffer = (char *)malloc(128);
+
+    switch (dwErrorCode) {
+        case FTLIB_ERR_IF_NO_PROGRAM:
+            if (dwTyp) strncpy(buffer, "There is no program stored to work with", 128);
+            else strncpy(buffer, "FTLIB_ERR_IF_NO_PROGRAM", 128);
+            break;
+        case FTLIB_ERR_SUCCESS:
+            if (dwTyp) strncpy(buffer, "Everything is fine", 128);
+            else strncpy(buffer, "FTLIB_ERR_SUCCESS", 128);
+            break;
+        case FTLIB_ERR_THREAD_IS_RUNNING:
+            if (dwTyp) strncpy(buffer, "Thread has been started successfully", 128);
+            else strncpy(buffer, "FTLIB_ERR_THREAD_IS_RUNNING", 128);
+            break;
+        case FTLIB_ERR_DOWNLOAD:
+            if (dwTyp) strncpy(buffer, "Failed to upload the program", 128);
+            else strncpy(buffer, "FTLIB_ERR_DOWNLOAD", 128);
+            break;
+        case FTLIB_ERR_DOWNLOAD_WRONG_MEM_BLOCK:
+            if (dwTyp) strncpy(buffer, "Bad target to upload the program to", 128);
+            else strncpy(buffer, "FTLIB_ERR_DOWNLOAD_WRONG_MEM_BLOCK", 128);
+            break;
+        case FTLIB_ERR_INVALID_PARAM:
+            if (dwTyp) strncpy(buffer, "A parameter specified has a wrong value", 128);
+            else strncpy(buffer, "FTLIB_ERR_INVALID_PARAM", 128);
+            break;
+        case FTLIB_ERR_LIB_IS_INITIALIZED:
+            if (dwTyp) strncpy(buffer, "This library has been initialized", 128);
+            else strncpy(buffer, "FTLIB_ERR_LIB_IS_INITIALIZED", 128);
+            break;
+        case FTLIB_ERR_NOT_SUPPORTED:
+            if (dwTyp) strncpy(buffer, "The requested action is not supported", 128);
+            else strncpy(buffer, "FTLIB_ERR_NOT_SUPPORTED", 128);
+            break;
+        case FTLIB_ERR_PORT_NUMBER_IS_NULL:
+            if (dwTyp) strncpy(buffer, "No handle given", 128);
+            else strncpy(buffer, "FTLIB_ERR_PORT_NUMBER_IS_NULL", 128);
+            break;
+        case FTLIB_ERR_THREAD_NOT_RUNNING:
+            if (dwTyp) strncpy(buffer, "Unable to start the thread", 128);
+            else strncpy(buffer, "FTLIB_ERR_THREAD_NOT_RUNNING", 128);
+            break;
+        default:
+            strncpy(buffer, "Unknown", 128);
+    }
+
+    return buffer;
+}
+
+
+/** \cond doxygen ignore start */
+//! \todo
+long int SetFtDeviceCommMode(FT_HANDLE hFt, long int dwMode, long int dwParameter, unsigned short *puiValue) {
+    return 0;
+}
+
+
+//! \todo
+long int GetFtDeviceSetting(FT_HANDLE hFt, FT_SETTING *pSet) {
+    return 0;
+}
+
+
+//! \todo
+long int SetFtDeviceSetting(FT_HANDLE hFt, FT_SETTING *pSet) {
+    return 0;
+}
+
+
+//! \todo
+long int SendFtMessage(FT_HANDLE hFt, unsigned char bHwId, unsigned char bSubId, long int dwMessage, long int dwWaitTime, long int dwOption) {
+    return 0;
+}
+
+
+//! \todo
+long int ClearFtMessageBuffer(FT_HANDLE hFt) {
+    return 0;
+}
+
+
+//! \todo
+long int GetFtMemoryLayout(FT_HANDLE hFt, unsigned char* pbArray, long int dwSize) {
+    return 0;
+}
+
+
+//! \todo
+long int GetFtMemoryData(FT_HANDLE hFt, unsigned char * pbArray, long int dwSize, long int dwAddress) {
+    return 0;
+}
+
+
+//! \todo
+long int WriteFtMemoryData(FT_HANDLE hFt, long int dwData, long int dwAddress) {
+    return 0;
+}
+
+#ifndef SPLITTRANSFER
+/** \cond doxygen ignore start */
+static void *FtThread(FT_HANDLE hFt) {
+    FT_TRANSFER_AREA *area = &hFt->transfer_area;
+    int ret;
+    unsigned char out[ABF_IF_COMPLETE_NUM_WRITE]; //= {ABF_IF_COMPLETE,1,0x07,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+    unsigned char in[ABF_IF_COMPLETE_NUM_READ];
+    int num_write = ABF_IF_COMPLETE_NUM_WRITE;
+    int num_read = ABF_IF_COMPLETE_NUM_READ;
+    int usb_endpoint_write = FT_ENDPOINT_INTERRUPT_OUT;
+    int usb_endpoint_read = FT_ENDPOINT_INTERRUPT_IN;
+    int i=0;
+    int ii_speed = 0;
+
+    out[0] = ABF_IF_COMPLETE;
+    area->TransferAktiv = 1;
+
+    switch (hFt->type) {
+        case FT_ROBO_IF_COM:
+            out[0] = 0xf2;
+            num_write = 17;
+            num_read = 21;
+            break;
+        case FT_INTELLIGENT_IF:
+            num_write = 2;
+            break;
+        case FT_INTELLIGENT_IF_SLAVE:
+            num_write = 3;
+            break;
+#ifdef USE_USB
+        case FT_ROBO_IO_EXTENSION:
+            out[0] = 0xf2;
+            num_write = 6;
+            num_read = 6;
+            break;
+        case FT_ROBO_IF_OVER_RF:
+        case FT_ROBO_RF_DATA_LINK:
+            usb_endpoint_write = FT_RF_ENDPOINT_INTERRUPT_OUT;
+            usb_endpoint_read = FT_RF_ENDPOINT_INTERRUPT_IN;
+
+            // init RF
+            // 0x102 == first RF
+            // 0x202 == 2nd RF
+            // ...
+            //ret = usb_control_msg(hFt->device, 0xc0, 0xfb, 0x102, 0x1, in, 2, FT_USB_TIMEOUT);
+            ret = usb_control_msg(hFt->device, 0xc0, 0xfb, hFt->transfer_area.RfModulNr << 8 | 0x02, 0x1, in, 2, FT_USB_TIMEOUT);
+            if (ret != 2) {
+                fprintf(stderr, "%d FtThread: Error initiating RF Module!\n");
+                area->TransferAktiv = 0;
+            }
+            break;
+#endif
+    }
+//here the real data exchange starts
+#ifdef MBED
+//viaUsb.putc('.');
+    /*while (area->TransferAktiv == 1)*/ { //procedure runs only once
+        if (!test_and_set(hFt->lock)) //return when busy
+            return 0;//return because there is no point in sending a nonsense request, alternatively the lock can be ignored in which case the data may be inconsistent
+#else
+    while (area->TransferAktiv == 1) {//thread runs continuously
+        sem_wait(&hFt->lock);//wait when busy
+#endif
+        out[1] = area->M_Main;
+        out[2] = (area->MPWM_Main[0] & 0x7) | (area->MPWM_Main[1]<<3 & 0x38) | (area->MPWM_Main[2]<<6 & 0xC0);
+        out[3] = (area->MPWM_Main[2] & 0x1) | (area->MPWM_Main[3]<<1 & 0xE) | (area->MPWM_Main[4]<<4 & 0x70) | (area->MPWM_Main[5]<<7 & 0x80);
+        out[4] = (area->MPWM_Main[5] & 0x3) | (area->MPWM_Main[6]<<2 & 0x1C) | (area->MPWM_Main[7]<<5 & 0xE0);
+        out[5] = area->M_Sub1;
+        out[6] = (area->MPWM_Sub1[0] & 0x7) | (area->MPWM_Sub1[1]<<3 & 0x38) | (area->MPWM_Sub1[2]<<6 & 0xC0);
+        out[7] = (area->MPWM_Sub1[2] & 0x1) | (area->MPWM_Sub1[3]<<1 & 0xE) | (area->MPWM_Sub1[4]<<4 & 0x70) | (area->MPWM_Sub1[5]<<7 & 0x80);
+        out[8] = (area->MPWM_Sub1[5] & 0x3) | (area->MPWM_Sub1[6]<<2 & 0x1C) | (area->MPWM_Sub1[7]<<5 & 0xE0);
+        out[9] = area->M_Sub2;
+        out[10] = (area->MPWM_Sub2[0] & 0x7) | (area->MPWM_Sub2[1]<<3 & 0x38) | (area->MPWM_Sub2[2]<<6 & 0xC0);
+        out[11] = (area->MPWM_Sub2[2] & 0x1) | (area->MPWM_Sub2[3]<<1 & 0xE) | (area->MPWM_Sub2[4]<<4 & 0x70) | (area->MPWM_Sub2[5]<<7 & 0x80);
+        out[12] = (area->MPWM_Sub2[5] & 0x3) | (area->MPWM_Sub2[6]<<2 & 0x1C) | (area->MPWM_Sub2[7]<<5 & 0xE0);
+        out[13] = area->M_Sub3;
+        out[14] = (area->MPWM_Sub3[0] & 0x7) | (area->MPWM_Sub3[1]<<3 & 0x38) | (area->MPWM_Sub3[2]<<6 & 0xC0);
+        out[15] = (area->MPWM_Sub3[2] & 0x1) | (area->MPWM_Sub3[3]<<1 & 0xE) | (area->MPWM_Sub3[4]<<4 & 0x70) | (area->MPWM_Sub3[5]<<7 & 0x80);
+        out[16] = (area->MPWM_Sub3[5] & 0x3) | (area->MPWM_Sub3[6]<<2 & 0x1C) | (area->MPWM_Sub3[7]<<5 & 0xE0);
+        out[17]    = 0;
+        out[18]    = 0;
+        out[19]    = 0;
+        out[20]    = 0;
+        out[21]    = 0;
+        out[22]    = 0;
+        out[23]    = 0;
+        out[24]    = 0;
+        out[25]    = 0;
+        out[26]    = 0;
+        out[27]    = 0;
+        out[28]    = 0;
+        out[29]    = 0;
+        out[30]    = 0;
+        out[31]    = 0;
+
+        // For the II we need to simulate different speeds here
+        if (hFt->type == FT_INTELLIGENT_IF || hFt->type == FT_INTELLIGENT_IF_SLAVE) {
+            int iCurMotor;
+            for (iCurMotor = 0; iCurMotor < 7; iCurMotor++) {
+                if (area->MPWM_Main[iCurMotor] < ii_speed) out[1] &= ~(1 << iCurMotor);
+                if (area->MPWM_Sub1[iCurMotor] < ii_speed) out[5] &= ~(1 << iCurMotor);
+            }
+
+            ii_speed++;
+            if (ii_speed > 7) ii_speed = 0;
+        }
+
+        if (hFt->type == FT_INTELLIGENT_IF) {
+            i++;
+            num_read = 1;
+            out[0] = 0xC1;
+            if (i % 20) { // EX
+                out[0] = 0xC5;
+                num_read = 3;
+            } else if (i % 10) { // EY
+                out[0] = 0xC9;
+                num_read = 3;
+            }
+        } else if (hFt->type == FT_INTELLIGENT_IF_SLAVE) {
+            i++;
+            num_read = 2;
+            out[0] = 0xC2;
+            out[2] = out[5];
+            if (i % 20) { // EX
+                out[0] = 0xC6;
+                num_read = 4;
+            } else if (i % 10) { // EY
+                out[0] = 0xCA;
+                num_read = 4;
+            }
+        }
+#ifdef MBED
+//viaUsb.putc('-');
+        increment(hFt->lock);//release the lock on shared memeory
+#else
+        sem_post(&hFt->lock);
+#endif
+        ret = 0;
+        switch (hFt->type) {//send the request
+#ifdef USE_USB
+            case FT_ROBO_IF_USB:
+            case FT_ROBO_IO_EXTENSION:
+            case FT_ROBO_IF_OVER_RF:
+            case FT_ROBO_RF_DATA_LINK:
+                ret = usb_interrupt_write(hFt->device, usb_endpoint_write, out, num_write, FT_USB_TIMEOUT);
+                break;
+#endif
+            case FT_ROBO_IF_COM:
+            case FT_INTELLIGENT_IF:
+            case FT_INTELLIGENT_IF_SLAVE:
+#ifdef MBED
+                //ret = hFt->sdev->printf("%*c", num_write, out);
+                ret = write(hFt->sdev, out, num_write);
+//                viaUsb.putc(';');
+#else
+                ret = write(hFt->sdev, &out, num_write);
+#endif
+                break;
+        }
+        if (ret != num_write) {
+            hFt->interface_connected = 0;
+            fprintf(stderr, "FtThread: Error writing to the Interface...exiting!\n");
+#ifdef MBED
+            return 0;
+#else
+            break;
+#endif
+        }
+
+        ret = 0;
+        switch (hFt->type) { //receive the reply
+#ifdef USE_USB
+            case FT_ROBO_IF_USB:
+            case FT_ROBO_IO_EXTENSION:
+            case FT_ROBO_IF_OVER_RF:
+            case FT_ROBO_RF_DATA_LINK:
+                ret = usb_interrupt_read(hFt->device, usb_endpoint_read, in, num_read, FT_USB_TIMEOUT);
+                break;
+#endif
+            case FT_ROBO_IF_COM:
+            case FT_INTELLIGENT_IF:
+            case FT_INTELLIGENT_IF_SLAVE:
+#ifdef MBED
+                //ret = hFt->sdev->scanf("%*c", num_read, in)==1 ? num_read : 0 ;
+                ret = read(hFt->sdev, in, num_read);
+//                viaUsb.putc('/');
+#else
+                ret = read(hFt->sdev, &in, num_read);
+#endif
+                break;
+        }
+        if (ret != num_read) {
+            hFt->interface_connected = 0;
+            fprintf(stderr, "FtThread: Error reading from the Interface\n");
+#ifdef MBED
+            return 0;
+#else
+            usleep(hFt->query_time);
+            continue;
+#endif
+        }
+
+#ifdef MBED
+        if (!test_and_set(hFt->lock))//skip when busy
+            return 0;
+#else
+        sem_wait(&hFt->lock);//wait when busy
+#endif
+        area->E_Main = in[0];
+        area->E_Sub1 = in[1];
+        area->E_Sub2 = in[2];
+        area->E_Sub3 = in[3];
+        area->AX = in[4];
+        area->AY = in[5];
+        area->A1 = in[6];
+        area->A2 = in[7];
+        area->AX |= (in[8] & 0x3) << 8;
+        area->AY |= (in[8] & 0xC) << 6;
+        area->A1 |= (in[8] & 0x30) << 4;
+        area->A2 |= (in[8] & 0xC0) << 2;
+        area->AZ = in[9];
+        area->D1 = in[10];
+        area->D2 = in[11];
+        area->AV = in[12];
+        area->AZ |= (in[13] & 0x3) << 8;
+        area->D1 |= (in[13] & 0xC) << 6;
+        area->D2 |= (in[13] & 0x30) << 4;
+        area->AV |= (in[13] & 0xC0) << 2;
+        area->IRKeys = in[14];
+        area->BusModules = in[15];
+        // 16
+        area->AXS1 = in[17];
+        area->AXS2 = in[18];
+        area->AXS3 = in[19];
+        area->AXS1 |= (in[20] & 0x3) << 8;
+        area->AXS2 |= (in[20] & 0xC) << 6;
+        area->AXS3 |= (in[20] & 0x30) << 4;
+        // 21
+        area->AVS1 = in[22];
+        area->AVS2 = in[23];
+        area->AVS3 = in[24];
+        area->AVS1 |= (in[25] & 0x3) << 8;
+        area->AVS2 |= (in[25] & 0xC) << 6;
+        area->AVS3 |= (in[25] & 0x30) << 4;
+        // 26...42
+        if (hFt->type == FT_INTELLIGENT_IF) {
+            if (i % hFt->analogcycle) { // EX
+                area->AX = in[1] & (8<<in[2]);
+            } else if (i % (2*hFt->analogcycle)) { // EY
+                area->AY = in[1] & (8<<in[2]);
+            }
+        } else if (hFt->type == FT_INTELLIGENT_IF_SLAVE) {
+            if (i % hFt->analogcycle) { // EX
+                area->AX = in[1] & (8<<in[2]);
+            } else if (i % (2*hFt->analogcycle)) { // EY
+                area->AY = in[1] & (8<<in[2]);
+            }
+        }
+#ifdef MBED
+        increment(hFt->lock);
+        hFt->interface_connected = 1;
+#else
+        sem_post(&hFt->lock);
+
+        hFt->interface_connected = 1;
+
+        usleep(hFt->query_time);
+#endif
+    }//end of the while loop (end of task)
+#ifdef USE_USB
+    if (hFt->type == FT_ROBO_IF_OVER_RF || hFt->type == FT_ROBO_RF_DATA_LINK) {
+        ret = usb_control_msg(hFt->device, 0xc0, 0x21, hFt->transfer_area.RfModulNr << 8, 0, in, 1, FT_USB_TIMEOUT);
+        if (ret != 1 || in[0] != 0xd7) {
+            fprintf(stderr, "Error uninitiating RF Module!\n");
+        }
+    }
+#endif
+#ifdef MBED
+    return 0;
+#else
+    hFt->transfer_area.TransferAktiv = 0;
+    pthread_exit((void *) 0);
+#endif
+}
+
+void ft_handle_devices::FtThread() {
+    ::FtThread(this);
+//    printf("%02X\r", transfer_area.E_Main);
+//    viaUsb.putc('.');
+}
+/** \endcond doxygen ignore end */
+
+#endif
+
+/** \endcond doxygen ignore end */
+