lsgunth / pyft232

Python bindings to d2xx and libftdi to access FT232 chips with the same interface as pyserial
GNU Lesser General Public License v2.1
11 stars 11 forks source link

checking the input buffer #8

Closed JBSchueler closed 5 years ago

JBSchueler commented 6 years ago

Does this library support in_waiting like serial does? I would like to check the buffer if there is a byte available before I do a "blocking" read.

The time out has been set to 5 ms and the baud rate at 9600. What is the result of sp.read() if there is no byte available?

Ben

JBSchueler commented 6 years ago

As how I solved it for now

    c = sp.read(1)
    if len( c ) > 0:

but this blocks the process for timeout seconds

lsgunth commented 6 years ago

Yeah, no it doesn't support that. That would be a bit of a pain to support given the support in libftdi -- not even sure about d2xx.

I'd maybe recommend having a separate read thread which just does blocking reads and use some other synchronisation method to inform the main thread when there's something interesting buffered up.

Logan

JBSchueler commented 5 years ago

Reading the D2XX_Programmer's_Guide, there is a function available to check the number of Rx and Tx bytes.

Looking at the example at page 18

Examples
1. This sample shows how to read all the data currently available.
FT_HANDLE ftHandle;
FT_STATUS ftStatus;
DWORD EventDWord;
DWORD TxBytes;
DWORD RxBytes;
DWORD BytesReceived;
char RxBuffer[256];
ftStatus = FT_Open(0, &ftHandle);
if(ftStatus != FT_OK) {
// FT_Open failed
return;
}
FT_GetStatus(ftHandle,&RxBytes,&TxBytes,&EventDWord);
if (RxBytes > 0) {
ftStatus = FT_Read(ftHandle,RxBuffer,RxBytes,&BytesReceived);
if (ftStatus == FT_OK) {
// FT_Read OK
}
else {
// FT_Read Failed
}
}
FT_Close(ftHandle);

the interresting part is this line

FT_GetStatus(ftHandle,&RxBytes,&TxBytes,&EventDWord);

The function FT_GetStatus is explained at page 34

A python function in d2xx.py to check if there are bytes available would be like

    def available(self):
        RxBytes = 0
        TxBytes = 0
        EventDWord = 0
        status = d2xx.FT_GetStatus(self.handle, RxBytes, TxBytes, EventDWord)
        if status != FT_OK: raise D2XXException(status)

        return (RxBytes > 0)

But this doesn't work :(

c:\temp\py>py ftditest.py

Auto detecting FTDI devices
Serial          Description
------          -----------
FT3027BL         TTL232R

Using :  FT3027BL

Traceback (most recent call last):
  File "ftditest.py", line 43, in <module>
    while sp.available():
  File "C:\Users\bsc\AppData\Local\Programs\Python\Python37\lib\site-packages\ft232\d2xx.py", line 356, in available
    status = d2xx.FT_GetStatus(self.handle, RxBytes, TxBytes, EventDWord)
OSError: exception: access violation writing 0x0000000000000000

c:\temp\py>

Any idea why? (do not blame me, I'm not a programmer)

JBSchueler commented 5 years ago

OK, casting issues...

this code does work

    def available(self):
        RxBytes = c.c_ulong()
        TxBytes = c.c_ulong()
        EventDWord = c.c_ulong()
        status = d2xx.FT_GetStatus(self.handle, c.byref(RxBytes), c.byref(TxBytes), c.byref(EventDWord) )
        if status != FT_OK: raise D2XXException(status)

        return (RxBytes.value > 0 )

now the Rx buf can be checked for available bytes like

while sp.available():
    print( "%s" % sp.read(1).decode("utf-8"), end="" )

I will commit the code for verification and merging

lsgunth commented 5 years ago

Glad to hear you got it working. But I don't think we can add it to the library unless you can find a way to do it for libftdi. The whole purpose of this library is to create a portable interface between libftdi and d2xx...