class library to access fischertechnik interfaces via USB
Dependencies: FatFileSystem mbed myBlueUSB neigbourhood rfcomm sdp
ftlib/ftlibclassdev.h
- Committer:
- networker
- Date:
- 2013-03-11
- Revision:
- 1:4676e8b9b357
- Parent:
- 0:7da612835693
File content as of revision 1:4676e8b9b357:
#ifndef FTLIBCLASSDEV_H #define FTLIBCLASSDEV_H #include "ftlib.h" #include "message.h" #define ABF_IF_COMPLETE_NUM_WRITE 32 #define ABF_IF_COMPLETE_NUM_READ 42 /***************************************************************************************** The interfaces use a combination of synchronous (blocking) and asynchronous (non-blocking) I/O. For serial I/O it is essential that non-blocking I/O is used otherwise the entire transfer timeslot would be consumed with busy waiting. For USB this constraint is less severe but I nevertheless used non-blocking I/O also for USB in the transfer thread (which is not a real thread). Outside the transfer thread, I/O can be synchronous which I indeed used because it is easier to write and easier to understand. The timing of the transfer thread is determined by a Ticker interrupt. But in order not to occupy the interrupt system for too long, it just increments a counter in every interface object. The main event loop polls this counter, initiates a transfer and resets it. Starting a thread works by calling FtThreadInit (which does some initialisation) and setting transferAktiv to FTX1RUN. The poll routine will then call guardedFtThreadBegin which in turn will call FtThreadBegin provided the previous run of the thread has ended. The thead is protected by a busy flag which is set in guardedFtThreadBegin and released in FtThreadEnd, as long as busy is active a new thread should not be begun (enforced by guardedFtThreadBegin). FtThreadBegin copies the transferArea (TA) to a buffer and calls the send routine which (being non-blocking) returns immediately. When the send completes a callback (interrupt) occurs which initiates the corresponding read (request-reply model). When the read finished another callback (interrupt) occurs which invokes FtThreadEnd. FtThreadEnd may call notification routines which will all like FtThreadEnd but unlike FtThreadBegin run in interrupt context. Both FtThreadBegin and FtThreadEnd operate on the TA which is shared between the application and the transfer thread. As this transfer- thread is not a real thread synchronisation is not strictly neccesary because FtThreadBegin runs in the background (like the application) and FtThreadEnd+callback run as interrupt and cannot be interrupted by the background. Still a semaphore 'lock' is in place to protect the TA from simultaneous access. When the area is locked, the transfer is simply skipped. A user application cal call test_and_set() which returns falls when the area is locked and true when it is free. After using the TA the user must then call increment() to release the lock on the TA. At the moment the onlu use-case is to provide a consistent set of motor-settings to the TX which will be communicated in the same packet. *****************************************************************************************/ inline char* strdup(const char *s) { char *d = new char[strlen(s)+1]; strcpy(d, s); return d; } class ftdev { protected: FT_TRANSFER_AREA* ta; NOTIFICATION_EVENTS ne; msgbuffer<SMESSAGE, 10> *messages; int type, sn; unsigned fw; unsigned char out[ABF_IF_COMPLETE_NUM_WRITE]; //these buffers have maximum size, alternatively each subclass could have its own properly sized buffer unsigned char in[ABF_IF_COMPLETE_NUM_READ]; int num_write, num_read; enum _ta_state {FTX1STOP, FTX1RUN, FTX1SYNC} transferAktiv; volatile int lock; //semaphore to control concurrent access to transferarea, FtThreadEnd is called in interrupt context volatile bool busy; //semaphore to prevent a transfer from being started while another is still in progress volatile bool interface_connected; volatile int triggered;//when >0 indicates that the next transfer should take place ftdev() {} //private default, construction takes place through subclasses ftdev(int t, int s): type(t), sn(s) { ta = 0; fw = 0; triggered = 0; busy = false; lock = 1; interface_connected = false; messages = 0; transferAktiv = FTX1STOP; } void trigger() { if (transferAktiv != FTX1STOP) triggered++; //called by onTick } bool guardedFtThreadBegin(); //called by 'poll' bool guardedStop(); virtual void FtThreadInit() { busy = false; if (ta) ta->TransferAktiv = true;} //called by StartFtTransferArea virtual void FtThreadBegin() = 0; //called by 'guardedFtThreadBegin' virtual void FtThreadEnd(); //called by interrupt when transfer completes virtual void FtThreadFinish() { if(ta) ta->TransferAktiv = false;} //called by StopFtTransferArea bool test_and_set(); //'lock' semphore void increment(); //'lock' semphore virtual unsigned pgm_message(unsigned code, unsigned dwMemBlock) = 0; public: virtual ~ftdev() { delete ta; delete messages; } //public API: These functions match those of the original ftlib virtual unsigned CloseFtDevice() = 0; virtual unsigned GetFtDeviceTyp() { return type; } virtual char* GetFtSerialNrStrg(); virtual unsigned GetFtSerialNr() { return sn; } virtual char* GetFtFirmwareStrg(); virtual unsigned GetFtFirmware() { return fw; } virtual char* GetFtManufacturerStrg() = 0; virtual char* GetFtShortNameStrg() = 0; virtual char* GetFtLongNameStrg() = 0; /* virtual unsigned GetFtDeviceSetting(FT_SETTING *pSet); virtual unsigned SetFtDeviceSetting(FT_SETTING *pSet); */ virtual unsigned SetFtDistanceSensorMode(unsigned dwMode, unsigned dwTol1, unsigned dwTol2, unsigned dwSchwell1, unsigned dwSchwell2, unsigned dwRepeat1, unsigned dwRepeat2) { return FTLIB_ERR_NOT_SUPPORTED; } virtual unsigned StartFtTransferArea(NOTIFICATION_EVENTS* sNEvent = 0); virtual unsigned StartFtTransferAreaWithCommunication(NOTIFICATION_EVENTS* sNEvent = 0); virtual unsigned StopFtTransferArea(); virtual FT_TRANSFER_AREA* GetFtTransferAreaAddress() { return ta; } virtual unsigned IsFtTransferActiv(); unsigned ResetFtTransfer (); unsigned SendFtMessage(unsigned char bHwId, unsigned char bSubId, unsigned dwMessage, unsigned dwWaitTime, unsigned dwOption); unsigned ClearFtMessageBuffer(); virtual unsigned StartFtProgram(unsigned dwMemBlock) { return FTLIB_ERR_NOT_SUPPORTED; } virtual unsigned StopFtProgram() { return FTLIB_ERR_NOT_SUPPORTED; } unsigned DeleteFtProgram(unsigned dwMemBlock) { return pgm_message(0xf5, dwMemBlock); } unsigned SetFtProgramActiv(unsigned dwMemBlock) { return pgm_message(0xf9, dwMemBlock); } }; /* still to be implemented unsigned GetFtMemoryLayout(unsigned char * pbArray, unsigned dwSize); unsigned DownloadFtProgram(unsigned dwMemBlock, unsigned char* pbArray, unsigned dwSize, unsigned dwParameter, unsigned char *pbName, unsigned dwNameLen); unsigned GetFtProgramName(unsigned dwMemBlock, unsigned dwSize, char* pName); unsigned WriteFtMemoryData(unsigned dwData, unsigned dwAddress); unsigned GetFtMemoryData(unsigned char * pbArray, unsigned dwSize, unsigned dwAddress); */ #endif