OpenCores
URL https://opencores.org/ocsvn/usb_ft232h_avalon-mm_interface/usb_ft232h_avalon-mm_interface/trunk

Subversion Repositories usb_ft232h_avalon-mm_interface

[/] [usb_ft232h_avalon-mm_interface/] [trunk/] [testbench/] [qt/] [test_usb_ft232h/] [main.cpp] - Rev 6

Compare with Previous | Blame | View Log

#include <iostream>
#include <iomanip>
#include <vector>
#include <algorithm>
#include <cmath>
#include <limits>
#include <chrono>
#include <unistd.h>
 
#include "ftd2xx.h"
 
 
using namespace std;
 
 
const int DEV_TYPE = 8;
const int DEV_VID = 0x0403;
const int DEV_PID = 0x75D8;
const int DEV_ID = (DEV_VID << 16) | DEV_PID;
 
const int BUFFER_SIZE = 524288;
const int MAX_TRANSACTION_SIZE = 65536 * 2;
 
 
enum TestMode {
    TM_READ = 1,
    TM_ECHO
};
 
 
FT_HANDLE ftHandle = 0;
FT_STATUS ftStatus = 0;
 
vector<int> devList;
 
uint8_t rxBuffer[BUFFER_SIZE] = {0};
uint8_t txBuffer[BUFFER_SIZE] = {0};
int txBufferHead = 0;
int rxBufferTail = 0;
 
DWORD readedBytesCount = 0;
DWORD writtenBytesCount = 0;
DWORD lastPortionSize = 0;
int errorsCount = 0;
 
DWORD targetSize = 524288 * 100;//262144;//524288;
int iterationCount = 5;
 
//DWORD startTime = 0, currentTime = 0, prevTime = 0;
double maxSpeed = 0, avgSpeed = 0, currentSpeed = 0;
double minSpeed = std::numeric_limits<DWORD>::max();
 
chrono::steady_clock::time_point timeBegin, timeCurrent, timePrev;
 
 
vector<int> errorsVector;
 
 
 
inline
void findDevice()
{
#ifdef linux
    ftStatus = FT_SetVIDPID(0x0403, 0x75d8);
#endif
    DWORD devCount = 0;
    devList.clear();
    ftStatus = FT_CreateDeviceInfoList(&devCount);
    if (!devCount)
        return;
    FT_DEVICE_LIST_INFO_NODE *ftDevInfo =
            (FT_DEVICE_LIST_INFO_NODE*)malloc(sizeof(FT_DEVICE_LIST_INFO_NODE)*devCount);
    FT_GetDeviceInfoList(ftDevInfo, &devCount);
    for (uint32_t i = 0; i < devCount; ++i) {
        if (ftDevInfo[i].ID == DEV_ID) {
            devList.push_back(i);
            cout << "Dev flags: " << ftDevInfo[i].Flags << endl;
        }
    }
    free(ftDevInfo);
}
 
inline
bool openDevice(int index)
{
    ftStatus = FT_Open(index, &ftHandle);
    if (!FT_SUCCESS(ftStatus)) {
        cout << "Unable to open USB device. " << ftStatus << endl;
        return false;
    }
    if (ftHandle == NULL) {
        cout << "No device found" << endl;
        return false;
    }
    //configure
    uint8_t mask=0xff, mode=0x0, latency=2;
    mode = 0x0; //reset mode
    ftStatus = FT_SetBitMode(ftHandle, mask, mode);
    usleep(1000000);
    mode = 0x40;
    ftStatus = FT_SetBitMode(ftHandle, mask, mode);
    if (!FT_SUCCESS(ftStatus)) {
        cout << "Set bit mode failed. " << ftStatus << endl;
        return false;
    }
    FT_SetLatencyTimer(ftHandle, latency);
    FT_SetUSBParameters(ftHandle, 0x10000, 0x10000);
    FT_SetFlowControl(ftHandle, FT_FLOW_RTS_CTS, 0x0, 0x0);
    FT_Purge(ftHandle, FT_PURGE_RX | FT_PURGE_TX);
    return true;
}
 
inline
void closeDevice()
{
    FT_Close(ftHandle);
}
 
 
inline
DWORD availableData()
{
    DWORD queue;
    ftStatus = FT_GetQueueStatus(ftHandle, &queue);
    if (!FT_SUCCESS(ftStatus)) {
        cout << "Get available data failed. " << ftStatus << endl;
        return 0;
    }
    return queue;
}
 
inline
bool readData(void *buffer, DWORD size, DWORD &bytesReaded)
{
    ftStatus = FT_Read(ftHandle, buffer, size, &bytesReaded);
    if (!FT_SUCCESS(ftStatus)) {
        cout << "Read data failed. " << ftStatus << endl;
        return false;
    }
    return true;
}
 
