I am trying to interact with a remote program via a serial port, basically I thought that putting all the serial port handling in one thread would be a good architectural separation (especially as at first it was mixed into the event loop). I am having issues with the serial port available and read commands.
My understanding is to use available as the call to see how many characters have been received and are therefore ready to read.
First question does the serial port opening etc need to be in the same thread (at first it wasn't and I got red lines in the code on debug to say it was uninitialized) Why is this so?
I need to do two things in my program with the received data..
a) find the next start of a line (just after LF) to "sync" with the lines being sent to me (line oriented replies)
b) then break these received characters into separate lines as many can arrive at once or spaced out in time (which I will later process according to the first 3 characters - right now I deposit them in two different list gadgets)
--- so this is getting hard for a number of reasons which YOU might be able to help be resolve (please!) - The variable length input and the time outs conspire to give me incomplete input lines (so using StringField to split on chr(10) sometimes gives me the "rest of the line" and I have to come around and find the next chr(10) on the subsequent read...
-- and StringField might or might not have "swallowed" the chr(10) - if it was there in the string read so far then it did, if we reached end of the data received so far it didn't (how can I tell??) - I need this to keep track of how far through I am in the currently read piece whose size I got from available call (and this piece might have part, one or many "lines").
-- reading here on serial port topics I find every example uses a SINGLE byte read from the input (ReadSerialPortData(port, *buf, 1)) ) - this can work of course but isn't it very inefficient??
-- should I read just one character at a time - forget stringfield and just search for line ends myself - is there a better way??
-- different topic (related for me) SHARED - what amongst the serial port handling must be shared explicitly??
-- also would it be cleaner (better or safer too) to send the received and split data out of the serial port handling thread via a eventPost or allow shared data strings??
thanks for reading this far and for any help (or pointers to where I missed a relevant topic) you can give me
Phil
example thread :-
Code: Select all
Procedure serial_rd(Parameter)
Shared *Pointer, nx$
Port$ = "COM4"
If OpenSerialPort(0, Port$, 230400, #PB_SerialPort_NoParity, 8, 1, #PB_SerialPort_NoHandshake, 1024, 1024)
MessageRequester("Information", "SerialPort opened with success - "+Port$)
Else
MessageRequester("Error", "Can't open the serial port: "+Port$)
;Break(1)
EndIf
position = 0
Repeat
; receive serial data
size = AvailableSerialPortInput(0)
reslen = ReadSerialPortData(0, *Pointer, size)
If reslen > 0
Rx$ = PeekS(*Pointer+position, reslen, #PB_Ascii)
position = 1
i = 1 ; trying to keep track of the segments supplied by stringfield calls
While position < reslen
nx$ = StringField(Rx$, i, Chr(10)) ; find between \n characters
i = i+1
position = position + StringByteLength(nx$,#PB_Ascii) +1 ; removed \n so real length one greater (help unless at end prematurely)
; send the nx$ out to rest of code
; if the string starts with "sfs" its for us
l$ = Left(nx$,3)
If l$ = "sfs"
; send it to main
AddGadgetItem(3, -1, nx$)
Else
; send it to other
AddGadgetItem(2, -1, nx$)
EndIf
Wend
reslen = 0
EndIf
ForEver
CloseSerialPort(0)
EndProcedure