class library to access fischertechnik interfaces via USB

Dependencies:   FatFileSystem mbed myBlueUSB neigbourhood rfcomm sdp

ftlib/ftlibclassdev.cpp

Committer:
networker
Date:
2013-03-11
Revision:
1:4676e8b9b357
Parent:
0:7da612835693

File content as of revision 1:4676e8b9b357:

#include "mbed.h"
#include "USBHost.h"
#include "ftlibclassdev.h"

#define usleep(x)    wait_us(x)
#define sleep(x)    wait(x)

//incorrect: should clear outputs when thread is NOT running
unsigned ftdev::ResetFtTransfer() {
    if (ta) {
        ta->M_Main = 0;
        ta->M_Sub1 = 0;
        ta->M_Sub2 = 0;
        ta->M_Sub3 = 0;
        return FTLIB_ERR_SUCCESS;
    }
    return FTLIB_ERR_DEVICE_NOT_OPEN;
}

unsigned ftdev::IsFtTransferActiv() {
    if (transferAktiv > 0)
        return FTLIB_ERR_THREAD_IS_RUNNING;
    return FTLIB_ERR_THREAD_NOT_RUNNING;
}

//not sure about this conversion
char * ftdev::GetFtFirmwareStrg() {
    unsigned ifw = GetFtFirmware();
    char *s = new char[16];
    int byte1 = ifw & 0xff;
    int byte2 = (ifw & 0xff00) >> 8;
    int byte3 = (ifw & 0xff0000) >> 16;
    int byte4 = (ifw & 0xff000000) >> 24;
    snprintf(s, 16, "%d.%02d.%02d.%02d", byte4, byte3, byte2, byte1);
    return s;
}

//not sure about this conversion
char * ftdev::GetFtSerialNrStrg() {
    DWORD ifw = GetFtSerialNr();
    char *s = new char[16];
    int byte1, byte2, byte3, byte4;
    byte1 = ifw % 100;
    ifw /= 100;
    byte2 = ifw % 100;
    ifw /= 100;
    byte3 = ifw % 100;
    ifw /= 100;
    byte4 = ifw % 100;
    ifw /= 100;
    snprintf(s, 16, "%d.%02d.%02d.%02d", byte4, byte3, byte2, byte1);
    return s;
}

unsigned ftdev::StartFtTransferArea(NOTIFICATION_EVENTS* ev) {
    int err = IsFtTransferActiv();
    if (err == FTLIB_ERR_THREAD_IS_RUNNING)
        return err;
    if (ta==0)
        return FTLIB_ERR_DEVICE_NOT_OPEN;
    if (ev)
        ne = *ev; //copy the entire struct
    else
        memset(&ne, 0, sizeof(NOTIFICATION_EVENTS));
    FtThreadInit();//setup buffers and serial handlers
    transferAktiv = FTX1RUN;
    return FTLIB_ERR_SUCCESS;
}

unsigned ftdev::StartFtTransferAreaWithCommunication(NOTIFICATION_EVENTS* ev) {
    if (type == FT_INTELLIGENT_IF || type == FT_INTELLIGENT_IF_SLAVE || type == FT_ROBO_IF_IIM)
        return FTLIB_ERR_NOT_SUPPORTED;
    if (messages == 0)
        messages = new msgbuffer<SMESSAGE, 10>;
    int ret = StartFtTransferArea(ev);
    if (ret) {
        delete messages;
        messages = 0;
    }
    return ret;
}

unsigned ftdev::StopFtTransferArea() {
    while (!guardedStop()) {
        USBLoop();//otherwise this loop gets stuck
        printf("waiting for thread to finish\r");
    }
    FtThreadFinish();
    if (messages) {
        delete messages;
        messages = 0;
    }
    busy = false;
    printf("\nthread stopped\n");
    return FTLIB_ERR_SUCCESS;
}

bool ftdev::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
  // printf("busy:%d-%d ", busy, triggered);
    __disable_irq();
    if (busy) {
        if (triggered > 100) { //interface has not responded within 100 slots or response was missed
            printf("Missed reply??? releasing busy\n");
            busy = false; //release the busy flag to reenable the request-reply process
        }
        __enable_irq();
        return false; //skip the timeslot when previous was not yet handled
    }
    busy = true;
    //printf("trig=%d\n", triggered);
    __enable_irq();
    FtThreadBegin();//here the request is sent to the interface
    return true;
}

