Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
libft.c
00001 //this file was adapted by Ad for use in the mbed environment 00002 //currently all USB functionality has been disabled, this may change in the future 00003 //the comport functionality has been adapted to the mbed serial class 00004 //threads and semphores were replaced by other primitives 00005 //as a consequence also the ftlib.h was adapted 00006 00007 /** @file 00008 * 00009 * Copyright (C) 2007 Erik Andresen erik@vontaene.de 00010 * 00011 * Open Source version of the fischertechnik ROBO Interface Library for Unix like systems 00012 * 00013 * Communication is done through a "transfer area" this is constantly updated. 00014 * 00015 * This library is free software; you can redistribute it and/or 00016 * modify it under the terms of the GNU Lesser General Public 00017 * License as published by the Free Software Foundation; either 00018 * version 2.1 of the License, or (at your option) any later version. 00019 * 00020 * This library is distributed in the hope that it will be useful, 00021 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00023 * Lesser General Public License for more details. 00024 * 00025 * You should have received a copy of the GNU Lesser General Public 00026 * License along with this library; if not, write to the Free Software 00027 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00028 * 00029 */ 00030 00031 /** 00032 * \example example.c 00033 * 00034 * \mainpage libft Index Page 00035 * 00036 * \section intro_sec Introduction 00037 * 00038 * libft is an Open Source version of the fischertechnik ROBO Interface Library for Unix like systems 00039 * 00040 * The goal is to create a library that is fully compatible with the ftlib by knobloch eletronic. 00041 * 00042 * This library should work on any systems supported by libusb, like Linux, BSD and Mac OS X and is released 00043 * under the GNU Lesser General Public License (LGPL) 00044 * 00045 * Included is the helper program "ftuploader" which allows you to upload programs to the Robo Interface.\n 00046 * Running ftuploader --help should give you an idea how to use it.\n 00047 * Also included is an Interface Diagnose utility. See section Interface Diagnose 00048 * 00049 * \section dl_sec Download 00050 * Current Version: 0.4.3 00051 * 00052 * See http://defiant.homedns.org/~erik/ft/libft/files/ \n 00053 * Download Latest version: http://defiant.homedns.org/~erik/ft/libft/files/libft-current.tar.gz 00054 * 00055 * \section req_sec Requirements 00056 * - libusb - http://libusb.sourceforge.net/ 00057 * - cmake at least version 2.4 - http://cmake.org 00058 * - pthreads (Should be included with every modern posix compatible OS) 00059 * 00060 * 00061 * \section apidoc_sec API Documentation 00062 * \see libft.c 00063 * 00064 * \section install_sec Installation 00065 * 00066 * \subsection step1 Step 1: Compiling 00067 * 00068 * Type 00069 * - cmake . 00070 * - make 00071 * \subsection step2 Step 2: Installation 00072 * Type 00073 * - make install 00074 * 00075 * After installing you should run 00076 * - ldconfig 00077 * 00078 * to make the library known to your system. Make sure that /etc/ld.so.conf is configured to include /usr/local/li 00079 * 00080 * To install the diagnose utility type 00081 * - make diag 00082 * 00083 * Debian packages are available. Please read http://vontaene.de/apt/README.txt.\n 00084 * You can install them with apt-get install libft0 libft-doc libft-python libft-diag 00085 * 00086 * \subsection step3 Step 3: udev 00087 * 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 00088 * Udev then needs a reload with 00089 * - udevcontrol reload_rules 00090 * 00091 * You will now need to replug your device. 00092 * 00093 * \subsection step4 Step 4: Create Documentation\n 00094 * Type\n 00095 * - make doc\n 00096 * to create the html API documentation. 00097 * 00098 * \subsection step5 Step 5: Python 00099 * A Python interface to this library is available, see the python folder for details.\n 00100 * Type\n 00101 * make python\n 00102 * 00103 * in the python/ -folder to install the python module. 00104 * Use pydoc to read its documentation: 00105 * - pydoc robointerface in the shell 00106 * - help(robointerface) from the python interpreter 00107 * 00108 * \section diag_sec Interface Diagnose 00109 * You can find it in the folder diag/.\n 00110 * It requires the python module (see above) and PyQT4. You can launch it by running "sh ftdiagnose" 00111 * \image html diag1.png 00112 * 00113 * \section author_sec Author 00114 * Erik Andresen - erik@vontaene.de 00115 * 00116 * Please contact me for bugs or any suggestions 00117 * 00118 * Homepage of libft: http://defiant.homedns.org/~erik/ft/libft/ 00119 * 00120 * 00121 * \section changes_sec Changes 00122 * 00123 * - 0.4.3: - Bug fix: Extension digital inputs at RoboRF 00124 * - ftdiagnose: Display connection status 00125 * - Added functions: (not in Knobloch lib): 00126 * - IsFtInterfaceConnected() 00127 * - Python added functions: 00128 * - IsConnected() 00129 * - 0.4.2: - Python support to open the interface by serial 00130 * - Some Bug fixes 00131 * - Added functions: (not in Knobloch lib) 00132 * - SetRealSerial() 00133 * - 0.4.1: 00134 * - Added support to change the RF address. 00135 * - Added functions: (not in Knobloch lib) 00136 * - SetRFMode() 00137 * - GetRFMode() 00138 * - Added support for functions: 00139 * - GetFtManufacturerStrg() 00140 * - GetFtShortNameStrg() 00141 * - GetFtLongNameStrg() 00142 * - GetFtLibErrorString() 00143 * - Some minor Bug fixes 00144 * - 0.4: 00145 * - Hopefully support for more then one Robo Interface attached to an RF Link. 00146 * - InitFtUsbDeviceList() will now also count the number of Robo Interfaces attached to an RF Link 00147 * - Added support for the ft distance sensor 00148 * - Added functions: 00149 * - GetFtDeviceTypeString() (not in Knobloch lib) 00150 * - Added support for functions: 00151 * - SetFtDistanceSensorMode() 00152 * - Python added functions: 00153 * - GetNumFtUsbDevices() 00154 * - RoboInterface.GetDeviceTypeString() 00155 * - GetD1() 00156 * - GetD2() 00157 * - Added ft Diagnose utility. 00158 * - 0.3: 00159 * - added (overwrite) --target option to the ftuploader 00160 * - included some documentation 00161 * - minor fixes 00162 * - enhanced python layer 00163 * - support for RF Module 00164 * - 0.2.1: 00165 * - fixed Analog/Voltage Sensor calculations 00166 * - 0.2: 00167 * - added udev file 00168 * - experimental support for uploading to the interface (usb only) 00169 * - included program ftuploader 00170 * - add support for functions: 00171 * - DownloadFtProgram() 00172 * - StartFtProgram() 00173 * - StopFtProgram() 00174 * - DeleteFtProgram() 00175 * - SetFtProgramActiv() 00176 * - GetFtProgramName() 00177 * - GetFtStatus() 00178 * - GetFtFirmware() 00179 * - GetFtFirmwareStrg() 00180 * - GetFtSerialNr() 00181 * - GetFtSerialNrStrg() 00182 * 00183 * 00184 * \section porting_sec Porting your program from the Knobloch Windows Library 00185 * When porting your program from the Knobloch Library for Microsoft Windows operation systems please note the following: 00186 * - The name of this library is libft, not ftlib (the Knobloch original) to follow the UNIX naming scheme 00187 * - Types like DWORD are replaced with their logical ANSI-C counterparts, like 00188 * -# DWORD - long int 00189 * -# LPCSTR - char * 00190 * -# LPVOID - void * 00191 * -# BYTE - unsigned char 00192 * -# USHORT - unsigned short int 00193 * -# UINT - unsigned int 00194 * -# UCHAR - unsigned char 00195 * - The Windows Notifications stuff will probably never be supported. 00196 * - Some return codes might be different, so if something is going wrong, check this manual. 00197 * 00198 */ 00199 #define MBED 00200 #define NOTNOW 00201 #define SPLITTRANSFER 00202 00203 #ifdef MBED 00204 #include "mbed.h" 00205 #define usleep(x) wait_us(x) 00206 #define sleep(x) wait(x) 00207 #define LIBFT_VERSION_MAJOR 1 00208 #define LIBFT_VERSION_MINOR 0 00209 #define LIBFT_VERSION_PATCH 0 00210 Serial viaUsb(USBTX, USBRX); 00211 #else 00212 #include <stdio.h> 00213 #include <string.h> 00214 #include <pthread.h> 00215 #include <semaphore.h> 00216 #include <termios.h> 00217 #include <fcntl.h> 00218 #endif 00219 #ifdef USE_USB 00220 #include <usb.h> 00221 #else 00222 //some dummy USB stuff 00223 #endif 00224 #ifdef USE_DOWNLOAD 00225 #include "crc.h" 00226 #endif 00227 #include "ftlib.h " 00228 00229 /** \cond doxygen ignore start */ 00230 #define VERSION_MAJOR LIBFT_VERSION_MAJOR 00231 #define VERSION_MINOR LIBFT_VERSION_MINOR 00232 #define VERSION_PATCH LIBFT_VERSION_PATCH 00233 #define FT_VENDOR_ID 0x146a 00234 #define ROBO_IF_PRODUCT_ID 0x1 00235 #define EXT_IF_PRODUCT_ID 0x2 00236 #define RF_DATA_LINK_PRODUCT_ID 0x3 00237 #define ABF_IF_COMPLETE 0x8b // 0xf2 00238 #define INTERFACE_QUERY_TIME 10000 // �s == 5ms 00239 #define INTERFACE_QUERY_TIME_SERIAL 10000 00240 #define FT_ENDPOINT_INTERRUPT_IN 0x81 00241 #define FT_ENDPOINT_INTERRUPT_OUT 0x1 00242 #define FT_ENDPOINT_BULK_IN 0x82 00243 #define FT_ENDPOINT_BULK_OUT 0x2 00244 #define FT_RF_ENDPOINT_INTERRUPT_IN 0x82 00245 #define FT_RF_ENDPOINT_INTERRUPT_OUT 0x2 00246 #define FT_USB_TIMEOUT 1000 00247 #define FT_USB_TIMEOUT_LONG 10000 00248 00249 #ifdef MBED 00250 #define BAUDRATE_II 9600 00251 #define BAUDRATE_RI 38400 00252 #else 00253 #define BAUDRATE_II B9600 00254 #define BAUDRATE_RI B38400 00255 #endif 00256 #define PROGRAM_UPLOAD_PACKET_SIZE 128 00257 00258 #ifndef MIN 00259 #define MIN(a, b) ( (a)<=(b) ? (a) : (b) ) 00260 #endif 00261 /** \endcond doxygen ignore end */ 00262 00263 00264 /** 00265 * \brief Returns lib version 00266 * 00267 * Returns the library version. 00268 * 00269 * @return version as Major Minor Patch 00270 */ 00271 long int GetLibVersion() { 00272 return VERSION_MAJOR<<16 | VERSION_MINOR<<8 | VERSION_PATCH; 00273 } 00274 00275 00276 /** 00277 * \brief Returns lib version 00278 * 00279 * Returns the library version. 00280 * The allocated space should be freed with free() later. 00281 * 00282 * @return Pointer to a string with the serial 00283 */ 00284 char *GetLibVersionStrg() { 00285 long int ver = GetLibVersion(); 00286 char *s = (char *)malloc(16); 00287 int byte1 = ver & 0xff; 00288 int byte2 = (ver & 0xff00) >> 8; 00289 int byte3 = (ver & 0xff0000) >> 16; 00290 00291 snprintf(s, 16, "%d.%02d.%02d", byte3, byte2, byte1); 00292 00293 return s; 00294 } 00295 00296 00297 /** 00298 * \brief Library initialization (dummy) 00299 * 00300 * Dummy for compatibility. Only used in original library. 00301 * @return Always FTLIB_ERR_SUCCESS 00302 */ 00303 long int InitFtLib() { 00304 return FTLIB_ERR_SUCCESS; 00305 } 00306 00307 00308 /** 00309 * \brief Initiates and scans the USB bus 00310 * 00311 * This function has to be called before any other USB action. 00312 * It will set up USB basic variables and then scan the USB bus. 00313 * 00314 * @return Always FTLIB_ERR_SUCCESS. Not able to fail. 00315 */ 00316 long int InitFtUsbDeviceList() { 00317 #ifdef USE_USB 00318 usb_init(); 00319 usb_find_busses(); 00320 usb_find_devices(); 00321 #endif 00322 return FTLIB_ERR_SUCCESS; 00323 } 00324 00325 00326 /** \cond doxygen ignore start */ 00327 static unsigned int GetNumFtDevicesFromRF(struct usb_device *dev) { 00328 unsigned int iNum = 0; 00329 #ifdef USE_USB 00330 usb_dev_handle *device; 00331 int ret; 00332 unsigned char buffer[35] = { 0 }; 00333 int i; 00334 00335 device = usb_open(dev); 00336 00337 for (i=1; i<9; i++) { 00338 ret = usb_control_msg(device, 0xc0, 0x52, i<<8 | 0x05, 0, buffer, 35, FT_USB_TIMEOUT); 00339 if (ret < 0) fprintf(stderr, "Error sending control msg 0xC0 0x52\n"); 00340 else if (buffer[0] == 0xfa && buffer[1] == 0) iNum++; // buffer[1] == 0xff => no device 00341 } 00342 00343 usb_close(device); 00344 #endif 00345 return iNum; 00346 } 00347 00348 00349 static unsigned int GetNthFtDeviceFromRF(struct usb_device *dev, int iNum) { 00350 int ret=0; 00351 #ifdef USE_USB 00352 usb_dev_handle *device; 00353 unsigned char buffer[35] = { 0 }; 00354 int i; 00355 00356 device = usb_open(dev); 00357 00358 for (i=1; i<9, iNum>0; i++) { 00359 ret = usb_control_msg(device, 0xc0, 0x52, i<<8 | 0x05, 0, buffer, 35, FT_USB_TIMEOUT); 00360 if (ret < 0) fprintf(stderr, "Error sending control msg 0xC0 0x52\n"); 00361 else if (buffer[0] == 0xfa && buffer[1] == 0) iNum--; // buffer[1] == 0xff => no device 00362 00363 ret = i; 00364 } 00365 00366 usb_close(device); 00367 #endif 00368 return ret; 00369 } 00370 00371 00372 static int GetFtDeviceFromRFWithSerial(struct usb_device *dev, long int dwSN) { 00373 #ifdef USE_USB 00374 usb_dev_handle *device; 00375 int ret; 00376 unsigned char buffer[35] = { 0 }; 00377 int i; 00378 long int serial; 00379 00380 device = usb_open(dev); 00381 00382 for (i=1; i<9; i++) { 00383 ret = usb_control_msg(device, 0xc0, 0x52, i<<8 | 0x05, 0, buffer, 35, FT_USB_TIMEOUT); 00384 if (ret < 0) fprintf(stderr, "Error sending control msg 0xC0 0x52\n"); 00385 else if (buffer[0] == 0xfa && buffer[1] == 0) { // buffer[1] == 0xff => no device 00386 serial = buffer[6]<<24 | buffer[5]<<16 | buffer[4]<<8 | buffer[3]; 00387 00388 if (serial == dwSN) { 00389 return i; 00390 } 00391 } 00392 } 00393 00394 usb_close(device); 00395 #endif 00396 return 0; 00397 } 00398 /** \endcond doxygen ignore end */ 00399 00400 00401 /** 00402 * \brief Get the count of found ft Interfaces over USB. 00403 * 00404 * If we find a Robo RF Data Link we will count the devices attached to it instead 00405 * 00406 * @return Number of ft Interface devices on the USB bus found. 00407 */ 00408 unsigned int GetNumFtUsbDevice() { 00409 unsigned int iNum = 0; 00410 #ifdef USE_USB 00411 struct usb_device *dev; 00412 struct usb_bus *busses; 00413 struct usb_bus *bus; 00414 busses = usb_get_busses(); 00415 00416 for (bus = busses; bus; bus = bus->next) { 00417 for (dev = bus->devices; dev; dev = dev->next) { 00418 if (dev->descriptor.idVendor == FT_VENDOR_ID) { 00419 if (dev->descriptor.idProduct == RF_DATA_LINK_PRODUCT_ID) { 00420 iNum+=GetNumFtDevicesFromRF(dev); 00421 } 00422 iNum++; 00423 } 00424 } 00425 } 00426 #endif 00427 return iNum; 00428 } 00429 00430 00431 /** \cond doxygen ignore start */ 00432 static int FtproductIDToInterfaceID(int iProductID) { 00433 switch (iProductID) { 00434 case ROBO_IF_PRODUCT_ID: 00435 return FT_ROBO_IF_USB; 00436 case EXT_IF_PRODUCT_ID: 00437 return FT_ROBO_IO_EXTENSION; 00438 case RF_DATA_LINK_PRODUCT_ID: 00439 return FT_ROBO_RF_DATA_LINK; 00440 } 00441 00442 return 0; 00443 } 00444 00445 00446 static int FtInterfaceIDToProductID(int InterfaceID) { 00447 switch (InterfaceID) { 00448 case FT_ROBO_IF_USB: 00449 return ROBO_IF_PRODUCT_ID; 00450 case FT_ROBO_IO_EXTENSION: 00451 return EXT_IF_PRODUCT_ID; 00452 case FT_ROBO_RF_DATA_LINK: 00453 return RF_DATA_LINK_PRODUCT_ID; 00454 } 00455 00456 return 0; 00457 } 00458 /** \endcond doxygen ignore end */ 00459 00460 00461 /** 00462 * \brief Gets the handle to a ft USB device. 00463 * 00464 * Get the handle for the ft USB device with this number. 00465 * Passing just 0 as argument will use the first device found. 00466 * 00467 * Count the interfaces with GetNumFtUsbDevice() 00468 * 00469 * @see GetNumFtUsbDevice() 00470 * @param Num selected Interface. If unsure try 0. 00471 * @return The ft device or NULL if error 00472 */ 00473 FT_HANDLE GetFtUsbDeviceHandle(unsigned char Num) { 00474 #ifdef USE_USB 00475 struct usb_device *dev; 00476 struct usb_bus *busses; 00477 struct usb_bus *bus; 00478 int i=0; 00479 FT_HANDLE ret; 00480 int count_ri_at_rf; 00481 busses = usb_get_busses(); 00482 00483 for (bus = busses; bus; bus = bus->next) { 00484 for (dev = bus->devices; dev; dev = dev->next) { 00485 if (dev->descriptor.idVendor == FT_VENDOR_ID) { 00486 if (dev->descriptor.idProduct == RF_DATA_LINK_PRODUCT_ID) { 00487 count_ri_at_rf = GetNumFtDevicesFromRF(dev); 00488 i+=count_ri_at_rf; 00489 } 00490 if (i >= Num) { // '>=' because any RF will add more then 1 to the count 00491 ret = (FT_HANDLE) malloc (sizeof(struct ft_handle_devices)); 00492 if (ret == NULL) { 00493 perror("GetFtUsbDeviceHandle malloc"); 00494 return NULL; 00495 } 00496 ret->device = NULL; 00497 ret->dev = dev; 00498 ret->sdev = 0; 00499 ret->type = FtproductIDToInterfaceID(dev->descriptor.idProduct); 00500 sem_init(&ret->lock, 0, 1); 00501 memset(&ret->transfer_area, 0, sizeof(struct _FT_TRANSFER_AREA)); 00502 ret->transfer_area.TransferAktiv = 0; 00503 ret->query_time = INTERFACE_QUERY_TIME; 00504 ret->transfer_area.RfModulNr = -1; 00505 ret->interface_connected = 0; 00506 00507 if (dev->descriptor.idProduct == RF_DATA_LINK_PRODUCT_ID) { 00508 ret->transfer_area.RfModulNr = GetNthFtDeviceFromRF(dev, Num); 00509 if (ret->transfer_area.RfModulNr == 0) // user has chosen the RF Modul, so choose the first Interface at RF for the user 00510 ret->transfer_area.RfModulNr = GetNthFtDeviceFromRF(dev, 1); 00511 else 00512 ret->type = FT_ROBO_IF_OVER_RF; 00513 } 00514 00515 return ret; 00516 } 00517 i++; 00518 } 00519 } 00520 } 00521 #endif 00522 return NULL; 00523 } 00524 00525 00526 /** 00527 * \brief Gets the handle to a ft USB device with a specific serial number. 00528 * 00529 * Get the handle for the ft USB device with this number. 00530 * Serial is 1 for most devices, unless explicitly changed in the device. 00531 * Second argument can be FT_AUTO_TYPE. 00532 * 00533 * @param dwSN Serial of the USB Device 00534 * @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 00535 * @return The ft device or NULL on error 00536 */ 00537 FT_HANDLE GetFtUsbDeviceHandleSerialNr(long int dwSN, long int dwTyp) { 00538 #ifdef USE_USB 00539 int i; 00540 FT_HANDLE ret; 00541 for (i=0; i < GetNumFtUsbDevice(); i++) { 00542 ret = GetFtUsbDeviceHandle(i); 00543 OpenFtUsbDevice(ret); 00544 00545 if ((dwTyp == FT_AUTO_TYPE || ret->type == dwTyp) && GetFtSerialNr(ret) == dwSN) { 00546 CloseFtDevice(ret); 00547 return ret; 00548 } 00549 00550 CloseFtDevice(ret); 00551 } 00552 #endif 00553 return NULL; 00554 } 00555 00556 00557 //blocking 00558 int read(Serial *d, unsigned char *ptr, int n) { 00559 for (int i = 0; i< n; i++) { 00560 ptr[i] = d->getc(); 00561 } 00562 return n; 00563 } 00564 int read(Serial *stream, unsigned char *buf, int n, int timeout_ms) { 00565 Timer t; 00566 t.start(); 00567 int i = 0; 00568 while (t.read_ms() < timeout_ms && i < n) { 00569 if (stream->readable()) 00570 buf[i++] = stream->getc(); 00571 } 00572 return i; 00573 } 00574 00575 //blocking 00576 int write(Serial *d, unsigned char *ptr, int n) { 00577 for (int i = 0; i< n; i++) { 00578 d->putc(ptr[i]); 00579 } 00580 return n; 00581 } 00582 int write(Serial *d, unsigned char *ptr, int n, int timeout_ms) { 00583 Timer t; 00584 t.start(); 00585 int i = 0; 00586 while (t.read_ms() < timeout_ms && i < n) { 00587 if (d->writeable()) 00588 d->putc(ptr[i++]); 00589 } 00590 return i; 00591 } 00592 00593 //non-blocking 00594 int ft_handle_devices::write() { 00595 windex = 0; 00596 //sdev->attach(this, &ft_handle_devices::writeByte, Serial::TxIrq);//could be moved to FtThreadInit 00597 //sdev->attach(this, &ft_handle_devices::readByte, Serial::RxIrq); 00598 writeByte(); //write the first byte, callback will take care of the rest 00599 return num_write; 00600 } 00601 void ft_handle_devices::writeByte() { 00602 if (windex < num_write) { 00603 sdev->putc(out[windex++]); 00604 if (windex == num_write) 00605 rindex = 0; 00606 } 00607 } 00608 void ft_handle_devices::readByte() { 00609 if (rindex < num_read) { 00610 in[rindex++] = sdev->getc(); 00611 if (rindex == num_read) { 00612 //sdev->attach(0,Serial::RxIrq);//could be moved to FtThreadFinish 00613 //sdev->attach(0,Serial::TxIrq); 00614 FtThreadEnd(); 00615 } 00616 } 00617 } 00618 /** 00619 * \brief Gets the handle to a ft serial device. 00620 * 00621 * Get the handle for the ft Serial device at the selected serial port. 00622 * 00623 * @param sDevice filename of your serial device, like /dev/ttyS0. 00624 * @param dwTyp Interface type. FT_INTELLIGENT_IF, FT_INTELLIGENT_IF_SLAVE or FT_ROBO_IF_COM. 00625 * @param dwZyklus Cycle to retrieve analog values (only II). Try 10. 00626 * @return The ft device or NULL if error. 00627 */ 00628 FT_HANDLE OpenFtCommDevice(char *sDevice, long int dwTyp, long int dwZyklus) {//makes a (blocking) comm request to the interface 00629 FT_HANDLE ret; 00630 unsigned char in[5]; 00631 unsigned char on[] = " ft-Robo-ON-V1"; 00632 on[0] = 0xA1; 00633 #ifdef MBED 00634 Serial *dev; 00635 switch (sDevice[3]) { 00636 case '1': 00637 dev = new Serial(p9, p10); 00638 break; 00639 case '2': 00640 dev = new Serial(p13, p14); 00641 break; 00642 case '3': 00643 dev = new Serial(p28, p27); 00644 break; 00645 // default: dev = new Serial(p9, p10); break; 00646 default: 00647 dev = &viaUsb; 00648 break; 00649 } 00650 ret = new ft_handle_devices; 00651 #else 00652 long int dev; 00653 if ((dev = open(sDevice, O_RDWR | O_NOCTTY)) < 0) { 00654 perror("OpenFtCommDevice open"); 00655 return NULL; 00656 } 00657 00658 if ((ret = (FT_HANDLE) malloc (sizeof(struct ft_handle_devices))) == NULL) { 00659 perror("GetFtUsbDeviceHandle malloc"); 00660 return NULL; 00661 } 00662 ret->device = NULL; 00663 ret->dev = NULL; 00664 #endif 00665 ret->type = dwTyp; 00666 memset(&ret->transfer_area, 0, sizeof(struct _FT_TRANSFER_AREA)); 00667 ret->transfer_area.TransferAktiv = 0; 00668 ret->analogcycle = dwZyklus/2.0+0.5; 00669 ret->query_time = INTERFACE_QUERY_TIME_SERIAL; 00670 ret->transfer_area.RfModulNr = -1; 00671 ret->interface_connected = 0; 00672 #ifdef MBED 00673 ret->lock = 1; //init the semaphore 00674 if (dev != &viaUsb) { 00675 if (dwTyp == FT_INTELLIGENT_IF || dwTyp == FT_INTELLIGENT_IF_SLAVE || dwTyp == FT_ROBO_IF_IIM) 00676 dev->baud(BAUDRATE_II); 00677 else // dwTyp == FT_ROBO_IF_COM 00678 dev->baud(BAUDRATE_RI); 00679 } 00680 ret->sdev = dev; 00681 if (dwTyp == FT_INTELLIGENT_IF) ret->transfer_area.BusModules = 1; 00682 else if (dwTyp == FT_INTELLIGENT_IF_SLAVE) ret->transfer_area.BusModules = 2; 00683 printf("about to send '%s'\n", on); 00684 if (dwTyp == FT_ROBO_IF_COM) { 00685 int sent = write(dev, on, strlen((const char*)on), 100/*ms*/); 00686 // int sent = dev->printf("%s", on); 00687 printf("sent %d bytes to COM\n", sent); 00688 if (sent == strlen((const char*)on)) { 00689 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 00690 printf("%02X: interface version: %d.%d.%d.%d\n", in[0], in[4], in[3], in[2], in[1]); 00691 if ((in[0] ^ on[0]) == 0x0FFU) { 00692 printf("opening of %s OK\n", sDevice); 00693 } else { 00694 printf("return code is %02X but should be %02X\n", in[0], ~on[0]&0xFF); 00695 delete ret; 00696 return NULL; 00697 } 00698 } else { 00699 printf("read did not return 5\n"); 00700 delete ret; 00701 return NULL; 00702 } 00703 } else { 00704 printf("only %d chars were sent i.o %d\n", sent, strlen((const char*)on)); 00705 delete ret; 00706 return NULL; 00707 } 00708 } 00709 //printf("OpenFtCommDevice: Error communicating with serial\n"); 00710 //delete ret; 00711 //return NULL; 00712 //} 00713 #else 00714 sem_init(&ret->lock, 0, 1); 00715 tcgetattr(dev, &ret->saveioset); /* save current modem settings */ 00716 bzero(&ret->newioset, sizeof(struct termios)); 00717 ret->newioset.c_cflag = CS8 | CLOCAL | CREAD; 00718 if (dwTyp == FT_INTELLIGENT_IF || dwTyp == FT_INTELLIGENT_IF_SLAVE || dwTyp == FT_ROBO_IF_IIM) 00719 ret->newioset.c_cflag |= BAUDRATE_II; 00720 else // dwTyp == FT_ROBO_IF_COM 00721 ret->newioset.c_cflag |= BAUDRATE_RI; 00722 ret->newioset.c_oflag = 0; 00723 ret->newioset.c_lflag = 0; 00724 ret->newioset.c_cc[VTIME] = 1; 00725 ret->newioset.c_cc[VMIN] = 0; 00726 tcflush(dev, TCIFLUSH); 00727 tcsetattr(dev, TCSANOW, &ret->newioset); 00728 ret->sdev = dev; 00729 if (dwTyp == FT_INTELLIGENT_IF) ret->transfer_area.BusModules = 1; 00730 else if (dwTyp == FT_INTELLIGENT_IF_SLAVE) ret->transfer_area.BusModules = 2; 00731 00732 if (dwTyp == FT_ROBO_IF_COM && ((write(dev, &on, 14)) != 14 || (read(dev, &in, 5)) != 5 || in[0] != 0x5E)) { 00733 fprintf(stderr, "OpenFtCommDevice: Error communicating with serial\n"); 00734 free(ret); 00735 return NULL; 00736 } 00737 #endif 00738 return ret; 00739 } 00740 00741 00742 /** 00743 * \brief Returns type of the interface 00744 * 00745 * This function will return the type of the interface that is behind the handle. 00746 * 00747 * @param hFt Handle of the device 00748 * @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 00749 */ 00750 long int GetFtDeviceTyp(FT_HANDLE hFt) { 00751 if (hFt == NULL) { 00752 fprintf(stderr, "GetFtDeviceTyp: No such device\n"); 00753 return NO_FT_DEVICE; 00754 } 00755 00756 return hFt->type; 00757 } 00758 00759 00760 /** 00761 * \brief Returns a string that identifies the interface with human words 00762 * 00763 * This function will give you a human readable string like "Robo Interface" you can work with. 00764 * 00765 * @param hFt Handle of the device 00766 * @param dest Buffer we can write the string to 00767 * @param len Maximum length of this buffer 00768 * @return FTLIB_ERR_SUCCESS or a failure 00769 */ 00770 long int GetFtDeviceTypeString(FT_HANDLE hFt, char *dest, int len) { 00771 // Todo: Maybe let usb query the string from the device? 00772 if (hFt == NULL) { 00773 fprintf(stderr, "GetFtDeviceTyp: No such device\n"); 00774 return NO_FT_DEVICE; 00775 } 00776 00777 switch (GetFtDeviceTyp(hFt)) { 00778 case FT_INTELLIGENT_IF: 00779 strncpy(dest, "Intelligent Interface", len); 00780 break; 00781 case FT_INTELLIGENT_IF_SLAVE: 00782 strncpy(dest, "Intelligent Interface with slave", len); 00783 break; 00784 case FT_ROBO_IF_IIM: 00785 strncpy(dest, "Robo Interface II mode", len); 00786 break; 00787 case FT_ROBO_IF_COM: 00788 strncpy(dest, "Robo Interface over serial", len); 00789 break; 00790 case FT_ROBO_IF_USB: 00791 strncpy(dest, "Robo Interface over USB", len); 00792 break; 00793 case FT_ROBO_IO_EXTENSION: 00794 strncpy(dest, "Robo IO Extension", len); 00795 break; 00796 case FT_ROBO_RF_DATA_LINK: 00797 strncpy(dest, "Robo RF Datalink", len); 00798 break; 00799 case FT_ROBO_IF_OVER_RF: 00800 strncpy(dest, "Robo Interface over RF Datalink", len); 00801 break; 00802 default: 00803 strncpy(dest, "Unknown", len); 00804 } 00805 00806 return FTLIB_ERR_SUCCESS; 00807 } 00808 00809 00810 00811 /** 00812 * \brief Opens this USB device. 00813 * 00814 * This function will try to open the ft USB device that belongs to the ft handle hFt. 00815 * You can get the ft handle with GetFtUsbDeviceHandle() or GetFtUsbDeviceHandleSerialNr(). 00816 * 00817 * @see GetFtUsbDeviceHandle() 00818 * @see GetFtUsbDeviceHandleSerialNr() 00819 * @param hFt ft USB Device to open 00820 * @return Number >= 0 on success, < 0 on error 00821 */ 00822 long int OpenFtUsbDevice(FT_HANDLE hFt) { 00823 #ifdef USE_USB 00824 long int ret; 00825 00826 if (hFt == NULL) { 00827 fprintf(stderr, "OpenFtUsbDevice: No such device\n"); 00828 return FTLIB_ERR_PORT_NUMBER_IS_NULL; 00829 } 00830 hFt->device = usb_open(hFt->dev); 00831 ret = usb_claim_interface(hFt->device, 0); 00832 if (ret < 0) perror("usb_claim_interface"); 00833 00834 return ret; 00835 #else 00836 return FTLIB_ERR_NOT_SUPPORTED; 00837 #endif 00838 } 00839 00840 00841 /** 00842 * \brief Close the ft Device 00843 * 00844 * This function will close the ft Device and free its memory. 00845 * 00846 * @param hFt Handle of the Device to close. 00847 * @return A number < 0 on error. 00848 */ 00849 long int CloseFtDevice(FT_HANDLE hFt) {//sends a comm request 00850 int ret = 0; 00851 unsigned char off = 0xA2; 00852 unsigned char in[1]; 00853 unsigned char buf[1]; 00854 00855 if (hFt == NULL) { 00856 fprintf(stderr, "CloseFtDevice: No such device\n"); 00857 return FTLIB_ERR_PORT_NUMBER_IS_NULL; 00858 } 00859 00860 while (hFt->transfer_area.TransferAktiv != 0) { 00861 fprintf(stderr, "Transfer area still active\n"); 00862 sleep(1); 00863 } 00864 00865 switch (hFt->type) { 00866 // usb 00867 #ifdef USE_USB 00868 case FT_ROBO_RF_DATA_LINK: 00869 case FT_ROBO_IF_OVER_RF: 00870 case FT_ROBO_IF_USB: 00871 case FT_ROBO_IO_EXTENSION: 00872 ret = usb_release_interface(hFt->device, 0); 00873 if (ret < 0) { 00874 fprintf(stderr, "CloseFtDevice(): Error in usb_release_interface()\n"); 00875 break; 00876 } 00877 ret = usb_close(hFt->device); 00878 break; 00879 #endif 00880 // serial 00881 #ifdef MBED 00882 case FT_ROBO_IF_COM: 00883 if (write(hFt->sdev, &off, 1) != 1 || read(hFt->sdev, in, 1) != 1 || (in[0]^off != 0xFF)) { 00884 fprintf(stderr, "CloseFtDevice: Error communicating with serial\n"); 00885 } 00886 case FT_ROBO_IF_IIM: 00887 case FT_INTELLIGENT_IF: 00888 case FT_INTELLIGENT_IF_SLAVE: 00889 delete hFt->sdev; 00890 ret = 0; 00891 break; 00892 #else 00893 case FT_ROBO_IF_COM: 00894 if ((write(hFt->sdev, &off, 1)) != 1 || (read(hFt->sdev, &in, 1)) != 1 || in[0] != 0x5D) { 00895 fprintf(stderr, "CloseFtDevice: Error communicating with serial\n"); 00896 } 00897 case FT_ROBO_IF_IIM: 00898 case FT_INTELLIGENT_IF: 00899 case FT_INTELLIGENT_IF_SLAVE: 00900 tcsetattr(hFt->sdev, TCSANOW, &hFt->saveioset); 00901 ret = close(hFt->sdev); 00902 break; 00903 #endif 00904 } 00905 #ifdef MBED 00906 delete hFt; 00907 #else 00908 free(hFt); 00909 #endif 00910 hFt = NULL; 00911 return ret; 00912 } 00913 00914 00915 /** 00916 * \brief Library deinitialization (dummy) 00917 * 00918 * Dummy for compatibility. Only used in original library. 00919 * @return Always FTLIB_ERR_SUCCESS 00920 */ 00921 long int CloseFtLib() { 00922 return FTLIB_ERR_SUCCESS; 00923 } 00924 00925 00926 /** 00927 * \brief Check for Library initialization (dummy) 00928 * 00929 * Dummy for compatibility. Only used in original library. 00930 * @return Always FTLIB_ERR_LIB_IS_INITIALIZED since initialization is ignored in this version 00931 */ 00932 long int IsFtLibInit() { 00933 return FTLIB_ERR_LIB_IS_INITIALIZED; 00934 } 00935 00936 bool test_and_set(int& s) { 00937 bool tmp; 00938 __disable_irq(); 00939 if (tmp = s>0) 00940 s--; 00941 __enable_irq(); 00942 return tmp; 00943 } 00944 00945 void increment(int& s) { 00946 __disable_irq(); 00947 s++; 00948 __enable_irq(); 00949 } 00950 #ifdef SPLITTRANSFER 00951 00952 //version for mbed with split functionality 00953 00954 void ft_handle_devices::FtThreadInit() {//setup buffers for this type of interface 00955 FT_TRANSFER_AREA *area = &transfer_area; 00956 num_write = ABF_IF_COMPLETE_NUM_WRITE; 00957 num_read = ABF_IF_COMPLETE_NUM_READ; 00958 usb_endpoint_write = FT_ENDPOINT_INTERRUPT_OUT; 00959 usb_endpoint_read = FT_ENDPOINT_INTERRUPT_IN; 00960 cycle=0; 00961 00962 out[0] = ABF_IF_COMPLETE; 00963 area->TransferAktiv = 1; 00964 sdev->attach(this, &ft_handle_devices::writeByte, Serial::TxIrq); 00965 sdev->attach(this, &ft_handle_devices::readByte, Serial::RxIrq); 00966 busy = false; 00967 00968 switch (type) { 00969 case FT_ROBO_IF_COM: 00970 out[0] = 0xf2; 00971 num_write = 17; 00972 num_read = 21; 00973 break; 00974 case FT_INTELLIGENT_IF: 00975 num_write = 2; 00976 break; 00977 case FT_INTELLIGENT_IF_SLAVE: 00978 num_write = 3; 00979 break; 00980 #ifdef USE_USB 00981 case FT_ROBO_IO_EXTENSION: 00982 out[0] = 0xf2; 00983 num_write = 6; 00984 num_read = 6; 00985 break; 00986 case FT_ROBO_IF_OVER_RF: 00987 case FT_ROBO_RF_DATA_LINK: 00988 usb_endpoint_write = FT_RF_ENDPOINT_INTERRUPT_OUT; 00989 usb_endpoint_read = FT_RF_ENDPOINT_INTERRUPT_IN; 00990 00991 // init RF 00992 // 0x102 == first RF 00993 // 0x202 == 2nd RF 00994 // ... 00995 //ret = usb_control_msg(hFt->device, 0xc0, 0xfb, 0x102, 0x1, in, 2, FT_USB_TIMEOUT); 00996 ret = usb_control_msg(hFt->device, 0xc0, 0xfb, hFt->transfer_area.RfModulNr << 8 | 0x02, 0x1, in, 2, FT_USB_TIMEOUT); 00997 if (ret != 2) { 00998 fprintf(stderr, "%d FtThread: Error initiating RF Module!\n"); 00999 area->TransferAktiv = 0; 01000 } 01001 break; 01002 #endif 01003 } 01004 } 01005 01006 extern int trigger_interface; 01007 01008 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 01009 //viaUsb.putc('.'); 01010 __disable_irq(); 01011 if (busy) { 01012 if (trigger_interface > 10) { //interface has not responded within 10 slots or response was missed 01013 putc('?',stderr); 01014 busy = false; //release the busy flag to reenable the request-reply process 01015 } 01016 __enable_irq(); 01017 return false; //skip the timeslot when previous was not yet handled 01018 } 01019 busy = true; 01020 __enable_irq(); 01021 FtThreadBegin();//here the request is sent to the interface 01022 return true; 01023 } 01024 01025 void ft_handle_devices::FtThreadTrigger() { 01026 trigger_interface++;//this is polled by the main loop 01027 //printf("%d ", trigger_interface); 01028 } 01029 01030 //here the real data exchange starts 01031 void ft_handle_devices::FtThreadBegin() {//called every 10ms to issue a request, should be non-blocking 01032 int ii_speed = 0; 01033 FT_TRANSFER_AREA *area = &transfer_area; 01034 if (!test_and_set(lock)) {//return when transferarea is in use 01035 busy = false; //release the mutex, otherwise the thread effectively stops 01036 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 01037 } 01038 out[1] = area->M_Main; 01039 out[2] = (area->MPWM_Main[0] & 0x7) | (area->MPWM_Main[1]<<3 & 0x38) | (area->MPWM_Main[2]<<6 & 0xC0); 01040 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); 01041 out[4] = (area->MPWM_Main[5] & 0x3) | (area->MPWM_Main[6]<<2 & 0x1C) | (area->MPWM_Main[7]<<5 & 0xE0); 01042 out[5] = area->M_Sub1; 01043 out[6] = (area->MPWM_Sub1[0] & 0x7) | (area->MPWM_Sub1[1]<<3 & 0x38) | (area->MPWM_Sub1[2]<<6 & 0xC0); 01044 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); 01045 out[8] = (area->MPWM_Sub1[5] & 0x3) | (area->MPWM_Sub1[6]<<2 & 0x1C) | (area->MPWM_Sub1[7]<<5 & 0xE0); 01046 out[9] = area->M_Sub2; 01047 out[10] = (area->MPWM_Sub2[0] & 0x7) | (area->MPWM_Sub2[1]<<3 & 0x38) | (area->MPWM_Sub2[2]<<6 & 0xC0); 01048 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); 01049 out[12] = (area->MPWM_Sub2[5] & 0x3) | (area->MPWM_Sub2[6]<<2 & 0x1C) | (area->MPWM_Sub2[7]<<5 & 0xE0); 01050 out[13] = area->M_Sub3; 01051 out[14] = (area->MPWM_Sub3[0] & 0x7) | (area->MPWM_Sub3[1]<<3 & 0x38) | (area->MPWM_Sub3[2]<<6 & 0xC0); 01052 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); 01053 out[16] = (area->MPWM_Sub3[5] & 0x3) | (area->MPWM_Sub3[6]<<2 & 0x1C) | (area->MPWM_Sub3[7]<<5 & 0xE0); 01054 out[17] = 0; 01055 out[18] = 0; 01056 out[19] = 0; 01057 out[20] = 0; 01058 out[21] = 0; 01059 out[22] = 0; 01060 out[23] = 0; 01061 out[24] = 0; 01062 out[25] = 0; 01063 out[26] = 0; 01064 out[27] = 0; 01065 out[28] = 0; 01066 out[29] = 0; 01067 out[30] = 0; 01068 out[31] = 0; 01069 01070 // For the II we need to simulate different speeds here 01071 if (type == FT_INTELLIGENT_IF || type == FT_INTELLIGENT_IF_SLAVE) { 01072 int iCurMotor; 01073 for (iCurMotor = 0; iCurMotor < 7; iCurMotor++) { 01074 if (area->MPWM_Main[iCurMotor] < ii_speed) out[1] &= ~(1 << iCurMotor); 01075 if (area->MPWM_Sub1[iCurMotor] < ii_speed) out[5] &= ~(1 << iCurMotor); 01076 } 01077 01078 ii_speed++; 01079 if (ii_speed > 7) ii_speed = 0; 01080 } 01081 01082 if (type == FT_INTELLIGENT_IF) { 01083 cycle++; 01084 num_read = 1; 01085 out[0] = 0xC1; 01086 if (cycle % 20) { // EX 01087 out[0] = 0xC5; 01088 num_read = 3; 01089 } else if (cycle % 10) { // EY 01090 out[0] = 0xC9; 01091 num_read = 3; 01092 } 01093 } else if (type == FT_INTELLIGENT_IF_SLAVE) { 01094 cycle++; 01095 num_read = 2; 01096 out[0] = 0xC2; 01097 out[2] = out[5]; 01098 if (cycle % 20) { // EX 01099 out[0] = 0xC6; 01100 num_read = 4; 01101 } else if (cycle % 10) { // EY 01102 out[0] = 0xCA; 01103 num_read = 4; 01104 } 01105 } 01106 //viaUsb.putc('-'); 01107 increment(lock);//release the lock on shared memeory 01108 int ret = 0; 01109 switch (type) {//send the request 01110 #ifdef USE_USB 01111 case FT_ROBO_IF_USB: 01112 case FT_ROBO_IO_EXTENSION: 01113 case FT_ROBO_IF_OVER_RF: 01114 case FT_ROBO_RF_DATA_LINK: 01115 ret = usb_interrupt_write(hFt->device, usb_endpoint_write, out, num_write, FT_USB_TIMEOUT); 01116 break; 01117 #endif 01118 case FT_ROBO_IF_COM: 01119 case FT_INTELLIGENT_IF: 01120 case FT_INTELLIGENT_IF_SLAVE: 01121 // ret = write(sdev, out, num_write); 01122 //sdev->dmaSend(out, num_write); 01123 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 01124 // viaUsb.putc(';'); 01125 break; 01126 } 01127 if (ret != num_write) { 01128 interface_connected = 0; 01129 fprintf(stderr, "FtThread: Error writing to the Interface...exiting!\n"); 01130 } 01131 } 01132 01133 void ft_handle_devices::FtThreadEnd() {//called by the receiver/dma callback when the reply is complete 01134 int ret = 0; 01135 FT_TRANSFER_AREA *area = &transfer_area; 01136 switch (type) { //receive the reply 01137 #ifdef USE_USB 01138 case FT_ROBO_IF_USB: 01139 case FT_ROBO_IO_EXTENSION: 01140 case FT_ROBO_IF_OVER_RF: 01141 case FT_ROBO_RF_DATA_LINK: 01142 ret = usb_interrupt_read(hFt->device, usb_endpoint_read, in, num_read, FT_USB_TIMEOUT); 01143 break; 01144 #endif 01145 case FT_ROBO_IF_COM: 01146 case FT_INTELLIGENT_IF: 01147 case FT_INTELLIGENT_IF_SLAVE: 01148 // ret = read(sdev, in, num_read); 01149 ret = num_read; 01150 // viaUsb.putc('/'); 01151 break; 01152 } 01153 if (ret != num_read) { 01154 interface_connected = 0; 01155 fprintf(stderr, "FtThread: Error reading from the Interface\n"); 01156 return; 01157 } 01158 01159 if (!test_and_set(lock)) {//skip when busy 01160 busy = false; 01161 return; 01162 } 01163 area->ChangeEg = area->E_Main != in[0] || area->E_Sub1 != in[1] || area->E_Sub2 != in[2] || area->E_Sub3 != in[3]; 01164 area->E_Main = in[0]; 01165 area->E_Sub1 = in[1]; 01166 area->E_Sub2 = in[2]; 01167 area->E_Sub3 = in[3]; 01168 area->ChangeAn = 1; //assume that analog always changes (noise) 01169 area->AX = in[4]; 01170 area->AY = in[5]; 01171 area->A1 = in[6]; 01172 area->A2 = in[7]; 01173 area->AX |= (in[8] & 0x3) << 8; 01174 area->AY |= (in[8] & 0xC) << 6; 01175 area->A1 |= (in[8] & 0x30) << 4; 01176 area->A2 |= (in[8] & 0xC0) << 2; 01177 area->AZ = in[9]; 01178 area->D1 = in[10]; 01179 area->D2 = in[11]; 01180 area->AV = in[12]; 01181 area->AZ |= (in[13] & 0x3) << 8; 01182 area->D1 |= (in[13] & 0xC) << 6; 01183 area->D2 |= (in[13] & 0x30) << 4; 01184 area->AV |= (in[13] & 0xC0) << 2; 01185 if (area->IRKeys != in[14]) 01186 area->ChangeIr = 1; 01187 area->IRKeys = in[14]; 01188 area->BusModules = in[15]; 01189 // 16 01190 area->AXS1 = in[17]; 01191 area->AXS2 = in[18]; 01192 area->AXS3 = in[19]; 01193 area->AXS1 |= (in[20] & 0x3) << 8; 01194 area->AXS2 |= (in[20] & 0xC) << 6; 01195 area->AXS3 |= (in[20] & 0x30) << 4; 01196 // 21 01197 area->AVS1 = in[22]; 01198 area->AVS2 = in[23]; 01199 area->AVS3 = in[24]; 01200 area->AVS1 |= (in[25] & 0x3) << 8; 01201 area->AVS2 |= (in[25] & 0xC) << 6; 01202 area->AVS3 |= (in[25] & 0x30) << 4; 01203 // 26...42 01204 if (type == FT_INTELLIGENT_IF) { 01205 if (cycle % analogcycle) { // EX 01206 area->AX = in[1] & (8<<in[2]); 01207 } else if (cycle % (2*analogcycle)) { // EY 01208 area->AY = in[1] & (8<<in[2]); 01209 } 01210 } else if (type == FT_INTELLIGENT_IF_SLAVE) { 01211 if (cycle % analogcycle) { // EX 01212 area->AX = in[1] & (8<<in[2]); 01213 } else if (cycle % (2*analogcycle)) { // EY 01214 area->AY = in[1] & (8<<in[2]); 01215 } 01216 } 01217 increment(lock); 01218 interface_connected = 1; 01219 if (ne.NotificationCallback) { 01220 // printf("%02X\r", transfer_area.E_Main); 01221 (*ne.NotificationCallback)(ne.Context); 01222 } 01223 busy = false; 01224 } 01225 01226 void ft_handle_devices::FtThreadFinish() {//called by StopFtTransferArea 01227 #ifdef USE_USB 01228 if (hFt->type == FT_ROBO_IF_OVER_RF || hFt->type == FT_ROBO_RF_DATA_LINK) { 01229 ret = usb_control_msg(hFt->device, 0xc0, 0x21, hFt->transfer_area.RfModulNr << 8, 0, in, 1, FT_USB_TIMEOUT); 01230 if (ret != 1 || in[0] != 0xd7) { 01231 fprintf(stderr, "Error uninitiating RF Module!\n"); 01232 } 01233 } 01234 #endif 01235 #ifdef MBED 01236 sdev->attach(0,Serial::RxIrq); 01237 sdev->attach(0,Serial::TxIrq); 01238 #endif 01239 transfer_area.TransferAktiv = 0; 01240 } 01241 01242 void ft_handle_devices::FtThread() { 01243 // ::FtThread(this); 01244 // printf("%02X\r", transfer_area.E_Main); 01245 // viaUsb.putc('.'); 01246 } 01247 01248 #endif 01249 01250 /** 01251 * \brief reset outputs 01252 * 01253 * Will clear all outputs. 01254 * 01255 * @return Always FTLIB_ERR_SUCCESS 01256 */ 01257 long int ResetFtTransfer(FT_HANDLE hFt) { 01258 FT_TRANSFER_AREA *area = &hFt->transfer_area; 01259 01260 area->M_Main = 0; 01261 area->M_Sub1 = 0; 01262 area->M_Sub2 = 0; 01263 area->M_Sub3 = 0; 01264 01265 return FTLIB_ERR_SUCCESS; 01266 } 01267 01268 01269 /** 01270 * \brief Starts the communication thread. 01271 * 01272 * This function is needed to start the communication with the interface in passive mode. 01273 * Get the handle with GetFtUsbDeviceHandle(), GetFtUsbDeviceHandleSerialNr() or OpenFtCommDevice(). 01274 * 01275 * @see GetFtUsbDeviceHandle() 01276 * @see GetFtUsbDeviceHandleSerialNr() 01277 * @see OpenFtCommDevice() 01278 * @param hFt Handle of the interface. 01279 * @param ignored The second argument is ignored in this version. 01280 * @return Everything except FTLIB_ERR_SUCCESS indicates an error. 01281 */ 01282 long int StartFtTransferArea(FT_HANDLE hFt, NOTIFICATION_EVENTS* ev) { 01283 int ret; 01284 01285 if (hFt == NULL) { 01286 fprintf(stderr, "StartFtTransferArea: No such device\n"); 01287 return NO_FT_DEVICE; 01288 } 01289 if (ev) 01290 hFt->ne = *ev; //copy the entire struct 01291 else 01292 memset(&hFt->ne, 0, sizeof(NOTIFICATION_EVENTS)); 01293 #ifdef MBED 01294 //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 01295 //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 01296 //handed over to IRQ/USB, the reply is gathered in a buffer and when complete the transfer area is updated. 01297 hFt->t = new Ticker; 01298 //printf("ticker created\n"); 01299 hFt->FtThreadInit();//setup buffers and serial handlers 01300 //hFt->t->attach_us(hFt, &ft_handle_devices::FtThreadBegin, INTERFACE_QUERY_TIME); 01301 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 01302 printf("thread attached\n"); 01303 ret = 0; 01304 #else 01305 ret = pthread_create(&hFt->t, NULL, (void *)FtThread, hFt); 01306 #endif 01307 usleep(INTERFACE_QUERY_TIME*10); 01308 if (ret != 0) { 01309 perror("StartFtTransferArea pthread_create"); 01310 return ret; 01311 } 01312 01313 return FTLIB_ERR_SUCCESS; 01314 } 01315 01316 01317 /** 01318 * \brief Starts the communication thread. 01319 * 01320 * Since notification are ignored in this version, will just call StartFtTransferArea(). 01321 * 01322 * @see StartFtTransferArea() 01323 */ 01324 long int StartFtTransferAreaWithCommunication(FT_HANDLE hFt, NOTIFICATION_EVENTS* ignored) { 01325 return StartFtTransferArea(hFt, ignored); 01326 } 01327 01328 01329 /** 01330 * \brief Get the transfer area 01331 * 01332 * This function will return a pointer to the transfer area of the given handle. 01333 * 01334 * @param hFt Handle of the device. 01335 * @return transfer area or NULL on error. 01336 */ 01337 FT_TRANSFER_AREA* GetFtTransferAreaAddress(FT_HANDLE hFt) { 01338 if (hFt == NULL) { 01339 fprintf(stderr, "GetFtTransferAreaAddress: No such device\n"); 01340 return NULL; 01341 } 01342 return &hFt->transfer_area; 01343 } 01344 01345 01346 /** 01347 * \brief Stops the communication thread. 01348 * \warning Will block a few microseconds until thread stopped. 01349 * 01350 * This function will stop the communication thread. 01351 * 01352 * @see StartFtTransferArea() 01353 * @param hFt Handle of the Interface. 01354 * @return Everything except FTLIB_ERR_SUCCESS indicates an error. 01355 */ 01356 long int StopFtTransferArea(FT_HANDLE hFt) { 01357 int ret; 01358 01359 if (hFt == NULL) { 01360 fprintf(stderr, "StopFtTransferArea: No such device\n"); 01361 return NO_FT_DEVICE; 01362 } 01363 01364 #ifdef MBED 01365 hFt->t->detach(); 01366 delete hFt->t; 01367 hFt->FtThreadFinish(); 01368 #else 01369 usleep(INTERFACE_QUERY_TIME*10); // wait to make sure the last command is send to the interface 01370 if (hFt->transfer_area.TransferAktiv == 1) { 01371 hFt->transfer_area.TransferAktiv = 2; // cleaner then pthread_cancel() 01372 } 01373 if ((ret = pthread_join(hFt->t, NULL)) != 0) return ret; 01374 #endif 01375 return FTLIB_ERR_SUCCESS; 01376 } 01377 01378 01379 /** 01380 * \brief check if transfer is active. 01381 * 01382 * Check if we are currently communicating with the device. 01383 * 01384 * @param hFt Handle of the Interface. 01385 * @return FTLIB_ERR_THREAD_IS_RUNNING or FTLIB_ERR_THREAD_NOT_RUNNING 01386 */ 01387 long int IsFtTransferActiv(FT_HANDLE hFt) { 01388 if (hFt == NULL) { 01389 fprintf(stderr, "StopFtTransferArea: No such device\n"); 01390 return NO_FT_DEVICE; 01391 } 01392 01393 if (hFt->transfer_area.TransferAktiv) return FTLIB_ERR_THREAD_IS_RUNNING; 01394 01395 return FTLIB_ERR_THREAD_NOT_RUNNING; 01396 } 01397 01398 01399 #ifdef USE_DOWNLOAD 01400 /** 01401 * \brief Upload a program to the interface 01402 * 01403 * Upload (download from the perspective of the interface) a program to the interface. 01404 * 01405 * @param hFt Handle of the Interface 01406 * @param dwMemBlock Destination 0 (Flash 1), 1 (Flash 2) or 2 (Ram) 01407 * @param pbArray Pointer to the program to upload 01408 * @param dwSize Size of the program to upload 01409 * @param dwParameter 1 to Autostart this program, else 0. 01410 * @param pbName Name of the program to upload 01411 * @param dwNameLen Length of the name 01412 * @return FTLIB_ERR_SUCCESS if you got lucky 01413 */ 01414 long int DownloadFtProgram(FT_HANDLE hFt, long int dwMemBlock, unsigned char *pbArray, long int dwSize, long int dwParameter, unsigned char *pbName, long int dwNameLen) { 01415 int ret; 01416 unsigned char buffer[128]; 01417 long int i; 01418 crc_t crc; 01419 int memblockarg; 01420 01421 if (hFt == NULL) { 01422 fprintf(stderr, "DownloadFtProgram: No such device\n"); 01423 return FTLIB_ERR_PORT_NUMBER_IS_NULL; 01424 } else if (hFt->type != FT_ROBO_IF_USB) { 01425 fprintf(stderr, "DownloadFtProgram: Sorry, I can only handle the Robo Interface over USB at this time.\n"); 01426 return FTLIB_ERR_NOT_SUPPORTED; 01427 } 01428 01429 switch (dwMemBlock) { 01430 case 0x0: // flash 1 01431 memblockarg = 0x100; 01432 if (dwParameter == 1) memblockarg += 0x100; 01433 break; 01434 case 0x1: // flash 2 01435 memblockarg = 0x101; 01436 if (dwParameter == 1) fprintf(stderr, "Warning: Autostart for flash 2 not supported\n"); 01437 break; 01438 case 0x2: // ram 01439 memblockarg = 0x102; 01440 if (dwParameter == 1) fprintf(stderr, "Warning: Autostart for RAM not supported\n"); 01441 break; 01442 case 0xf0: // firmware A 01443 memblockarg = 0xf200; 01444 break; 01445 case 0xf1: // firmware B 01446 memblockarg = 0xf201; 01447 break; 01448 default: 01449 fprintf(stderr, "Unknown Memblock Target\n"); 01450 return FTLIB_ERR_DOWNLOAD_WRONG_MEM_BLOCK; 01451 } 01452 01453 // init upload 01454 ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x20, 0, buffer, 1, FT_USB_TIMEOUT_LONG); 01455 if (ret < 0) { 01456 fprintf(stderr, "Error sending control msg 0xC0 0xF0\n"); 01457 return ret; 01458 } 01459 if (buffer[0] != 1) { 01460 fprintf(stderr, "Error uploading Program: Return value for 0xC0 0xF0 is 0x%x\n", buffer[0]); 01461 return FTLIB_ERR_DOWNLOAD; 01462 } 01463 01464 // write name 01465 memset(buffer, 0, 128); // clean buffer 01466 if (pbName != NULL) 01467 strncpy(buffer, pbName, MIN(dwNameLen, 80)); // copy to buffer, so we not change the original content 01468 ret = usb_control_msg(hFt->device, 0x40, 0x10, memblockarg, dwSize/PROGRAM_UPLOAD_PACKET_SIZE, buffer, 80, FT_USB_TIMEOUT_LONG); 01469 if (ret < 0) { 01470 fprintf(stderr, "Error sending control msg 0x40 0x10\n"); 01471 return ret; 01472 } 01473 01474 // check 01475 ret = usb_control_msg(hFt->device, 0xC0, 0x20, 0x0, 0x0, buffer, 1, FT_USB_TIMEOUT_LONG); 01476 if (ret < 0) { 01477 fprintf(stderr, "Error sending control ms 0xC0 0x20g\n"); 01478 return ret; 01479 } 01480 if (buffer[0] != dwMemBlock || (buffer[0] == 0 && memblockarg == 0xf200) || (buffer[0] == 1 && memblockarg == 0xf201)) { 01481 fprintf(stderr, "Upload Error: Target mismatch\n"); 01482 } 01483 01484 // write the data 01485 for (i=0; dwSize >= PROGRAM_UPLOAD_PACKET_SIZE; i++, dwSize -= PROGRAM_UPLOAD_PACKET_SIZE) { 01486 memset(buffer, 0, 128); // clean buffer 01487 memcpy(buffer, pbArray + (i*PROGRAM_UPLOAD_PACKET_SIZE), MIN(dwSize, PROGRAM_UPLOAD_PACKET_SIZE)); // make sure we not change the original content 01488 01489 crc = crc_init(); 01490 crc = crc_update(crc, buffer, PROGRAM_UPLOAD_PACKET_SIZE); 01491 crc = crc_finalize(crc); 01492 01493 // write 128 byte 01494 /*printf("CRC: 0x%x\n", crc); 01495 printf("Paket: 0x%x\n", i+1); 01496 for(k=0; k<128; k++) { 01497 printf("0x%x ", buffer[k]); 01498 if ((k+1) % 16 == 0 && k != 0) printf("\n"); 01499 } 01500 printf("\n");*/ 01501 ret = usb_control_msg(hFt->device, 0x40, 0x11, i+1, crc, buffer, PROGRAM_UPLOAD_PACKET_SIZE, FT_USB_TIMEOUT_LONG); 01502 if (ret < 0) { 01503 fprintf(stderr, "Error sending control msg 0x40 0x11 0x%x\n", i+1); 01504 return ret; 01505 } 01506 01507 // check 01508 ret = usb_control_msg(hFt->device, 0xC0, 0x20, 0x0, 0x0, buffer, 1, FT_USB_TIMEOUT_LONG); 01509 if (ret < 0) { 01510 fprintf(stderr, "Error sending control msg 0xC0 0x20\n"); 01511 return ret; 01512 } 01513 if (buffer[0] != 1) { 01514 fprintf(stderr, "Error uploading Program: Return value for 0xC0, 0x20 is 0x%x\n", buffer[0]); 01515 return FTLIB_ERR_DOWNLOAD; 01516 } 01517 } 01518 01519 return FTLIB_ERR_SUCCESS; 01520 } 01521 01522 01523 /** 01524 * \brief Start a program 01525 * 01526 * Will start a program that has been Successfully uploaded to the interface. 01527 * 01528 * @param hFt Handle of the Interface 01529 * @param dwMemBlock Destination 0 (Flash 1), 1 (Flash 2) or 2 (Ram) 01530 * @return FTLIB_ERR_SUCCESS or FTLIB_ERR_IF_NO_PROGRAM 01531 */ 01532 long int StartFtProgram(FT_HANDLE hFt, long int dwMemBlock) { 01533 int ret; 01534 unsigned char buffer[2]; 01535 01536 if (hFt == NULL) { 01537 fprintf(stderr, "StartFtProgram: No such device\n"); 01538 return FTLIB_ERR_PORT_NUMBER_IS_NULL; 01539 } 01540 01541 switch (hFt->type) { 01542 case FT_ROBO_IF_USB: 01543 // note: serial documentation says 0xf4 here, sniffer says 0x12 01544 ret = usb_control_msg(hFt->device, 0xc0, 0x12, dwMemBlock, 0, buffer, 1, FT_USB_TIMEOUT_LONG); 01545 if (ret < 0) { 01546 fprintf(stderr, "Error sending control msg 0xC0 0xF4\n"); 01547 return ret; 01548 } 01549 if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS; 01550 else return FTLIB_ERR_IF_NO_PROGRAM; 01551 break; 01552 case FT_ROBO_IF_COM: 01553 buffer[0] = 0xf4; 01554 buffer[1] = dwMemBlock; 01555 if ((write(hFt->sdev, &buffer, 2)) != 2 || (read(hFt->sdev, &buffer, 1)) != 1) { 01556 return FTLIB_ERR_IF_NO_PROGRAM; 01557 } 01558 if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS; 01559 else return FTLIB_ERR_IF_NO_PROGRAM; 01560 break; 01561 } 01562 01563 return FTLIB_ERR_NOT_SUPPORTED; 01564 } 01565 01566 01567 /** 01568 * \brief Stop a program 01569 * 01570 * Will stop the current running program that has been uploaded to the interface. 01571 * 01572 * @param hFt Handle of the Interface 01573 * @return FTLIB_ERR_SUCCESS or FTLIB_ERR_IF_NO_PROGRAM 01574 */ 01575 long int StopFtProgram(FT_HANDLE hFt) { 01576 int ret; 01577 unsigned char buffer[1]; 01578 01579 if (hFt == NULL) { 01580 fprintf(stderr, "StopFtProgram: No such device\n"); 01581 return FTLIB_ERR_PORT_NUMBER_IS_NULL; 01582 } 01583 01584 switch (hFt->type) { 01585 case FT_ROBO_IF_USB: 01586 // note: serial documentation says 0xf8 here, sniffer says 0x13 01587 ret = usb_control_msg(hFt->device, 0xc0, 0x13, 0, 0, buffer, 1, FT_USB_TIMEOUT_LONG); 01588 if (ret < 0) { 01589 fprintf(stderr, "Error sending control msg 0xC0 0x13\n"); 01590 return ret; 01591 } 01592 01593 if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS; 01594 else return FTLIB_ERR_IF_NO_PROGRAM; 01595 break; 01596 case FT_ROBO_IF_COM: 01597 buffer[0] = 0xf8; 01598 if ((write(hFt->sdev, &buffer, 1)) != 1 || (read(hFt->sdev, &buffer, 1)) != 1) { 01599 return FTLIB_ERR_IF_NO_PROGRAM; 01600 } 01601 if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS; 01602 else return FTLIB_ERR_IF_NO_PROGRAM; 01603 break; 01604 } 01605 01606 return FTLIB_ERR_NOT_SUPPORTED; 01607 } 01608 01609 01610 /** 01611 * \brief Delete a program 01612 * 01613 * Will delete a program that has been uploaded to the interface. 01614 * 01615 * @param hFt Handle of the Interface 01616 * @param dwMemBlock Destination 0 (Flash 1), 1 (Flash 2) or 2 (Ram) 01617 * @return FTLIB_ERR_SUCCESS or FTLIB_ERR_IF_NO_PROGRAM 01618 */ 01619 long int DeleteFtProgram(FT_HANDLE hFt, long int dwMemBlock) { 01620 int ret; 01621 unsigned char buffer[2]; 01622 01623 if (hFt == NULL) { 01624 fprintf(stderr, "DeleteFtProgram: No such device\n"); 01625 return FTLIB_ERR_PORT_NUMBER_IS_NULL; 01626 } 01627 01628 switch (hFt->type) { 01629 case FT_ROBO_IF_USB: 01630 ret = usb_control_msg(hFt->device, 0xc0, 0xf5, dwMemBlock, 0, buffer, 1, FT_USB_TIMEOUT_LONG); 01631 if (ret < 0) { 01632 fprintf(stderr, "Error sending control msg 0xC0 0xF5\n"); 01633 return ret; 01634 } 01635 01636 if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS; 01637 else return FTLIB_ERR_IF_NO_PROGRAM; 01638 break; 01639 case FT_ROBO_IF_COM: 01640 buffer[0] = 0xf5; 01641 buffer[1] = dwMemBlock; 01642 if ((write(hFt->sdev, &buffer, 2)) != 2 || (read(hFt->sdev, &buffer, 1)) != 1) { 01643 return FTLIB_ERR_IF_NO_PROGRAM; 01644 } 01645 if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS; 01646 else return FTLIB_ERR_IF_NO_PROGRAM; 01647 break; 01648 } 01649 01650 return FTLIB_ERR_NOT_SUPPORTED; 01651 } 01652 01653 01654 /** 01655 * \brief Activate a program 01656 * 01657 * Will activate a program that has been uploaded to the interface. 01658 * 01659 * @param hFt Handle of the Interface 01660 * @param dwMemBlock Destination 0 (Flash 1) or 1 (Flash 2) 01661 * @return FTLIB_ERR_SUCCESS or FTLIB_ERR_IF_NO_PROGRAM 01662 */ 01663 long int SetFtProgramActiv(FT_HANDLE hFt, long int dwMemBlock) { 01664 int ret; 01665 unsigned char buffer[1]; 01666 01667 if (hFt == NULL) { 01668 fprintf(stderr, "SetFtProgramActiv: No such device\n"); 01669 return FTLIB_ERR_PORT_NUMBER_IS_NULL; 01670 } 01671 01672 switch (hFt->type) { 01673 case FT_ROBO_IF_USB: 01674 ret = usb_control_msg(hFt->device, 0xc0, 0xf9, dwMemBlock, 0, buffer, 1, FT_USB_TIMEOUT_LONG); 01675 if (ret < 0) { 01676 fprintf(stderr, "Error sending control msg 0xC0 0xf9\n"); 01677 return ret; 01678 } 01679 01680 if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS; 01681 else return FTLIB_ERR_IF_NO_PROGRAM; 01682 break; 01683 case FT_ROBO_IF_COM: 01684 buffer[0] = 0xf9; 01685 buffer[1] = dwMemBlock; 01686 if ((write(hFt->sdev, &buffer, 2)) != 2 || (read(hFt->sdev, &buffer, 1)) != 1) { 01687 return FTLIB_ERR_IF_NO_PROGRAM; 01688 } 01689 if ((buffer[0]) == 0x1) return FTLIB_ERR_SUCCESS; 01690 else return FTLIB_ERR_IF_NO_PROGRAM; 01691 break; 01692 } 01693 01694 return FTLIB_ERR_NOT_SUPPORTED; 01695 } 01696 01697 01698 /** 01699 * \brief Get the name of a program 01700 * 01701 * Will write the name of a program that has been uploaded to the interface to a given area. 01702 * 01703 * @param hFt Handle of the Interface 01704 * @param dwMemBlock Destination 0 (Flash 1), 1 (Flash 2) or 2 (Ram) 01705 * @param pName Pointer to the area where we can store the name 01706 * @param dwSize Size of the area to store the name to 01707 * @return FTLIB_ERR_SUCCESS or FTLIB_ERR_IF_NO_PROGRAM 01708 */ 01709 long int GetFtProgramName(FT_HANDLE hFt, long int dwMemBlock, long int dwSize, void *pName) { 01710 int ret; 01711 unsigned char buffer[dwSize+1]; 01712 01713 if (hFt == NULL) { 01714 fprintf(stderr, "GetFtProgramName: No such device\n"); 01715 return FTLIB_ERR_PORT_NUMBER_IS_NULL; 01716 } 01717 01718 switch (hFt->type) { 01719 case FT_ROBO_IF_USB: 01720 ret = usb_control_msg(hFt->device, 0xc0, 0xfa, dwMemBlock, 0, buffer, dwSize + 1, FT_USB_TIMEOUT_LONG); 01721 if (ret < 0) { 01722 fprintf(stderr, "Error sending control msg 0xC0 0xFA\n"); 01723 return ret; 01724 } 01725 memcpy(pName, buffer+1, ret-1); 01726 01727 if (buffer[0] == 0x1) return FTLIB_ERR_SUCCESS; 01728 if (buffer[0] == 0xf3) return FTLIB_ERR_IF_NO_PROGRAM; 01729 return buffer[1]; 01730 break; 01731 case FT_ROBO_IF_COM: 01732 buffer[0] = 0xfa; 01733 buffer[1] = dwMemBlock; 01734 if ((write(hFt->sdev, &buffer, 2)) != 2 || (ret = read(hFt->sdev, &buffer, dwSize+1)) < 0 || buffer[0] != 0x01) { 01735 return FTLIB_ERR_IF_NO_PROGRAM; 01736 } 01737 memcpy(pName, buffer+1, ret-1); 01738 if (buffer[0] == 0x1) return FTLIB_ERR_SUCCESS; 01739 break; 01740 } 01741 01742 return FTLIB_ERR_NOT_SUPPORTED; 01743 } 01744 01745 01746 /** 01747 * \brief Checks if a program is running 01748 * 01749 * Checks if a program is currently running. 01750 * 01751 * @param hFt Handle of the Interface 01752 * @param num Area where we can store the number of the running program. 01753 * @return 1 if a program is running, else 0 01754 */ 01755 int GetFtStatus(FT_HANDLE hFt, int *num) { 01756 int ret; 01757 unsigned char buffer[3]; 01758 01759 if (hFt == NULL) { 01760 fprintf(stderr, "GetFtStatus: No such device\n"); 01761 return FTLIB_ERR_PORT_NUMBER_IS_NULL; 01762 } 01763 01764 switch (hFt->type) { 01765 case FT_ROBO_IF_USB: 01766 // test replace 0xf0 with 0x50 01767 ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x3, 0, buffer, 3, FT_USB_TIMEOUT); 01768 if (ret < 0) { 01769 fprintf(stderr, "Error sending control msg 0xC0 0xF0\n"); 01770 return ret; 01771 } 01772 ret = buffer[1]; 01773 *num = buffer[2]; 01774 break; 01775 case FT_ROBO_IF_COM: 01776 buffer[0] = 0xf0; 01777 buffer[1] = 0x3; 01778 if ((write(hFt->sdev, &buffer, 2)) != 2 || (ret = read(hFt->sdev, &buffer, 3)) < 0 || buffer[0] != 0xfc) { 01779 return ret; 01780 } 01781 ret = buffer[1]; 01782 *num = buffer[2]; 01783 break; 01784 default: 01785 return FTLIB_ERR_NOT_SUPPORTED; 01786 } 01787 01788 return ret; 01789 } 01790 #endif //USE_DOWNLOAD 01791 01792 /** 01793 * \brief Get the firmware number of this interface. 01794 * 01795 * Returns the firmware number of the interface squashed into a single int. 01796 * 01797 * @param hFt Handle of the Interface 01798 * @return Firmware number as int byte4 | byte3 | byte2 | byte1, 0 on error. 01799 */ 01800 long int GetFtFirmware(FT_HANDLE hFt) {//makes a blocking comm request 01801 int ret; 01802 unsigned char buffer[35] = { 0 }; 01803 long int firmware = 0; 01804 01805 if (hFt == NULL) { 01806 fprintf(stderr, "GetFtFirmware: No such device\n"); 01807 return FTLIB_ERR_PORT_NUMBER_IS_NULL; 01808 } 01809 01810 01811 switch (hFt->type) { 01812 case FT_INTELLIGENT_IF: 01813 case FT_INTELLIGENT_IF_SLAVE: 01814 return 0; 01815 #ifdef USE_USB 01816 case FT_ROBO_IF_USB: 01817 case FT_ROBO_IO_EXTENSION: 01818 case FT_ROBO_RF_DATA_LINK: 01819 ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x1, 0, buffer, 5, FT_USB_TIMEOUT); 01820 if (ret < 0) { 01821 fprintf(stderr, "Error sending control msg 0xC0 0xF0\n"); 01822 return 0; 01823 } 01824 firmware = buffer[1] | buffer[2]<<8 | buffer[3]<<16 | buffer[4]<<24; 01825 break; 01826 case FT_ROBO_IF_OVER_RF: 01827 ret = usb_control_msg(hFt->device, 0xc0, 0x52, hFt->transfer_area.RfModulNr<<8 | 0x05, 0, buffer, 35, FT_USB_TIMEOUT); 01828 if (ret < 0) { 01829 fprintf(stderr, "Error sending control msg 0xC0 0x52\n"); 01830 return 0; 01831 } 01832 if (buffer[0] == 0xfa && buffer[1] == 0) { // buffer[1] == 0xff => no device 01833 firmware = buffer[23]<<24 | buffer[22]<<16 | buffer[21]<<8 | buffer[20]; 01834 } 01835 break; 01836 #endif 01837 case FT_ROBO_IF_COM: 01838 buffer[0] = 0xf0; 01839 buffer[1] = 0x01; 01840 #ifdef MBED 01841 //printf("requesting FW\n"); 01842 //ret = hFt->sdev->printf("%2c", buffer); 01843 ret = write(hFt->sdev, buffer, 2); 01844 // printf("request was sent %d\n", ret); 01845 #else 01846 ret = write(hFt->sdev, &buffer, 2); 01847 #endif 01848 if (ret != 2) { 01849 fprintf(stderr, "Error writing msg 0xF0 0x01\n"); 01850 return 0; 01851 } 01852 #ifdef MBED 01853 //ret = hFt->sdev->scanf("%5c", buffer)==1 ? 5 : 0 ; 01854 ret = read(hFt->sdev, buffer, 5); 01855 #else 01856 ret = read(hFt->sdev, &buffer, 5); 01857 #endif 01858 if (ret != 5) { 01859 fprintf(stderr, "Error reading msg 0xF0 0x01\n"); 01860 return 0; 01861 } 01862 firmware = buffer[1] | buffer[2]<<8 | buffer[3]<<16 | buffer[4]<<24; 01863 // printf("fw: %ld\n", firmware); 01864 break; 01865 default: 01866 return FTLIB_ERR_NOT_SUPPORTED; 01867 } 01868 01869 return firmware; 01870 } 01871 01872 01873 /** 01874 * \brief Get the firmware number of this interface. 01875 * 01876 * Returns the firmware number of the interface with this handle. 01877 * The allocated space should be freed with free() later. 01878 * 01879 * @param hFt Handle of the Interface 01880 * @return Pointer to a string with the firmware 01881 */ 01882 char *GetFtFirmwareStrg(FT_HANDLE hFt) { 01883 long int ifw = GetFtFirmware(hFt); 01884 char *s = (char *)malloc(16); 01885 int byte1 = ifw & 0xff; 01886 int byte2 = (ifw & 0xff00) >> 8; 01887 int byte3 = (ifw & 0xff0000) >> 16; 01888 int byte4 = (ifw & 0xff000000) >> 24; 01889 01890 snprintf(s, 16, "%d.%02d.%02d.%02d", byte4, byte3, byte2, byte1); 01891 01892 return s; 01893 } 01894 01895 01896 #ifndef NOTNOW 01897 /** 01898 * \brief Get the serial number of this interface. 01899 * 01900 * Returns the serial number of the interface squashed into a single int. 01901 * 01902 * @param hFt Handle of the Interface 01903 * @return Serial number as int byte4 | byte3 | byte2 | byte1, 0 on error. 01904 */ 01905 long int GetFtSerialNr(FT_HANDLE hFt) { 01906 int ret; 01907 unsigned char buffer[35] = { 0 }; 01908 long int serial = 0; 01909 01910 if (hFt == NULL) { 01911 fprintf(stderr, "GetFtSerialNr: No such device\n"); 01912 return FTLIB_ERR_PORT_NUMBER_IS_NULL; 01913 } 01914 01915 01916 switch (hFt->type) { 01917 case FT_INTELLIGENT_IF: 01918 case FT_INTELLIGENT_IF_SLAVE: 01919 return 0; 01920 break; 01921 case FT_ROBO_IF_USB: 01922 ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x2, 0, buffer, 5, FT_USB_TIMEOUT); 01923 if (ret < 0) { 01924 fprintf(stderr, "Error sending control msg 0xC0 0xF0\n"); 01925 return 0; 01926 } 01927 serial = buffer[1] + buffer[2]*100 + buffer[3]*10000 + buffer[4]*1000000; 01928 break; 01929 case FT_ROBO_IO_EXTENSION: 01930 ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x2, 0, buffer, 14, FT_USB_TIMEOUT); 01931 if (ret < 0) { 01932 fprintf(stderr, "Error sending control msg 0xC0 0xF0\n"); 01933 return 0; 01934 } 01935 serial = buffer[1] + buffer[2]*100 + buffer[3]*10000 + buffer[4]*1000000; 01936 break; 01937 case FT_ROBO_RF_DATA_LINK: 01938 ret = usb_control_msg(hFt->device, 0xc0, 0xf0, 0x2, 0, buffer, 14, FT_USB_TIMEOUT); 01939 if (ret < 0) { 01940 fprintf(stderr, "Error sending control msg 0xC0 0x52\n"); 01941 return 0; 01942 } 01943 serial = buffer[1] + buffer[2]*100 + buffer[3]*10000 + buffer[4]*1000000; 01944 break; 01945 case FT_ROBO_IF_OVER_RF: 01946 ret = usb_control_msg(hFt->device, 0xc0, 0x52, hFt->transfer_area.RfModulNr<<8 | 0x05, 0, buffer, 35, FT_USB_TIMEOUT); 01947 if (ret < 0) { 01948 fprintf(stderr, "Error sending control msg 0xC0 0x52\n"); 01949 return 0; 01950 } 01951 if (buffer[0] == 0xfa && buffer[1] == 0) { // buffer[1] == 0xff => no device 01952 serial = buffer[6]*1000000 + buffer[5]*10000 + buffer[4]*100 + buffer[3]; 01953 } 01954 break; 01955 case FT_ROBO_IF_COM: 01956 buffer[0] = 0xf0; 01957 buffer[1] = 0x02; 01958 ret = write(hFt->sdev, &buffer, 2); 01959 if (ret != 2) { 01960 fprintf(stderr, "Error writing msg 0xF0 0x02\n"); 01961 return 0; 01962 } 01963 ret = read(hFt->sdev, &buffer, 5); 01964 if (ret != 5) { 01965 fprintf(stderr, "Error reading msg 0xF0 0x02\n"); 01966 return 0; 01967 } 01968 serial = buffer[1] + buffer[2]*100 + buffer[3]*10000 + buffer[4]*1000000; 01969 break; 01970 default: 01971 return FTLIB_ERR_NOT_SUPPORTED; 01972 } 01973 01974 return serial; 01975 } 01976 01977 01978 /** 01979 * \brief Get the serial number of this interface. 01980 * 01981 * Returns the serial number of the interface with this handle. 01982 * The allocated space should be freed with free() later. 01983 * 01984 * @param hFt Handle of the Interface 01985 * @return Pointer to a string with the serial 01986 */ 01987 char *GetFtSerialNrStrg(FT_HANDLE hFt) { 01988 long int ifw = GetFtSerialNr(hFt); 01989 char *s = (char *)malloc(16); 01990 int byte1, byte2, byte3, byte4; 01991 01992 byte1 = ifw % 100; 01993 ifw /= 100; 01994 byte2 = ifw % 100; 01995 ifw /= 100; 01996 byte3 = ifw % 100; 01997 ifw /= 100; 01998 byte4 = ifw % 100; 01999 ifw /= 100; 02000 02001 snprintf(s, 16, "%d.%02d.%02d.%02d", byte4, byte3, byte2, byte1); 02002 02003 return s; 02004 } 02005 02006 02007 /** 02008 * \brief Close all ft devices 02009 * 02010 * Dummy. Can't be supported. Only used in original library. 02011 * 02012 * @return Always FTLIB_ERR_NOT_SUPPORTED 02013 */ 02014 long int CloseAllFtDevices() { 02015 return FTLIB_ERR_NOT_SUPPORTED; 02016 } 02017 02018 02019 /** 02020 * \brief Set the inputs D1 and D2 to distance oder voltage measuring 02021 * 02022 * This function allows to enable the inputs D1 and D2 to measure distances. 02023 * Must be called before StartFtTransferArea() 02024 * 02025 * Note by Hardware Vendor: 02026 * "Since the operating mode of the D1 / D2 inputs can be set by means of software, we recommend that no 02027 * voltage be supplied 'directly' to these connections in order to avoid damage to the interface during software 02028 * errors. Since the inputs are highly resistive, a resistance of approximately 200 Ohm - 470 Ohm should be 02029 * directly connected to the D1 / D2 socket (series connection). We recommend to connect the voltage range to 02030 * be measured 'behind' it." 02031 * 02032 * @param hFt Handle of the Interface 02033 * @param dwMode Set mode to IF_DS_INPUT_VOLTAGE (measure voltage) or IF_DS_INPUT_DISTANCE (measure distance) 02034 * @param dwTol1 Range of tolerance for D1. Try IF_DS_INPUT_TOL_STD (20). 02035 * @param dwTol2 Range of tolerance for D2. Try IF_DS_INPUT_TOL_STD (20). 02036 * @param dwLevel1 Threshold for D1. Try 100. 02037 * @param dwLevel2 Threshold for D2. Try 100. 02038 * @param dwRepeat1 Repition value for D1. Try IF_DS_INPUT_REP_STD (3). 02039 * @param dwRepeat2 Repition value for D2. Try IF_DS_INPUT_REP_STD (3). 02040 * @return FTLIB_ERR_SUCCESS on success 02041 */ 02042 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) { 02043 int ret; 02044 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 02045 int i; 02046 02047 buffer[1] = dwTol1; 02048 buffer[2] = dwTol2; 02049 buffer[3] = dwLevel1; 02050 buffer[4] = dwLevel1>>8; 02051 buffer[5] = dwLevel2; 02052 buffer[6] = dwLevel2>>8; 02053 buffer[7] = dwRepeat1; 02054 buffer[8] = dwRepeat2; 02055 02056 if (hFt == NULL) { 02057 fprintf(stderr, "GetFtFirmware: No such device\n"); 02058 return FTLIB_ERR_PORT_NUMBER_IS_NULL; 02059 } 02060 02061 switch (hFt->type) { 02062 case FT_ROBO_IF_USB: 02063 ret = usb_control_msg(hFt->device, 0x40, 0xf1, 0x1, dwMode, buffer+1, 8, FT_USB_TIMEOUT); 02064 if (ret != 8) { 02065 fprintf(stderr, "Error sending control msg 0x40 0xf1\n"); 02066 return ret; 02067 } 02068 break; 02069 case FT_ROBO_RF_DATA_LINK: 02070 case FT_ROBO_IF_OVER_RF: 02071 ret = usb_control_msg(hFt->device, 0x40, 0x53, hFt->transfer_area.RfModulNr<<8 | 0x01, 0, buffer, 34, FT_USB_TIMEOUT); 02072 if (ret != 34) { 02073 fprintf(stderr, "Error sending control msg 0x40 0x53\n"); 02074 return ret; 02075 } 02076 break; 02077 case FT_ROBO_IF_COM: 02078 // move data in array for two bytes 02079 for (i=10; i>=3; i--) { 02080 buffer[i] = buffer[i-2]; 02081 } 02082 buffer[0] = 0xf1; 02083 buffer[1] = 0x01; 02084 buffer[2] = dwMode; 02085 if ((write(hFt->sdev, &buffer, 11)) != 11 || (read(hFt->sdev, &buffer, 1)) != 1 || buffer[0] != 0x01) { 02086 fprintf(stderr, "SetFtDistanceSensorMode: Error communicating with serial\n"); 02087 return buffer[0]; 02088 } 02089 break; 02090 default: 02091 return FTLIB_ERR_NOT_SUPPORTED; 02092 } 02093 02094 usleep(100000); // wait before continue, else it doesn't always work 02095 02096 return FTLIB_ERR_SUCCESS; 02097 } 02098 02099 02100 /** 02101 * \brief Sets the frequency and call sign for a Robo Interface or RF Data Link. 02102 * 02103 * Sets the frequency and call sign which allows to control multiple Interfaces at one RF Data Link. 02104 * The value won't be lost on power failure. 02105 * 02106 * @param hFt Handle of the Interface 02107 * @param frequency to use. May be between 2 and 80. 02108 * @param callSign call sign for this Interface. May be between 1 and 8. (ignored for the RF Data Link) 02109 * @return FTLIB_ERR_SUCCESS on success 02110 */ 02111 long int SetRFMode(FT_HANDLE hFt, long int frequency, long int callSign) { 02112 int ret; 02113 unsigned char buffer[5]; 02114 02115 if (hFt == NULL) { 02116 fprintf(stderr, "GetFtFirmware: No such device\n"); 02117 return FTLIB_ERR_PORT_NUMBER_IS_NULL; 02118 } else if (frequency < 2 || frequency > 80) { 02119 return FTLIB_ERR_INVALID_PARAM; 02120 } else if (callSign > 8) { 02121 return FTLIB_ERR_INVALID_PARAM; 02122 } 02123 02124 switch (hFt->type) { 02125 case FT_ROBO_RF_DATA_LINK: 02126 ret = usb_control_msg(hFt->device, 0xc0, 0xfb, 1, frequency, buffer, 2, FT_USB_TIMEOUT); 02127 if (ret != 2 || buffer[0] != 0xfe || buffer[1] != 0) { 02128 fprintf(stderr, "Error sending control msg 0xc0 0xfb\n"); 02129 return ret; 02130 } 02131 break; 02132 case FT_ROBO_IF_USB: 02133 // not or-ing 1 to frequency seems to disable the modul 02134 ret = usb_control_msg(hFt->device, 0xc0, 0xfb, (callSign<<8) | 1, (1<<8) | frequency, buffer, 2, FT_USB_TIMEOUT); 02135 if (ret != 2 || buffer[0] != 0xfe || buffer[1] != 0) { 02136 fprintf(stderr, "Error sending control msg 0xc0 0xfb\n"); 02137 return ret; 02138 } 02139 break; 02140 case FT_ROBO_IF_COM: 02141 buffer[0] = 0xfb; 02142 buffer[1] = 0x1; 02143 buffer[2] = 0x7f; 02144 buffer[3] = frequency; 02145 buffer[4] = callSign; 02146 if ((write(hFt->sdev, &buffer, 5)) != 5 || (ret = read(hFt->sdev, &buffer, 2)) != 2 || buffer[0] != 0xfe) { 02147 fprintf(stderr, "SetRFMode: Error communicating with serial\n"); 02148 return ret; 02149 } 02150 break; 02151 default: 02152 return FTLIB_ERR_NOT_SUPPORTED; 02153 } 02154 02155 return FTLIB_ERR_SUCCESS; 02156 } 02157 02158 02159 /** 02160 * \brief Gets the frequency and call sign of a Robo Interface or RF Data Link. 02161 * 02162 * Sets the frequency and call sign which allows to control multiple Interfaces at one RF Data Link. 02163 * 02164 * @param hFt Handle of the Interface 02165 * @param frequency Points to a place to store the frequency. 02166 * @param callSign Points to a place to store the callSign. (Value will be 0 for the RF Data Link) 02167 * @return FTLIB_ERR_SUCCESS on success 02168 */ 02169 long int GetRFMode(FT_HANDLE hFt, long int *frequency, long int *callSign) { 02170 int ret; 02171 unsigned char buffer[8]; 02172 02173 if (hFt == NULL) { 02174 fprintf(stderr, "GetFtFirmware: No such device\n"); 02175 return FTLIB_ERR_PORT_NUMBER_IS_NULL; 02176 } 02177 02178 switch (hFt->type) { 02179 case FT_ROBO_IF_USB: 02180 case FT_ROBO_RF_DATA_LINK: 02181 ret = usb_control_msg(hFt->device, 0xc0, 0xfb, 0x81, 0, buffer, 8, FT_USB_TIMEOUT); 02182 if (ret != 8) { 02183 fprintf(stderr, "Error sending control msg 0xc0 0xfb\n"); 02184 return ret; 02185 } 02186 *frequency = buffer[6]; 02187 *callSign = buffer[7]; 02188 break; 02189 case FT_ROBO_IF_COM: 02190 buffer[0] = 0xfb; 02191 buffer[1] = 0x81; 02192 if ((write(hFt->sdev, &buffer, 2)) != 2 || (ret = read(hFt->sdev, &buffer, 8)) != 8 || buffer[0] != 0x7e) { 02193 fprintf(stderr, "GetRFMode: Error communicating with serial\n"); 02194 return ret; 02195 } 02196 *frequency = buffer[6]; 02197 *callSign = buffer[7]; 02198 break; 02199 default: 02200 return FTLIB_ERR_NOT_SUPPORTED; 02201 } 02202 02203 return FTLIB_ERR_SUCCESS; 02204 } 02205 02206 02207 /** 02208 * \brief Switches between the real serial and 0001 of a device. 02209 * 02210 * Every ft Interface is shipped with 0001 as serial. 02211 * Nevertheless each has its own serial which can be activated. 02212 * 02213 * @param hFt Handle of the Interface 02214 * @param bOn 0 to use 0001, else the real serial 02215 * @return FTLIB_ERR_SUCCESS on success 02216 */ 02217 long int SetRealSerial(FT_HANDLE hFt, unsigned char bOn) { 02218 int ret; 02219 // on: 2 0xd2 0x3a 02220 // off: 1 0x81 0x6f 02221 // RF: 2 d8 77 vs 1 8b 22 02222 // Whats the number? 02223 // SetSerial(hFt, 5386); 02224 unsigned char buffer[16] = {0xaf, 0x83, 0x55, 0xa1, 1, 0, 0, 0, 1, 0x81, 0x6f, 0, 0, 0, 0, 0}; 02225 02226 if (hFt == NULL) { 02227 fprintf(stderr, "GetFtFirmware: No such device\n"); 02228 return FTLIB_ERR_PORT_NUMBER_IS_NULL; 02229 } 02230 02231 switch (hFt->type) { 02232 case FT_ROBO_IF_USB: 02233 if (bOn) { 02234 buffer[8] = 2; 02235 buffer[9] = 0xd2; 02236 buffer[10] = 0x3a; 02237 } else { 02238 buffer[8] = 1; 02239 buffer[9] = 0x81; 02240 buffer[10] = 0x6f; 02241 } 02242 ret = usb_control_msg(hFt->device, 0x40, 0xaf, 0x83, 0, buffer, 16, 200000); 02243 if (ret != 16) { 02244 fprintf(stderr, "Error sending control msg 0x40 0xaf\n"); 02245 return ret; 02246 } 02247 break; 02248 case FT_ROBO_IF_OVER_RF: 02249 if (bOn) { 02250 buffer[8] = 2; 02251 buffer[9] = 0xd8; 02252 buffer[10] = 0x77; 02253 } else { 02254 buffer[8] = 1; 02255 buffer[9] = 0x8b; 02256 buffer[10] = 0x22; 02257 } 02258 ret = usb_control_msg(hFt->device, 0x40, 0xaf, 0x83, 0, buffer, 16, 200000); 02259 if (ret != 16) { 02260 fprintf(stderr, "Error sending control msg 0x40 0xaf\n"); 02261 return ret; 02262 } 02263 break; 02264 case FT_ROBO_IO_EXTENSION: 02265 if (bOn) { 02266 buffer[8] = 2; 02267 buffer[9] = 0x5f; 02268 buffer[10] = 0x28; 02269 } else { 02270 buffer[8] = 1; 02271 buffer[9] = 0x0c; 02272 buffer[10] = 0x7d; 02273 } 02274 ret = usb_control_msg(hFt->device, 0x40, 0xaf, 0x83, 0, buffer, 16, 200000); 02275 if (ret != 16) { 02276 fprintf(stderr, "Error sending control msg 0x40 0xaf\n"); 02277 return ret; 02278 } 02279 break; 02280 case FT_ROBO_IF_COM: 02281 if ((write(hFt->sdev, &buffer, 16)) != 16 || (ret = read(hFt->sdev, &buffer, 2)) != 2 || buffer[0] != 0x7c) { 02282 fprintf(stderr, "SetRealSerial: Error communicating with serial\n"); 02283 return ret; 02284 } 02285 break; 02286 default: 02287 return FTLIB_ERR_NOT_SUPPORTED; 02288 } 02289 02290 return FTLIB_ERR_SUCCESS; 02291 } 02292 02293 02294 02295 /** 02296 * @brief Gets the Manufacturer of the Interface 02297 * 02298 * Will return the Manufacturer of a fischertechnik USB device. 02299 * The allocated space should be freed with free() later. 02300 * 02301 * @param hFt Handle of the Interface 02302 * @return Pointer to the string with the name 02303 */ 02304 char *GetFtManufacturerStrg(FT_HANDLE hFt) { 02305 char *buffer = (char *)malloc(128); 02306 memset(buffer, '\0', 128); 02307 02308 if (hFt == NULL) { 02309 fprintf(stderr, "GetFtFirmware: No such device\n"); 02310 } 02311 02312 switch (hFt->type) { 02313 case FT_ROBO_IF_USB: 02314 case FT_ROBO_RF_DATA_LINK: 02315 case FT_ROBO_IF_OVER_RF: 02316 usb_get_string_simple(hFt->device, 1, buffer, 128); 02317 break; 02318 } 02319 02320 return buffer; 02321 } 02322 02323 02324 /** 02325 * @brief Gets the short name of the Interface 02326 * 02327 * Will return the short name of a fischertechnik USB device. 02328 * The allocated space should be freed with free() later. 02329 * 02330 * @param hFt Handle of the Interface 02331 * @return Pointer to the string with the name 02332 */ 02333 char *GetFtShortNameStrg(FT_HANDLE hFt) { 02334 char *buffer = (char *)malloc(128); 02335 memset(buffer, '\0', 128); 02336 02337 if (hFt == NULL) { 02338 fprintf(stderr, "GetFtFirmware: No such device\n"); 02339 } 02340 02341 switch (hFt->type) { 02342 case FT_ROBO_IF_USB: 02343 case FT_ROBO_RF_DATA_LINK: 02344 case FT_ROBO_IF_OVER_RF: 02345 usb_get_string_simple(hFt->device, 5, buffer, 128); 02346 break; 02347 } 02348 02349 return buffer; 02350 } 02351 02352 02353 /** 02354 * @brief Gets the long name of the Interface 02355 * 02356 * Will return the long name of a fischertechnik USB device. 02357 * The allocated space should be freed with free() later. 02358 * 02359 * @param hFt Handle of the Interface 02360 * @return Pointer to the string with the name 02361 */ 02362 char *GetFtLongNameStrg(FT_HANDLE hFt) { 02363 char *buffer = (char *)malloc(128); 02364 memset(buffer, '\0', 128); 02365 02366 if (hFt == NULL) { 02367 fprintf(stderr, "GetFtFirmware: No such device\n"); 02368 } 02369 02370 switch (hFt->type) { 02371 case FT_ROBO_IF_USB: 02372 case FT_ROBO_RF_DATA_LINK: 02373 case FT_ROBO_IF_OVER_RF: 02374 usb_get_string_simple(hFt->device, 2, buffer, 128); 02375 break; 02376 } 02377 02378 return buffer; 02379 } 02380 #endif //NOTNOW 02381 02382 /** 02383 * @brief Tells if we successfuly got a connection to the Interface 02384 * 02385 * @param hFt Handle of the Interface 02386 * @return 0 if the Interface is not connected 02387 */ 02388 char IsFtInterfaceConnected(FT_HANDLE hFt) { 02389 return hFt->interface_connected; 02390 } 02391 02392 02393 /** 02394 * @brief Gets the description of an error 02395 * 02396 * Will return a description of an error. 02397 * The allocated space should be freed with free() later. 02398 * 02399 * The return value is the constant as string if parameter dwTyp is 0, 02400 * else a verbose description of the error. 02401 * 02402 * @param dwErrorCode Error Code 02403 * @param dwTyp Type of the return value (see description) 02404 * @return Pointer to a string (see description) 02405 */ 02406 char *GetFtLibErrorString(long int dwErrorCode, long int dwTyp) { 02407 char *buffer = (char *)malloc(128); 02408 02409 switch (dwErrorCode) { 02410 case FTLIB_ERR_IF_NO_PROGRAM: 02411 if (dwTyp) strncpy(buffer, "There is no program stored to work with", 128); 02412 else strncpy(buffer, "FTLIB_ERR_IF_NO_PROGRAM", 128); 02413 break; 02414 case FTLIB_ERR_SUCCESS: 02415 if (dwTyp) strncpy(buffer, "Everything is fine", 128); 02416 else strncpy(buffer, "FTLIB_ERR_SUCCESS", 128); 02417 break; 02418 case FTLIB_ERR_THREAD_IS_RUNNING: 02419 if (dwTyp) strncpy(buffer, "Thread has been started successfully", 128); 02420 else strncpy(buffer, "FTLIB_ERR_THREAD_IS_RUNNING", 128); 02421 break; 02422 case FTLIB_ERR_DOWNLOAD: 02423 if (dwTyp) strncpy(buffer, "Failed to upload the program", 128); 02424 else strncpy(buffer, "FTLIB_ERR_DOWNLOAD", 128); 02425 break; 02426 case FTLIB_ERR_DOWNLOAD_WRONG_MEM_BLOCK: 02427 if (dwTyp) strncpy(buffer, "Bad target to upload the program to", 128); 02428 else strncpy(buffer, "FTLIB_ERR_DOWNLOAD_WRONG_MEM_BLOCK", 128); 02429 break; 02430 case FTLIB_ERR_INVALID_PARAM: 02431 if (dwTyp) strncpy(buffer, "A parameter specified has a wrong value", 128); 02432 else strncpy(buffer, "FTLIB_ERR_INVALID_PARAM", 128); 02433 break; 02434 case FTLIB_ERR_LIB_IS_INITIALIZED: 02435 if (dwTyp) strncpy(buffer, "This library has been initialized", 128); 02436 else strncpy(buffer, "FTLIB_ERR_LIB_IS_INITIALIZED", 128); 02437 break; 02438 case FTLIB_ERR_NOT_SUPPORTED: 02439 if (dwTyp) strncpy(buffer, "The requested action is not supported", 128); 02440 else strncpy(buffer, "FTLIB_ERR_NOT_SUPPORTED", 128); 02441 break; 02442 case FTLIB_ERR_PORT_NUMBER_IS_NULL: 02443 if (dwTyp) strncpy(buffer, "No handle given", 128); 02444 else strncpy(buffer, "FTLIB_ERR_PORT_NUMBER_IS_NULL", 128); 02445 break; 02446 case FTLIB_ERR_THREAD_NOT_RUNNING: 02447 if (dwTyp) strncpy(buffer, "Unable to start the thread", 128); 02448 else strncpy(buffer, "FTLIB_ERR_THREAD_NOT_RUNNING", 128); 02449 break; 02450 default: 02451 strncpy(buffer, "Unknown", 128); 02452 } 02453 02454 return buffer; 02455 } 02456 02457 02458 /** \cond doxygen ignore start */ 02459 //! \todo 02460 long int SetFtDeviceCommMode(FT_HANDLE hFt, long int dwMode, long int dwParameter, unsigned short *puiValue) { 02461 return 0; 02462 } 02463 02464 02465 //! \todo 02466 long int GetFtDeviceSetting(FT_HANDLE hFt, FT_SETTING *pSet) { 02467 return 0; 02468 } 02469 02470 02471 //! \todo 02472 long int SetFtDeviceSetting(FT_HANDLE hFt, FT_SETTING *pSet) { 02473 return 0; 02474 } 02475 02476 02477 //! \todo 02478 long int SendFtMessage(FT_HANDLE hFt, unsigned char bHwId, unsigned char bSubId, long int dwMessage, long int dwWaitTime, long int dwOption) { 02479 return 0; 02480 } 02481 02482 02483 //! \todo 02484 long int ClearFtMessageBuffer(FT_HANDLE hFt) { 02485 return 0; 02486 } 02487 02488 02489 //! \todo 02490 long int GetFtMemoryLayout(FT_HANDLE hFt, unsigned char* pbArray, long int dwSize) { 02491 return 0; 02492 } 02493 02494 02495 //! \todo 02496 long int GetFtMemoryData(FT_HANDLE hFt, unsigned char * pbArray, long int dwSize, long int dwAddress) { 02497 return 0; 02498 } 02499 02500 02501 //! \todo 02502 long int WriteFtMemoryData(FT_HANDLE hFt, long int dwData, long int dwAddress) { 02503 return 0; 02504 } 02505 02506 #ifndef SPLITTRANSFER 02507 /** \cond doxygen ignore start */ 02508 static void *FtThread(FT_HANDLE hFt) { 02509 FT_TRANSFER_AREA *area = &hFt->transfer_area; 02510 int ret; 02511 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}; 02512 unsigned char in[ABF_IF_COMPLETE_NUM_READ]; 02513 int num_write = ABF_IF_COMPLETE_NUM_WRITE; 02514 int num_read = ABF_IF_COMPLETE_NUM_READ; 02515 int usb_endpoint_write = FT_ENDPOINT_INTERRUPT_OUT; 02516 int usb_endpoint_read = FT_ENDPOINT_INTERRUPT_IN; 02517 int i=0; 02518 int ii_speed = 0; 02519 02520 out[0] = ABF_IF_COMPLETE; 02521 area->TransferAktiv = 1; 02522 02523 switch (hFt->type) { 02524 case FT_ROBO_IF_COM: 02525 out[0] = 0xf2; 02526 num_write = 17; 02527 num_read = 21; 02528 break; 02529 case FT_INTELLIGENT_IF: 02530 num_write = 2; 02531 break; 02532 case FT_INTELLIGENT_IF_SLAVE: 02533 num_write = 3; 02534 break; 02535 #ifdef USE_USB 02536 case FT_ROBO_IO_EXTENSION: 02537 out[0] = 0xf2; 02538 num_write = 6; 02539 num_read = 6; 02540 break; 02541 case FT_ROBO_IF_OVER_RF: 02542 case FT_ROBO_RF_DATA_LINK: 02543 usb_endpoint_write = FT_RF_ENDPOINT_INTERRUPT_OUT; 02544 usb_endpoint_read = FT_RF_ENDPOINT_INTERRUPT_IN; 02545 02546 // init RF 02547 // 0x102 == first RF 02548 // 0x202 == 2nd RF 02549 // ... 02550 //ret = usb_control_msg(hFt->device, 0xc0, 0xfb, 0x102, 0x1, in, 2, FT_USB_TIMEOUT); 02551 ret = usb_control_msg(hFt->device, 0xc0, 0xfb, hFt->transfer_area.RfModulNr << 8 | 0x02, 0x1, in, 2, FT_USB_TIMEOUT); 02552 if (ret != 2) { 02553 fprintf(stderr, "%d FtThread: Error initiating RF Module!\n"); 02554 area->TransferAktiv = 0; 02555 } 02556 break; 02557 #endif 02558 } 02559 //here the real data exchange starts 02560 #ifdef MBED 02561 //viaUsb.putc('.'); 02562 /*while (area->TransferAktiv == 1)*/ { //procedure runs only once 02563 if (!test_and_set(hFt->lock)) //return when busy 02564 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 02565 #else 02566 while (area->TransferAktiv == 1) {//thread runs continuously 02567 sem_wait(&hFt->lock);//wait when busy 02568 #endif 02569 out[1] = area->M_Main; 02570 out[2] = (area->MPWM_Main[0] & 0x7) | (area->MPWM_Main[1]<<3 & 0x38) | (area->MPWM_Main[2]<<6 & 0xC0); 02571 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); 02572 out[4] = (area->MPWM_Main[5] & 0x3) | (area->MPWM_Main[6]<<2 & 0x1C) | (area->MPWM_Main[7]<<5 & 0xE0); 02573 out[5] = area->M_Sub1; 02574 out[6] = (area->MPWM_Sub1[0] & 0x7) | (area->MPWM_Sub1[1]<<3 & 0x38) | (area->MPWM_Sub1[2]<<6 & 0xC0); 02575 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); 02576 out[8] = (area->MPWM_Sub1[5] & 0x3) | (area->MPWM_Sub1[6]<<2 & 0x1C) | (area->MPWM_Sub1[7]<<5 & 0xE0); 02577 out[9] = area->M_Sub2; 02578 out[10] = (area->MPWM_Sub2[0] & 0x7) | (area->MPWM_Sub2[1]<<3 & 0x38) | (area->MPWM_Sub2[2]<<6 & 0xC0); 02579 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); 02580 out[12] = (area->MPWM_Sub2[5] & 0x3) | (area->MPWM_Sub2[6]<<2 & 0x1C) | (area->MPWM_Sub2[7]<<5 & 0xE0); 02581 out[13] = area->M_Sub3; 02582 out[14] = (area->MPWM_Sub3[0] & 0x7) | (area->MPWM_Sub3[1]<<3 & 0x38) | (area->MPWM_Sub3[2]<<6 & 0xC0); 02583 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); 02584 out[16] = (area->MPWM_Sub3[5] & 0x3) | (area->MPWM_Sub3[6]<<2 & 0x1C) | (area->MPWM_Sub3[7]<<5 & 0xE0); 02585 out[17] = 0; 02586 out[18] = 0; 02587 out[19] = 0; 02588 out[20] = 0; 02589 out[21] = 0; 02590 out[22] = 0; 02591 out[23] = 0; 02592 out[24] = 0; 02593 out[25] = 0; 02594 out[26] = 0; 02595 out[27] = 0; 02596 out[28] = 0; 02597 out[29] = 0; 02598 out[30] = 0; 02599 out[31] = 0; 02600 02601 // For the II we need to simulate different speeds here 02602 if (hFt->type == FT_INTELLIGENT_IF || hFt->type == FT_INTELLIGENT_IF_SLAVE) { 02603 int iCurMotor; 02604 for (iCurMotor = 0; iCurMotor < 7; iCurMotor++) { 02605 if (area->MPWM_Main[iCurMotor] < ii_speed) out[1] &= ~(1 << iCurMotor); 02606 if (area->MPWM_Sub1[iCurMotor] < ii_speed) out[5] &= ~(1 << iCurMotor); 02607 } 02608 02609 ii_speed++; 02610 if (ii_speed > 7) ii_speed = 0; 02611 } 02612 02613 if (hFt->type == FT_INTELLIGENT_IF) { 02614 i++; 02615 num_read = 1; 02616 out[0] = 0xC1; 02617 if (i % 20) { // EX 02618 out[0] = 0xC5; 02619 num_read = 3; 02620 } else if (i % 10) { // EY 02621 out[0] = 0xC9; 02622 num_read = 3; 02623 } 02624 } else if (hFt->type == FT_INTELLIGENT_IF_SLAVE) { 02625 i++; 02626 num_read = 2; 02627 out[0] = 0xC2; 02628 out[2] = out[5]; 02629 if (i % 20) { // EX 02630 out[0] = 0xC6; 02631 num_read = 4; 02632 } else if (i % 10) { // EY 02633 out[0] = 0xCA; 02634 num_read = 4; 02635 } 02636 } 02637 #ifdef MBED 02638 //viaUsb.putc('-'); 02639 increment(hFt->lock);//release the lock on shared memeory 02640 #else 02641 sem_post(&hFt->lock); 02642 #endif 02643 ret = 0; 02644 switch (hFt->type) {//send the request 02645 #ifdef USE_USB 02646 case FT_ROBO_IF_USB: 02647 case FT_ROBO_IO_EXTENSION: 02648 case FT_ROBO_IF_OVER_RF: 02649 case FT_ROBO_RF_DATA_LINK: 02650 ret = usb_interrupt_write(hFt->device, usb_endpoint_write, out, num_write, FT_USB_TIMEOUT); 02651 break; 02652 #endif 02653 case FT_ROBO_IF_COM: 02654 case FT_INTELLIGENT_IF: 02655 case FT_INTELLIGENT_IF_SLAVE: 02656 #ifdef MBED 02657 //ret = hFt->sdev->printf("%*c", num_write, out); 02658 ret = write(hFt->sdev, out, num_write); 02659 // viaUsb.putc(';'); 02660 #else 02661 ret = write(hFt->sdev, &out, num_write); 02662 #endif 02663 break; 02664 } 02665 if (ret != num_write) { 02666 hFt->interface_connected = 0; 02667 fprintf(stderr, "FtThread: Error writing to the Interface...exiting!\n"); 02668 #ifdef MBED 02669 return 0; 02670 #else 02671 break; 02672 #endif 02673 } 02674 02675 ret = 0; 02676 switch (hFt->type) { //receive the reply 02677 #ifdef USE_USB 02678 case FT_ROBO_IF_USB: 02679 case FT_ROBO_IO_EXTENSION: 02680 case FT_ROBO_IF_OVER_RF: 02681 case FT_ROBO_RF_DATA_LINK: 02682 ret = usb_interrupt_read(hFt->device, usb_endpoint_read, in, num_read, FT_USB_TIMEOUT); 02683 break; 02684 #endif 02685 case FT_ROBO_IF_COM: 02686 case FT_INTELLIGENT_IF: 02687 case FT_INTELLIGENT_IF_SLAVE: 02688 #ifdef MBED 02689 //ret = hFt->sdev->scanf("%*c", num_read, in)==1 ? num_read : 0 ; 02690 ret = read(hFt->sdev, in, num_read); 02691 // viaUsb.putc('/'); 02692 #else 02693 ret = read(hFt->sdev, &in, num_read); 02694 #endif 02695 break; 02696 } 02697 if (ret != num_read) { 02698 hFt->interface_connected = 0; 02699 fprintf(stderr, "FtThread: Error reading from the Interface\n"); 02700 #ifdef MBED 02701 return 0; 02702 #else 02703 usleep(hFt->query_time); 02704 continue; 02705 #endif 02706 } 02707 02708 #ifdef MBED 02709 if (!test_and_set(hFt->lock))//skip when busy 02710 return 0; 02711 #else 02712 sem_wait(&hFt->lock);//wait when busy 02713 #endif 02714 area->E_Main = in[0]; 02715 area->E_Sub1 = in[1]; 02716 area->E_Sub2 = in[2]; 02717 area->E_Sub3 = in[3]; 02718 area->AX = in[4]; 02719 area->AY = in[5]; 02720 area->A1 = in[6]; 02721 area->A2 = in[7]; 02722 area->AX |= (in[8] & 0x3) << 8; 02723 area->AY |= (in[8] & 0xC) << 6; 02724 area->A1 |= (in[8] & 0x30) << 4; 02725 area->A2 |= (in[8] & 0xC0) << 2; 02726 area->AZ = in[9]; 02727 area->D1 = in[10]; 02728 area->D2 = in[11]; 02729 area->AV = in[12]; 02730 area->AZ |= (in[13] & 0x3) << 8; 02731 area->D1 |= (in[13] & 0xC) << 6; 02732 area->D2 |= (in[13] & 0x30) << 4; 02733 area->AV |= (in[13] & 0xC0) << 2; 02734 area->IRKeys = in[14]; 02735 area->BusModules = in[15]; 02736 // 16 02737 area->AXS1 = in[17]; 02738 area->AXS2 = in[18]; 02739 area->AXS3 = in[19]; 02740 area->AXS1 |= (in[20] & 0x3) << 8; 02741 area->AXS2 |= (in[20] & 0xC) << 6; 02742 area->AXS3 |= (in[20] & 0x30) << 4; 02743 // 21 02744 area->AVS1 = in[22]; 02745 area->AVS2 = in[23]; 02746 area->AVS3 = in[24]; 02747 area->AVS1 |= (in[25] & 0x3) << 8; 02748 area->AVS2 |= (in[25] & 0xC) << 6; 02749 area->AVS3 |= (in[25] & 0x30) << 4; 02750 // 26...42 02751 if (hFt->type == FT_INTELLIGENT_IF) { 02752 if (i % hFt->analogcycle) { // EX 02753 area->AX = in[1] & (8<<in[2]); 02754 } else if (i % (2*hFt->analogcycle)) { // EY 02755 area->AY = in[1] & (8<<in[2]); 02756 } 02757 } else if (hFt->type == FT_INTELLIGENT_IF_SLAVE) { 02758 if (i % hFt->analogcycle) { // EX 02759 area->AX = in[1] & (8<<in[2]); 02760 } else if (i % (2*hFt->analogcycle)) { // EY 02761 area->AY = in[1] & (8<<in[2]); 02762 } 02763 } 02764 #ifdef MBED 02765 increment(hFt->lock); 02766 hFt->interface_connected = 1; 02767 #else 02768 sem_post(&hFt->lock); 02769 02770 hFt->interface_connected = 1; 02771 02772 usleep(hFt->query_time); 02773 #endif 02774 }//end of the while loop (end of task) 02775 #ifdef USE_USB 02776 if (hFt->type == FT_ROBO_IF_OVER_RF || hFt->type == FT_ROBO_RF_DATA_LINK) { 02777 ret = usb_control_msg(hFt->device, 0xc0, 0x21, hFt->transfer_area.RfModulNr << 8, 0, in, 1, FT_USB_TIMEOUT); 02778 if (ret != 1 || in[0] != 0xd7) { 02779 fprintf(stderr, "Error uninitiating RF Module!\n"); 02780 } 02781 } 02782 #endif 02783 #ifdef MBED 02784 return 0; 02785 #else 02786 hFt->transfer_area.TransferAktiv = 0; 02787 pthread_exit((void *) 0); 02788 #endif 02789 } 02790 02791 void ft_handle_devices::FtThread() { 02792 ::FtThread(this); 02793 // printf("%02X\r", transfer_area.E_Main); 02794 // viaUsb.putc('.'); 02795 } 02796 /** \endcond doxygen ignore end */ 02797 02798 #endif 02799 02800 /** \endcond doxygen ignore end */ 02801
Generated on Tue Jul 12 2022 20:02:50 by
1.7.2