inline
bool writeData(void *data, DWORD size, DWORD &bytesWritten)
{
    ftStatus = FT_Write(ftHandle, data, size, &bytesWritten);
    if (!FT_SUCCESS(ftStatus)) {
        cout << "Write data failed. " << ftStatus << endl;
        return false;
    }
    return true;
}
 
 
void calcSpeed(bool force = false)
{
    timeCurrent = chrono::steady_clock::now();
    double time = chrono::duration_cast<chrono::milliseconds>(timeCurrent - timePrev).count();
    if (( time >= 500 ) || force) {
        double dataSize = lastPortionSize * 1.0 / 1000;
        time /= 1000;
        currentSpeed = dataSize / time;
        dataSize = (readedBytesCount + writtenBytesCount) * 1.0 / 1000;
        time = chrono::duration_cast<chrono::milliseconds>(timeCurrent - timeBegin).count();
        time /= 1000;
        avgSpeed = dataSize / time;
        if (currentSpeed > maxSpeed)
            maxSpeed = currentSpeed;
        if (currentSpeed < minSpeed)
            minSpeed = currentSpeed;
        timePrev = timeCurrent;
        lastPortionSize = 0;
 
        cout << "Time: " << floor(time) << " Size(w/r): " << fixed << setprecision(3)
             << writtenBytesCount * 1.0 / 1000 << "/"
             << readedBytesCount * 1.0 / 1000 << defaultfloat
             << " kB \tRate (min/max/avg/current): " << int(floor(minSpeed)) << "/"
             << int(floor(maxSpeed)) << "/" << int(floor(avgSpeed)) << "/"
             << int(floor(currentSpeed)) << " kB/s \tErrors: " << errorsCount << endl;
        flush(cout);
    }
}
 
inline
void checkData(int offset, int size)
{
    for (int i = offset; (i < BUFFER_SIZE) && (i < offset + size); ++i) {
        if (rxBuffer[i] != txBuffer[i]) {
            if (errorsCount == 0) {
                int pi = i - 1;
                if (pi < 0)
                    pi = targetSize - 1;
                while (pi > BUFFER_SIZE) {
                    pi -= BUFFER_SIZE;
                }
                int ni = i + 1;
                if (ni >= BUFFER_SIZE)
                    ni = 0;
 
                cout << i << " " << int(txBuffer[i]) << " - " << int(rxBuffer[i])
                     << " \t" << pi << " " << int(txBuffer[pi]) << " - "
                     << int(rxBuffer[pi]) << " \t" << ni << " "
                     << int(txBuffer[ni]) << " I: ";
 
                /*for (int j = 0; (j < targetSize) && (j < BUFFER_SIZE); ++j) {
                    if (txBuffer[j] == rxBuffer[i]) {
//                        cout << j << " ";
                        auto fit = find(begin(errorsVector), end(errorsVector), j);
                        if ( fit != errorsVector.end()) {
                            cout << j << " ";
                        }
                    }
                }*/
                cout << endl;
            }
            ++errorsCount;
        }
    }
}
 
 
inline
void readMode()
{
    DWORD available = 0;
    DWORD bytesRead = 0;
    uint8_t value = 0;
 
    readedBytesCount = 0;
    writtenBytesCount = 0;
    lastPortionSize = 0;
    txBufferHead = 0;
    rxBufferTail = 0;
    errorsCount = 0;
    maxSpeed = 0;
    minSpeed = std::numeric_limits<DWORD>::max();
    avgSpeed = 0;
    currentSpeed = 0;
 
    txBuffer[0] = TM_READ;
    if (!writeData(txBuffer, 1, bytesRead)) {
        return;
    }
    timePrev = timeCurrent = timeBegin = chrono::steady_clock::now();
    while (true) {
        available = availableData();
        if (!available)
            continue;
        if (available > BUFFER_SIZE)
            available = BUFFER_SIZE;
        if (!readData(rxBuffer, available, bytesRead)) {
            return;
        }
        if (!bytesRead)
            continue;
        if (!readedBytesCount) {
            value = rxBuffer[0];
        }
        for (DWORD i = 0; i < bytesRead; ++i) {
            if (value != rxBuffer[i]) {
                ++errorsCount;
                value = rxBuffer[i];
            }
            ++value &= 0xFF;
        }
        readedBytesCount += bytesRead;
        lastPortionSize += bytesRead;
 
        calcSpeed();
    }
}
 