bool ftdev::guardedStop() {//called every 10ms by the main loop to issue a request, should be non-blocking, guarded by busy flag to avoid multiple pending requests
    __disable_irq();
    if (busy) {
        if (triggered > 100) { //interface has not responded within 10 slots or response was missed
            printf("busy ");
        }
        __enable_irq();
        return false; //skip the timeslot when previous was not yet handled
    }
    busy = true;
    __enable_irq();
    triggered = 0;
    transferAktiv = FTX1STOP;
    return true;
}

bool ftdev::test_and_set() {
    bool tmp;
    __disable_irq();
    if (tmp = (lock>0))
        lock--;
    __enable_irq();
    return tmp;
}

void ftdev::increment() {
    __disable_irq();
    lock++;
    __enable_irq();
}

void ftdev::FtThreadEnd() {//called by the receiver/dma callback when the reply is complete
    if (!test_and_set()) {//skip when busy
        busy = false;
        printf("ftdev::FtThreadEnd: release busy\n");
        return;
    }
    ta->ChangeEg = ta->E_Main != in[0] || ta->E_Sub1 != in[1] || ta->E_Sub2 != in[2] || ta->E_Sub3 != in[3];
    ta->E_Main = in[0];
    ta->E_Sub1 = in[1];
    ta->E_Sub2 = in[2];
    ta->E_Sub3 = in[3];
    ta->ChangeAn = 1; //assume that analog always changes (noise)
    ta->AX = in[4];
    ta->AY = in[5];
    ta->A1 = in[6];
    ta->A2 = in[7];
    ta->AX |= (in[8] & 0x3) << 8;
    ta->AY |= (in[8] & 0xC) << 6;
    ta->A1 |= (in[8] & 0x30) << 4;
    ta->A2 |= (in[8] & 0xC0) << 2;
    ta->AZ = in[9];
    ta->D1 = in[10];
    ta->D2 = in[11];
    ta->AV = in[12];
    ta->AZ |= (in[13] & 0x3) << 8;
    ta->D1 |= (in[13] & 0xC) << 6;
    ta->D2 |= (in[13] & 0x30) << 4;
    ta->AV |= (in[13] & 0xC0) << 2;
    if (ta->IRKeys != in[14])
        ta->ChangeIr = 1;
    ta->IRKeys = in[14];
    ta->BusModules = in[15];
    // 16
    ta->AXS1 = in[17];
    ta->AXS2 = in[18];
    ta->AXS3 = in[19];
    ta->AXS1 |= (in[20] & 0x3) << 8;
    ta->AXS2 |= (in[20] & 0xC) << 6;
    ta->AXS3 |= (in[20] & 0x30) << 4;
    // 21
    ta->AVS1 = in[22];
    ta->AVS2 = in[23];
    ta->AVS3 = in[24];
    ta->AVS1 |= (in[25] & 0x3) << 8;
    ta->AVS2 |= (in[25] & 0xC) << 6;
    ta->AVS3 |= (in[25] & 0x30) << 4;
    // 26...42
    ta->AV *= 3;
    ta->AVS1 *= 3;
    ta->AVS2 *= 3;
    ta->AVS3 *= 3;
    //message processing
    if (messages && ne.CallbackMessage) { //just to check if communication was enabled
        if (in[28])
            ne.CallbackMessage((SMESSAGE*)(in+29));
        if (in[35])
            ne.CallbackMessage((SMESSAGE*)(in+36));
    }
    increment();
    interface_connected = 1;
    if (ne.NotificationCallback) {
        (*ne.NotificationCallback)(ne.Context);
    }
    busy = false;
        printf("ftdev::FtThreadEnd: release busy at exit\n");
}

unsigned ftdev::SendFtMessage(unsigned char bHwId, unsigned char bSubId, unsigned dwMessage, unsigned dwWaitTime, unsigned dwOption) {
    SMESSAGE m;
    m.L.ucHwId = bHwId;
    m.L.ucSubId = bSubId;
    m.L.dw = dwMessage;
    //waittime ignored
    if (messages)
        return messages->push(m, dwOption) < 0 ? FTLIB_ERR_MSG_BUFFER_FULL_TIMEOUT : 0;
    return FTLIB_ERR_MSG_HWID_WRONG; //not the correct error code
}

unsigned ftdev::ClearFtMessageBuffer() {
    if (messages)
        messages->clear();
    return 0;
}