James,

From the looks of it you made good progress reading the hardware and using a dedicated thread for it. Congrats! Seems you're in the thick of it now ready to get the minute details sorted out.

Anyway, just a heads up that concurrent programming (threads, synchronization, etc) has many pitfalls.

My armchair guess is that your program is just not reading fast enough to keep up with the rate of data that the hardware is generated. Having time sensitive code in a separate thread is a good idea but you should also store the report data in an adequately sized and thread safe data structure such as a thread-safe list/queue. FreePascal has something you could use (https://www.freepascal.org/docs-html/rtl/classes/tthreadlist.html) and although dynamically allocated, it may be fast enough for your purposes. Thread safety is crucial to avoid multiple threads overwriting the data structures they share. The way I see it, your timing sensitive hardware reading thread would fill up the queue and then, every so often, your main thread would consume the data from it. You have to also imagine mechanisms to check that one can keep up with the other and signal errors when that is not the case.

Hope this helps, and good luck!

On 8/18/19 12:05 PM, James Richters wrote:
I have a question about USB data transfer.. but it's going to take some 
explanation...

I've been doing more testing with my device and Libusbxhid.  Here's the device: 
https://www.amazon.com/gp/product/B07M5ZY1P2

I have all the inputs working,  still have to figure out how to output to the 
LCD...  I've implemented a test program that shows what button I have pressed, 
and it also processes the switches and handwheel properly...  The hand wheel 
has 100 indents on it, and if I rotated it clockwise, it gives me a positive 
count, and if I rotate it counter-clockwise, it gives me two's compliment 
representation of a negative count, it only sends a single byte, and the number 
it sends is the number of ticks since the last time it reported....  so it 
would have to be read at least every 127 ticks.

ok.. so I got that all working but then I discovered an issue...  I thought the 
count on the hand wheel was the number of ticks since the last time I got the 
report... because if I turn the when very slow, I only get 1 or -1... but if I 
turn it faster, I get larger numbers... but once I got it reporting the total 
count... I found that if I start with the wheel at the 0 mark, and turn it 
really slow, it will count exactly 100 times when it returns to the zero 
point.. but if I got at even a slow (but not ridiculous) speed, then the count 
would come up short, and if I turned it fast, it would come up really short...

So I tried a test,  and disabled the writeln to the console... and now it is 
much more accurate.. at slow and medium speeds it is exact but at really fast 
speeds it is still slightly short.  So I thought this would be a great use for 
a thread!   So I looked into it.. and I guess in windows I don't even need a 
unit to run a thread.. I just need to define a function and do a BeginThread() 
to run the function in a thread... well I didn't think it would be THAT easy.. 
but yes it works!   Now I'm going to have threads everywhere LOL.  I have the 
thread running the tightest possible loop to just read the data and store it in 
the fastest way possible so it can get back to reading again... then outside 
the thread I read the variables once every 5 seconds and just put where it 
is... well this improved things greatly, and I will probably use the thread 
method in the final program... but one thing is still bugging me... it's just 
not 100% exact all the time, even with the thread method, I still miss count 
here and there...

So back to the in-line code with writeln's of a minute...   I tried another 
test... this time I read the device as normal, then I put a huge delay in.. 5 
seconds or so, then I started reading it again.. now if my previous theory was 
correct, then I should be able to give up to 127 pulses during the delay and it 
would show the total since the last report... but that's not what happened.. it 
just forgets about whatever happened during the delay....I was careful to only 
do 1/2 rotation which would be about 50 pulses so I know I didn't make it 
overflow.... so this behavior makes me think I am not reading it the correct 
way.... it's like it sends the report out every so often whether I am reading 
it or not.. and when I do read it I get whatever count it is since the last 
OUTPUT, even if I missed the last output... also if I push a button and release 
it during the delay, I have no indication it was ever pressed.

So my question is..  does this behavior suggest that the device is expecting 
some other transfer method that would guarantee synchronization?   I see in 
pas-libusb there are test2controlsync and test test3controlasync  I'm curious 
if synchronous transfer would be the way to communicate with the device that 
would guarantee no data loss.  I don't really understand how either of these 
work, but one is sync and the other is async, so I thought maybe sync was more 
the method I should be using.   My program in libusbxhid is using:

hidReportData[reportIdx].dataLen:=libusbhid_interrupt_read(device_context,$81{endpoint},{out}hidReportData[reportIdx].hid_data,64{report
 length, varies by device}, {timeout=}3000);

Maybe it's not either of those.. but some other method where the device pushes 
data into a buffer whenever it wants that I can then read.. or something like 
that?  Or maybe the interrupt read is the best I can do?  Is there any way to 
give my read thread to have a higher priority or something like that?

Any thoughts?



James
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal


--
_______________________________________________________
_______________________________________________
fpc-pascal maillist  -  fpc-pascal@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply via email to