inline
void echoMode()
{
    DWORD available = 0;
    DWORD bytesRead = 0;
    DWORD bytesWrite = 0;
    DWORD writeSize = 0;
 
    readedBytesCount = 0;
    writtenBytesCount = 0;
    lastPortionSize = 0;
    txBufferHead = 0;
    rxBufferTail = 0;
    errorsCount = 0;
    maxSpeed = 0;
    minSpeed = std::numeric_limits<DWORD>::max();
    avgSpeed = 0;
    currentSpeed = 0;
 
    uint8_t mode = TM_ECHO;
    /*if (!writeData(&mode, 1, bytesRead)) {
        return;
    }
    if (!writeData(&targetSize, 4, bytesRead)) {
        return;
    }*/
 
//    prevTime = currentTime = startTime = GetTickCount();
    timePrev = timeCurrent = timeBegin = chrono::steady_clock::now();
 
    cout << "Start loop" << endl;
    while ((writtenBytesCount < targetSize) || (readedBytesCount < targetSize)) {
        // send
        if ((writtenBytesCount < targetSize)
                && ((writtenBytesCount - readedBytesCount) < MAX_TRANSACTION_SIZE)) {
            writeSize = BUFFER_SIZE - txBufferHead;
            if (writeSize > (targetSize - writtenBytesCount))
                writeSize = targetSize - writtenBytesCount;
            if (writeSize > MAX_TRANSACTION_SIZE)
                writeSize = MAX_TRANSACTION_SIZE;
            if (!writeData(&txBuffer[txBufferHead], writeSize, bytesWrite)) {
                return;
            }
//            cout << "write " << txBufferHead << " " << int(txBuffer[txBufferHead])
//                 << " " << bytesWrite << endl;
            writtenBytesCount += bytesWrite;
            lastPortionSize += bytesWrite;
            txBufferHead += bytesWrite;
            if (txBufferHead == BUFFER_SIZE) {
                txBufferHead = 0;
            }
            else if (txBufferHead > BUFFER_SIZE) {
                cout << "Tx buffer range error" << endl;
                return;
            }
        }
 
        // read
        available = availableData();
        if ((readedBytesCount < targetSize) && available) {
            if (available > (BUFFER_SIZE - rxBufferTail))
                available = BUFFER_SIZE - rxBufferTail;
            if (available > (targetSize - readedBytesCount)) {
                cout << "More data then need " << available << "/"
                     << targetSize - readedBytesCount << endl;
                available = targetSize - readedBytesCount;
            }
            if (!readData(&rxBuffer[rxBufferTail], available, bytesRead)) {
                return;
            }
//            cout << "read " << rxBufferTail << " " << bytesRead
//                 << " " << rxBufferTail + bytesRead << endl;
            readedBytesCount += bytesRead;
            lastPortionSize += bytesRead;
            checkData(rxBufferTail, bytesRead);
            rxBufferTail += bytesRead;
            if (rxBufferTail == BUFFER_SIZE) {
                rxBufferTail = 0;
            }
            else if (rxBufferTail > BUFFER_SIZE) {
                cout << "Rx buffer range error" << endl;
                return;
            }
        }
 
        calcSpeed();
    }
    calcSpeed(true);
    cout << endl << availableData() << endl;
}
 
 
int main(int argc, char *argv[])
{
    cout << "Hello World!" << endl;
 
    for (int i = 0; i < BUFFER_SIZE; ++i) {
        txBuffer[i] = rand() & 0xFF;
        if (txBuffer[i] == 94) {
            errorsVector.push_back(i);
            --i;
        }
    }
 
    findDevice();
    cout << devList.size() << " devices found" << endl;
    if (!devList.size())
        return 0;
    DWORD index;
    cout << "Put device index (from 0 to devices count): ";
    cin >> index;
    cout << endl;
    if (index >= devList.size()) {
        cout << "You fool!" << endl;
        return 0;
    }
    cout << "Open device " << index << " ... ";
    if (!openDevice(index)) {
        cout << "[FAIL]" << endl;
        return 0;
    }
    cout << "[ OK ]" << endl;
 
    cout << "Select mode:\n\t" << TM_READ << " - read\n\t"
         << TM_ECHO << " - echo\n\t* - exit" << endl;
    cout<< "Enter your choice: ";
    cin >> index;
    cout << endl;
    switch (index) {
    case TM_READ:
        cout << "Start read mode" << endl;
        readMode();
        break;
    case TM_ECHO:
        cout << "Start echo mode" << endl;
        while (iterationCount-- && (errorsCount == 0)) {
            echoMode();
//            cout << "Data:" << endl;
//            for (int i = 0; i < targetSize; ++i) {
//                cout << int(txBuffer[i]) << " = " << int(rxBuffer[i]) << endl;
//            }
//            ++targetSize;
        }
        break;
    default:
        break;
    }
 
    closeDevice();
    cout << "Finish" << endl;
    return 0;
}
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.